Compare commits

...

81 Commits

Author SHA1 Message Date
Daniel Stenberg
27197bcff3 Added 'TODO' file (again) with some fresh things I could think of right now 2008-12-26 07:54:08 +00:00
Daniel Stenberg
64b3e5e3f6 Added libssh2_trace man page 2008-12-26 07:46:45 +00:00
Daniel Stenberg
ba79d6b52d libssh2_base64_decode is deprecated and subject for removal in a future
version (like on the next soname bump)
2008-12-26 07:37:55 +00:00
Daniel Stenberg
6b38e21fa7 wrote up a first libssh2_base64_decode man page, added a few missing man
pages to the tarball
2008-12-23 13:23:45 +00:00
Daniel Stenberg
11330ee6da based on Heiner Steven's report, fix the name and description of these man
pages!
2008-12-23 12:34:17 +00:00
Daniel Stenberg
b3649e86a8 briefly mention my recent sftp-related fixes 2008-12-22 23:40:27 +00:00
Daniel Stenberg
2f32080772 mention web site and mailing list, as I think they're not mentioned anywhere
else in the package!
2008-12-22 23:39:46 +00:00
Daniel Stenberg
7aac082782 removed obviously superfluous comments 2008-12-22 22:43:05 +00:00
Daniel Stenberg
5a35edcb9a use a single >>32 instead of "(value / 65536) / 65536", just make sure that
the shift is done on a 64bit type
2008-12-22 22:33:03 +00:00
Daniel Stenberg
079d20aca8 remove unused #ifndef, and two whitespace changes 2008-12-22 22:31:51 +00:00
Daniel Stenberg
b357379923 style/indent changes only to enforce < 80 column lines more strict 2008-12-22 22:10:47 +00:00
Daniel Stenberg
62769b438f libssh2_sftp_seek64() it is now for the 64bit seek function too as the seek2
name has never been used in a release and it makes the naming consistent
2008-12-22 13:18:36 +00:00
Daniel Stenberg
d602478e87 0.19 is now 1.0 2008-12-22 12:51:27 +00:00
Daniel Stenberg
8eba2961ac Based on Alexander Lamaison's patch, there's now a new
function called libssh2_sftp_tell64() that returns the 64 bit file offset,
as the existing libssh2_sftp_tell() only returns a size_t.
2008-12-22 12:46:45 +00:00
Daniel Stenberg
962a41e4ec first conversion of a malloc => buffer in the sftp handle struct 2008-12-22 12:38:41 +00:00
Daniel Stenberg
31841e7c74 helper script for emacs users to get the code style done libssh2-style
automatically
2008-12-20 12:36:50 +00:00
Daniel Stenberg
70f844e57c - Markus Moeller fixed the issue also reported by Alexander Lamaison which
caused SFTP reads with large buffers to fail.
2008-12-19 22:21:36 +00:00
Simon Josefsson
942a81c8d5 Sshd is slow to start on some systems. 2008-12-17 16:22:37 +00:00
Daniel Stenberg
e26956be72 Avoid one malloc by putting the entire handle buffer in the handle struct
at once, use a define for the maximum size length of the handle instead of
'256' in the code.
2008-12-17 10:45:20 +00:00
Daniel Stenberg
2535c5c2ee removed some more libssh2_ prefixes from private functions
Made the libssh2_sftp_open_ex() deal with servers that first responds with
STATUS OK and then sends the actual HANDLE. It seems openssh does this at
times and it screwed things up. To me it seems like a spec violation...
2008-12-16 15:35:33 +00:00
Daniel Stenberg
197a26ef8c removed unused code, intended the code somewhat 2008-12-16 15:32:20 +00:00
Daniel Stenberg
f1dae83d5e Nothing used libssh2_sftp_packet_read's flush argument anymore so I removed
it and simplified the code somewhat thanks to that. I then renamed the function
to sftp_packet_read() only since it is private in this file anyway.
2008-12-16 12:31:58 +00:00
Daniel Stenberg
bcad67636b renamed libssh2_sftp_packet_requirev to plain sftp_packet_requirev since it
is private in this file only and a shorter name is nicer

Removed a "flush" of the data in sftp_packet_requirev() that now seems to have
made SFTP operations a lot more reliable. It didn't make much sense to have it
there but if someone can present a reason for one I figure we should carefully
investigate one and only do it conditionally where/when needed.
2008-12-15 22:58:07 +00:00
Daniel Stenberg
fbb25c7ad0 Clarify that this is only fine to use after an actual SFTP protocol error
return code.
2008-12-15 18:48:09 +00:00
Simon Josefsson
e47bedf17c Support EXEEXT in self-test. 2008-11-27 16:00:07 +00:00
Simon Josefsson
19f78244de Cygwin needs -lcrypto for -lssl.
Reported by "Yang Tse" <yangsita@gmail.com>.
2008-11-27 15:47:05 +00:00
Daniel Stenberg
9d5ba0dee2 oops, add missing file 2008-11-27 12:19:43 +00:00
Yang Tse
0934c4b39d fix again cygwin build failure unreleased regression 2008-11-26 18:15:09 +00:00
Dan Fandrich
cc3a7d8e83 Fixed a potential use of an uninitialized variable, the result of which lead
to an unneeded but harmless realloc.
Reduced the scope of some automatic variables.
2008-11-25 07:01:47 +00:00
Dan Fandrich
8f860e249e Fixed some typos in log messages 2008-11-25 06:49:04 +00:00
Daniel Stenberg
160f89f42e - Vlad Grachov brought the new function called
libssh2_session_block_directions() which returns a bitmask for what
  directions the connection blocks. It is to be used applications that use
  non-blocking sockets and when a libssh2 function returns
  LIBSSH2_ERROR_EAGAIN this function can be used to figure out in which
  direction the socket would block and thus it can wait for the socket to
  again be ready for communication in that direction before it calls libssh2
  again.
2008-11-24 13:31:00 +00:00
Simon Josefsson
881b01e522 Add a more realistic self-test of libssh2. 2008-11-21 15:00:18 +00:00
Simon Josefsson
74d33d50ba Ignore coverage/. 2008-11-21 14:51:43 +00:00
Simon Josefsson
fcaa810350 Add rules to generate a code coverage report. 2008-11-21 14:51:28 +00:00
Simon Josefsson
1f015d72b1 Use AM_CPPFLAGS instead of deprecated INCLUDES. 2008-11-21 14:34:03 +00:00
Simon Josefsson
8c8ba3bc20 Add self-test of base64 decode. 2008-11-21 08:36:38 +00:00
Simon Josefsson
9d433d4f80 Add gcov files. 2008-11-21 08:23:54 +00:00
Dan Fandrich
50a3255dde Use only C89-style comments 2008-11-21 02:25:38 +00:00
Dan Fandrich
482072939a Check LIBSSH2_HMAC_RIPEMD consistently 2008-11-21 01:07:08 +00:00
Simon Josefsson
f2253aeee9 Fix compiler warnings. 2008-11-20 10:29:01 +00:00
Simon Josefsson
2b5becfe85 Move pem.c to libgcrypt section, it is not needed for OpenSSL. 2008-11-20 10:09:43 +00:00
Simon Josefsson
8b25820589 Drop pkg-config test, not needed now. 2008-11-19 11:17:53 +00:00
Simon Josefsson
fd0bffdb2e Rewrite OpenSSL+libz detection logic. 2008-11-19 11:10:48 +00:00
Simon Josefsson
86eaae7886 Add more. 2008-11-18 17:00:57 +00:00
Daniel Stenberg
8e8dc43b0c fix the include path to also point out the build dir's src/ dir for the cases
where we build the lot outside of the source dir
2008-11-11 22:33:26 +00:00
Daniel Stenberg
e45bddb9fd avoid duplicate function declarations on windows 2008-11-11 22:32:33 +00:00
Daniel Stenberg
e5a36fb1cf WINSOCK_VERSION is no longer used (Richard W.M. Jones fixed) 2008-11-10 21:26:14 +00:00
Daniel Stenberg
5438cffd9a Richard W.M. Jones' 5 patches that enables libssh2 to get cross-compiled with
mingw
2008-11-10 16:48:41 +00:00
Paul Thomas
95b73812e7 Fixes a problem that the last code change apparently didn't fix. Verified
that this works correctly with another user.
2008-11-09 17:54:23 +00:00
Paul Thomas
85b953d0dd Fixed an issue with a patch that I submitted where the channel_read_ex()
could get stuck in a busy read loop.
2008-11-01 17:28:30 +00:00
Yang Tse
c3447ea29f fix cygwin build failure unreleased regression 2008-10-25 01:43:08 +00:00
Paul Thomas
8896b675f8 Reformatted the code, updated line endings to match original file,
fixed the build problem, removed tabs and replaced with spaces
 and removed C89 unfriendly comments.
2008-10-03 01:14:46 +00:00
Daniel Stenberg
b2334b227d mention libssh2_channel_request_pty_size_ex() 2008-10-02 09:44:38 +00:00
Daniel Stenberg
88d0ef1f3f two new committers! 2008-10-02 09:42:09 +00:00
Paul Thomas
006f233361 This fix addresses bug# 2141548. Channel reads would fail despite
libssh2_poll() detecting that there was data ready to be read on
the socket. This is seen when small amounts of data are ready to
be read, typically 1-4 chars worth.
2008-10-02 02:26:49 +00:00
Paul Thomas
fa620b2a7b Committed changes to add in support for pty resizing. Credit for this
patch goes to Vincent Jaulin.
2008-10-01 01:47:48 +00:00
Paul Thomas
b228f132f7 Fixed an issue with the libssh2_poll_channel_read function not
reading both normal and extended data when a non-zero value
is passed in as the 2nd parameter. This now matches the functionallity
described in the documentation.
2008-10-01 01:31:15 +00:00
Daniel Stenberg
8c43bc52b1 Carlo Bramini fixed the build for msys+mingw. Bug #1943976. 2008-09-30 21:54:20 +00:00
Daniel Stenberg
d26a330483 Carlo Bramini's fixes for the nonblocking examples for msys/mingw 2008-09-30 08:55:35 +00:00
Daniel Stenberg
b4b8c51b32 Neil Gierman provided improved Visual Studio 2008 code in bug #1946268 2008-09-29 18:59:40 +00:00
Daniel Stenberg
818e9edfb1 - Bug #1862727 fixed libssh2_poll() to work on windows (by defining HAVE_SELECT). 2008-09-29 14:16:19 +00:00
Daniel Stenberg
61fda23340 - Based on bug #1815692, we introduce libssh2_sftp_seek2() that allows seeking
beyond the 2GB margin even on 32bit machines.
2008-09-29 14:11:29 +00:00
Daniel Stenberg
93ae080bbc - Based on a patch in bug #1878059 by Steven Ayre libssh2 now parses >2GB file
sizes when downloading SCP files.
2008-09-29 14:04:01 +00:00
Daniel Stenberg
bd3dfed7e8 Adhere to RFC4253 better and don't use dash in the banner string. Bug #2064371 2008-09-29 13:42:41 +00:00
Daniel Stenberg
99afc66665 Sean Peterson's key re-exchange fix. See his long explanation on:
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
2008-07-03 16:26:55 +00:00
Daniel Stenberg
903307113e minor language updates 2008-07-03 10:58:53 +00:00
Daniel Stenberg
9b31ca67ac Gah, I broke Sebastian's patch when I left out the parentheses his patch
did contain. Added properly now.
2008-06-24 22:33:25 +00:00
Daniel Stenberg
3f0d30d1d6 |sftp.c:1470: warning: cast to pointer from integer of different size Another
reason why macros are evil: The string (which is allready char *) should be
cast into char * not the integer.

Signed-off-by: Sebastian Siewior <sebastian@breakpoint.cc>
2008-06-23 22:20:00 +00:00
Mikhail Gusarov
d4aa801f6f Added manpage for libssh2_userauth_keyboard_interactive_ex(3) 2008-03-08 18:26:32 +00:00
Daniel Stenberg
f56daac7fe - Mike Protts filed the bug report #1908724 that identified and fixed a problem
with SFTP stat on files >4GB in size. Previously it used 32bit math only.
2008-03-07 11:55:07 +00:00
Dan Fandrich
a55e6c10c9 Removed a stderr debug message that was accidentally left in (bug #1863153) 2008-01-03 19:12:50 +00:00
Daniel Stenberg
2fcaa00e3a as mentioned in bug #1841442, select wants maxfd+1 in its first argument! 2008-01-02 14:48:48 +00:00
Daniel Stenberg
0242a3b6af corrected wrong comment and made libssh2_channel_wait_closed() return 0 as
documented!
2007-11-29 11:32:34 +00:00
Daniel Stenberg
b310cc3465 oops 2007-11-29 10:04:16 +00:00
Daniel Stenberg
092e5f4b44 added libssh2_channel_wait_closed man page 2007-11-29 10:02:58 +00:00
Daniel Stenberg
c1a83abff9 remove trailing junk character 2007-11-29 09:57:22 +00:00
Mikhail Gusarov
f3c344da22 Fix syntax errors in libssh2_sftp_init and libssh2_sftp_open_ex manpages. 2007-11-21 14:07:32 +00:00
Guenter Knauf
4600d108ed fixed 'uninitialized' compiler warnings. 2007-11-18 20:57:13 +00:00
Daniel Stenberg
76e8e81402 valgrind was friendly enough to point out that doing memcpy() on overlapping
memory areas is a very bad idea so I changed this to memmove()
2007-11-12 23:09:45 +00:00
Daniel Stenberg
d27dd927cd add 0.18 release date 2007-11-12 09:22:32 +00:00
Daniel Stenberg
63d863241a 0.19 in progress 2007-11-12 09:21:46 +00:00
77 changed files with 2017 additions and 606 deletions

View File

@@ -7,3 +7,5 @@ edink:Edink Kadribasic
jehousley: James Housley jehousley: James Housley
gknauf: Guenter Knauf gknauf: Guenter Knauf
dfandrich: Dan Fandrich dfandrich: Dan Fandrich
yangtse: Yang Tse
thomaspu: Paul Thomas

View File

@@ -16,7 +16,7 @@ win32/config.mk win32/Makefile win32/test/Makefile.win32 win32/libssh2_lib.dsp \
win32/libssh2_config.h win32/tests.dsp win32/rules.mk win32/libssh2_config.h win32/tests.dsp win32/rules.mk
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \ EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
maketgz NMakefile maketgz NMakefile TODO
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
@@ -34,3 +34,26 @@ dist-hook:
strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \ strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \
cp $$file $(distdir)$$strip; \ cp $$file $(distdir)$$strip; \
done) done)
# Code Coverage
init-coverage:
make clean
lcov --directory . --zerocounters
COVERAGE_CCOPTS ?= "-g --coverage"
COVERAGE_OUT ?= docs/coverage
build-coverage:
make CFLAGS=$(COVERAGE_CCOPTS) check
mkdir -p $(COVERAGE_OUT)
lcov --directory . --output-file $(COVERAGE_OUT)/$(PACKAGE).info \
--capture
gen-coverage:
genhtml --output-directory $(COVERAGE_OUT) \
$(COVERAGE_OUT)/$(PACKAGE).info \
--highlight --frames --legend \
--title "$(PACKAGE_NAME)"
coverage: init-coverage build-coverage gen-coverage

59
NEWS
View File

@@ -1,5 +1,60 @@
Version 0.18 Version 1.0 ( )
------------ -------------------------------
- (Dec 20 2008) Based on Alexander Lamaison's patch, there's now a new
function called libssh2_sftp_tell64() that returns the 64 bit file offset,
as the existing libssh2_sftp_tell() only returns a size_t.
- (Dec 18 2008) Markus Moeller fixed the issue also reported by Alexander
Lamaison which caused SFTP reads with large buffers to fail.
- Several flaws were fixed that prevented at least SFTP to work reliably
- Vlad Grachov brought the new function called
libssh2_session_block_directions() which returns a bitmask for what
directions the connection blocks. It is to be used applications that use
non-blocking sockets and when a libssh2 function returns
LIBSSH2_ERROR_EAGAIN this function can be used to figure out in which
direction the socket would block and thus it can wait for the socket to
again be ready for communication in that direction before it calls libssh2
again.
- Vincent Jaulin brought the new libssh2_channel_request_pty_size_ex()
function.
- Carlo Bramini fixed the build for msys+mingw. Bug #1943976.
- Neil Gierman provided improved Visual Studio 2008 code in bug #1946268
- Bug #1862727 fixed libssh2_poll() to work on windows (by defining
HAVE_SELECT).
- Based on bug #1815692, we introduce libssh2_sftp_seek64() that allows
seeking beyond the 2GB margin even on 32bit machines.
- Based on a patch in bug #1878059 by Steven Ayre libssh2 now parses >2GB file
sizes when downloading SCP files.
- Bug #2064371 pointed out that the SSH2 banner may not use dash
('-'). Reported by Bjorn Stenborg.
- Sean Peterson fixed a key re-exchange bug:
http://daniel.haxx.se/projects/libssh2/mail/libssh2-devel-archive-2008-06/0002.shtml
- Mike Protts filed the bug report #1908724 that identified and fixed a problem
with SFTP stat on files >4GB in size. Previously it used 32bit math only.
- Removed a stderr debug message that was accidentally left in (bug #1863153)
- OpenSSL and libz detection changed to make cross-compiling to Mingw
work. See README for parameters to use if the auto-detection does
not work for you. From Simon Josefsson.
- Simon Josefsson added a self-test that uses libssh2 to connect to a
local sshd (only enabled if if OpenSSH is installed).
Version 0.18 (November 11 2007)
-------------------------------
- Various changes that improve non-blocking operations and prevent stalls. - Various changes that improve non-blocking operations and prevent stalls.
Especially noticable on Windows since libssh2 just didn't work properly Especially noticable on Windows since libssh2 just didn't work properly

54
README
View File

@@ -4,6 +4,10 @@ libssh2 - SSH2 library
libssh2 is a library implementing the SSH2 protocol, available under libssh2 is a library implementing the SSH2 protocol, available under
the revised BSD license. the revised BSD license.
Web site: http://www.libssh2.org/
Mailing list: https://lists.sourceforge.net/lists/listinfo/libssh2-devel
Generic installation instructions are in INSTALL. Some ./configure Generic installation instructions are in INSTALL. Some ./configure
options deserve additional comments: options deserve additional comments:
@@ -48,49 +52,43 @@ options deserve additional comments:
the older more reliable method. the older more reliable method.
* --with-libgcrypt * --with-libgcrypt
* --without-libgcrypt
* --with-libgcrypt-prefix=DIR * --with-libgcrypt-prefix=DIR
libssh2 can use the Libgcrypt library libssh2 can use the Libgcrypt library
(http://www.gnupg.org/) for cryptographic operations. (http://www.gnupg.org/) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate Libgcrypt in the Configure will attempt to locate Libgcrypt
default location, but if you have installed it automatically.
somewhere else, use the --with-libgrypt-prefix=DIR
parameter.
* --with-openssl=[DIR] If your installation of Libgcrypt is in another
location, specify it using --with-libgcrypt-prefix.
* --with-openssl
* --without-openssl
* --with-libssl-prefix=[DIR]
libssh2 can use the OpenSSL library libssh2 can use the OpenSSL library
(http://www.openssl.org) for cryptographic operations. (http://www.openssl.org) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate OpenSSL in a number Configure will attempt to locate OpenSSL in the
of default locations: default location.
/usr/local/ssl
/usr/local
/usr
/usr/local/openssl
If your installation of OpenSSL is in another If your installation of OpenSSL is in another
location, specify it here. location, specify it using --with-libssl-prefix.
* --with-libz=[DIR] * --with-libz
* --without-libz
* --with-libz-prefix=[DIR]
If present, libssh2 will attempt to use the zlib (http://www.zlib.org) If present, libssh2 will attempt to use the zlib
for payload compression, however zlib is not required. (http://www.zlib.org) for payload compression, however
zlib is not required.
Configure will attempt to location a zlib installation If your installation of Libz is in another location,
in a number of default locations: specify it using --with-libz-prefix.
/usr/local
/usr
/usr/local/libz
/usr/libz
/usr/local/zlib
/usr/zlib
If your installation of zlib is in another location,
you may specify it here.
* --enable-debug * --enable-debug

30
TODO Normal file
View File

@@ -0,0 +1,30 @@
Things TODO
===========
* Add one of the missing man pages:
libssh2_channel_receive_window_adjust
libssh2_channel_request_pty_size_ex
libssh2_channel_window_read_ex
libssh2_channel_window_write_ex
libssh2_publickey_add_ex
libssh2_publickey_init
libssh2_publickey_list_fetch
libssh2_publickey_list_free
libssh2_publickey_remove_ex
libssh2_publickey_shutdown
libssh2_session_flag
libssh2_session_get_blocking
libssh2_userauth_hostbased_fromfile_ex
* Decrease the number of mallocs. Everywhere.
* Use SO_NOSIGPIPE for Mac OS/BSD systems where MSG_NOSIGNAL doesn't exist/work
* Extend the test suite to actually test lots of aspects of libssh2
At next SONAME bump
===================
* remove libssh2_base64_decode() from the API/ABI

View File

@@ -1,7 +1,7 @@
# AC_PREREQ(2.57) # AC_PREREQ(2.57)
AC_INIT(libssh2, [-], libssh2-devel@lists.sourceforge.net) AC_INIT(libssh2, [-], libssh2-devel@lists.sourceforge.net)
AC_CONFIG_SRCDIR([src]) AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([src/libssh2_config.h example/simple/config.h]) AC_CONFIG_HEADER([src/libssh2_config.h])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
dnl SED is needed by some of the tools dnl SED is needed by some of the tools
@@ -28,6 +28,10 @@ AB_INIT
# get this removed. # get this removed.
AC_CANONICAL_HOST AC_CANONICAL_HOST
case "$host" in case "$host" in
*-mingw*)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32 -DWINSOCK_VERSION=0x0200"
LIBS="$LIBS -lws2_32"
;;
*-cygwin) *-cygwin)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32" CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
;; ;;
@@ -40,6 +44,11 @@ case "$host" in
;; ;;
esac esac
AC_CHECK_TYPE(long long,
[AC_DEFINE(HAVE_LONGLONG, 1,
[Define to 1 if the compiler supports the 'long long' data type.])]
longlong="yes"
)
# Some systems (Solaris?) have socket() in -lsocket. # Some systems (Solaris?) have socket() in -lsocket.
AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(socket, socket)
@@ -52,153 +61,57 @@ AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AC_PATH_PROGS(SSHD, [sshd], [],
[$PATH$PATH_SEPARATOR/usr/libexec$PATH_SEPARATOR]dnl
[/usr/sbin$PATH_SEPARATOR/usr/etc$PATH_SEPARATOR/etc])
AM_CONDITIONAL(SSHD, test -n "$SSHD")
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
AC_C_BIGENDIAN AC_C_BIGENDIAN
if test -z "$PKG_CONFIG"; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
fi
dnl check for how to do large files dnl check for how to do large files
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
# Look for libgcrypt. # Configure parameters
AC_ARG_WITH(libgcrypt, AC_ARG_WITH(libgcrypt,
AC_HELP_STRING([--with-libgcrypt],[Use libgcrypt for crypto]), AC_HELP_STRING([--with-libgcrypt],[Use Libgcrypt for crypto]),
use_libgcrypt=$withval,use_libgcrypt=no) use_libgcrypt=$withval,use_libgcrypt=auto)
if test "$use_libgcrypt" != "no"; then AC_ARG_WITH(openssl,
AC_HELP_STRING([--with-openssl],[Use OpenSSL for crypto]),
use_openssl=$withval,use_openssl=auto)
AC_ARG_WITH(libz,
AC_HELP_STRING([--with-libz],[Use Libz for compression]),
use_libz=$withval,use_libz=auto)
# Look for OpenSSL (default)
if test "$use_openssl" != "no" && test "$use_libgcrypt" != "yes"; then
AC_LIB_HAVE_LINKFLAGS([ssl], [crypto], [#include <openssl/ssl.h>])
fi
# Look for libgcrypt
if test "$ac_cv_libssl" != "yes" && test "$use_libgcrypt" != "no"; then
AC_LIB_HAVE_LINKFLAGS([gcrypt], [], [#include <gcrypt.h>]) AC_LIB_HAVE_LINKFLAGS([gcrypt], [], [#include <gcrypt.h>])
fi fi
if test "$ac_cv_libgcrypt" = yes; then
use_libgcrypt=yes if test "$ac_cv_libssl" != "yes" && test "$ac_cv_libgcrypt" != "yes"; then
AC_MSG_ERROR([cannot find OpenSSL or Libgcrypt,
try --with-libssl-prefix=PATH or --with-libgcrypt-prefix=PATH])
fi
if test "$ac_cv_libgcrypt" = "yes"; then
AC_DEFINE(LIBSSH2_LIBGCRYPT, 1, [Use libgcrypt]) AC_DEFINE(LIBSSH2_LIBGCRYPT, 1, [Use libgcrypt])
fi fi
AM_CONDITIONAL(LIBGCRYPT, test "$use_libgcrypt" != "no") AM_CONDITIONAL(LIBGCRYPT, test "$ac_cv_libgcrypt" = "yes")
# Need to define SHLIB_SUFFIX_NAME before checking for libcrypt and libz # Look for Libz
# $shrext_cmds (from libtool) can contain commands so it must be eval'd if test "$use_libz" != "no"; then
# Simon's note: replace the find-openssl/libz logic with Bruno's AC_LIB_HAVE_LINKFLAGS([z], [], [#include <zlib.h>])
# AC_LIB_LINKFLAGS which is more portable and flexible. if test "$ac_cv_libz" != yes; then
eval SHLIB_SUFFIX_NAME=\"$shrext_cmds\" AC_MSG_NOTICE([Cannot find libz, disabling compression])
AC_SUBST(SHLIB_SUFFIX_NAME) AC_MSG_NOTICE([Try --with-libz-prefix=PATH if you know you have it])
#
# Look for OpenSSL
#
AC_ARG_WITH(openssl,
AC_HELP_STRING([--with-openssl=DIR],[Look for OpenSSL in PATH]),
[LIBSSH2_OPENSSL_DIR=$withval],[LIBSSH2_OPENSSL_DIR=yes])
if test "$use_libgcrypt" = "no"; then
if test "$LIBSSH2_OPENSSL_DIR" = "no" || test "$LIBSSH2_OPENSSL_DIR" = "yes"; then
unset LIBSSH2_OPENSSL_DIR
fi
found_openssl=no
pkgcfg_openssl=no
unset OPENSSL_INCDIR
unset OPENSSL_INCLINE
unset OPENSSL_LIBLINE
AC_MSG_CHECKING([for OpenSSL])
# Explicit path given, use it rather than pkg-config
if test ! -z "$LIBSSH2_OPENSSL_DIR"; then
found_openssl=yes
OPENSSL_LIBLINE="-L$LIBSSH2_OPENSSL_DIR/lib -lcrypto"
OPENSSL_INCLINE="-I$LIBSSH2_OPENSSL_DIR/include"
OPENSSL_INCDIR=$LIBSSH2_OPENSSL_DIR/include
AC_MSG_RESULT([Using explicit path $LIBSSH2_OPENSSL_DIR])
fi
# If pkg-config is found try using it
if test "$found_openssl" = "no" && test -x "$PKG_CONFIG" && $PKG_CONFIG --exists openssl; then
found_openssl=yes
pkgcfg_openssl=yes
OPENSSL_LIBLINE=`$PKG_CONFIG --libs openssl`
OPENSSL_INCLINE=`$PKG_CONFIG --cflags-only-I openssl`
AC_MSG_RESULT([Using paths from pkg-config])
fi
# Elsewise, search for OpenSSL wherever it might be
if test "$found_openssl" = "no"; then
OPENSSL_SEARCH_PATH="/usr/local/ssl /usr/local /usr /usr/local/openssl"
for i in $OPENSSL_SEARCH_PATH; do
if test -r $i/include/openssl/evp.h; then
OPENSSL_INCLINE="-I$i/include"
OPENSSL_INCDIR=$i/include
fi
if test -r $i/include/openssl/hmac.h; then
OPENSSL_INCLINE="-I$i/include"
OPENSSL_INCDIR=$i/include
fi
if test -r $i/lib/libcrypto.a -o -r $i/lib/libcrypto$SHLIB_SUFFIX_NAME; then
OPENSSL_LIBLINE="-L$i/lib -lcrypto"
fi
test -n "$OPENSSL_INCLINE" && test -n "$OPENSSL_LIBLINE" && break
done
if test -z "$OPENSSL_INCLINE"; then
AC_MSG_ERROR([Cannot find OpenSSL's <evp.h> or <hmac.h>])
fi
if test -z "$OPENSSL_LIBLINE"; then
AC_MSG_ERROR([Cannot find OpenSSL's libcrypto])
fi
AC_MSG_RESULT([$OPENSSL_INCLINE $OPENSSL_LIBLINE])
fi
#
# Confirm required OpenSSL libs
#
if test ! "$pkgcfg_openssl" = "yes"; then
if test ! -r $OPENSSL_INCDIR/openssl/bn.h || test ! -r $OPENSSL_INCDIR/openssl/evp.h || \
test ! -r $OPENSSL_INCDIR/openssl/hmac.h || test ! -r $OPENSSL_INCDIR/openssl/pem.h || \
test ! -r $OPENSSL_INCDIR/openssl/sha.h; then
AC_MSG_ERROR([Missing one or more of <openssl/bn.h>, <openssl/evp.h>, <openssl/hmac.h>, <openssl/pem.h>, <openssl/sha.h>])
fi
fi
CFLAGS="$CFLAGS $OPENSSL_INCLINE"
LDFLAGS="$LDFLAGS $OPENSSL_LIBLINE"
fi
#
# zlib
#
AC_ARG_WITH(libz,
AC_HELP_STRING([--with-libz=PATH],[Look for libz in PATH]),
[LIBSSH2_LIBZ_DIR=$withval],[LIBSSH2_LIBZ_DIR="/usr/local /usr /usr/local/libz /usr/libz /usr/local/zlib /usr/zlib"])
if test "$LIBSSH2_LIBZ_DIR" = "no" || test "$LIBSSH2_LIBZ_DIR" = "yes"; then
unset LIBSSH2_LIBZ_DIR
fi
unset LIBZ_INCDIR
unset LIBZ_LIBDIR
AC_MSG_CHECKING([for libz])
for i in $LIBSSH2_LIBZ_DIR; do
if test -r $i/include/zlib.h; then
LIBZ_INCDIR=$i/include
fi
if test -r $i/lib/libz.a -o -r $i/lib/libz$SHLIB_SUFFIX_NAME; then
LIBZ_LIBDIR=$i/lib
fi
test -n "$LIBZ_INCDIR" && test -n "$LIBZ_LIBDIR" && break
done
if test -n "$LIBZ_INCDIR" && test -n "$LIBZ_LIBDIR"; then
AC_MSG_RESULT([Found in $LIBZ_INCDIR $LIBZ_LIBDIR])
CFLAGS="$CFLAGS -I$LIBZ_INCDIR"
LDFLAGS="$LDFLAGS -L$LIBZ_LIBDIR -lz"
AC_DEFINE(LIBSSH2_HAVE_ZLIB, 1, [Compile in zlib support])
else else
AC_MSG_RESULT([Cannot find libz's <zlib.h>]) AC_DEFINE(LIBSSH2_HAVE_ZLIB, 1, [Compile in zlib support])
fi
fi fi
# #
@@ -249,7 +162,39 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h]) AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/ioctl.h sys/time.h]) AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/ioctl.h sys/time.h])
AC_CHECK_HEADERS([arpa/inet.h netinet/in.h]) AC_CHECK_HEADERS([arpa/inet.h netinet/in.h])
AC_CHECK_FUNCS(poll gettimeofday select)
case $host in
*-*-cygwin* | *-*-cegcc*)
# These are POSIX-like systems using BSD-like sockets API.
;;
*)
AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
;;
esac
AC_CHECK_FUNCS(poll gettimeofday select strtoll)
dnl Check for select() into ws2_32 for Msys/Mingw
if test "$ac_cv_func_select" != "yes"; then
AC_MSG_CHECKING([for select in ws2_32])
AC_TRY_LINK([
#ifdef HAVE_WINSOCK2_H
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#endif
],[
select(0,(fd_set *)NULL,(fd_set *)NULL,(fd_set *)NULL,(struct timeval *)NULL);
],[
AC_MSG_RESULT([yes])
HAVE_SELECT="1"
AC_DEFINE_UNQUOTED(HAVE_SELECT, 1,
[Define to 1 if you have the select function.])
],[
AC_MSG_RESULT([no])
])
fi
AC_FUNC_ALLOCA AC_FUNC_ALLOCA

View File

@@ -1,2 +1,3 @@
Makefile Makefile
Makefile.in Makefile.in
coverage

View File

@@ -1,4 +1,4 @@
# $Id: Makefile.am,v 1.26 2007/06/15 11:01:22 jehousley Exp $ # $Id: Makefile.am,v 1.31 2008/12/26 07:46:45 bagder Exp $
EXTRA_DIST = template.3 EXTRA_DIST = template.3
@@ -23,11 +23,14 @@ dist_man_MANS = \
libssh2_channel_set_blocking.3 \ libssh2_channel_set_blocking.3 \
libssh2_channel_setenv_ex.3 \ libssh2_channel_setenv_ex.3 \
libssh2_channel_wait_eof.3 \ libssh2_channel_wait_eof.3 \
libssh2_channel_wait_closed.3 \
libssh2_channel_write_ex.3 \
libssh2_channel_x11_req_ex.3 \ libssh2_channel_x11_req_ex.3 \
libssh2_hostkey_hash.3 \ libssh2_hostkey_hash.3 \
libssh2_scp_recv.3 \ libssh2_scp_recv.3 \
libssh2_scp_send_ex.3 \ libssh2_scp_send_ex.3 \
libssh2_session_abstract.3 \ libssh2_session_abstract.3 \
libssh2_session_block_directions.3 \
libssh2_session_callback_set.3 \ libssh2_session_callback_set.3 \
libssh2_session_free.3 \ libssh2_session_free.3 \
libssh2_session_disconnect_ex.3 \ libssh2_session_disconnect_ex.3 \
@@ -55,9 +58,13 @@ dist_man_MANS = \
libssh2_sftp_stat_ex.3 \ libssh2_sftp_stat_ex.3 \
libssh2_sftp_symlink_ex.3 \ libssh2_sftp_symlink_ex.3 \
libssh2_sftp_tell.3 \ libssh2_sftp_tell.3 \
libssh2_sftp_tell64.3 \
libssh2_sftp_unlink_ex.3 \ libssh2_sftp_unlink_ex.3 \
libssh2_sftp_write.3 \ libssh2_sftp_write.3 \
libssh2_userauth_authenticated.3 \ libssh2_userauth_authenticated.3 \
libssh2_userauth_keyboard_interactive_ex.3 \
libssh2_userauth_list.3 \ libssh2_userauth_list.3 \
libssh2_userauth_password_ex.3 \ libssh2_userauth_password_ex.3 \
libssh2_userauth_publickey_fromfile.3 libssh2_userauth_publickey_fromfile.3 \
libssh2_base64_decode.3 \
libssh2_trace.3

View File

@@ -0,0 +1,27 @@
.\" $Id: libssh2_base64_decode.3,v 1.2 2008/12/26 07:37:55 bagder Exp $
.\"
.TH libssh2_base64_decode 3 "23 Dec 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME
libssh2_base64_decode - decode a base64 encoded string
.SH SYNOPSIS
#include <libssh2.h>
int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest,
unsigned int *dest_len, const char *src,
unsigned int src_len);
.SH DESCRIPTION
This function is deemed DEPRECATED and will be removed from libssh2 in a
future version. Don't use it!
Decode a base64 chunk and store it into a newly allocated buffer. 'dest_len'
will be set to hold the length of the returned buffer that '*dest' will point
to.
The returned buffer is allocated by this function, but it is not clear how to
free that memory!
.SH BUGS
The memory that *dest points to is allocated by the malloc function libssh2
uses, but there's no way for an appliction to free this data in a safe and
reliable way!
.SH RETURN VALUE
0 if successful, -1 if any error occurred.

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_channel_close.3,v 1.1 2007/06/13 17:03:38 jehousley Exp $ .\" $Id: libssh2_channel_close.3,v 1.2 2007/11/29 09:57:22 bagder Exp $
.\" .\"
.TH libssh2_channel_close 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_channel_close 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_channel_close - close a channel< libssh2_channel_close - close a channel
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>

View File

@@ -0,0 +1,24 @@
.\" $Id: libssh2_channel_wait_closed.3,v 1.2 2007/11/29 10:04:16 bagder Exp $
.\"
.TH libssh2_channel_wait_closed 3 "29 Nov 2007" "libssh2 0.19" "libssh2 manual"
.SH NAME
libssh2_channel_wait_closed - wait for the remote to close the channel
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
.SH DESCRIPTION
Enter a temporary blocking state until the remote host closes the named
channel. Typically sent after \fIlibssh2_channel_close(3)\fP in order to
examine the exit status.
.SH RETURN VALUE
Return 0 on success or negative on failure. It returns LIBSSH2_ERROR_EAGAIN
when it would otherwise block. While LIBSSH2_ERROR_EAGAIN is a negative
number, it isn't really a failure per se.
.SH SEE ALSO
.BR libssh2_channel_send_eof(3)
.BR libssh2_channel_eof(3)
.BR libssh2_channel_wait_eof(3)

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_session_abstract.3,v 1.1 2007/06/14 15:26:58 jehousley Exp $ .\" $Id: libssh2_session_abstract.3,v 1.2 2008/07/03 10:58:53 bagder Exp $
.\" .\"
.TH libssh2_session_abstract 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_session_abstract 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
@@ -14,9 +14,9 @@ libssh2_session_abstract(LIBSSH2_SESSION *session);
.BR libssh2_session_init_ex(3) .BR libssh2_session_init_ex(3)
Return a pointer to where the abstract pointer provided to Return a pointer to where the abstract pointer provided to
.BR libssh2_session_init_ex(3) \fBlibssh2_session_init_ex(3)\fP is stored. By providing a doubly
is stored. By providing a doubly de-referenced pointer, the internal de-referenced pointer, the internal storage of the session instance may be
storage of the session instance may be modified in place. modified in place.
.SH RETURN VALUE .SH RETURN VALUE
A pointer to session internal storage whos contents point to previously A pointer to session internal storage whos contents point to previously

View File

@@ -0,0 +1,31 @@
.\" $Id: libssh2_session_block_directions.3,v 1.2 2008/12/22 12:51:27 bagder Exp $
.\"
.TH libssh2_session_block_directions 3 "1 Oct 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME
libssh2_session_block_directions - get directions that socket should wait for before calling libssh2 function again
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_session_block_directions(LIBSSH2_SESSION *session);
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by \fBlibssh2_session_init(3)\fP
When any of libssh2 functions return \fBLIBSSH2_ERROR_EAGAIN\fP an application
should wait for the socket to have data available for reading or
writing. Depending on the return value of
\fIlibssh2_session_block_directions(3)\fP an application should wait for read,
write or both.
.SH RETURN VALUE
Returns the set of directions as a binary mask. Can be a combination of:
LIBSSH2_SESSION_BLOCK_INBOUND: Inbound direction blocked.
LIBSSH2_SESSION_BLOCK_OUTBOUND: Outbound direction blocked.
Application should wait for data to be available for socket prior to calling a
libssh2 function again. If \fBLIBSSH2_SESSION_BLOCK_INBOUND\fP is set select
should contain the session socket in readfds set. Correspondingly in case of
\fBLIBSSH2_SESSION_BLOCK_INBOUND\fP writefds set should contain the socket.
.SH AVAILABILITY
Added in 1.0

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_session_set_blocking.3,v 1.1 2007/06/14 17:23:13 jehousley Exp $ .\" $Id: libssh2_session_set_blocking.3,v 1.2 2008/07/03 10:58:53 bagder Exp $
.\" .\"
.TH libssh2_session_set_blocking 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_session_set_blocking 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
@@ -16,14 +16,14 @@ libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking);
\fIblocking\fP - Set to a non-zero value to make the channel block, or zero to \fIblocking\fP - Set to a non-zero value to make the channel block, or zero to
make it non-blocking. make it non-blocking.
Set or clear blocking mode on the selected on the sessoin. This will Set or clear blocking mode on the selected on the session. This will
instantly affect any channels associtated with this session. If a read is instantly affect any channels associated with this session. If a read is
performed on a session with no data currently available, a blocking performed on a session with no data currently available, a blocking session
session will wait for data to arrive and return what it receives. will wait for data to arrive and return what it receives. A non-blocking
A non-blocking session will return immediately with an empty buffer. session will return immediately with an empty buffer. If a write is performed
If a write is performed on a session with on a session with no room for more data, a blocking session will wait for
no room for more data, a blocking session will wait for room. A non-blocking room. A non-blocking session will return immediately without writing
session will return immediately without writing anything. anything.
.SH RETURN VALUE .SH RETURN VALUE
None None

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_init.3,v 1.6 2007/06/13 16:41:33 jehousley Exp $ .\" $Id: libssh2_sftp_init.3,v 1.7 2007/11/21 14:07:32 dottedmag Exp $
.\" .\"
.TH libssh2_sftp_init 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_init 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_init - libssh2_sftp_init - open SFTP channel for the given SSH session.
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_sftp_last_error.3,v 1.1 2007/06/14 16:08:43 jehousley Exp $ .\" $Id: libssh2_sftp_last_error.3,v 1.2 2008/12/15 18:48:09 bagder Exp $
.\" .\"
.TH libssh2_sftp_last_error 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_last_error 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
@@ -14,7 +14,10 @@ libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
\fIsftp\fP - SFTP instance as returned by \fIsftp\fP - SFTP instance as returned by
.BR libssh2_sftp_init(3) .BR libssh2_sftp_init(3)
Determines the last error code produced by the SFTP layer. Returns the last error code produced by the SFTP layer. Note that this only
returns a sensible error code if libssh2 returned LIBSSH2_ERROR_SFTP_PROTOCOL
in a previous call. Using \fBlibssh2_sftp_last_error(3)\fP without a
preceeding SFTP protocol error, it will return an unspecified value.
.SH RETURN VALUE .SH RETURN VALUE
Current error code state of the SFTP instance. Current error code state of the SFTP instance.

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_open_ex.3,v 1.8 2007/06/13 16:41:33 jehousley Exp $ .\" $Id: libssh2_sftp_open_ex.3,v 1.9 2007/11/21 14:07:32 dottedmag Exp $
.\" .\"
.TH libssh2_sftp_open_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_open_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_open - libssh2_sftp_open - open filehandle for file on SFTP.
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_rename_ex.3,v 1.1 2007/06/14 16:08:43 jehousley Exp $ .\" $Id: libssh2_sftp_rename_ex.3,v 1.2 2008/12/23 12:34:17 bagder Exp $
.\" .\"
.TH libssh2_sftp_rename_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_rename_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_rename_ex - rename a file libssh2_sftp_rename_ex - rename an SFTP file
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_rmdir_ex.3,v 1.1 2007/06/14 16:08:43 jehousley Exp $ .\" $Id: libssh2_sftp_rmdir_ex.3,v 1.2 2008/12/23 12:34:17 bagder Exp $
.\" .\"
.TH libssh2_sftp_rmdir_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_rmdir_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_rmdir_ex - rename a file libssh2_sftp_rmdir_ex - remove an SFTP directory
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,6 +1,6 @@
.\" $Id: libssh2_sftp_seek.3,v 1.1 2007/06/14 16:08:43 jehousley Exp $ .\" $Id: libssh2_sftp_seek.3,v 1.3 2008/12/22 13:18:36 bagder Exp $
.\" .\"
.TH libssh2_sftp_seek 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_seek 3 "22 Dec 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_seek - set the read/write position indicator within a file libssh2_sftp_seek - set the read/write position indicator within a file
.SH SYNOPSIS .SH SYNOPSIS
@@ -10,6 +10,9 @@ libssh2_sftp_seek - set the read/write position indicator within a file
void void
libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset); libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset);
.SH DESCRIPTION .SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by \fIhandle\fP - SFTP File Handle as returned by
.BR libssh2_sftp_open(3) .BR libssh2_sftp_open(3)
@@ -21,6 +24,7 @@ Note that libssh2 implements file pointers as a localized concept to make
file access appear more POSIX like. No packets are exchanged with the server file access appear more POSIX like. No packets are exchanged with the server
during a seek operation. The localized file pointer is simply used as a during a seek operation. The localized file pointer is simply used as a
convenience offset during read/write operations. convenience offset during read/write operations.
.SH AVAILABILITY
libssh2_sftp_seek64(3) was added in 1.0
.SH SEE ALSO .SH SEE ALSO
.BR libssh2_sftp_open(3) .BR libssh2_sftp_open(3)

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_stat_ex.3,v 1.1 2007/06/14 16:33:38 jehousley Exp $ .\" $Id: libssh2_sftp_stat_ex.3,v 1.2 2008/12/23 12:34:17 bagder Exp $
.\" .\"
.TH libssh2_sftp_stat_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_stat_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_stat_ex - rename a file libssh2_sftp_stat_ex - get status about an SFTP file
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,4 +1,4 @@
.\" $Id: libssh2_sftp_tell.3,v 1.1 2007/06/14 16:33:38 jehousley Exp $ .\" $Id: libssh2_sftp_tell.3,v 1.2 2008/12/22 12:46:45 bagder Exp $
.\" .\"
.TH libssh2_sftp_tell 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_tell 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
@@ -11,16 +11,12 @@ size_t
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle); libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
.SH DESCRIPTION .SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by \fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open(3)\fP.
.BR libssh2_sftp_open(3)
Identify the current offset of the file handle's internal pointer. Note
that the SSH2 protocol does not have a notion of file pointers and that
libssh2 implements this using a localized file pointer which is updated
with each read/write call.
Returns the current offset of the file handle's internal pointer. Note that
this is now deprecated. Use the newer \fBlibssh2_sftp_tell64(3)\fP instead!
.SH RETURN VALUE .SH RETURN VALUE
Current offset from beginning of file in bytes. Current offset from beginning of file in bytes.
.SH SEE ALSO .SH SEE ALSO
.BR libssh2_sftp_open(3) .BR libssh2_sftp_open(3),
.BR libssh2_sftp_tell64(3)

View File

@@ -0,0 +1,23 @@
.\" $Id: libssh2_sftp_tell64.3,v 1.1 2008/12/22 12:46:45 bagder Exp $
.\"
.TH libssh2_sftp_tell64 3 "22 Dec 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME
libssh2_sftp_tell64 - get the current read/write position indicator for a file
.SH SYNOPSIS
#include <libssh2.h>
#include <libssh2_sftp.h>
libssh2_uint64_t
libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle);
.SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open(3)\fP
Identify the current offset of the file handle's internal pointer.
.SH RETURN VALUE
Current offset from beginning of file in bytes.
.SH AVAILABILITY
Added in libssh2 1.0
.SH SEE ALSO
.BR libssh2_sftp_open(3),
.BR libssh2_sftp_tell(3)

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_unlink_ex.3,v 1.1 2007/06/14 16:46:14 jehousley Exp $ .\" $Id: libssh2_sftp_unlink_ex.3,v 1.2 2008/12/23 12:34:17 bagder Exp $
.\" .\"
.TH libssh2_sftp_unlink_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_unlink_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_unlink_ex - rename a file libssh2_sftp_unlink_ex - unlink an SFTP file
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

View File

@@ -1,8 +1,8 @@
.\" $Id: libssh2_sftp_write.3,v 1.1 2007/06/14 16:46:14 jehousley Exp $ .\" $Id: libssh2_sftp_write.3,v 1.2 2008/12/23 12:34:17 bagder Exp $
.\" .\"
.TH libssh2_sftp_rename_ex 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" .TH libssh2_sftp_write 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual"
.SH NAME .SH NAME
libssh2_sftp_rename_ex - rename a file libssh2_sftp_write - write SFTP data
.SH SYNOPSIS .SH SYNOPSIS
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>

35
docs/libssh2_trace.3 Normal file
View File

@@ -0,0 +1,35 @@
.\" $Id: libssh2_trace.3,v 1.1 2008/12/26 07:46:45 bagder Exp $
.\"
.TH libssh2_trace 3 "26 Dec 2008" "libssh2 1.0" "libssh2 manual"
.SH NAME
libssh2_trace - enable debug info from inside libssh2
.SH SYNOPSIS
#include <libssh2.h>
void libssh2_trace(int bitmask);
.SH DESCRIPTION
This is a function present in the library that can be used to get debug info
from within libssh2 when it is running. Helpful when trying to trace or debug
behaviors. This function has no effect unless libssh2 was built to support
this option, and a typical "release build" might not.
\fBbitmask\fP can be set to none, one or more of these bits:
.RS
.IP LIBSSH2_TRACE_TRANS
Transport layer debugging
.IP LIBSSH2_TRACE_KEX
Key exchange debugging
.IP LIBSSH2_TRACE_AUTH
Authentication debugging
.IP LIBSSH2_TRACE_CONN
Connection layer debugging
.IP LIBSSH2_TRACE_SCP
SCP debugging
.IP LIBSSH2_TRACE_SFTP
SFTP debugging
.IP LIBSSH2_TRACE_ERROR
Error debugging
.IP LIBSSH2_TRACE_PUBLICKEY
Public Key debugging
.RE

View File

@@ -0,0 +1,43 @@
.\" $Id: libssh2_userauth_keyboard_interactive_ex.3,v 1.1 2008/03/08 18:26:32 dottedmag Exp $
.\"
.TH libssh2_userauth_keyboard_interactive_ex 3 "8 Mar 2008" "libssh2 0.19" "libssh2 manual"
.SH NAME
libssh2_userauth_keyboard_interactive_ex - authenticate a session using a challenge-response authentication
.SH SYNOPSIS
#include <libssh2.h>
int
libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(*response_callback));
int
libssh2_userauth_keyboard_interactive(LIBSSH2_SESSION *session, const char *username, LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(*response_callback));
.SH DESCRIPTION
\fIsession\fP - Session instance as returned by
.BR libssh2_session_init(3)
\fIusername\fP - Name of user to attempt plain password authentication for.
\fIusername_len\fP - Length of username parameter.
\fIresponse_callback\fP - As authentication proceeds, host issues several (1 or more) challenges and requires responses. This callback will be called at this moment. Callback is responsible to obtain responses for the challenges, fill the provided data structure and then return control. Responses will be sent to the host. String values will be free(3)ed by the library.
Attempts keyboard-interactive (challenge/response) authentication.
Note that many SSH servers will always issue single "password" challenge,
requesting actual password as response, but it is not required by the protocol,
and various authentication schemes, such as smartcard authentication may use
keyboard-interactive authentication type too.
.SH RETURN VALUE
Return 0 on success or negative on failure. It returns
LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
.SH ERRORS
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed.
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
.SH SEE ALSO
.BR libssh2_session_init(3)

View File

@@ -2,8 +2,12 @@ Makefile
Makefile.in Makefile.in
.deps .deps
.libs .libs
*.gcno
*.gcda
scp scp
scp_nonblock scp_nonblock
scp_write
scp_write_nonblock
sftp sftp
sftp_nonblock sftp_nonblock
sftpdir sftpdir

View File

@@ -10,6 +10,7 @@ noinst_PROGRAMS = ssh2 \
sftp_RW_nonblock \ sftp_RW_nonblock \
sftpdir sftpdir_nonblock sftpdir sftpdir_nonblock
INCLUDES = -I. -I$(top_srcdir)/include # the examples need the $(top_builddir)/src since when building outside of the
# source dir they still need to reach the libssh2_config.h header
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
LDADD = $(top_builddir)/src/libssh2.la LDADD = $(top_builddir)/src/libssh2.la

View File

@@ -1,10 +1,10 @@
/* /*
* $Id: scp.c,v 1.10 2007/08/09 01:10:11 dfandrich Exp $ * $Id: scp.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do a simple SCP transfer. * Sample showing how to do a simple SCP transfer.
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,10 +1,10 @@
/* /*
* $Id: scp_nonblock.c,v 1.11 2007/09/24 12:15:45 bagder Exp $ * $Id: scp_nonblock.c,v 1.13 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SCP transfers in a non-blocking manner. * Sample showing how to do SCP transfers in a non-blocking manner.
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
@@ -45,12 +45,15 @@ int main(int argc, char *argv[])
const char *scppath="/tmp/TEST"; const char *scppath="/tmp/TEST";
struct stat fileinfo; struct stat fileinfo;
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
off_t got=0; off_t got=0;
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -88,8 +91,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance */ /* Create a session instance */

View File

@@ -1,10 +1,10 @@
/* /*
* $Id: scp_write.c,v 1.5 2007/08/09 01:10:11 dfandrich Exp $ * $Id: scp_write.c,v 1.6 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do a simple SCP transfer. * Sample showing how to do a simple SCP transfer.
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,10 +1,10 @@
/* /*
* $Id: scp_write_nonblock.c,v 1.7 2007/08/09 01:10:11 dfandrich Exp $ * $Id: scp_write_nonblock.c,v 1.9 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do a simple SCP transfer. * Sample showing how to do a simple SCP transfer.
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
@@ -47,6 +47,9 @@ int main(int argc, char *argv[])
const char *scppath="/tmp/TEST"; const char *scppath="/tmp/TEST";
FILE *local; FILE *local;
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
char mem[1024]; char mem[1024];
size_t nread; size_t nread;
char *ptr; char *ptr;
@@ -55,7 +58,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -105,8 +108,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance /* Create a session instance

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp.c,v 1.14 2007/09/24 12:14:18 bagder Exp $ * $Id: sftp.c,v 1.15 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP transfers. * Sample showing how to do SFTP transfers.
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/secrets -p|-i|-k" * "sftp 192.168.0.1 user password /tmp/secrets -p|-i|-k"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_RW_nonblock.c,v 1.10 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_RW_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP transfers in a non-blocking manner. * Sample showing how to do SFTP transfers in a non-blocking manner.
* *
@@ -9,7 +9,7 @@
* Using the SFTP server running on 127.0.0.1 * Using the SFTP server running on 127.0.0.1
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -53,6 +53,9 @@ int main(int argc, char *argv[])
const char *sftppath="/tmp/TEST"; /* source path */ const char *sftppath="/tmp/TEST"; /* source path */
const char *dest="/tmp/TEST2"; /* destination path */ const char *dest="/tmp/TEST2"; /* destination path */
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle; LIBSSH2_SFTP_HANDLE *sftp_handle;
FILE *tempstorage; FILE *tempstorage;
@@ -63,7 +66,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
/* Ultra basic "connect to port 22 on localhost" /* Ultra basic "connect to port 22 on localhost"
@@ -87,8 +90,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance /* Create a session instance

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_mkdir.c,v 1.7 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_mkdir.c,v 1.8 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP mkdir * Sample showing how to do SFTP mkdir
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/sftp_mkdir" * "sftp 192.168.0.1 user password /tmp/sftp_mkdir"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_mkdir_nonblock.c,v 1.9 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_mkdir_nonblock.c,v 1.11 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP non-blocking mkdir. * Sample showing how to do SFTP non-blocking mkdir.
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/sftp_write_nonblock.c" * "sftp 192.168.0.1 user password /tmp/sftp_write_nonblock.c"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -46,12 +46,15 @@ int main(int argc, char *argv[])
const char *password="password"; const char *password="password";
const char *sftppath="/tmp/sftp_mkdir_nonblock"; const char *sftppath="/tmp/sftp_mkdir_nonblock";
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -91,8 +94,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance /* Create a session instance

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_nonblock.c,v 1.13 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_nonblock.c,v 1.15 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP non-blocking transfers. * Sample showing how to do SFTP non-blocking transfers.
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/secrets" * "sftp 192.168.0.1 user password /tmp/secrets"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -49,13 +49,16 @@ int main(int argc, char *argv[])
const char *password="password"; const char *password="password";
const char *sftppath="/tmp/TEST"; const char *sftppath="/tmp/TEST";
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle; LIBSSH2_SFTP_HANDLE *sftp_handle;
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -94,8 +97,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance */ /* Create a session instance */

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_write.c,v 1.8 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_write.c,v 1.9 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP write transfers. * Sample showing how to do SFTP write transfers.
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password sftp_write.c /tmp/secrets" * "sftp 192.168.0.1 user password sftp_write.c /tmp/secrets"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -57,7 +57,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftp_write_nonblock.c,v 1.10 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftp_write_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SFTP non-blocking write transfers. * Sample showing how to do SFTP non-blocking write transfers.
* *
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password sftp_write_nonblock.c /tmp/sftp_write_nonblock.c" * "sftp 192.168.0.1 user password sftp_write_nonblock.c /tmp/sftp_write_nonblock.c"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -47,6 +47,9 @@ int main(int argc, char *argv[])
const char *loclfile="sftp_write_nonblock.c"; const char *loclfile="sftp_write_nonblock.c";
const char *sftppath="/tmp/sftp_write_nonblock.c"; const char *sftppath="/tmp/sftp_write_nonblock.c";
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
FILE *local; FILE *local;
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle; LIBSSH2_SFTP_HANDLE *sftp_handle;
@@ -57,7 +60,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -106,8 +109,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance /* Create a session instance

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftpdir.c,v 1.9 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftpdir.c,v 1.10 2008/11/10 16:48:41 bagder Exp $
* *
* Sample doing an SFTP directory listing. * Sample doing an SFTP directory listing.
* *
@@ -9,7 +9,7 @@
* "sftpdir 192.168.0.1 user password /tmp/secretdir" * "sftpdir 192.168.0.1 user password /tmp/secretdir"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: sftpdir_nonblock.c,v 1.10 2007/08/09 01:10:11 dfandrich Exp $ * $Id: sftpdir_nonblock.c,v 1.12 2008/11/10 16:48:41 bagder Exp $
* *
* Sample doing an SFTP directory listing. * Sample doing an SFTP directory listing.
* *
@@ -9,7 +9,7 @@
* "sftpdir 192.168.0.1 user password /tmp/secretdir" * "sftpdir 192.168.0.1 user password /tmp/secretdir"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
@@ -46,13 +46,16 @@ int main(int argc, char *argv[])
const char *password="password"; const char *password="password";
const char *sftppath="/tmp/secretdir"; const char *sftppath="/tmp/secretdir";
int rc; int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session; LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle; LIBSSH2_SFTP_HANDLE *sftp_handle;
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {
@@ -91,8 +94,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */ /* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0); rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK); fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#elif defined(HAVE_IOCTLSOCKET)
ioctlsocket(sock, FIONBIO, &flag);
#else
#ifdef WIN32
u_long mode = 1;
ioctlsocket (sock, FIONBIO, &mode);
#else #else
#error "add support for setting the socket non-blocking here" #error "add support for setting the socket non-blocking here"
#endif
#endif #endif
/* Create a session instance /* Create a session instance

View File

@@ -1,5 +1,5 @@
/* /*
* $Id: ssh2.c,v 1.17 2007/08/09 01:10:11 dfandrich Exp $ * $Id: ssh2.c,v 1.18 2008/11/10 16:48:41 bagder Exp $
* *
* Sample showing how to do SSH2 connect. * Sample showing how to do SSH2 connect.
* *
@@ -9,10 +9,13 @@
* "ssh2 host user password [-p|-i|-k]" * "ssh2 host user password [-p|-i|-k]"
*/ */
#include "config.h" #include "libssh2_config.h"
#include <libssh2.h> #include <libssh2.h>
#include <libssh2_sftp.h> #include <libssh2_sftp.h>
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#ifdef HAVE_WINSOCK2_H #ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
#endif #endif
@@ -73,7 +76,7 @@ int main(int argc, char *argv[])
#ifdef WIN32 #ifdef WIN32
WSADATA wsadata; WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata); WSAStartup(MAKEWORD(2,0), &wsadata);
#endif #endif
if (argc > 1) { if (argc > 1) {

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -82,12 +82,16 @@ typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t; typedef long long libssh2_int64_t;
#endif #endif
#define LIBSSH2_VERSION "0.18.0-CVS" /* We use underscore instead of dash when appending CVS in dev versions just
to make the BANNER define (used by src/session.c) be a valid SSH
banner. Release versions have no appended strings and may of coruse not
have dashes either. */
#define LIBSSH2_VERSION "1.0.0_CVS"
/* The numeric version number is also available "in parts" by using these /* The numeric version number is also available "in parts" by using these
defines: */ defines: */
#define LIBSSH2_VERSION_MAJOR 0 #define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 18 #define LIBSSH2_VERSION_MINOR 0
#define LIBSSH2_VERSION_PATCH 0 #define LIBSSH2_VERSION_PATCH 0
/* This is the numeric version of the libssh2 version number, meant for easier /* This is the numeric version of the libssh2 version number, meant for easier
@@ -105,7 +109,7 @@ typedef long long libssh2_int64_t;
and it is always a greater number in a more recent release. It makes and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work. comparisons with greater than and less than work.
*/ */
#define LIBSSH2_VERSION_NUM 0x001200 #define LIBSSH2_VERSION_NUM 0x010000
/* /*
* This is the date and time when the full source package was created. The * This is the date and time when the full source package was created. The
@@ -240,6 +244,11 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel Disconnect */ #define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel Disconnect */
#define LIBSSH2_POLLFD_LISTENER_CLOSED 0x0080 /* Listener Disconnect */ #define LIBSSH2_POLLFD_LISTENER_CLOSED 0x0080 /* Listener Disconnect */
#define HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
/* Block Direction Types */
#define LIBSSH2_SESSION_BLOCK_INBOUND 0x0001
#define LIBSSH2_SESSION_BLOCK_OUTBOUND 0x0002
/* Hash Types */ /* Hash Types */
#define LIBSSH2_HOSTKEY_HASH_MD5 1 #define LIBSSH2_HOSTKEY_HASH_MD5 1
#define LIBSSH2_HOSTKEY_HASH_SHA1 2 #define LIBSSH2_HOSTKEY_HASH_SHA1 2
@@ -320,6 +329,7 @@ LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method
LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type); LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf); LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session); LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value); LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value);
@@ -389,6 +399,9 @@ LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, const char *
LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, unsigned int term_len, const char *modes, unsigned int modes_len, int width, int height, int width_px, int height_px); LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, unsigned int term_len, const char *modes, unsigned int modes_len, int width, int height, int width_px, int height_px);
#define libssh2_channel_request_pty(channel, term) libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX) #define libssh2_channel_request_pty(channel, term) libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX)
LIBSSH2_API int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel, int width, int height, int width_px, int height_px);
#define libssh2_channel_request_pty_size(channel, width, height) libssh2_channel_request_pty_size_ex( (channel), (width), (height), 0, 0)
LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, const char *auth_proto, const char *auth_cookie, int screen_number); LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, const char *auth_proto, const char *auth_cookie, int screen_number);
#define libssh2_channel_x11_req(channel, screen_number) libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number)) #define libssh2_channel_x11_req(channel, screen_number) libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number))

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -206,9 +206,11 @@ LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
#define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle) #define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle)
LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset); LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
#define libssh2_sftp_rewind(handle) libssh2_sftp_seek((handle), 0) LIBSSH2_API void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset);
#define libssh2_sftp_rewind(handle) libssh2_sftp_seek64((handle), 0)
LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle); LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
LIBSSH2_API libssh2_uint64_t libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle);
LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat); LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat);
#define libssh2_sftp_fstat(handle, attrs) libssh2_sftp_fstat_ex((handle), (attrs), 0) #define libssh2_sftp_fstat(handle, attrs) libssh2_sftp_fstat_ex((handle), (attrs), 0)

51
libssh2-style.el Normal file
View File

@@ -0,0 +1,51 @@
;;;; Emacs Lisp help for writing libssh2 code. ;;;;
;;;; $Id: libssh2-style.el,v 1.1 2008/12/20 12:36:50 bagder Exp $
;;; The libssh2 hacker's C conventions.
;;; See the sample.emacs file on how this file can be made to take
;;; effect automatically when editing libssh2 source files.
(defconst libssh2-c-style
'((c-basic-offset . 4)
(c-comment-only-line-offset . 0)
(c-hanging-braces-alist . ((substatement-open before after)))
(c-offsets-alist . ((topmost-intro . 0)
(topmost-intro-cont . 0)
(substatement . +)
(substatement-open . 0)
(statement-case-intro . +)
(statement-case-open . 0)
(case-label . 0)
))
)
"Libssh2 C Programming Style")
(defun libssh2-code-cleanup ()
"tabify and delete trailing whitespace"
(interactive)
(untabify (point-min) (point-max))
(delete-trailing-whitespace)
)
;; Customizations for all of c-mode, c++-mode, and objc-mode
(defun libssh2-c-mode-common-hook ()
"Libssh2 C mode hook"
;; add libssh2 style and set it for the current buffer
(c-add-style "libssh2" libssh2-c-style t)
(setq tab-width 8
indent-tabs-mode nil ; Use spaces, not tabs.
comment-column 40
c-font-lock-extra-types (append '("libssh2_int64_t" "LIBSSH2_USERAUTH_KBDINT_PROMPT" "LIBSSH2_SESSION" "LIBSSH2_CHANNEL" "ssize_t" "size_t" "uint32_t" "LIBSSH2_LISTENER" "LIBSSH2_POLLFD"))
)
;; keybindings for C, C++, and Objective-C. We can put these in
;; c-mode-base-map because of inheritance ...
(define-key c-mode-base-map "\M-q" 'c-fill-paragraph)
(define-key c-mode-base-map "\M-m" 'libssh2-code-cleanup)
(setq c-recognize-knr-p nil)
;;; (add-hook 'write-file-hooks 'delete-trailing-whitespace t)
(setq show-trailing-whitespace t)
)
;; Set this is in your .emacs if you want to use the c-mode-hook as
;; defined here right out of the box.
; (add-hook 'c-mode-common-hook 'libssh2-c-mode-common-hook)

5
m4/.cvsignore Normal file
View File

@@ -0,0 +1,5 @@
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4

View File

@@ -5,6 +5,8 @@
*.dll *.dll
*.exe *.exe
*.obj *.obj
*.gcno
*.gcda
.*.swp .*.swp
Debug Debug
Release Release

View File

@@ -1,12 +1,12 @@
# $Id: Makefile.am,v 1.10 2007/07/17 13:22:55 gknauf Exp $ # $Id: Makefile.am,v 1.13 2008/11/21 14:34:03 jas4711 Exp $
AUTOMAKE_OPTIONS = foreign nostdinc AUTOMAKE_OPTIONS = foreign nostdinc
libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c \ libssh2_la_SOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c \
misc.c packet.c publickey.c scp.c session.c sftp.c userauth.c \ misc.c packet.c publickey.c scp.c session.c sftp.c userauth.c \
libssh2_priv.h openssl.h libgcrypt.h pem.c transport.c libssh2_priv.h openssl.h libgcrypt.h transport.c
if LIBGCRYPT if LIBGCRYPT
libssh2_la_SOURCES += libgcrypt.c libssh2_la_SOURCES += libgcrypt.c pem.c
else else
libssh2_la_SOURCES += openssl.c libssh2_la_SOURCES += openssl.c
endif endif
@@ -18,7 +18,7 @@ lib_LTLIBRARIES = libssh2.la
# srcdir/include for the shipped headers # srcdir/include for the shipped headers
# builddir/src for the generated config header when building out of the source # builddir/src for the generated config header when building out of the source
# tree # tree
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/src AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/src
VERSION=-version-info 1:0:0 VERSION=-version-info 1:0:0
@@ -50,4 +50,5 @@ VERSION=-version-info 1:0:0
# set age to 0. (c:r:a=0) # set age to 0. (c:r:a=0)
# #
libssh2_la_LDFLAGS = $(VERSION) -no-undefined $(LTLIBGCRYPT) libssh2_la_LDFLAGS = $(VERSION) -no-undefined \
$(LTLIBGCRYPT) $(LTLIBSSL) $(LTLIBZ)

View File

@@ -1,4 +1,6 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2008 by Daniel Stenberg
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -63,10 +65,12 @@ libssh2_channel_nextid(LIBSSH2_SESSION * session)
channel = channel->next; channel = channel->next;
} }
/* This is a shortcut to avoid waiting for close packets on channels we've forgotten about, /* This is a shortcut to avoid waiting for close packets on channels we've
* This *could* be a problem if we request and close 4 billion or so channels in too rapid succession * forgotten about, This *could* be a problem if we request and close 4
* for the remote end to respond, but the worst case scenario is that some data meant for another channel * billion or so channels in too rapid succession for the remote end to
* Gets picked up by the new one.... Pretty unlikely all told... * respond, but the worst case scenario is that some data meant for
* another channel Gets picked up by the new one.... Pretty unlikely all
* told...
*/ */
session->next_channel = id + 1; session->next_channel = id + 1;
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Allocated new channel ID#%lu", _libssh2_debug(session, LIBSSH2_DBG_CONN, "Allocated new channel ID#%lu",
@@ -95,7 +99,7 @@ libssh2_channel_locate(LIBSSH2_SESSION * session, unsigned long channel_id)
/* }}} */ /* }}} */
#define libssh2_channel_add(session, channel) \ #define CHANNEL_ADD(session, channel) \
{ \ { \
if ((session)->channels.tail) { \ if ((session)->channels.tail) { \
(session)->channels.tail->next = (channel); \ (session)->channels.tail->next = (channel); \
@@ -130,7 +134,8 @@ libssh2_channel_open_ex(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel = NULL; session->open_channel = NULL;
session->open_packet = NULL; session->open_packet = NULL;
session->open_data = NULL; session->open_data = NULL;
/* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) + window_size(4) + packet_size(4) */ /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
* window_size(4) + packet_size(4) */
session->open_packet_len = channel_type_len + message_len + 17; session->open_packet_len = channel_type_len + message_len + 17;
session->open_local_channel = libssh2_channel_nextid(session); session->open_local_channel = libssh2_channel_nextid(session);
@@ -169,7 +174,7 @@ libssh2_channel_open_ex(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel->remote.window_size_initial = window_size; session->open_channel->remote.window_size_initial = window_size;
session->open_channel->remote.packet_size = packet_size; session->open_channel->remote.packet_size = packet_size;
libssh2_channel_add(session, session->open_channel); CHANNEL_ADD(session, session->open_channel);
s = session->open_packet = s = session->open_packet =
LIBSSH2_ALLOC(session, session->open_packet_len); LIBSSH2_ALLOC(session, session->open_packet_len);
@@ -242,7 +247,8 @@ libssh2_channel_open_ex(LIBSSH2_SESSION * session, const char *channel_type,
session->open_channel->local.packet_size = session->open_channel->local.packet_size =
libssh2_ntohu32(session->open_data + 13); libssh2_ntohu32(session->open_data + 13);
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Connection Established - ID: %lu/%lu win: %lu/%lu pack: %lu/%lu", "Connection Established - ID: %lu/%lu win: %lu/%lu"
" pack: %lu/%lu",
session->open_channel->local.id, session->open_channel->local.id,
session->open_channel->remote.id, session->open_channel->remote.id,
session->open_channel->local.window_size, session->open_channel->local.window_size,
@@ -408,7 +414,8 @@ libssh2_channel_forward_listen_ex(LIBSSH2_SESSION * session, const char *host,
if (session->fwdLstn_state == libssh2_NB_state_idle) { if (session->fwdLstn_state == libssh2_NB_state_idle) {
session->fwdLstn_host_len = session->fwdLstn_host_len =
(host ? strlen(host) : (sizeof("0.0.0.0") - 1)); (host ? strlen(host) : (sizeof("0.0.0.0") - 1));
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */ /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
+ port(4) */
session->fwdLstn_packet_len = session->fwdLstn_packet_len =
session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14; session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14;
@@ -450,12 +457,14 @@ libssh2_channel_forward_listen_ex(LIBSSH2_SESSION * session, const char *host,
session->fwdLstn_packet_len); session->fwdLstn_packet_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending global-request packet for forward listen request", "Would block sending global-request packet for "
"forward listen request",
0); 0);
return NULL; return NULL;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send global-request packet for forward listen request", "Unable to send global-request packet for forward "
"listen request",
0); 0);
LIBSSH2_FREE(session, session->fwdLstn_packet); LIBSSH2_FREE(session, session->fwdLstn_packet);
session->fwdLstn_packet = NULL; session->fwdLstn_packet = NULL;
@@ -567,7 +576,8 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)
LIBSSH2_CHANNEL *queued = listener->queue; LIBSSH2_CHANNEL *queued = listener->queue;
unsigned char *packet, *s; unsigned char *packet, *s;
unsigned long host_len = strlen(listener->host); unsigned long host_len = strlen(listener->host);
/* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */ /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
port(4) */
unsigned long packet_len = unsigned long packet_len =
host_len + 14 + sizeof("cancel-tcpip-forward") - 1; host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
int rc; int rc;
@@ -609,7 +619,8 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)
listener->chanFwdCncl_data = packet; listener->chanFwdCncl_data = packet;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send global-request packet for forward listen request", "Unable to send global-request packet for forward "
"listen request",
0); 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
listener->chanFwdCncl_state = libssh2_NB_state_idle; listener->chanFwdCncl_state = libssh2_NB_state_idle;
@@ -721,7 +732,8 @@ libssh2_channel_setenv_ex(LIBSSH2_CHANNEL * channel, const char *varname,
sizeof(channel->setenv_packet_requirev_state)); sizeof(channel->setenv_packet_requirev_state));
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Setting remote environment variable: %s=%s on channel %lu/%lu", "Setting remote environment variable: %s=%s on "
"channel %lu/%lu",
varname, value, channel->local.id, channel->remote.id); varname, value, channel->local.id, channel->remote.id);
s = channel->setenv_packet = s = channel->setenv_packet =
@@ -762,7 +774,8 @@ libssh2_channel_setenv_ex(LIBSSH2_CHANNEL * channel, const char *varname,
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel-request packet for setenv request", "Unable to send channel-request packet for "
"setenv request",
0); 0);
LIBSSH2_FREE(session, channel->setenv_packet); LIBSSH2_FREE(session, channel->setenv_packet);
channel->setenv_packet = NULL; channel->setenv_packet = NULL;
@@ -930,6 +943,81 @@ libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL * channel, const char *term,
/* }}} */ /* }}} */
LIBSSH2_API int
libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel, int width,
int height, int width_px, int height_px)
{
LIBSSH2_SESSION *session = channel->session;
unsigned char *s;
int rc;
if (channel->reqPTY_state == libssh2_NB_state_idle) {
channel->reqPTY_packet_len = 39;
/* Zero the whole thing out */
memset(&channel->reqPTY_packet_requirev_state, 0,
sizeof(channel->reqPTY_packet_requirev_state));
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"changing tty size on channel %lu/%lu",
channel->local.id,
channel->remote.id);
s = channel->reqPTY_packet =
LIBSSH2_ALLOC(session, channel->reqPTY_packet_len);
if (!channel->reqPTY_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for pty-request", 0);
return -1;
}
*(s++) = SSH_MSG_CHANNEL_REQUEST;
libssh2_htonu32(s, channel->remote.id);
s += 4;
libssh2_htonu32(s, sizeof("window-change") - 1);
s += 4;
memcpy(s, "window-change", sizeof("window-change") - 1);
s += sizeof("window-change") - 1;
*(s++) = 0x00; /* Don't reply */
libssh2_htonu32(s, width);
s += 4;
libssh2_htonu32(s, height);
s += 4;
libssh2_htonu32(s, width_px);
s += 4;
libssh2_htonu32(s, height_px);
s += 4;
channel->reqPTY_state = libssh2_NB_state_created;
}
if (channel->reqPTY_state == libssh2_NB_state_created) {
rc = libssh2_packet_write(session, channel->reqPTY_packet,
channel->reqPTY_packet_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send window-change packet", 0);
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
}
LIBSSH2_FREE(session, channel->reqPTY_packet);
channel->reqPTY_packet = NULL;
libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
channel->reqPTY_state = libssh2_NB_state_sent;
return 0;
}
channel->reqPTY_state = libssh2_NB_state_idle;
return -1;
}
/* Keep this an even number */ /* Keep this an even number */
#define LIBSSH2_X11_RANDOM_COOKIE_LEN 32 #define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
@@ -963,7 +1051,8 @@ libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL * channel, int single_connection,
sizeof(channel->reqX11_packet_requirev_state)); sizeof(channel->reqX11_packet_requirev_state));
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Requesting x11-req for channel %lu/%lu: single=%d proto=%s cookie=%s screen=%d", "Requesting x11-req for channel %lu/%lu: single=%d "
"proto=%s cookie=%s screen=%d",
channel->local.id, channel->remote.id, channel->local.id, channel->remote.id,
single_connection, single_connection,
auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1", auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
@@ -1218,7 +1307,8 @@ libssh2_channel_flush_ex(LIBSSH2_CHANNEL * channel, int streamid)
int bytes_to_flush = packet->data_len - packet->data_head; int bytes_to_flush = packet->data_len - packet->data_head;
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
"Flushing %d bytes of data from stream %lu on channel %lu/%lu", "Flushing %d bytes of data from stream "
"%lu on channel %lu/%lu",
bytes_to_flush, packet_stream_id, bytes_to_flush, packet_stream_id,
channel->local.id, channel->remote.id); channel->local.id, channel->remote.id);
@@ -1294,7 +1384,8 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
&& (adjustment + channel->adjust_queue < && (adjustment + channel->adjust_queue <
LIBSSH2_CHANNEL_MINADJUST)) { LIBSSH2_CHANNEL_MINADJUST)) {
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
"Queueing %lu bytes for receive window adjustment for channel %lu/%lu", "Queueing %lu bytes for receive window adjustment "
"for channel %lu/%lu",
adjustment, channel->local.id, channel->remote.id); adjustment, channel->local.id, channel->remote.id);
channel->adjust_queue += adjustment; channel->adjust_queue += adjustment;
return channel->remote.window_size; return channel->remote.window_size;
@@ -1313,7 +1404,8 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
libssh2_htonu32(channel->adjust_adjust + 1, channel->remote.id); libssh2_htonu32(channel->adjust_adjust + 1, channel->remote.id);
libssh2_htonu32(channel->adjust_adjust + 5, adjustment); libssh2_htonu32(channel->adjust_adjust + 5, adjustment);
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
"Adjusting window %lu bytes for data flushed from channel %lu/%lu", "Adjusting window %lu bytes for data flushed from "
"channel %lu/%lu",
adjustment, channel->local.id, channel->remote.id); adjustment, channel->local.id, channel->remote.id);
channel->adjust_state = libssh2_NB_state_created; channel->adjust_state = libssh2_NB_state_created;
@@ -1324,7 +1416,8 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (rc) { } else if (rc) {
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send transfer-window adjustment packet, deferring", "Unable to send transfer-window adjustment packet, "
"deferring",
0); 0);
channel->adjust_queue = adjustment; channel->adjust_queue = adjustment;
channel->adjust_state = libssh2_NB_state_idle; channel->adjust_state = libssh2_NB_state_idle;
@@ -1339,10 +1432,11 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
/* }}} */ /* }}} */
/* {{{ libssh2_channel_handle_extended_data /* {{{ libssh2_channel_handle_extended_data
* How should extended data look to the calling app? *
* Keep it in separate channels[_read() _read_stdder()]? (NORMAL) * How should extended data look to the calling app? Keep it in separate
* Merge the extended data to the standard data? [everything via _read()]? (MERGE) * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
* Ignore it entirely [toss out packets as they come in]? (IGNORE) * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
* out packets as they come in]? (IGNORE)
*/ */
LIBSSH2_API void LIBSSH2_API void
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL * channel, libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL * channel,
@@ -1414,14 +1508,11 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
} while (rc > 0); } while (rc > 0);
if ((rc < 0) && (rc != PACKET_EAGAIN)) { if ((rc < 0) && (rc != PACKET_EAGAIN)) {
fprintf(stderr, "return rc = %d\n", rc);
return rc; return rc;
} }
channel->read_bytes_read = 0; channel->read_bytes_read = 0;
channel->read_block = 0;
channel->read_packet = session->packets.head; channel->read_packet = session->packets.head;
channel->read_state = libssh2_NB_state_created; channel->read_state = libssh2_NB_state_created;
} }
@@ -1435,21 +1526,34 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
} }
rc = 0; rc = 0;
channel->read_block = 0;
do { do {
if (channel->read_block) { if (channel->read_block) {
/* in the second lap and onwards, do this */ /* in the second lap and onwards, do this...
* If we haven't yet filled our buffer, try to read more
* data. */
if ( channel->read_bytes_read < (int) buflen) {
rc = libssh2_packet_read(session); rc = libssh2_packet_read(session);
channel->read_packet = session->packets.head;
/* If we didn't find any more data to read */
if (rc < 0) {
if ( channel->read_bytes_read > 0){
break; /* finish processing and return */
} }
if (rc < 0) { /* no packets available, no data read. */
if (rc != PACKET_EAGAIN) {
channel->read_state = libssh2_NB_state_idle; channel->read_state = libssh2_NB_state_idle;
}
/* no packets available */
return rc; return rc;
} }
/* We read more data, restart our processing at the beginning
* of our packet list. */
channel->read_packet = session->packets.head;
}
else { /* The read buffer is full, finish processing and return */
break;
}
}
while (channel->read_packet while (channel->read_packet
&& (channel->read_bytes_read < (int) buflen)) { && (channel->read_bytes_read < (int) buflen)) {
@@ -1521,7 +1625,8 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Unlinking empty packet buffer from channel %lu/%lu", "Unlinking empty packet buffer from "
"channel %lu/%lu",
channel->local.id, channel->remote.id); channel->local.id, channel->remote.id);
channel_read_ex_point1: channel_read_ex_point1:
channel->read_state = libssh2_NB_state_jump1; channel->read_state = libssh2_NB_state_jump1;
@@ -1597,7 +1702,8 @@ libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
&& (channel->local.id == read_local_id) && (channel->local.id == read_local_id)
&& (stream_id == (int) libssh2_ntohu32(read_packet->data + 5))) && (stream_id == (int) libssh2_ntohu32(read_packet->data + 5)))
|| (!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA) || (!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
&& (channel->local.id == read_local_id)) || (!stream_id && (channel->local.id == read_local_id)) ||
(!stream_id
&& (read_packet-> && (read_packet->
data[0] == data[0] ==
SSH_MSG_CHANNEL_EXTENDED_DATA) SSH_MSG_CHANNEL_EXTENDED_DATA)
@@ -1610,7 +1716,6 @@ libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
== ==
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE)))
{ {
return (read_packet->data_len - read_packet->data_head); return (read_packet->data_len - read_packet->data_head);
} }
read_packet = read_packet->next; read_packet = read_packet->next;
@@ -1651,32 +1756,8 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel, int stream_id,
0); 0);
} }
#if 0 /* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] +
/* buflen(4) */
The following chunk of code is #ifdef'ed out, since I wanted it to
remain here with the given explanation why having the code in here
is not a good idea. The text is taken from the email Gavrie
Philipson wrote to libssh2-devel on Nov 8 2007.
The logic behind this is that in nonblocking mode, if the local
window size has shrunk to zero, there's no point in trying to send
anything more. However, exiting the function at that point does not
allow any adjusts from the remote side to be received, since
libssh2_packet_read (that is called further on in this function) is
never called in this case.
Removing this bit of code fixes the problem. This should not cause
busy waiting, since after the libssh2_packet_read, the function
correctly returns PACKET_EAGAIN if the window size was not adjusted.
*/
if (!channel->session->socket_block &&
(channel->local.window_size <= 0)) {
/* Can't write anything */
return 0;
}
#endif
/* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] + buflen(4) */
channel->write_packet_len = buflen + (stream_id ? 13 : 9); channel->write_packet_len = buflen + (stream_id ? 13 : 9);
channel->write_packet = channel->write_packet =
LIBSSH2_ALLOC(session, channel->write_packet_len); LIBSSH2_ALLOC(session, channel->write_packet_len);
@@ -1733,14 +1814,16 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel, int stream_id,
/* REMEMBER local means local as the SOURCE of the data */ /* REMEMBER local means local as the SOURCE of the data */
if (channel->write_bufwrite > channel->local.window_size) { if (channel->write_bufwrite > channel->local.window_size) {
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Splitting write block due to %lu byte window_size on %lu/%lu/%d", "Splitting write block due to %lu byte "
"window_size on %lu/%lu/%d",
channel->local.window_size, channel->local.id, channel->local.window_size, channel->local.id,
channel->remote.id, stream_id); channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.window_size; channel->write_bufwrite = channel->local.window_size;
} }
if (channel->write_bufwrite > channel->local.packet_size) { if (channel->write_bufwrite > channel->local.packet_size) {
_libssh2_debug(session, LIBSSH2_DBG_CONN, _libssh2_debug(session, LIBSSH2_DBG_CONN,
"Splitting write block due to %lu byte packet_size on %lu/%lu/%d", "Splitting write block due to %lu byte "
"packet_size on %lu/%lu/%d",
channel->local.packet_size, channel->local.id, channel->local.packet_size, channel->local.id,
channel->remote.id, stream_id); channel->remote.id, stream_id);
channel->write_bufwrite = channel->local.packet_size; channel->write_bufwrite = channel->local.packet_size;
@@ -1763,8 +1846,11 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel, int stream_id,
channel->write_s - channel->write_s -
channel->write_packet); channel->write_packet);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"libssh2_packet_write returned EAGAIN");
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (rc) { }
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel data", 0); "Unable to send channel data", 0);
LIBSSH2_FREE(session, channel->write_packet); LIBSSH2_FREE(session, channel->write_packet);
@@ -1854,7 +1940,7 @@ libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
/* }}} */ /* }}} */
/* {{{ libssh2_channel_wait_closed /* {{{ libssh2_channel_wait_eof
* Awaiting channel EOF * Awaiting channel EOF
*/ */
LIBSSH2_API int LIBSSH2_API int
@@ -1976,7 +2062,8 @@ libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)
if (!libssh2_channel_eof(channel)) { if (!libssh2_channel_eof(channel)) {
libssh2_error(session, LIBSSH2_ERROR_INVAL, libssh2_error(session, LIBSSH2_ERROR_INVAL,
"libssh2_channel_wait_closed() invoked when channel is not in EOF state", "libssh2_channel_wait_closed() invoked when channel is "
"not in EOF state",
0); 0);
return -1; return -1;
} }
@@ -2007,7 +2094,7 @@ libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)
channel->wait_closed_state = libssh2_NB_state_idle; channel->wait_closed_state = libssh2_NB_state_idle;
return 1; return 0;
} }
/* }}} */ /* }}} */
@@ -2110,10 +2197,12 @@ libssh2_channel_free(LIBSSH2_CHANNEL * channel)
/* }}} */ /* }}} */
/* {{{ libssh2_channel_window_read_ex /* {{{ libssh2_channel_window_read_ex
* Check the status of the read window *
* Returns the number of bytes which the remote end may send without overflowing the window limit * Check the status of the read window. Returns the number of bytes which the
* read_avail (if passed) will be populated with the number of bytes actually available to be read * remote end may send without overflowing the window limit read_avail (if
* window_size_initial (if passed) will be populated with the window_size_initial as defined by the channel_open request * passed) will be populated with the number of bytes actually available to be
* read window_size_initial (if passed) will be populated with the
* window_size_initial as defined by the channel_open request
*/ */
LIBSSH2_API unsigned long LIBSSH2_API unsigned long
libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel, libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
@@ -2149,16 +2238,19 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
/* }}} */ /* }}} */
/* {{{ libssh2_channel_window_write_ex /* {{{ libssh2_channel_window_write_ex
* Check the status of the write window *
* Returns the number of bytes which may be safely writen on the channel without blocking * Check the status of the write window Returns the number of bytes which may
* window_size_initial (if passed) will be populated with the size of the initial window as defined by the channel_open request * be safely writen on the channel without blocking window_size_initial (if
* passed) will be populated with the size of the initial window as defined by
* the channel_open request
*/ */
LIBSSH2_API unsigned long LIBSSH2_API unsigned long
libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel, libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel,
unsigned long *window_size_initial) unsigned long *window_size_initial)
{ {
if (window_size_initial) { if (window_size_initial) {
/* For locally initiated channels this is very often 0, so it's not *that* useful as information goes */ /* For locally initiated channels this is very often 0, so it's not
* *that* useful as information goes */
*window_size_initial = channel->local.window_size_initial; *window_size_initial = channel->local.window_size_initial;
} }

View File

@@ -818,7 +818,7 @@ static int
{ {
unsigned char *s; unsigned char *s;
unsigned long p_len, g_len; unsigned long p_len, g_len;
int ret; int ret = 0;
int rc; int rc;
if (key_state->state == libssh2_NB_state_idle) { if (key_state->state == libssh2_NB_state_idle) {
@@ -1674,12 +1674,14 @@ libssh2_kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
* Returns 0 on success, non-zero on failure * Returns 0 on success, non-zero on failure
*/ */
int int
libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flags |= SERVER */ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
key_exchange_state_t * key_state) key_exchange_state_t * key_state)
{ {
int rc = 0; int rc = 0;
int retcode; int retcode;
session->state |= LIBSSH2_STATE_KEX_ACTIVE;
if (key_state->state == libssh2_NB_state_idle) { if (key_state->state == libssh2_NB_state_idle) {
/* Prevent loop in packet_add() */ /* Prevent loop in packet_add() */
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
@@ -1711,11 +1713,14 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
if (key_state->state == libssh2_NB_state_sent) { if (key_state->state == libssh2_NB_state_sent) {
retcode = libssh2_kexinit(session); retcode = libssh2_kexinit(session);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (retcode) { } else if (retcode) {
session->local.kexinit = key_state->oldlocal; session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len; session->local.kexinit_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle; key_state->state = libssh2_NB_state_idle;
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
return -1; return -1;
} }
@@ -1729,6 +1734,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
&key_state->data_len, 0, NULL, 0, &key_state->data_len, 0, NULL, 0,
&key_state->req_state); &key_state->req_state);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (retcode) { } else if (retcode) {
if (session->local.kexinit) { if (session->local.kexinit) {
@@ -1737,6 +1743,8 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
session->local.kexinit = key_state->oldlocal; session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len; session->local.kexinit_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle; key_state->state = libssh2_NB_state_idle;
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
return -1; return -1;
} }
@@ -1763,6 +1771,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
session->kex->exchange_keys(session, session->kex->exchange_keys(session,
&key_state->key_state_low); &key_state->key_state_low);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
@@ -1782,6 +1791,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
session->remote.kexinit = NULL; session->remote.kexinit = NULL;
} }
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
key_state->state = libssh2_NB_state_idle; key_state->state = libssh2_NB_state_idle;

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2006, 2007, The Written Word, Inc.
* Author: Simon Josefsson * Copyright (C) 2008, Simon Josefsson
* All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
* with or without modification, are permitted provided * with or without modification, are permitted provided
@@ -150,10 +151,10 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase) FILE * fp, unsigned const char *passphrase)
{ {
char *data, *save_data; unsigned char *data, *save_data;
unsigned int datalen; unsigned int datalen;
int ret; int ret;
char *n, *e, *d, *p, *q, *e1, *e2, *coeff; unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen; unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
(void) passphrase; (void) passphrase;
@@ -245,10 +246,10 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session, LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase) FILE * fp, unsigned const char *passphrase)
{ {
char *data, *save_data; unsigned char *data, *save_data;
unsigned int datalen; unsigned int datalen;
int ret; int ret;
char *p, *q, *g, *y, *x; unsigned char *p, *q, *g, *y, *x;
unsigned int plen, qlen, glen, ylen, xlen; unsigned int plen, qlen, glen, ylen, xlen;
(void) passphrase; (void) passphrase;

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2006, 2007, The Written Word, Inc.
* Author: Simon Josefsson * Copyright (C) 2008, Simon Josefsson
* All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
* with or without modification, are permitted provided * with or without modification, are permitted provided
@@ -174,7 +175,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#define _libssh2_bn struct gcry_mpi #define _libssh2_bn struct gcry_mpi
#define _libssh2_bn_ctx int #define _libssh2_bn_ctx int
#define _libssh2_bn_ctx_new() 0 #define _libssh2_bn_ctx_new() 0
#define _libssh2_bn_ctx_free(bnctx) 0 #define _libssh2_bn_ctx_free(bnctx) ((void)0)
#define _libssh2_bn_init() gcry_mpi_new(0) #define _libssh2_bn_init() gcry_mpi_new(0)
#define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM) #define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM)
#define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m) #define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m)

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -41,6 +41,17 @@
#define LIBSSH2_LIBRARY #define LIBSSH2_LIBRARY
#include "libssh2_config.h" #include "libssh2_config.h"
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#include <stdio.h>
#include <time.h>
/* The following CPP block should really only be in session.c and /* The following CPP block should really only be in session.c and
packet.c. However, AIX have #define's for 'events' and 'revents' packet.c. However, AIX have #define's for 'events' and 'revents'
and we are using those names in libssh2.h, so we need to include and we are using those names in libssh2.h, so we need to include
@@ -51,12 +62,10 @@
http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html
http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html
*/ */
#include <stdio.h>
#ifdef HAVE_POLL #ifdef HAVE_POLL
# include <sys/poll.h> # include <sys/poll.h>
#else #else
# ifdef HAVE_SELECT # if defined(HAVE_SELECT) && !defined(WIN32)
# ifdef HAVE_SYS_SELECT_H # ifdef HAVE_SYS_SELECT_H
# include <sys/select.h> # include <sys/select.h>
# else # else
@@ -70,6 +79,28 @@
#include "libssh2_publickey.h" #include "libssh2_publickey.h"
#include "libssh2_sftp.h" #include "libssh2_sftp.h"
/* Provide iovec / writev on WIN32 platform. */
#ifdef WIN32
/* same as WSABUF */
struct iovec {
u_long iov_len;
char *iov_base;
};
#define inline __inline
static inline int writev(int sock, struct iovec *iov, int nvecs)
{
DWORD ret;
if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
return ret;
}
return -1;
}
#endif /* WIN32 */
/* Needed for struct iovec on some platforms */ /* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H #ifdef HAVE_SYS_UIO_H
#include <sys/uio.h> #include <sys/uio.h>
@@ -91,6 +122,26 @@
#include "openssl.h" #include "openssl.h"
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#ifdef _MSC_VER
/* "inline" keyword is valid only with C++ engine! */
#define inline __inline
#endif
/* not really usleep, but safe for the way we use it in this lib */
static inline int usleep(int udelay)
{
Sleep(udelay / 1000);
return 0;
}
#endif
/* RFC4253 section 6.1 Maximum Packet Length says: /* RFC4253 section 6.1 Maximum Packet Length says:
* *
* "All implementations MUST be able to process packets with * "All implementations MUST be able to process packets with
@@ -481,12 +532,19 @@ struct _LIBSSH2_PUBLICKEY
unsigned long listFetch_data_len; unsigned long listFetch_data_len;
}; };
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
struct _LIBSSH2_SFTP_HANDLE struct _LIBSSH2_SFTP_HANDLE
{ {
LIBSSH2_SFTP *sftp; LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *prev, *next; LIBSSH2_SFTP_HANDLE *prev, *next;
char *handle; /* This is a pre-allocated buffer used for sending SFTP requests as the
whole thing might not get sent in one go. This buffer is used for read,
write, close and MUST thus be big enough to suit all these. */
unsigned char request_packet[SFTP_HANDLE_MAXLEN + 25];
char handle[SFTP_HANDLE_MAXLEN];
int handle_len; int handle_len;
char handle_type; char handle_type;
@@ -654,6 +712,7 @@ struct _LIBSSH2_SESSION
int socket_fd; int socket_fd;
int socket_block; int socket_block;
int socket_state; int socket_state;
int socket_block_directions;
/* Error tracking */ /* Error tracking */
char *err_msg; char *err_msg;
@@ -811,7 +870,14 @@ struct _LIBSSH2_SESSION
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long scpRecv_response_len; unsigned long scpRecv_response_len;
long scpRecv_mode; long scpRecv_mode;
#if defined(HAVE_LONGLONG) && defined(strtoll)
/* we have the type and we can parse such numbers */
long long scpRecv_size;
#define scpsize_strtol strtoll
#else
long scpRecv_size; long scpRecv_size;
#define scpsize_strtol strtol
#endif
long scpRecv_mtime; long scpRecv_mtime;
long scpRecv_atime; long scpRecv_atime;
char *scpRecv_err_msg; char *scpRecv_err_msg;
@@ -833,6 +899,7 @@ struct _LIBSSH2_SESSION
#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001 #define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
#define LIBSSH2_STATE_NEWKEYS 0x00000002 #define LIBSSH2_STATE_NEWKEYS 0x00000002
#define LIBSSH2_STATE_AUTHENTICATED 0x00000004 #define LIBSSH2_STATE_AUTHENTICATED 0x00000004
#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
/* session.flag helpers */ /* session.flag helpers */
#ifdef MSG_NOSIGNAL #ifdef MSG_NOSIGNAL
@@ -1136,7 +1203,7 @@ const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void);
int _libssh2_pem_parse(LIBSSH2_SESSION * session, int _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin, const char *headerbegin,
const char *headerend, const char *headerend,
FILE * fp, char **data, unsigned int *datalen); FILE * fp, unsigned char **data, unsigned int *datalen);
int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen); int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
unsigned char **i, unsigned int *ilen); unsigned char **i, unsigned int *ilen);

View File

@@ -294,7 +294,7 @@ static const LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = {
&libssh2_mac_method_hmac_sha1_96, &libssh2_mac_method_hmac_sha1_96,
&libssh2_mac_method_hmac_md5, &libssh2_mac_method_hmac_md5,
&libssh2_mac_method_hmac_md5_96, &libssh2_mac_method_hmac_md5_96,
#ifdef LIBSSH2_HMAC_RIPEMD #if LIBSSH2_HMAC_RIPEMD
&libssh2_mac_method_hmac_ripemd160, &libssh2_mac_method_hmac_ripemd160,
&libssh2_mac_method_hmac_ripemd160_openssh_com, &libssh2_mac_method_hmac_ripemd160_openssh_com,
#endif /* LIBSSH2_HMAC_RIPEMD */ #endif /* LIBSSH2_HMAC_RIPEMD */

View File

@@ -51,8 +51,7 @@ libssh2_ntohu32(const unsigned char *buf)
/* }}} */ /* }}} */
/* {{{ libssh2_ntohu64 /* {{{ libssh2_ntohu64
* Note: Some 32-bit platforms have issues with bitops on long longs *
* Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses
*/ */
libssh2_uint64_t libssh2_uint64_t
libssh2_ntohu64(const unsigned char *buf) libssh2_ntohu64(const unsigned char *buf)
@@ -62,7 +61,7 @@ libssh2_ntohu64(const unsigned char *buf)
msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
return ((msl * 65536) * 65536) + lsl; return ((libssh2_uint64_t)msl <<32) | lsl;
} }
/* }}} */ /* }}} */
@@ -85,7 +84,7 @@ libssh2_htonu32(unsigned char *buf, unsigned long value)
void void
libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value) libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
{ {
unsigned long msl = (value / 65536) / 65536; unsigned long msl = ((libssh2_uint64_t)value >> 32);
buf[0] = (msl >> 24) & 0xFF; buf[0] = (msl >> 24) & 0xFF;
buf[1] = (msl >> 16) & 0xFF; buf[1] = (msl >> 16) & 0xFF;

View File

@@ -665,6 +665,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
datalen - 13, datalen - 13,
0); 0);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
session->packAdd_state = libssh2_NB_state_idle; session->packAdd_state = libssh2_NB_state_idle;
@@ -817,6 +819,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
&session-> &session->
packAdd_Qlstn_state); packAdd_Qlstn_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -833,6 +837,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
rc = libssh2_packet_x11_open(session, data, datalen, rc = libssh2_packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state); &session->packAdd_x11open_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -914,11 +920,31 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
session->packAdd_state = libssh2_NB_state_sent2; session->packAdd_state = libssh2_NB_state_sent2;
} }
/*
* The KEXINIT message has been added to the queue.
* The packAdd and readPack states need to be reset
* because libssh2_kex_exchange (eventually) calls upon
* libssh2_packet_read to read the rest of the key exchange
* conversation.
*/
session->readPack_state = libssh2_NB_state_idle;
session->packet.total_num = 0;
session->packAdd_state = libssh2_NB_state_idle;
session->fullpacket_state = libssh2_NB_state_idle;
/*
* Also, don't use packAdd_key_state for key re-exchange,
* as it will be wiped out in the middle of the exchange.
* How about re-using the startup_key_state?
*/
memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
/* /*
* If there was a key reexchange failure, let's just hope we didn't * If there was a key reexchange failure, let's just hope we didn't
* send NEWKEYS yet, otherwise remote will drop us like a rock * send NEWKEYS yet, otherwise remote will drop us like a rock
*/ */
rc = libssh2_kex_exchange(session, 1, &session->packAdd_key_state); rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2007 The Written Word, Inc.
* Author: Simon Josefsson * Copyright (C) 2008, Simon Josefsson
* All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
* with or without modification, are permitted provided * with or without modification, are permitted provided
@@ -58,7 +59,7 @@ int
_libssh2_pem_parse(LIBSSH2_SESSION * session, _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin, const char *headerbegin,
const char *headerend, const char *headerend,
FILE * fp, char **data, unsigned int *datalen) FILE * fp, unsigned char **data, unsigned int *datalen)
{ {
char line[LINE_SIZE]; char line[LINE_SIZE];
char *b64data = NULL; char *b64data = NULL;
@@ -96,7 +97,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
} }
} while (strcmp(line, headerend) != 0); } while (strcmp(line, headerend) != 0);
if (libssh2_base64_decode(session, data, datalen, b64data, b64datalen)) { if (libssh2_base64_decode(session, (char**) data, datalen,
b64data, b64datalen)) {
ret = -1; ret = -1;
goto out; goto out;
} }

View File

@@ -109,7 +109,7 @@ static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = {
* Format an error message from a status code * Format an error message from a status code
*/ */
#define LIBSSH2_PUBLICKEY_STATUS_TEXT_START "Publickey Subsystem Error: \"" #define LIBSSH2_PUBLICKEY_STATUS_TEXT_START "Publickey Subsystem Error: \""
#define LIBSSH2_PUBLICKEY_STATUS_TEXT_MID "\" Server Resports: \"" #define LIBSSH2_PUBLICKEY_STATUS_TEXT_MID "\" Server Reports: \""
#define LIBSSH2_PUBLICKEY_STATUS_TEXT_END "\"" #define LIBSSH2_PUBLICKEY_STATUS_TEXT_END "\""
static void static void
libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY * pkey, libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY * pkey,
@@ -404,7 +404,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
"publickey", strlen("publickey")); "publickey", strlen("publickey"));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0); "Would block starting publickey subsystem", 0);
return NULL; return NULL;
} else if (rc) { } else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
@@ -420,7 +420,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0); "Would block starting publickey subsystem", 0);
return NULL; return NULL;
} }
@@ -457,7 +457,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
(char *) buffer, (s - buffer)); (char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickkey version packet", 0); "Would block sending publickey version packet", 0);
return NULL; return NULL;
} else if ((s - buffer) != rc) { } else if ((s - buffer) != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -487,7 +487,7 @@ libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
*(s++) = '\0'; *(s++) = '\0';
/* Make sure we don't get fooled by leftover values */ /* Make sure we don't get fooled by leftover values */
errno = 0; errno = 0;
session->scpRecv_size = strtol(p, &e, 10); session->scpRecv_size = scpsize_strtol(p, &e, 10);
if ((e && *e) || errno) { if ((e && *e) || errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid size", "Invalid response from SCP server, invalid size",

View File

@@ -133,6 +133,8 @@ libssh2_banner_receive(LIBSSH2_SESSION * session)
} }
#endif /* WIN32 */ #endif /* WIN32 */
if (errno == EAGAIN) { if (errno == EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
session->banner_TxRx_total_send = banner_len; session->banner_TxRx_total_send = banner_len;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -235,6 +237,8 @@ libssh2_banner_send(LIBSSH2_SESSION * session)
if (ret != (banner_len - session->banner_TxRx_total_send)) { if (ret != (banner_len - session->banner_TxRx_total_send)) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) { if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* the whole packet could not be sent, save the what was */ /* the whole packet could not be sent, save the what was */
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
session->banner_TxRx_total_send += ret; session->banner_TxRx_total_send += ret;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -1189,14 +1193,18 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = session->packets.head;
while (packet) { while (packet)
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) && {
(channel->local.id == libssh2_ntohu32(packet->data + 1))) || if ( channel->local.id == libssh2_ntohu32(packet->data + 1)) {
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) if ( extended == 1 &&
&& (extended != 0) (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
&& (channel->local.id == libssh2_ntohu32(packet->data + 1)))) { || packet->data[0] == SSH_MSG_CHANNEL_DATA )) {
/* Found data waiting to be read */
return 1; return 1;
} else if ( extended == 0 &&
packet->data[0] == SSH_MSG_CHANNEL_DATA) {
return 1;
}
/* else - no data of any type is ready to be read */
} }
packet = packet->next; packet = packet->next;
} }
@@ -1478,7 +1486,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
struct timeval tv_begin, tv_end; struct timeval tv_begin, tv_end;
gettimeofday((struct timeval *) &tv_begin, NULL); gettimeofday((struct timeval *) &tv_begin, NULL);
sysret = select(maxfd, &rfds, &wfds, NULL, &tv); sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
gettimeofday((struct timeval *) &tv_end, NULL); gettimeofday((struct timeval *) &tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000; timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
@@ -1488,7 +1496,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
/* If the platform doesn't support gettimeofday, /* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away * then just make the call non-blocking and walk away
*/ */
sysret = select(maxfd, &rfds, &wfds, NULL, &tv); sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
timeout_remaining = 0; timeout_remaining = 0;
#endif #endif
@@ -1532,4 +1540,15 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
return active_fds; return active_fds;
} }
/* {{{ libssh2_session_block_direction
* Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
* Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
* or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked
*/
LIBSSH2_API int
libssh2_session_block_directions(LIBSSH2_SESSION *session)
{
return session->socket_block_directions;
}
/* }}} */ /* }}} */

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -82,18 +82,18 @@
/* S_IFDIR */ /* S_IFDIR */
#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000 #define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
/* {{{ libssh2_sftp_packet_add /* {{{ sftp_packet_add
* Add a packet to the SFTP packet brigade * Add a packet to the SFTP packet brigade
*/ */
static int static int
libssh2_sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data, sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
unsigned long data_len) unsigned long data_len)
{ {
LIBSSH2_SESSION *session = sftp->channel->session; LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet; LIBSSH2_PACKET *packet;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d", _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
(int) data[0]); (int) data[0], data_len);
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packet) { if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
@@ -120,11 +120,11 @@ libssh2_sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_packet_read /* {{{ sftp_packet_read
* Frame an SFTP packet off the channel * Frame an SFTP packet off the channel
*/ */
static int static int
libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush) sftp_packet_read(LIBSSH2_SFTP * sftp)
{ {
LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
@@ -136,30 +136,27 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Waiting for packet"); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Waiting for packet");
if (flush && sftp->partial_packet) {
/* When flushing, remove previous partial */
LIBSSH2_FREE(session, sftp->partial_packet);
sftp->partial_packet = NULL;
}
/* If there was a previous partial, start using it */ /* If there was a previous partial, start using it */
if (sftp->partial_packet) { if (sftp->partial_packet) {
packet = sftp->partial_packet; packet = sftp->partial_packet;
packet_len = sftp->partial_len; packet_len = sftp->partial_len;
packet_received = sftp->partial_received; packet_received = sftp->partial_received;
sftp->partial_packet = NULL; sftp->partial_packet = NULL;
} else {
if (flush && session->socket_block && !libssh2_waitsocket(session, 0)) { _libssh2_debug(session, LIBSSH2_DBG_SFTP,
/* While flushing in blocking mode, check before reading */ "partial read cont, len: %lu", packet_len);
return -1;
} }
else {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4); rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
if (flush && (rc < 0)) { if (rc == PACKET_EAGAIN) {
/* When flushing, exit quickly */
return -1;
} else if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (4 != rc) { }
else if (4 != rc) {
/* TODO: this is stupid since we can in fact get 1-3 bytes in a
legitimate working case as well if the connection happens to be
super slow or something */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for FXP packet", 0); "Timeout waiting for FXP packet", 0);
return -1; return -1;
@@ -191,14 +188,7 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
(char *) packet + packet_received, (char *) packet + packet_received,
packet_len - packet_received); packet_len - packet_received);
if (flush && (bytes_received < 0)) { if (bytes_received == PACKET_EAGAIN) {
if (packet) {
/* When flushing, remove packet if existing */
LIBSSH2_FREE(session, packet);
}
/* When flushing, exit quickly */
return -1;
} else if (bytes_received == PACKET_EAGAIN) {
/* /*
* We received EAGAIN, save what we have and * We received EAGAIN, save what we have and
* return to EAGAIN to the caller * return to EAGAIN to the caller
@@ -209,7 +199,8 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
packet = NULL; packet = NULL;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (bytes_received < 0) { }
else if (bytes_received < 0) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Receive error waiting for SFTP packet", 0); "Receive error waiting for SFTP packet", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
@@ -218,7 +209,7 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
packet_received += bytes_received; packet_received += bytes_received;
} }
if (libssh2_sftp_packet_add(sftp, packet, packet_len)) { if (sftp_packet_add(sftp, packet, packet_len)) {
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
return -1; return -1;
} }
@@ -228,11 +219,11 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_packet_ask /* {{{ sftp_packet_ask
* A la libssh2_packet_ask() * A la libssh2_packet_ask()
*/ */
static int static int
libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type, sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data, unsigned long request_id, unsigned char **data,
unsigned long *data_len, int poll_channel) unsigned long *data_len, int poll_channel)
{ {
@@ -244,7 +235,7 @@ libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet", _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet",
(int) packet_type); (int) packet_type);
if (poll_channel) { if (poll_channel) {
int ret = libssh2_sftp_packet_read(sftp, 0); int ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (ret < 0) { } else if (ret < 0) {
@@ -288,11 +279,11 @@ libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_packet_require /* {{{ sftp_packet_require
* A la libssh2_packet_require * A la libssh2_packet_require
*/ */
static int static int
libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type, sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data, unsigned long request_id, unsigned char **data,
unsigned long *data_len) unsigned long *data_len)
{ {
@@ -302,14 +293,14 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet", _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet",
(int) packet_type); (int) packet_type);
if (libssh2_sftp_packet_ask if (sftp_packet_ask(sftp, packet_type, request_id, data,
(sftp, packet_type, request_id, data, data_len, 0) == 0) { data_len, 0) == 0) {
/* The right packet was available in the packet brigade */ /* The right packet was available in the packet brigade */
return 0; return 0;
} }
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
ret = libssh2_sftp_packet_read(sftp, 0); ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) { if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (ret <= 0) { } else if (ret <= 0) {
@@ -318,7 +309,7 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
if (packet_type == ret) { if (packet_type == ret) {
/* Be lazy, let packet_ask pull it out of the brigade */ /* Be lazy, let packet_ask pull it out of the brigade */
return libssh2_sftp_packet_ask(sftp, packet_type, request_id, data, return sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0); data_len, 0);
} }
} }
@@ -329,11 +320,11 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_packet_requirev /* {{{ sftp_packet_requirev
* Requie one of N possible reponses * Require one of N possible reponses
*/ */
static int static int
libssh2_sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses, sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
const unsigned char *valid_responses, const unsigned char *valid_responses,
unsigned long request_id, unsigned char **data, unsigned long request_id, unsigned char **data,
unsigned long *data_len) unsigned long *data_len)
@@ -341,24 +332,15 @@ libssh2_sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
int i; int i;
int ret; int ret;
/* /* If no timeout is active, start a new one */
* If no timeout is active, start a new one and flush
* any pending packets
*/
if (sftp->requirev_start == 0) { if (sftp->requirev_start == 0) {
_libssh2_debug(sftp->channel->session, LIBSSH2_DBG_SFTP,
"_requirev(): Initialize timeout");
sftp->requirev_start = time(NULL); sftp->requirev_start = time(NULL);
/* Flush */
while (libssh2_sftp_packet_read(sftp, 1) > 0);
} }
while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
for(i = 0; i < num_valid_responses; i++) { for(i = 0; i < num_valid_responses; i++) {
if (libssh2_sftp_packet_ask if (sftp_packet_ask(sftp, valid_responses[i], request_id,
(sftp, valid_responses[i], request_id, data, data_len, data, data_len, 0) == 0) {
0) == 0) {
/* /*
* Set to zero before all returns to say * Set to zero before all returns to say
* the timeout is not active * the timeout is not active
@@ -368,7 +350,7 @@ libssh2_sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
} }
} }
ret = libssh2_sftp_packet_read(sftp, 0); ret = sftp_packet_read(sftp);
if ((ret < 0) && (ret != PACKET_EAGAIN)) { if ((ret < 0) && (ret != PACKET_EAGAIN)) {
sftp->requirev_start = 0; sftp->requirev_start = 0;
return -1; return -1;
@@ -534,7 +516,7 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
libssh2_sftp_close_handle(sftp->handles); libssh2_sftp_close_handle(sftp->handles);
} }
/* Free the partial packet storage for libssh2_sftp_packet_read */ /* Free the partial packet storage for sftp_packet_read */
if (sftp->partial_packet) { if (sftp->partial_packet) {
LIBSSH2_FREE(session, sftp->partial_packet); LIBSSH2_FREE(session, sftp->partial_packet);
} }
@@ -659,7 +641,7 @@ libssh2_sftp_init(LIBSSH2_SESSION * session)
} }
/* For initiallization we are requiring blocking, probably reasonable */ /* For initiallization we are requiring blocking, probably reasonable */
rc = libssh2_sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION, rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
0, &data, &data_len); 0, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -744,10 +726,6 @@ libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
LIBSSH2_FREE(sftp->channel->session, sftp->open_packet); LIBSSH2_FREE(sftp->channel->session, sftp->open_packet);
sftp->open_packet = NULL; sftp->open_packet = NULL;
} }
if (sftp->read_packet) {
LIBSSH2_FREE(sftp->channel->session, sftp->read_packet);
sftp->read_packet = NULL;
}
if (sftp->readdir_packet) { if (sftp->readdir_packet) {
LIBSSH2_FREE(sftp->channel->session, sftp->readdir_packet); LIBSSH2_FREE(sftp->channel->session, sftp->readdir_packet);
sftp->readdir_packet = NULL; sftp->readdir_packet = NULL;
@@ -814,7 +792,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
int rc; int rc;
if (sftp->open_state == libssh2_NB_state_idle) { if (sftp->open_state == libssh2_NB_state_idle) {
/* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + flags(4) */ /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
flags(4) */
sftp->open_packet_len = filename_len + 13 + sftp->open_packet_len = filename_len + 13 +
((open_type == ((open_type ==
LIBSSH2_SFTP_OPENFILE) ? (4 + LIBSSH2_SFTP_OPENFILE) ? (4 +
@@ -823,7 +802,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len); s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
if (!sftp->open_packet) { if (!sftp->open_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_OPEN or FXP_OPENDIR packet", "Unable to allocate memory for FXP_OPEN or "
"FXP_OPENDIR packet",
0); 0);
return NULL; return NULL;
} }
@@ -866,7 +846,11 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
"Would block sending FXP_OPEN or FXP_OPENDIR command", "Would block sending FXP_OPEN or FXP_OPENDIR command",
0); 0);
return NULL; return NULL;
} else if (sftp->open_packet_len != rc) { }
else if (sftp->open_packet_len != rc) {
/* TODO: partial writes should be fine too and is not a sign of
an error when in non-blocking mode! */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_OPEN or FXP_OPENDIR command", 0); "Unable to send FXP_OPEN or FXP_OPENDIR command", 0);
LIBSSH2_FREE(session, sftp->open_packet); LIBSSH2_FREE(session, sftp->open_packet);
@@ -881,14 +865,15 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
} }
if (sftp->open_state == libssh2_NB_state_sent) { if (sftp->open_state == libssh2_NB_state_sent) {
rc = libssh2_sftp_packet_requirev(sftp, 2, fopen_responses, rc = sftp_packet_requirev(sftp, 2, fopen_responses,
sftp->open_request_id, &data, sftp->open_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for status message", 0); "Would block waiting for status message", 0);
return NULL; return NULL;
} else if (rc) { }
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->open_state = libssh2_NB_state_idle; sftp->open_state = libssh2_NB_state_idle;
@@ -898,13 +883,39 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
sftp->open_state = libssh2_NB_state_idle; sftp->open_state = libssh2_NB_state_idle;
/* OPEN can basically get STATUS or HANDLE back, where HANDLE implies a
fine response while STATUS means error. It seems though that at times
we get an SSH_FX_OK back in a STATUS, followed the "real" HANDLE so
we need to properly deal with that. */
if (data[0] == SSH_FXP_STATUS) { if (data[0] == SSH_FXP_STATUS) {
int badness = 1;
sftp->last_errno = libssh2_ntohu32(data + 5);
if(LIBSSH2_FX_OK == sftp->last_errno) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got HANDLE FXOK!");
/* silly situation, but check for a HANDLE */
rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
sftp->open_request_id, &data, &data_len);
if(rc == PACKET_EAGAIN) {
/* go back to sent state and wait for something else */
sftp->open_state = libssh2_NB_state_sent;
return NULL;
}
else if(!rc)
/* we got the handle so this is not a bad situation */
badness = 0;
}
if(badness) {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file", 0); "Failed opening remote file", 0);
sftp->last_errno = libssh2_ntohu32(data + 5); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
sftp->last_errno);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return NULL; return NULL;
} }
}
fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE)); fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
if (!fp) { if (!fp) {
@@ -920,18 +931,11 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
LIBSSH2_SFTP_HANDLE_DIR; LIBSSH2_SFTP_HANDLE_DIR;
fp->handle_len = libssh2_ntohu32(data + 5); fp->handle_len = libssh2_ntohu32(data + 5);
if (fp->handle_len > 256) { if (fp->handle_len > SFTP_HANDLE_MAXLEN) {
/* SFTP doesn't allow handles longer than 256 characters */ /* SFTP doesn't allow handles longer than 256 characters */
fp->handle_len = 256; fp->handle_len = SFTP_HANDLE_MAXLEN;
}
fp->handle = LIBSSH2_ALLOC(session, fp->handle_len);
if (!fp->handle) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate space for SFTP file/dir handle", 0);
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, fp);
return NULL;
} }
memcpy(fp->handle, data + 9, fp->handle_len); memcpy(fp->handle, data + 9, fp->handle_len);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@@ -960,8 +964,9 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
LIBSSH2_SFTP *sftp = handle->sftp; LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, request_id; unsigned long data_len, request_id = 0;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + length(4) */ /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
offset(8) + length(4) */
ssize_t packet_len = handle->handle_len + 25; ssize_t packet_len = handle->handle_len + 25;
unsigned char *packet, *s, *data; unsigned char *packet, *s, *data;
static const unsigned char read_responses[2] = static const unsigned char read_responses[2] =
@@ -975,12 +980,7 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, _libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Reading %lu bytes from SFTP handle", "Reading %lu bytes from SFTP handle",
(unsigned long) buffer_maxlen); (unsigned long) buffer_maxlen);
packet = LIBSSH2_ALLOC(session, packet_len); packet = handle->request_packet;
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_CLOSE packet", 0);
return -1;
}
sftp->read_state = libssh2_NB_state_allocated; sftp->read_state = libssh2_NB_state_allocated;
} else { } else {
packet = sftp->read_packet; packet = sftp->read_packet;
@@ -996,9 +996,23 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
* So we request data by pieces. * So we request data by pieces.
*/ */
bytes_requested = buffer_maxlen - total_read; bytes_requested = buffer_maxlen - total_read;
/* 10 = packet_type(1)+request_id(4)+data_length(4)+end_of_line_flag(1) */ /* 10 = packet_type(1) + request_id(4) + data_length(4) +
if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 10) { end_of_line_flag(1)
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 10;
10 is changed to 13 below simple because it seems there's a
"GlobalScape" SFTP server that responds with a slightly too big
buffer at times and we can apparently compensate for that by doing
this trick.
Further details on this issue:
https://sourceforge.net/mailarchive/forum.php?thread_name=9c3275a90811261517v6c0b1da2u918cc1b8370abf83%40mail.gmail.com&forum_name=libssh2-devel
http://forums.globalscape.com/tm.aspx?m=15249
*/
if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 13) {
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 13;
} }
#ifdef LIBSSH2_DEBUG_SFTP #ifdef LIBSSH2_DEBUG_SFTP
_libssh2_debug(session, LIBSSH2_DBG_SFTP, _libssh2_debug(session, LIBSSH2_DBG_SFTP,
@@ -1022,7 +1036,7 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
libssh2_htonu64(s, handle->u.file.offset); libssh2_htonu64(s, handle->u.file.offset);
s += 8; s += 8;
libssh2_htonu32(s, buffer_maxlen); libssh2_htonu32(s, bytes_requested);
s += 4; s += 4;
sftp->read_state = libssh2_NB_state_created; sftp->read_state = libssh2_NB_state_created;
@@ -1038,9 +1052,10 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp->read_total_read = total_read; sftp->read_total_read = total_read;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (packet_len != retcode) { } else if (packet_len != retcode) {
/* TODO: a partial write is not a critical error when in
non-blocking mode! */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_READ command", 0); "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1053,14 +1068,13 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
if (sftp->read_state == libssh2_NB_state_sent) { if (sftp->read_state == libssh2_NB_state_sent) {
retcode = retcode =
libssh2_sftp_packet_requirev(sftp, 2, read_responses, sftp_packet_requirev(sftp, 2, read_responses,
request_id, &data, &data_len); request_id, &data, &data_len);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (retcode) { } else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1072,7 +1086,6 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
switch (data[0]) { switch (data[0]) {
case SSH_FXP_STATUS: case SSH_FXP_STATUS:
retcode = libssh2_ntohu32(data + 5); retcode = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
@@ -1089,7 +1102,6 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
case SSH_FXP_DATA: case SSH_FXP_DATA:
bytes_read = libssh2_ntohu32(data + 5); bytes_read = libssh2_ntohu32(data + 5);
if (bytes_read > (data_len - 9)) { if (bytes_read > (data_len - 9)) {
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
@@ -1110,7 +1122,6 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
} }
} }
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle; sftp->read_state = libssh2_NB_state_idle;
return total_read; return total_read;
@@ -1244,7 +1255,7 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
} }
retcode = retcode =
libssh2_sftp_packet_requirev(sftp, 2, read_responses, sftp_packet_requirev(sftp, 2, read_responses,
sftp->readdir_request_id, &data, sftp->readdir_request_id, &data,
&data_len); &data_len);
if (retcode == PACKET_EAGAIN) { if (retcode == PACKET_EAGAIN) {
@@ -1331,7 +1342,8 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, retcode; unsigned long data_len, retcode;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + count(4) */ /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
offset(8) + count(4) */
ssize_t packet_len = handle->handle_len + count + 25; ssize_t packet_len = handle->handle_len + count + 25;
unsigned char *s, *data; unsigned char *s, *data;
int rc; int rc;
@@ -1385,7 +1397,7 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
sftp->write_state = libssh2_NB_state_sent; sftp->write_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len); sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
@@ -1468,8 +1480,8 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (packet_len != rc) { } else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
setstat ? (char *) "Unable to send FXP_FSETSTAT" (setstat ? "Unable to send FXP_FSETSTAT"
: (char *) "Unable to send FXP_FSTAT command", 0); : "Unable to send FXP_FSTAT command"), 0);
LIBSSH2_FREE(session, sftp->fstat_packet); LIBSSH2_FREE(session, sftp->fstat_packet);
sftp->fstat_packet = NULL; sftp->fstat_packet = NULL;
sftp->fstat_state = libssh2_NB_state_idle; sftp->fstat_state = libssh2_NB_state_idle;
@@ -1481,7 +1493,7 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
sftp->fstat_state = libssh2_NB_state_sent; sftp->fstat_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_requirev(sftp, 2, fstat_responses, rc = sftp_packet_requirev(sftp, 2, fstat_responses,
sftp->fstat_request_id, &data, sftp->fstat_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -1528,6 +1540,17 @@ libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle, size_t offset)
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_seek64
* Set the read/write pointer to an arbitrary position within the file
*/
LIBSSH2_API void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle, libssh2_uint64_t offset)
{
handle->u.file.offset = offset;
}
/* }}} */
/* {{{ libssh2_sftp_tell /* {{{ libssh2_sftp_tell
* Return the current read/write pointer's offset * Return the current read/write pointer's offset
*/ */
@@ -1537,6 +1560,15 @@ libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
return handle->u.file.offset; return handle->u.file.offset;
} }
/* {{{ libssh2_sftp_tell64
* Return the current read/write pointer's offset
*/
LIBSSH2_API libssh2_uint64_t
libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle)
{
return handle->u.file.offset;
}
/* }}} */ /* }}} */
@@ -1600,7 +1632,7 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
} }
if (handle->close_state == libssh2_NB_state_sent) { if (handle->close_state == libssh2_NB_state_sent) {
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data, handle->close_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -1640,7 +1672,6 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
handle->close_state = libssh2_NB_state_idle; handle->close_state = libssh2_NB_state_idle;
LIBSSH2_FREE(session, handle->handle);
LIBSSH2_FREE(session, handle); LIBSSH2_FREE(session, handle);
return 0; return 0;
@@ -1711,12 +1742,13 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
sftp->unlink_state = libssh2_NB_state_sent; sftp->unlink_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data, sftp->unlink_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (rc) { }
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->unlink_state = libssh2_NB_state_idle; sftp->unlink_state = libssh2_NB_state_idle;
@@ -1820,7 +1852,7 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
sftp->rename_state = libssh2_NB_state_sent; sftp->rename_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data, sftp->rename_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
@@ -1936,7 +1968,7 @@ libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->mkdir_packet = NULL; sftp->mkdir_packet = NULL;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data, rc = sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
@@ -2023,7 +2055,7 @@ libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->rmdir_state = libssh2_NB_state_sent; sftp->rmdir_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len); sftp->rmdir_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
@@ -2133,7 +2165,7 @@ libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->stat_state = libssh2_NB_state_sent; sftp->stat_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_requirev(sftp, 2, stat_responses, rc = sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len); sftp->stat_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
@@ -2200,8 +2232,8 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len); s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->symlink_packet) { if (!sftp->symlink_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for SYMLINK/READLINK/REALPATH packet", "Unable to allocate memory for SYMLINK/READLINK"
0); "/REALPATH packet", 0);
return -1; return -1;
} }
@@ -2263,12 +2295,13 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->symlink_state = libssh2_NB_state_sent; sftp->symlink_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_requirev(sftp, 2, link_responses, rc = sftp_packet_requirev(sftp, 2, link_responses,
sftp->symlink_request_id, &data, sftp->symlink_request_id, &data,
&data_len); &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} else if (rc) { }
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0); "Timeout waiting for status message", 0);
sftp->symlink_state = libssh2_NB_state_idle; sftp->symlink_state = libssh2_NB_state_idle;

374
src/sshentry.c Normal file
View File

@@ -0,0 +1,374 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "libssh2_priv.h"
static int
ssh_host_parse_hostnames (LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
char *end
);
static int
ssh_host_parse_key (LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
int is_base64_encoded
);
/* Returns zero if successful, > zero for malformed data, < 0 not supported. */
LIBSSH2_API int
libssh2_new_host_entry(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS ** s,
char *line)
{
char *tmp = NULL;
LIBSSH2_KNOWNHOSTS *t = NULL;
int i;
if (line == NULL || *line == 0)
return 1;
if (s == NULL)
return 2;
tmp = strchr (line, ' ');
if (tmp == NULL)
return 3;
t = (LIBSSH2_KNOWNHOSTS *)
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_KNOWNHOSTS));
t->hostname_line = NULL;
t->hostnames = NULL;
t->hostnames_size = t->bits = t->exponent = -1;
t->modulus = NULL;
t->modulus_length = -1;
t->ssh_version = -1;
t->md5 = NULL;
i = ssh_host_parse_hostnames (session, t, line, tmp);
if (i != 0) {
libssh2_free_host_entry (session, t);
return ((i > 0) ? 4 : -1);
}
line = tmp + 1;
tmp = strchr (line, ' ');
if (tmp != NULL)
tmp = strchr (tmp + 1, ' ');
i = ssh_host_parse_key (session, t, line, tmp == NULL ? 1 : 0);
if (i != 0) {
libssh2_free_host_entry (session, t);
return ((i > 0) ? 5 : -2);
}
*s = t;
return 0;
}
static int
ssh_host_parse_hostnames(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
char *end)
{
char *start;
char *comma = NULL;
int i;
/* TODO: we don't handle the hashed name format because the hashing
* mechanism isnt defined (at least based on the man page)
*/
if (*line == '|')
return -1;
if (line == end || *line == ' ')
return 1;
s->hostname_line = (char *) LIBSSH2_ALLOC (session, (end - line) + 1);
strncpy (s->hostname_line, line, (end - line) + 1);
start = end = s->hostname_line + (end - line);
*end = 0;
s->hostnames_size = 1;
comma = s->hostname_line;
while ((comma = strchr (comma, ',')) != NULL) {
comma++;
if (*comma == ',' || *comma == 0) {
LIBSSH2_FREE (session, s->hostname_line);
s->hostname_line = NULL;
return 2;
}
s->hostnames_size++;
}
s->hostnames = (char **) LIBSSH2_ALLOC
(session, sizeof (char *) * s->hostnames_size);
start = comma = s->hostname_line;
i = 0;
while ((comma = strchr (comma, ',')) != NULL) {
*comma = 0;
s->hostnames[i] = start;
comma++;
start = comma;
i++;
}
s->hostnames[i] = start;
return 0;
}
/** Returns the number of bytes read or -1. */
static int
ssh_proto_str_read(LIBSSH2_SESSION * session,
char *line,
char **val,
char *end
)
{
unsigned int len;
if (line + 4 > end)
return -1;
len = (line[0] << 24) + (line[1] << 16) + (line[2] << 8) + line[3];
if (line + 4 + len > end)
return -1;
*val = LIBSSH2_ALLOC (session, len);
memcpy (*val, line + 4, len);
return len + 4;
}
static int
ssh_host_parse_key(LIBSSH2_SESSION * session,
LIBSSH2_KNOWNHOSTS * s,
char *line,
int is_base64_encoded)
{
int i, j;
char *tmp, *tmp2;
/* workaround for the MD5 stuff */
libssh2_md5_ctx ctx;
/* the bits, exponent, modulus format */
if (is_base64_encoded == 0) {
s->ssh_version = 1;
s->key_type = 0;
if (!isdigit (*line))
return -1;
if (sscanf (line, "%hu %hu ", &(s->bits), &(s->exponent)) != 2)
return -2;
/* TODO:
* There's probably an acceptable range...
*/
if (s->bits <= 0 || s->exponent <= 0)
return 1;
line = strchr (line, ' ');
if (line == NULL)
return -3;
line++;
line = strchr (line, ' ');
if (line == NULL)
return -4;
line++;
/* TODO:
* figure out what format modulus is in since its not clear
* from the man page
*/
return -5;
}
else {
s->ssh_version = 2;
/* we only handle the rsa type */
if (strstr (line, "ssh-rsa") != line)
return -6;
s->key_type = 0;
line += 7;
if (*line != ' ')
return 2;
line++;
i = 0;
while (*line) {
if ((line[i] >= 0x30 && line[i] <= 0x39) ||
(line[i] >= 0x41 && line[i] <= 0x5a) ||
(line[i] >= 0x61 && line[i] <= 0x7a) ||
(line[i] == '+') || (line[i] == '/') || (line[i] == '='))
i++;
else
break;
}
if (i == 0)
return 3;
tmp = LIBSSH2_ALLOC (session, sizeof (char) * (i + 5));
strncpy (tmp, line, i);
/* this should hopefully avoid any issues with reading
* past the array if its malformed */
tmp[i] = tmp[i + 1] = tmp[i + 2] = tmp[i + 3] = tmp[i + 4] = 0;
{
/* TODO: rework the api interface instead of making a local
instance */
i = libssh2_base64_decode(session, &tmp2, (unsigned int *)&j,
tmp, strlen(tmp));
LIBSSH2_FREE(session, tmp);
if (i != 0)
return 4;
}
/* printf("Decode Size: %d\n", i); */
/* free (tmp); */
#if LIBSSH2_MD5
s->md5 = LIBSSH2_ALLOC (session, 16);
libssh2_md5_init (&ctx);
libssh2_md5_update (ctx, tmp2, j);
libssh2_md5_final (ctx, s->md5);
#endif
line = tmp2;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 5;
}
/* TODO: verify that its ssh-rsa -- its the only one
* supported
*/
if (!(i == 11 && tmp[0] == 's' && tmp[1] == 's' &&
tmp[2] == 'h' && tmp[3] == '-' && tmp[4] == 'r' &&
tmp[5] == 's' && tmp[6] == 'a')) {
free (tmp);
free (tmp2);
return 8;
}
LIBSSH2_FREE (session, tmp);
line += i;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 6;
}
/* TODO: verify that the exponent is valid */
if (i == 5)
s->exponent = (unsigned short) ((unsigned char) *tmp);
else {
LIBSSH2_FREE (session, tmp);
LIBSSH2_FREE (session, tmp2);
return 9;
}
LIBSSH2_FREE (session, tmp);
line += i;
i = ssh_proto_str_read (session, line, &tmp, tmp2 + j);
if (i < 0) {
LIBSSH2_FREE (session, tmp2);
return 7;
}
/* TODO: the modulus may need to be converted to
* big integer format
*/
s->modulus_length = i - 4;
s->modulus = tmp;
s->bits = (s->modulus_length - 1) * 8;
LIBSSH2_FREE (session, tmp2);
return 0;
}
}
LIBSSH2_API void
libssh2_free_host_entry(LIBSSH2_SESSION * session, LIBSSH2_KNOWNHOSTS * s)
{
/* int i; */
if (s == NULL)
return;
if (s->hostname_line != NULL) {
LIBSSH2_FREE (session, s->hostname_line);
s->hostname_line = NULL;
}
if (s->hostnames != NULL && s->hostnames_size > 0) {
LIBSSH2_FREE (session, s->hostnames);
s->hostnames = NULL;
}
s->hostnames_size = s->bits = s->exponent = -1;
if (s->modulus != NULL) {
LIBSSH2_FREE (session, s->modulus);
s->modulus = NULL;
}
s->modulus_length = -1;
s->ssh_version = -1;
if (s->md5 != NULL) {
LIBSSH2_FREE (session, s->md5);
s->md5 = NULL;
}
LIBSSH2_FREE (session, s);
}
#ifdef SSH_HOSTNAME_TESTS
int
ssh_unit_tests (int argc, char **argv)
{
char *l[] = {
"closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net",
"cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
" cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=",
"",
",",
"f, ",
"cvs.example.net ssh-rsa AAAA1234.....=",
"192.168.30.118 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwWVqxKm2Biwilakq9Ex8/tzHVQjRrzEkwlrWTDneptodVgqAzXUFQSa6Oj9AwzdDPhKe71vTv7RhXYg0ZvB1a5dIkzgCdoF/mIuTb80LvK7f0NxCaAHWODuHbwlJeMmjHV0WFsjsdOf690fPqeinD/8jfBQB950M1K3Qesib9H75gsnawF06MzZ52nC1HHi8mG2tGy2PMyP+mJs7KN1v4T+nobZ10ePe1dMqYXMdro/PB0JQmuGL7bBR5GRDEkK6nFcp2HsvuzXSeWZJcmWDdo+1n0cNg2th5VEIxrrFG5iy0CA2AXVPMqkf3VrAXGXV66dJTGtBqZ5GoxJCxDgW6w==",
"|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsaAAAA1234.....="
};
int s;
int cases = sizeof (l) / sizeof (char *);
if (argc == 2) {
s = atoi (argv[1]);
if (s >= 0 && s < cases) {
LIBSSH2_KNOWNHOSTS *x = NULL;
printf ("%d\n", s = new_ssh_host_entry (&x, l[s]));
libssh2_free_host_entry (x);
return s;
}
}
}
#endif
/** Returns 0 for a match, non-zero otherwise. */
LIBSSH2_API int
libssh2_host_entry_match(LIBSSH2_KNOWNHOSTS * x, char *host)
{
/* TODO: Add pattern matching and/or DNS matching against
* to entries found in x
*/
int i;
if (host == NULL || x == NULL)
return -1;
/* FIXME: this should use a case-insensitive compare as dns hostnames
* are generally case insensitive anyways
*/
for (i = 0; i < x->hostnames_size; i++)
if (!strcmp (x->hostnames[i], host))
return 0;
return 1;
}

View File

@@ -269,6 +269,40 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
int blocksize; int blocksize;
int encrypted = 1; int encrypted = 1;
int status;
/*
* All channels, systems, subsystems, etc eventually make it down here
* when looking for more incoming data. If a key exchange is going on
* (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end
* will ONLY send key exchange related traffic. In non-blocking mode,
* there is a chance to break out of the kex_exchange function with an
* EAGAIN status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS
* is active, then we must redirect to the key exchange. However,
* if kex_exchange is active (as in it is the one that calls this execution
* of packet_read, then don't redirect, as that would be an infinite loop!
*/
if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
/* Whoever wants a packet won't get anything until the key re-exchange
* is done!
*/
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
" key re-exchange");
status = libssh2_kex_exchange(session, 1, &session->startup_key_state);
if (status == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block exchanging encryption keys", 0);
return PACKET_EAGAIN;
} else if (status) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
"Unable to exchange encryption keys",0);
return LIBSSH2_ERROR_KEX_FAILURE;
}
}
/* /*
* =============================== NOTE =============================== * =============================== NOTE ===============================
* I know this is very ugly and not a really good use of "goto", but * I know this is very ugly and not a really good use of "goto", but
@@ -351,6 +385,8 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
} }
#endif /* WIN32 */ #endif /* WIN32 */
if ((nread < 0) && (errno == EAGAIN)) { if ((nread < 0) && (errno == EAGAIN)) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
return PACKET_FAIL; return PACKET_FAIL;
@@ -527,8 +563,21 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
libssh2_packet_read_point1: libssh2_packet_read_point1:
rc = fullpacket(session, encrypted); rc = fullpacket(session, encrypted);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
if (session->packAdd_state != libssh2_NB_state_idle)
{
/* fullpacket only returns PACKET_EAGAIN if
* libssh2_packet_add returns PACKET_EAGAIN. If that
* returns PACKET_EAGAIN but the packAdd_state is idle,
* then the packet has been added to the brigade, but some
* immediate action that was taken based on the packet
* type (such as key re-exchange) is not yet complete.
* Clear the way for a new packet to be read in.
*/
session->readPack_encrypted = encrypted; session->readPack_encrypted = encrypted;
session->readPack_state = libssh2_NB_state_jump1; session->readPack_state = libssh2_NB_state_jump1;
}
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -543,8 +592,6 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
/* }}} */ /* }}} */
#ifndef OLDSEND
static libssh2pack_t static libssh2pack_t
send_existing(LIBSSH2_SESSION * session, unsigned char *data, send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret) unsigned long data_len, ssize_t * ret)
@@ -587,6 +634,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
/* send failure! */ /* send failure! */
return PACKET_FAIL; return PACKET_FAIL;
} }
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
@@ -605,6 +653,10 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
* call this function again as soon as it is likely that more data can be * call this function again as soon as it is likely that more data can be
* sent, and this function should then be called with the same argument set * sent, and this function should then be called with the same argument set
* (same data pointer and same data_len) until zero or failure is returned. * (same data pointer and same data_len) until zero or failure is returned.
*
* NOTE: this function does not verify that 'data_len' is less than ~35000
* which is what all implementations should support at least as packet size.
* (RFC4253 section 6.1)
*/ */
int int
libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data, libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
@@ -641,9 +693,10 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
/* check if we should compress */ /* check if we should compress */
if (encrypted && strcmp(session->local.comp->name, "none")) { if (encrypted && strcmp(session->local.comp->name, "none")) {
if (session->local.comp-> if (session->local.comp->comp(session, 1, &data, &data_len,
comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP, LIBSSH2_PACKET_MAXCOMP,
&free_data, data, data_len, &session->local.comp_abstract)) { &free_data, data, data_len,
&session->local.comp_abstract)) {
return PACKET_COMPRESS; /* compression failure */ return PACKET_COMPRESS; /* compression failure */
} }
} }
@@ -722,8 +775,8 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
The MAC field is not encrypted. */ The MAC field is not encrypted. */
for(i = 0; i < packet_length; i += session->local.crypt->blocksize) { for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
unsigned char *ptr = &p->outbuf[i]; unsigned char *ptr = &p->outbuf[i];
if (session->local.crypt-> if (session->local.crypt->crypt(session, ptr,
crypt(session, ptr, &session->local.crypt_abstract)) &session->local.crypt_abstract))
return PACKET_FAIL; /* encryption failure */ return PACKET_FAIL; /* encryption failure */
} }
} }
@@ -739,6 +792,7 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
if (ret != total_length) { if (ret != total_length) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) { if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* the whole packet could not be sent, save the rest */ /* the whole packet could not be sent, save the rest */
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata; p->odata = orgdata;
p->olen = orgdata_len; p->olen = orgdata_len;
p->osent = (ret == -1) ? 0 : ret; p->osent = (ret == -1) ? 0 : ret;
@@ -758,4 +812,4 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
} }
/* }}} */ /* }}} */
#endif

View File

@@ -149,7 +149,9 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *username,
} }
methods_len = libssh2_ntohu32(session->userauth_list_data + 1); methods_len = libssh2_ntohu32(session->userauth_list_data + 1);
memcpy(session->userauth_list_data, session->userauth_list_data + 5,
/* Do note that the memory areas overlap! */
memmove(session->userauth_list_data, session->userauth_list_data + 5,
methods_len); methods_len);
session->userauth_list_data[methods_len] = '\0'; session->userauth_list_data[methods_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s", _libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s",
@@ -588,17 +590,19 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
const char *local_username, const char *local_username,
unsigned int local_username_len) unsigned int local_username_len)
{ {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *pubkeydata, *sig;
static const unsigned char reply_codes[3] = static const unsigned char reply_codes[3] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long pubkeydata_len, sig_len, data_len;
int rc; int rc;
if (session->userauth_host_state == libssh2_NB_state_idle) { if (session->userauth_host_state == libssh2_NB_state_idle) {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
unsigned char *pubkeydata, *sig;
unsigned long pubkeydata_len;
unsigned long sig_len;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
/* Zero the whole thing out */ /* Zero the whole thing out */
memset(&session->userauth_host_packet_requirev_state, 0, memset(&session->userauth_host_packet_requirev_state, 0,
sizeof(session->userauth_host_packet_requirev_state)); sizeof(session->userauth_host_packet_requirev_state));
@@ -775,6 +779,7 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
} }
if (session->userauth_host_state == libssh2_NB_state_sent) { if (session->userauth_host_state == libssh2_NB_state_sent) {
unsigned long data_len;
rc = libssh2_packet_requirev_ex(session, reply_codes, rc = libssh2_packet_requirev_ex(session, reply_codes,
&session->userauth_host_data, &session->userauth_host_data,
&data_len, 0, NULL, 0, &data_len, 0, NULL, 0,
@@ -822,19 +827,16 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
const char *privatekey, const char *privatekey,
const char *passphrase) const char *passphrase)
{ {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj; unsigned long pubkeydata_len = 0;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *pubkeydata, *sig;
unsigned char reply_codes[4] = unsigned char reply_codes[4] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
SSH_MSG_USERAUTH_PK_OK, 0 SSH_MSG_USERAUTH_PK_OK, 0
}; };
unsigned long pubkeydata_len, sig_len;
int rc; int rc;
if (session->userauth_pblc_state == libssh2_NB_state_idle) { if (session->userauth_pblc_state == libssh2_NB_state_idle) {
unsigned char *pubkeydata;
/* Zero the whole thing out */ /* Zero the whole thing out */
memset(&session->userauth_pblc_packet_requirev_state, 0, memset(&session->userauth_pblc_packet_requirev_state, 0,
sizeof(session->userauth_pblc_packet_requirev_state)); sizeof(session->userauth_pblc_packet_requirev_state));
@@ -933,6 +935,13 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
} }
if (session->userauth_pblc_state == libssh2_NB_state_sent) { if (session->userauth_pblc_state == libssh2_NB_state_sent) {
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *sig;
unsigned long sig_len;
rc = libssh2_packet_requirev_ex(session, reply_codes, rc = libssh2_packet_requirev_ex(session, reply_codes,
&session->userauth_pblc_data, &session->userauth_pblc_data,
&session->userauth_pblc_data_len, 0, &session->userauth_pblc_data_len, 0,
@@ -1023,6 +1032,10 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
privkeyobj->dtor(session, &abstract); privkeyobj->dtor(session, &abstract);
} }
/*
* If this function was restarted, pubkeydata_len might still be 0
* which will cause an unnecessary but harmless realloc here.
*/
if (sig_len > pubkeydata_len) { if (sig_len > pubkeydata_len) {
unsigned char *newpacket; unsigned char *newpacket;
/* Should *NEVER* happen, but...well.. better safe than sorry */ /* Should *NEVER* happen, but...well.. better safe than sorry */
@@ -1044,6 +1057,7 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
session->userauth_pblc_s = session->userauth_pblc_s =
session->userauth_pblc_packet + session->userauth_pblc_packet_len; session->userauth_pblc_packet + session->userauth_pblc_packet_len;
session->userauth_pblc_b = NULL;
libssh2_htonu32(session->userauth_pblc_s, libssh2_htonu32(session->userauth_pblc_s,
4 + session->userauth_pblc_method_len + 4 + sig_len); 4 + session->userauth_pblc_method_len + 4 + sig_len);

View File

@@ -1,5 +1,8 @@
.deps .deps
.libs .libs
*.gcno
*.gcda
Makefile Makefile
Makefile.in Makefile.in
simple simple
ssh2

View File

@@ -1,6 +1,19 @@
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
LDADD = ../src/libssh2.la LDADD = ../src/libssh2.la
if SSHD
noinst_PROGRAMS = ssh2
ssh2_SOURCES = ssh2.c
endif
ctests = simple ctests = simple
TESTS = $(ctests) TESTS = $(ctests)
if SSHD
TESTS += ssh2.sh
endif
check_PROGRAMS = $(ctests) check_PROGRAMS = $(ctests)
TESTS_ENVIRONMENT = SSHD=$(SSHD) EXEEXT=$(EXEEXT)
EXTRA_DIST = ssh2.sh
EXTRA_DIST += etc/host etc/host.pub etc/user etc/user.pub

27
tests/etc/host Normal file
View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAwJaOo3i1X3N401hMd92lRec0tPMBgaF6ZDanovBiQP+PNo6g
VNtuF15AspbyxrViqtAyjLWQQlKGWgEFb2ga3ukzJll4dKPtNff3mO++W19ia0WQ
ZFWTAGcYqet4fvSALIpG+t/3u5MZXMNZPyCU8u1l+QXX14f6dEjzgRw7s3fSy/uv
Qawkgn8TQFvtSBOfvUTJPTAhhZqxZAt3nGH8d6vqD1hBNvdOpsohy6EgFh8V+kxn
UdQntrYe9WSz0djt0RRrdAvRkM0hq1UY8C9FTQQWni1n168c7FVrf65+GdJOn7NQ
Du0Whmh/R3flXR0kIBG+F7e8+e9W9OhlionkPwIBIwKCAQEAqpP6rgvT2DMTPtkt
yUCoU9tpMo4XRu4b8lxLVc2Y2nvz391pb7sJvO0Uu2/BFmYkMORKB5l/xbbOxL8T
cU2UJIVn0YJyAOj2rCTFW5KEB8mDDo4SLPtWUNBXrHF5WoDJTAVyEWdJInr5NOeJ
j68k1yoJ3JAlkwNozWUvclrVytZNohPhiYdKkj2DPlWKL//0INGIo9TU31AGJx2R
ymy105EFCXWDv1GAIWwqBjNNxzlyxDauuGTwWr2iYDyectBYApCkjyJzMpFn4Yiu
Mq5XomwkQhefK3y32bRasm+HSrQsGswSvSyS8I5YosjSKMmiWdYj4WxrSciT6gG/
KHanEwKBgQDucA7E/s9aKs6rECypXPaCORxvbLqdqAiwzJ0edufE+g0aQU/Zm3xj
m6LGovdEcaBog4rfKCSB9NRKi35m4HV9PO4YBw6/lQ0NeO6jrb8OnZp/P97FbomT
AXBibzUjQ8fhbPCaJF/2TUEoyhNbzJkpl+M0zu2aQ3MUYVd4dZ4y4wKBgQDOxfeA
RH3ZPvdYI50jxW+/kKcio+APZZJ9xhtqOKzmEuJOPzlngWk5WQgS8B1aicHyFRhw
UT2vKeJvqqoeLbIE9Fm6qlpN22594S88+LOiMda4wRswxG9wBZ2J4+rrYKpcb1gt
JXvVKY7h5qLWGCR0x+ovOcNXABWsF8CAnOnb9QKBgA2gANgOj4F+yfslfuUbQUlF
F5FWq5P6+S6sm0ORxBniZyYSXFWT2zjkUnHAK2L/LbzUURQQ7CSu5487K8tdSIrQ
SB6hUUzGsEnppzyNleOT+jMoOJ2RSbCg/xuRU35bpQWRMlHzczKlVC43btILsPsP
/lrJ/vLfSGeQiKfMNOz3AoGAC9DMUHjxP50ytJRSH00cVBbk+qpHUVZC4p2bKqQn
IxcFnhI9y2Z7CpdfjA24iNSr/zRny+dinEuJSDWjUi5/M3utWx+tY4jhvgzeIL3B
HzYMRRJZUz5sxJKbSbVAn7xhgZ/2aPrT4EuEge/sDDvk03kjUyffRszOCdV4tuRl
IoMCgYEAnrexTd5GuxEEBg3qJgN4IMwoBzZlJ1voaI6I/AMuvQ5kVklYvHTPTZOI
kSIrvaG8xaOdf0f76XNdT7U/dkx0C0vcesy5++hqakmeRCHjfsE1wN7m+hGo5WcR
Jq8Ph9ZnH5RKjqDsHh7Y4BCewQNrMBqNQEzDebZCDBUTnK9OgOg=
-----END RSA PRIVATE KEY-----

1
tests/etc/host.pub Normal file
View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwJaOo3i1X3N401hMd92lRec0tPMBgaF6ZDanovBiQP+PNo6gVNtuF15AspbyxrViqtAyjLWQQlKGWgEFb2ga3ukzJll4dKPtNff3mO++W19ia0WQZFWTAGcYqet4fvSALIpG+t/3u5MZXMNZPyCU8u1l+QXX14f6dEjzgRw7s3fSy/uvQawkgn8TQFvtSBOfvUTJPTAhhZqxZAt3nGH8d6vqD1hBNvdOpsohy6EgFh8V+kxnUdQntrYe9WSz0djt0RRrdAvRkM0hq1UY8C9FTQQWni1n168c7FVrf65+GdJOn7NQDu0Whmh/R3flXR0kIBG+F7e8+e9W9OhlionkPw== jas@mocca

3
tests/etc/sshd_config Normal file
View File

@@ -0,0 +1,3 @@
Port 4711
Protocol 2
AuthorizedKeysFile /home/jas/src/libssh2/tests/etc/user.pub

27
tests/etc/user Normal file
View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAxIgBuZS39D4bFnWminE7svGQLdVKx1aWKnEYEa+XtNU4DKZ/
pxUHg0zbEBya+IkX1yqQYWALoiOwI8XhdemLp8g03BX7o+DLSWisfiHpCDVGAuNq
RDF7qnFyL/ZBH6e0XKMtsoB51TDuBc4Rxh6p1V2QL/fg8BoHcCrnKkoqN8PSoKUX
2lPKJ3JIF/P8cDLbKYCvbSTFOdf56eqg0GJe7jFtSwweE9yz3IWZ3kSS1E/9E6sX
aNCu/hUt1bvQthICQyBNoTtQP/igEUJ7n0GMetsnq9wiUSomLzWqIWNqmvOv62aC
XRi5sYgpSAR4Zvnm3Cx/Wl0BEPz2rrFkG+G0SQIBIwKCAQEAgSYtBOyzZfztOqUV
q277WFWZQrC8HJf8R8aparU3zpq+braOZnuImByP9KUVYX6pRECKw6WD/NWfonq4
uzMSoXTviVBGRx6xeWIK880kG1Y1UlruD447Ur+ULiV7QLAIzylnLCiKk2lL9S+l
R63AD95mEOS4Y0ROB+Gt2fY5ABHRMqhGLvRKK8qwn35C1Z9qnTGhgiRbeoc373A5
ZAYyegyLnbvyV47UfPYS/TVzxZ9RCx3D3I/9fI7ZAFafkkIufQX3QPaVxf0zFUwW
de/f+gTbySTL4RDF185Evunx+tYvzCyIimB0cTE5dfsCWcHDtO6DwehKiOgJsbeW
IrpeTwKBgQDnEMfv7ORR35Ouj91iNCSfLU/v0TSzAJBfqYovByhXRsopgWAKXUmH
mWpBBP5vcGu3NvKfiZcMMbBPfllvlxkafQwvCqrdn5mg01MdAHMWP/O9yfvuxMDE
KycU2G2CT8j85mIPn19WeIgXC/kws+P0RAVNCBNeq89Gvp4IdLN67wKBgQDZvTYh
TPCYG32jBK+CcWmOna2SLvBloDcNevhzfu3RGjLIXzUHGxLdx7slsP/tpndmXIAL
CgV6GfrLxix5bO08203S2qnnwP8VrjjNIv1CyZIbbQFAFIeC3QxZMZHnXieLrO0z
qF5CuUXcL3cMeGmF/0HN/rB+4sF0qfv8wD8kRwKBgFXTCG8O2HYueK6NNPiXBknA
X4T17wCocCOIHWHstzZcHzP82oeBvDmuAuTzOe7gnQmJcA9e/ZbQoJKOA/Y/b7lh
pXCO7wHcMb9kb1PqOWAJIASqG78V4TLrdOp8Re6Sqb0FHRu+2kSwbQ/f4DapN2lb
F+lpZke8KGq71ExImm99AoGAN/10UbSy5UjlytVRs9QFM00eAQTBeTfTpGFzFmJ3
qsw48bIU8zLY9zNcAmC21rXG7m+Oo8C/lG0UmsyPF+jPSinDjf22qU7iger4qccr
Lm5YxTlJduC1IaaOJZBnWMBwkaF+0sTlCdfew5ctPbiQKcVLb3wBf7amxjpWvVYB
m50CgYAT6t2/Suav21J5zpzyrrt+oMZQ3MMzBnPHFRUQ1FdqZnE4eW5a10g0P+E+
YeTol+fYxL34+cI5PREK3dcnW1E8g8KOsOQqMgWdTfZEDHYRLqEyGIhu20aqfJCY
qu9tBburQoSlym9aQp41CMxIyHrL4GnwRlJkTTEVhDuab1HmKw==
-----END RSA PRIVATE KEY-----

1
tests/etc/user.pub Normal file
View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxIgBuZS39D4bFnWminE7svGQLdVKx1aWKnEYEa+XtNU4DKZ/pxUHg0zbEBya+IkX1yqQYWALoiOwI8XhdemLp8g03BX7o+DLSWisfiHpCDVGAuNqRDF7qnFyL/ZBH6e0XKMtsoB51TDuBc4Rxh6p1V2QL/fg8BoHcCrnKkoqN8PSoKUX2lPKJ3JIF/P8cDLbKYCvbSTFOdf56eqg0GJe7jFtSwweE9yz3IWZ3kSS1E/9E6sXaNCu/hUt1bvQthICQyBNoTtQP/igEUJ7n0GMetsnq9wiUSomLzWqIWNqmvOv62aCXRi5sYgpSAR4Zvnm3Cx/Wl0BEPz2rrFkG+G0SQ== jas@mocca

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2007 The Written Word, Inc.
* Author: Simon Josefsson * Copyright (C) 2008 Simon Josefsson
* All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
* with or without modification, are permitted provided * with or without modification, are permitted provided
@@ -36,9 +37,36 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "libssh2.h" #include "libssh2.h"
int test_libssh2_base64_decode (LIBSSH2_SESSION *session)
{
char *data;
unsigned int datalen;
const char *src = "Zm5vcmQ=";
unsigned int src_len = strlen (src);
int ret;
ret = libssh2_base64_decode(session, &data, &datalen,
src, src_len);
if (ret)
return ret;
if (datalen != 5 || strcmp (data, "fnord") != 0)
{
fprintf (stderr,
"libssh2_base64_decode() failed (%d, %.*s)\n",
datalen, datalen, data);
return 1;
}
free (data);
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
@@ -50,6 +78,8 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
test_libssh2_base64_decode (session);
libssh2_session_free(session); libssh2_session_free(session);
return 0; return 0;

170
tests/ssh2.c Normal file
View File

@@ -0,0 +1,170 @@
/* Self test, based on examples/simple/ssh2.c. */
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
# ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
unsigned long hostaddr;
int sock, i, auth_pw = 0;
struct sockaddr_in sin;
const char *fingerprint;
char *userauthlist;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
const char *pubkeyfile="etc/user.pub";
const char *privkeyfile="etc/user";
const char *username="username";
const char *password="password";
int ec = 1;
if (getenv ("USER"))
username = getenv ("USER");
if (getenv ("PRIVKEY"))
privkeyfile = getenv ("PRIVKEY");
if (getenv ("PRIVKEY"))
pubkeyfile = getenv ("PUBKEY");
hostaddr = htonl(0x7F000001);
sock = socket(AF_INET, SOCK_STREAM, 0);
#ifndef WIN32
fcntl(sock, F_SETFL, 0);
#endif
sin.sin_family = AF_INET;
sin.sin_port = htons(4711);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance and start it up
* This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers
*/
session = libssh2_session_init();
if (libssh2_session_startup(session, sock)) {
fprintf(stderr, "Failure establishing SSH session\n");
return -1;
}
/* At this point we havn't authenticated,
* The first thing to do is check the hostkey's fingerprint against our known hosts
* Your app may have it hard coded, may go to a file, may present it to the user, that's your call
*/
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");
/* check what authentication methods are available */
userauthlist = libssh2_userauth_list(session, username, strlen(username));
printf("Authentication methods: %s\n", userauthlist);
if (strstr(userauthlist, "password") != NULL) {
auth_pw |= 1;
}
if (strstr(userauthlist, "keyboard-interactive") != NULL) {
auth_pw |= 2;
}
if (strstr(userauthlist, "publickey") != NULL) {
auth_pw |= 4;
}
if (auth_pw & 4) {
/* Authenticate by public key */
if (libssh2_userauth_publickey_fromfile(session, username, pubkeyfile, privkeyfile, password)) {
printf("\tAuthentication by public key failed!\n");
goto shutdown;
} else {
printf("\tAuthentication by public key succeeded.\n");
}
} else {
printf("No supported authentication methods found!\n");
goto shutdown;
}
/* Request a shell */
if (!(channel = libssh2_channel_open_session(session))) {
fprintf(stderr, "Unable to open a session\n");
goto shutdown;
}
/* Some environment variables may be set,
* It's up to the server which ones it'll allow though
*/
libssh2_channel_setenv(channel, "FOO", "bar");
/* Request a terminal with 'vanilla' terminal emulation
* See /etc/termcap for more options
*/
if (libssh2_channel_request_pty(channel, "vanilla")) {
fprintf(stderr, "Failed requesting pty\n");
goto skip_shell;
}
/* Open a SHELL on that pty */
if (libssh2_channel_shell(channel)) {
fprintf(stderr, "Unable to request shell on allocated pty\n");
goto shutdown;
}
ec = 0;
skip_shell:
if (channel) {
libssh2_channel_free(channel);
channel = NULL;
}
shutdown:
libssh2_session_disconnect(session, "Normal Shutdown");
libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
return ec;
}

39
tests/ssh2.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
# Written by Simon Josefsson.
# Start sshd, invoke parameters, saving exit code, kill sshd, and
# return exit code.
srcdir=${srcdir:-$PWD}
SSHD=${SSHD:-/usr/sbin/sshd}
cmd="./ssh2${EXEEXT}"
srcdir=`cd $srcdir; pwd`
PRIVKEY=$srcdir/etc/user
export PRIVKEY
PUBKEY=$srcdir/etc/user.pub
export PUBKEY
chmod go-r $srcdir/etc/host*
$SSHD -f /dev/null -h $srcdir/etc/host \
-o 'Port 4711' -o 'Protocol 2' \
-o "AuthorizedKeysFile $srcdir/etc/user.pub" -D &
sshdpid=$!
trap "kill ${sshdpid}; echo signal killing sshd; exit 1;" EXIT
: "started sshd (${sshdpid})"
sleep 3
: Invoking $cmd...
eval $cmd
ec=$?
: Self-test exit code $ec
: "killing sshd (${sshdpid})"
kill "${sshdpid}" > /dev/null 2>&1
trap "" EXIT
exit $ec

28
tests/sshdwrap Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/sh -x
# Written by Simon Josefsson
# Start sshd, invoke parameters, saving exit code, kill sshd, and
# return exit code.
cmd="$@"
SSHD=${SSHD:-/usr/sbin/sshd}
$SSHD -f etc/sshd_config -h $PWD/etc/host -D &
sshdpid=$!
trap "kill ${sshdpid}; echo signal killing sshd; exit 1;" EXIT
: "started sshd (${sshdpid})"
sleep 1
: Invoking $cmd...
eval $cmd
ec=$?
: Self-test exit code $ec
: "killing sshd (${sshdpid})"
kill "${sshdpid}" > /dev/null 2>&1
trap "" EXIT
exit $ec

View File

@@ -16,43 +16,21 @@
#define HAVE_WINSOCK2_H #define HAVE_WINSOCK2_H
#define HAVE_IOCTLSOCKET #define HAVE_IOCTLSOCKET
#define HAVE_SELECT
/* same as WSABUF */
struct iovec {
u_long iov_len;
char *iov_base;
};
#define inline __inline
static inline int writev(int sock, struct iovec *iov, int nvecs)
{
DWORD ret;
if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
return ret;
}
return -1;
}
/* not really usleep, but safe for the way we use it in this lib */
static inline int usleep(int udelay)
{
Sleep(udelay / 1000);
return 0;
}
#ifdef _MSC_VER #ifdef _MSC_VER
#define snprintf _snprintf #define snprintf _snprintf
#if _MSC_VER < 1500
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#else
#define ssize_t SSIZE_T
#define uint32_t UINT32
#endif
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#define strcasecmp _stricmp #define strcasecmp _stricmp
#else #else
#ifdef __MINGW32__
#define WINSOCK_VERSION MAKEWORD(2,0)
#else
#define strncasecmp strnicmp #define strncasecmp strnicmp
#define strcasecmp stricmp #define strcasecmp stricmp
#endif /* __MINGW32__ */
#endif /* _MSC_VER */ #endif /* _MSC_VER */
/* Compile in zlib support */ /* Compile in zlib support */