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
gknauf: Guenter Knauf
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
EXTRA_DIST = $(WIN32FILES) buildconf $(NETWAREFILES) get_ver.awk HACKING \
maketgz NMakefile
maketgz NMakefile TODO
ACLOCAL_AMFLAGS = -I m4
@@ -34,3 +34,26 @@ dist-hook:
strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \
cp $$file $(distdir)$$strip; \
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.
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
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
options deserve additional comments:
@@ -48,49 +52,43 @@ options deserve additional comments:
the older more reliable method.
* --with-libgcrypt
* --without-libgcrypt
* --with-libgcrypt-prefix=DIR
libssh2 can use the Libgcrypt library
(http://www.gnupg.org/) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate Libgcrypt in the
default location, but if you have installed it
somewhere else, use the --with-libgrypt-prefix=DIR
parameter.
Configure will attempt to locate Libgcrypt
automatically.
* --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
(http://www.openssl.org) for cryptographic operations.
Either Libgcrypt or OpenSSL is required.
Configure will attempt to locate OpenSSL in a number
of default locations:
/usr/local/ssl
/usr/local
/usr
/usr/local/openssl
Configure will attempt to locate OpenSSL in the
default location.
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)
for payload compression, however zlib is not required.
If present, libssh2 will attempt to use the zlib
(http://www.zlib.org) for payload compression, however
zlib is not required.
Configure will attempt to location a zlib installation
in a number of default locations:
/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.
If your installation of Libz is in another location,
specify it using --with-libz-prefix.
* --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_INIT(libssh2, [-], libssh2-devel@lists.sourceforge.net)
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
dnl SED is needed by some of the tools
@@ -28,6 +28,10 @@ AB_INIT
# get this removed.
AC_CANONICAL_HOST
case "$host" in
*-mingw*)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32 -DWINSOCK_VERSION=0x0200"
LIBS="$LIBS -lws2_32"
;;
*-cygwin)
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
;;
@@ -40,6 +44,11 @@ case "$host" in
;;
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.
AC_SEARCH_LIBS(socket, socket)
@@ -52,153 +61,57 @@ AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
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_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
AC_SYS_LARGEFILE
# Look for libgcrypt.
# Configure parameters
AC_ARG_WITH(libgcrypt,
AC_HELP_STRING([--with-libgcrypt],[Use libgcrypt for crypto]),
use_libgcrypt=$withval,use_libgcrypt=no)
if test "$use_libgcrypt" != "no"; then
AC_HELP_STRING([--with-libgcrypt],[Use Libgcrypt for crypto]),
use_libgcrypt=$withval,use_libgcrypt=auto)
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>])
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])
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
# $shrext_cmds (from libtool) can contain commands so it must be eval'd
# Simon's note: replace the find-openssl/libz logic with Bruno's
# AC_LIB_LINKFLAGS which is more portable and flexible.
eval SHLIB_SUFFIX_NAME=\"$shrext_cmds\"
AC_SUBST(SHLIB_SUFFIX_NAME)
#
# 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>])
# Look for Libz
if test "$use_libz" != "no"; then
AC_LIB_HAVE_LINKFLAGS([z], [], [#include <zlib.h>])
if test "$ac_cv_libz" != yes; then
AC_MSG_NOTICE([Cannot find libz, disabling compression])
AC_MSG_NOTICE([Try --with-libz-prefix=PATH if you know you have it])
else
AC_DEFINE(LIBSSH2_HAVE_ZLIB, 1, [Compile in zlib support])
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
AC_MSG_RESULT([Cannot find libz's <zlib.h>])
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([sys/select.h sys/socket.h sys/ioctl.h sys/time.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

View File

@@ -1,2 +1,3 @@
Makefile
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
@@ -23,11 +23,14 @@ dist_man_MANS = \
libssh2_channel_set_blocking.3 \
libssh2_channel_setenv_ex.3 \
libssh2_channel_wait_eof.3 \
libssh2_channel_wait_closed.3 \
libssh2_channel_write_ex.3 \
libssh2_channel_x11_req_ex.3 \
libssh2_hostkey_hash.3 \
libssh2_scp_recv.3 \
libssh2_scp_send_ex.3 \
libssh2_session_abstract.3 \
libssh2_session_block_directions.3 \
libssh2_session_callback_set.3 \
libssh2_session_free.3 \
libssh2_session_disconnect_ex.3 \
@@ -55,9 +58,13 @@ dist_man_MANS = \
libssh2_sftp_stat_ex.3 \
libssh2_sftp_symlink_ex.3 \
libssh2_sftp_tell.3 \
libssh2_sftp_tell64.3 \
libssh2_sftp_unlink_ex.3 \
libssh2_sftp_write.3 \
libssh2_userauth_authenticated.3 \
libssh2_userauth_keyboard_interactive_ex.3 \
libssh2_userauth_list.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"
.SH NAME
libssh2_channel_close - close a channel<
libssh2_channel_close - close a channel
.SH SYNOPSIS
#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"
.SH NAME
@@ -14,9 +14,9 @@ libssh2_session_abstract(LIBSSH2_SESSION *session);
.BR libssh2_session_init_ex(3)
Return a pointer to where the abstract pointer provided to
.BR libssh2_session_init_ex(3)
is stored. By providing a doubly de-referenced pointer, the internal
storage of the session instance may be modified in place.
\fBlibssh2_session_init_ex(3)\fP is stored. By providing a doubly
de-referenced pointer, the internal storage of the session instance may be
modified in place.
.SH RETURN VALUE
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"
.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
make it non-blocking.
Set or clear blocking mode on the selected on the sessoin. This will
instantly affect any channels associtated with this session. If a read is
performed on a session with no data currently available, a blocking
session will wait for data to arrive and return what it receives.
A non-blocking session will return immediately with an empty buffer.
If a write is performed on a session with
no room for more data, a blocking session will wait for room. A non-blocking
session will return immediately without writing anything.
Set or clear blocking mode on the selected on the session. This will
instantly affect any channels associated with this session. If a read is
performed on a session with no data currently available, a blocking session
will wait for data to arrive and return what it receives. A non-blocking
session will return immediately with an empty buffer. If a write is performed
on a session with no room for more data, a blocking session will wait for
room. A non-blocking session will return immediately without writing
anything.
.SH RETURN VALUE
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"
.SH NAME
libssh2_sftp_init -
libssh2_sftp_init - open SFTP channel for the given SSH session.
.SH SYNOPSIS
#include <libssh2.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"
.SH NAME
@@ -14,7 +14,10 @@ libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
\fIsftp\fP - SFTP instance as returned by
.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
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"
.SH NAME
libssh2_sftp_open -
libssh2_sftp_open - open filehandle for file on SFTP.
.SH SYNOPSIS
#include <libssh2.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"
.SH NAME
libssh2_sftp_rename_ex - rename a file
libssh2_sftp_rename_ex - rename an SFTP file
.SH SYNOPSIS
#include <libssh2.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"
.SH NAME
libssh2_sftp_rmdir_ex - rename a file
libssh2_sftp_rmdir_ex - remove an SFTP directory
.SH SYNOPSIS
#include <libssh2.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
libssh2_sftp_seek - set the read/write position indicator within a file
.SH SYNOPSIS
@@ -10,6 +10,9 @@ libssh2_sftp_seek - set the read/write position indicator within a file
void
libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset);
.SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by
.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
during a seek operation. The localized file pointer is simply used as a
convenience offset during read/write operations.
.SH AVAILABILITY
libssh2_sftp_seek64(3) was added in 1.0
.SH SEE ALSO
.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"
.SH NAME
libssh2_sftp_stat_ex - rename a file
libssh2_sftp_stat_ex - get status about an SFTP file
.SH SYNOPSIS
#include <libssh2.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"
.SH NAME
@@ -11,16 +11,12 @@ size_t
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
.SH DESCRIPTION
\fIhandle\fP - SFTP File Handle as returned by
.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.
\fIhandle\fP - SFTP File Handle as returned by \fBlibssh2_sftp_open(3)\fP.
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
Current offset from beginning of file in bytes.
.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"
.SH NAME
libssh2_sftp_unlink_ex - rename a file
libssh2_sftp_unlink_ex - unlink an SFTP file
.SH SYNOPSIS
#include <libssh2.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
libssh2_sftp_rename_ex - rename a file
libssh2_sftp_write - write SFTP data
.SH SYNOPSIS
#include <libssh2.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
.deps
.libs
*.gcno
*.gcda
scp
scp_nonblock
scp_write
scp_write_nonblock
sftp
sftp_nonblock
sftpdir

View File

@@ -10,6 +10,7 @@ noinst_PROGRAMS = ssh2 \
sftp_RW_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

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.
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#ifdef HAVE_WINSOCK2_H
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#ifdef HAVE_WINSOCK2_H
@@ -45,12 +45,15 @@ int main(int argc, char *argv[])
const char *scppath="/tmp/TEST";
struct stat fileinfo;
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
off_t got=0;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -88,8 +91,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#ifdef HAVE_WINSOCK2_H
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
@@ -47,6 +47,9 @@ int main(int argc, char *argv[])
const char *scppath="/tmp/TEST";
FILE *local;
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
char mem[1024];
size_t nread;
char *ptr;
@@ -55,7 +58,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -105,8 +108,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/secrets -p|-i|-k"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*
@@ -9,7 +9,7 @@
* Using the SFTP server running on 127.0.0.1
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -53,6 +53,9 @@ int main(int argc, char *argv[])
const char *sftppath="/tmp/TEST"; /* source path */
const char *dest="/tmp/TEST2"; /* destination path */
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
FILE *tempstorage;
@@ -63,7 +66,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
/* 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 */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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
*
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/sftp_mkdir"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/sftp_write_nonblock.c"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -46,12 +46,15 @@ int main(int argc, char *argv[])
const char *password="password";
const char *sftppath="/tmp/sftp_mkdir_nonblock";
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -91,8 +94,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password /tmp/secrets"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -49,13 +49,16 @@ int main(int argc, char *argv[])
const char *password="password";
const char *sftppath="/tmp/TEST";
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -94,8 +97,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*
@@ -9,7 +9,7 @@
* "sftp 192.168.0.1 user password sftp_write.c /tmp/secrets"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -57,7 +57,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*
@@ -9,7 +9,7 @@
* "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_sftp.h>
@@ -47,6 +47,9 @@ int main(int argc, char *argv[])
const char *loclfile="sftp_write_nonblock.c";
const char *sftppath="/tmp/sftp_write_nonblock.c";
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
FILE *local;
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
@@ -57,7 +60,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -106,8 +109,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*
@@ -9,7 +9,7 @@
* "sftpdir 192.168.0.1 user password /tmp/secretdir"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*
@@ -9,7 +9,7 @@
* "sftpdir 192.168.0.1 user password /tmp/secretdir"
*/
#include "config.h"
#include "libssh2_config.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
@@ -46,13 +46,16 @@ int main(int argc, char *argv[])
const char *password="password";
const char *sftppath="/tmp/secretdir";
int rc;
#if defined(HAVE_IOCTLSOCKET)
long flag = 1;
#endif
LIBSSH2_SFTP *sftp_session;
LIBSSH2_SFTP_HANDLE *sftp_handle;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
if (argc > 1) {
@@ -91,8 +94,15 @@ int main(int argc, char *argv[])
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
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
#error "add support for setting the socket non-blocking here"
#endif
#endif
/* 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.
*
@@ -9,10 +9,13 @@
* "ssh2 host user password [-p|-i|-k]"
*/
#include "config.h"
#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
@@ -73,7 +76,7 @@ int main(int argc, char *argv[])
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
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.
*
* 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;
#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
defines: */
#define LIBSSH2_VERSION_MAJOR 0
#define LIBSSH2_VERSION_MINOR 18
#define LIBSSH2_VERSION_MAJOR 1
#define LIBSSH2_VERSION_MINOR 0
#define LIBSSH2_VERSION_PATCH 0
/* 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
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
@@ -240,6 +244,11 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel 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 */
#define LIBSSH2_HOSTKEY_HASH_MD5 1
#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 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_block_directions(LIBSSH2_SESSION *session);
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);
#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);
#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.
*
* 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)
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 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);
#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
*.exe
*.obj
*.gcno
*.gcda
.*.swp
Debug
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
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 \
libssh2_priv.h openssl.h libgcrypt.h pem.c transport.c
libssh2_priv.h openssl.h libgcrypt.h transport.c
if LIBGCRYPT
libssh2_la_SOURCES += libgcrypt.c
libssh2_la_SOURCES += libgcrypt.c pem.c
else
libssh2_la_SOURCES += openssl.c
endif
@@ -18,7 +18,7 @@ lib_LTLIBRARIES = libssh2.la
# srcdir/include for the shipped headers
# builddir/src for the generated config header when building out of the source
# 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
@@ -50,4 +50,5 @@ VERSION=-version-info 1:0: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) 2008 by Daniel Stenberg
*
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -63,10 +65,12 @@ libssh2_channel_nextid(LIBSSH2_SESSION * session)
channel = channel->next;
}
/* This is a shortcut to avoid waiting for close packets on channels we've forgotten about,
* This *could* be a problem if we request and close 4 billion or so channels in too rapid succession
* for the remote end to 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...
/* This is a shortcut to avoid waiting for close packets on channels we've
* forgotten about, This *could* be a problem if we request and close 4
* billion or so channels in too rapid succession for the remote end to
* 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;
_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) { \
(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_packet = 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_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.packet_size = packet_size;
libssh2_channel_add(session, session->open_channel);
CHANNEL_ADD(session, session->open_channel);
s = session->open_packet =
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 =
libssh2_ntohu32(session->open_data + 13);
_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->remote.id,
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) {
session->fwdLstn_host_len =
(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_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);
if (rc == PACKET_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);
return NULL;
} else if (rc) {
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);
LIBSSH2_FREE(session, session->fwdLstn_packet);
session->fwdLstn_packet = NULL;
@@ -567,7 +576,8 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)
LIBSSH2_CHANNEL *queued = listener->queue;
unsigned char *packet, *s;
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 =
host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
int rc;
@@ -609,7 +619,8 @@ libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)
listener->chanFwdCncl_data = packet;
} else if (rc) {
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);
LIBSSH2_FREE(session, packet);
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));
_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);
s = channel->setenv_packet =
@@ -762,7 +774,8 @@ libssh2_channel_setenv_ex(LIBSSH2_CHANNEL * channel, const char *varname,
return PACKET_EAGAIN;
} else if (rc) {
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);
LIBSSH2_FREE(session, channel->setenv_packet);
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 */
#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));
_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,
single_connection,
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;
_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,
channel->local.id, channel->remote.id);
@@ -1294,7 +1384,8 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
&& (adjustment + channel->adjust_queue <
LIBSSH2_CHANNEL_MINADJUST)) {
_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);
channel->adjust_queue += adjustment;
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 + 5, adjustment);
_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);
channel->adjust_state = libssh2_NB_state_created;
@@ -1324,7 +1416,8 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
return PACKET_EAGAIN;
} else if (rc) {
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);
channel->adjust_queue = adjustment;
channel->adjust_state = libssh2_NB_state_idle;
@@ -1339,10 +1432,11 @@ libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
/* }}} */
/* {{{ libssh2_channel_handle_extended_data
* How should extended data look to the calling app?
* Keep it in separate channels[_read() _read_stdder()]? (NORMAL)
* Merge the extended data to the standard data? [everything via _read()]? (MERGE)
* Ignore it entirely [toss out packets as they come in]? (IGNORE)
*
* How should extended data look to the calling app? Keep it in separate
* channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
* standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
* out packets as they come in]? (IGNORE)
*/
LIBSSH2_API void
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);
if ((rc < 0) && (rc != PACKET_EAGAIN)) {
fprintf(stderr, "return rc = %d\n", rc);
return rc;
}
channel->read_bytes_read = 0;
channel->read_block = 0;
channel->read_packet = session->packets.head;
channel->read_state = libssh2_NB_state_created;
}
@@ -1435,20 +1526,33 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
}
rc = 0;
channel->read_block = 0;
do {
if (channel->read_block) {
/* in the second lap and onwards, do this */
rc = libssh2_packet_read(session);
channel->read_packet = session->packets.head;
}
/* 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);
if (rc < 0) {
if (rc != PACKET_EAGAIN) {
channel->read_state = libssh2_NB_state_idle;
/* If we didn't find any more data to read */
if (rc < 0) {
if ( channel->read_bytes_read > 0){
break; /* finish processing and return */
}
/* no packets available, no data read. */
channel->read_state = libssh2_NB_state_idle;
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;
}
/* no packets available */
return rc;
}
while (channel->read_packet
@@ -1521,7 +1625,8 @@ libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
_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_read_ex_point1:
channel->read_state = libssh2_NB_state_jump1;
@@ -1597,20 +1702,20 @@ libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
&& (channel->local.id == read_local_id)
&& (stream_id == (int) libssh2_ntohu32(read_packet->data + 5)))
|| (!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
&& (channel->local.id == read_local_id)) || (!stream_id
&& (read_packet->
data[0] ==
SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (channel->
local.id ==
read_local_id)
&& (channel->
remote.
extended_data_ignore_mode
==
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE)))
&& (channel->local.id == read_local_id)) ||
(!stream_id
&& (read_packet->
data[0] ==
SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (channel->
local.id ==
read_local_id)
&& (channel->
remote.
extended_data_ignore_mode
==
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE)))
{
return (read_packet->data_len - read_packet->data_head);
}
read_packet = read_packet->next;
@@ -1651,32 +1756,8 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel, int stream_id,
0);
}
#if 0
/*
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) */
/* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] +
buflen(4) */
channel->write_packet_len = buflen + (stream_id ? 13 : 9);
channel->write_packet =
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 */
if (channel->write_bufwrite > channel->local.window_size) {
_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->remote.id, stream_id);
channel->write_bufwrite = channel->local.window_size;
}
if (channel->write_bufwrite > channel->local.packet_size) {
_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->remote.id, stream_id);
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_packet);
if (rc == PACKET_EAGAIN) {
_libssh2_debug(session, LIBSSH2_DBG_CONN,
"libssh2_packet_write returned EAGAIN");
return PACKET_EAGAIN;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send channel data", 0);
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
*/
LIBSSH2_API int
@@ -1976,7 +2062,8 @@ libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)
if (!libssh2_channel_eof(channel)) {
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);
return -1;
}
@@ -2007,7 +2094,7 @@ libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)
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
* Check the status of the read window
* Returns the number of bytes which the remote end may send without overflowing the window limit
* read_avail (if 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
*
* Check the status of the read window. Returns the number of bytes which the
* remote end may send without overflowing the window limit read_avail (if
* 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_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
@@ -2149,16 +2238,19 @@ libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
/* }}} */
/* {{{ 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
* window_size_initial (if passed) will be populated with the size of the initial window as defined by the channel_open request
*
* Check the status of the write window Returns the number of bytes which may
* 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_channel_window_write_ex(LIBSSH2_CHANNEL * channel,
unsigned long *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;
}

View File

@@ -818,7 +818,7 @@ static int
{
unsigned char *s;
unsigned long p_len, g_len;
int ret;
int ret = 0;
int rc;
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
*/
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)
{
int rc = 0;
int retcode;
session->state |= LIBSSH2_STATE_KEX_ACTIVE;
if (key_state->state == libssh2_NB_state_idle) {
/* Prevent loop in packet_add() */
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) {
retcode = libssh2_kexinit(session);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
} else if (retcode) {
session->local.kexinit = key_state->oldlocal;
session->local.kexinit_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle;
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
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->req_state);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
} else if (retcode) {
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_len = key_state->oldlocal_len;
key_state->state = libssh2_NB_state_idle;
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
return -1;
}
@@ -1763,6 +1771,7 @@ libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flag
session->kex->exchange_keys(session,
&key_state->key_state_low);
if (retcode == PACKET_EAGAIN) {
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
return PACKET_EAGAIN;
} else if (retcode) {
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->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
key_state->state = libssh2_NB_state_idle;

View File

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

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Author: Simon Josefsson
/* Copyright (C) 2006, 2007, The Written Word, Inc.
* Copyright (C) 2008, Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* 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_ctx int
#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_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)

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.
*
* Redistribution and use in source and binary forms,
@@ -41,6 +41,17 @@
#define LIBSSH2_LIBRARY
#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
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
@@ -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/msg00224.html
*/
#include <stdio.h>
#ifdef HAVE_POLL
# include <sys/poll.h>
#else
# ifdef HAVE_SELECT
# if defined(HAVE_SELECT) && !defined(WIN32)
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
@@ -70,6 +79,28 @@
#include "libssh2_publickey.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 */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
@@ -91,6 +122,26 @@
#include "openssl.h"
#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:
*
* "All implementations MUST be able to process packets with
@@ -481,12 +532,19 @@ struct _LIBSSH2_PUBLICKEY
unsigned long listFetch_data_len;
};
#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
struct _LIBSSH2_SFTP_HANDLE
{
LIBSSH2_SFTP *sftp;
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;
char handle_type;
@@ -654,6 +712,7 @@ struct _LIBSSH2_SESSION
int socket_fd;
int socket_block;
int socket_state;
int socket_block_directions;
/* Error tracking */
char *err_msg;
@@ -811,7 +870,14 @@ struct _LIBSSH2_SESSION
unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long scpRecv_response_len;
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;
#define scpsize_strtol strtol
#endif
long scpRecv_mtime;
long scpRecv_atime;
char *scpRecv_err_msg;
@@ -833,6 +899,7 @@ struct _LIBSSH2_SESSION
#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
#define LIBSSH2_STATE_NEWKEYS 0x00000002
#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
/* session.flag helpers */
#ifdef MSG_NOSIGNAL
@@ -1136,7 +1203,7 @@ const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void);
int _libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin,
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_integer(unsigned char **data, unsigned int *datalen,
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_md5,
&libssh2_mac_method_hmac_md5_96,
#ifdef LIBSSH2_HMAC_RIPEMD
#if LIBSSH2_HMAC_RIPEMD
&libssh2_mac_method_hmac_ripemd160,
&libssh2_mac_method_hmac_ripemd160_openssh_com,
#endif /* LIBSSH2_HMAC_RIPEMD */

View File

@@ -51,8 +51,7 @@ libssh2_ntohu32(const unsigned char *buf)
/* }}} */
/* {{{ 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_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];
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
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[1] = (msl >> 16) & 0xFF;

View File

@@ -665,6 +665,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
datalen - 13,
0);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
session->packAdd_state = libssh2_NB_state_idle;
@@ -817,6 +819,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
&session->
packAdd_Qlstn_state);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
@@ -833,6 +837,8 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
rc = libssh2_packet_x11_open(session, data, datalen,
&session->packAdd_x11open_state);
if (rc == PACKET_EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_OUTBOUND;
return PACKET_EAGAIN;
}
@@ -914,11 +920,31 @@ libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
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
* 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) {
return PACKET_EAGAIN;
}

View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
* Author: Simon Josefsson
/* Copyright (C) 2007 The Written Word, Inc.
* Copyright (C) 2008, Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@@ -58,7 +59,7 @@ int
_libssh2_pem_parse(LIBSSH2_SESSION * session,
const char *headerbegin,
const char *headerend,
FILE * fp, char **data, unsigned int *datalen)
FILE * fp, unsigned char **data, unsigned int *datalen)
{
char line[LINE_SIZE];
char *b64data = NULL;
@@ -96,7 +97,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
}
} 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;
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
*/
#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 "\""
static void
libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY * pkey,
@@ -404,7 +404,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
"publickey", strlen("publickey"));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0);
"Would block starting publickey subsystem", 0);
return NULL;
} else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
@@ -420,7 +420,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block starting publickkey subsystem", 0);
"Would block starting publickey subsystem", 0);
return NULL;
}
@@ -457,7 +457,7 @@ libssh2_publickey_init(LIBSSH2_SESSION * session)
(char *) buffer, (s - buffer));
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block sending publickkey version packet", 0);
"Would block sending publickey version packet", 0);
return NULL;
} else if ((s - buffer) != rc) {
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.
*
* 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';
/* Make sure we don't get fooled by leftover values */
errno = 0;
session->scpRecv_size = strtol(p, &e, 10);
session->scpRecv_size = scpsize_strtol(p, &e, 10);
if ((e && *e) || errno) {
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid response from SCP server, invalid size",

View File

@@ -133,6 +133,8 @@ libssh2_banner_receive(LIBSSH2_SESSION * session)
}
#endif /* WIN32 */
if (errno == EAGAIN) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
session->banner_TxRx_total_send = banner_len;
return PACKET_EAGAIN;
}
@@ -235,6 +237,8 @@ libssh2_banner_send(LIBSSH2_SESSION * session)
if (ret != (banner_len - session->banner_TxRx_total_send)) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* 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;
return PACKET_EAGAIN;
}
@@ -1189,14 +1193,18 @@ libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
LIBSSH2_SESSION *session = channel->session;
LIBSSH2_PACKET *packet = session->packets.head;
while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) && (extended == 0) &&
(channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
&& (extended != 0)
&& (channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
/* Found data waiting to be read */
return 1;
while (packet)
{
if ( channel->local.id == libssh2_ntohu32(packet->data + 1)) {
if ( extended == 1 &&
(packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
|| packet->data[0] == SSH_MSG_CHANNEL_DATA )) {
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;
}
@@ -1478,7 +1486,7 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
struct timeval tv_begin, tv_end;
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);
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,
* 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;
#endif
@@ -1532,4 +1540,15 @@ libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
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.
*
* Redistribution and use in source and binary forms,
@@ -82,18 +82,18 @@
/* S_IFDIR */
#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
/* {{{ libssh2_sftp_packet_add
/* {{{ sftp_packet_add
* Add a packet to the SFTP packet brigade
*/
static int
libssh2_sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
unsigned long data_len)
sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
unsigned long data_len)
{
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d",
(int) data[0]);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
(int) data[0], data_len);
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packet) {
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
*/
static int
libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
sftp_packet_read(LIBSSH2_SFTP * sftp)
{
LIBSSH2_CHANNEL *channel = sftp->channel;
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");
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 (sftp->partial_packet) {
packet = sftp->partial_packet;
packet_len = sftp->partial_len;
packet_received = sftp->partial_received;
sftp->partial_packet = NULL;
} else {
if (flush && session->socket_block && !libssh2_waitsocket(session, 0)) {
/* While flushing in blocking mode, check before reading */
return -1;
}
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
"partial read cont, len: %lu", packet_len);
}
else {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
if (flush && (rc < 0)) {
/* When flushing, exit quickly */
return -1;
} else if (rc == PACKET_EAGAIN) {
if (rc == 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,
"Timeout waiting for FXP packet", 0);
return -1;
@@ -191,14 +188,7 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
(char *) packet + packet_received,
packet_len - packet_received);
if (flush && (bytes_received < 0)) {
if (packet) {
/* When flushing, remove packet if existing */
LIBSSH2_FREE(session, packet);
}
/* When flushing, exit quickly */
return -1;
} else if (bytes_received == PACKET_EAGAIN) {
if (bytes_received == PACKET_EAGAIN) {
/*
* We received EAGAIN, save what we have and
* return to EAGAIN to the caller
@@ -209,7 +199,8 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
packet = NULL;
return PACKET_EAGAIN;
} else if (bytes_received < 0) {
}
else if (bytes_received < 0) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Receive error waiting for SFTP packet", 0);
LIBSSH2_FREE(session, packet);
@@ -218,7 +209,7 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
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);
return -1;
}
@@ -228,13 +219,13 @@ libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
/* }}} */
/* {{{ libssh2_sftp_packet_ask
/* {{{ sftp_packet_ask
* A la libssh2_packet_ask()
*/
static int
libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len, int poll_channel)
sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len, int poll_channel)
{
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet = sftp->packets.head;
@@ -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",
(int) packet_type);
if (poll_channel) {
int ret = libssh2_sftp_packet_read(sftp, 0);
int ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (ret < 0) {
@@ -288,13 +279,13 @@ libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */
/* {{{ libssh2_sftp_packet_require
/* {{{ sftp_packet_require
* A la libssh2_packet_require
*/
static int
libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
{
LIBSSH2_SESSION *session = sftp->channel->session;
int ret;
@@ -302,14 +293,14 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet",
(int) packet_type);
if (libssh2_sftp_packet_ask
(sftp, packet_type, request_id, data, data_len, 0) == 0) {
if (sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0) == 0) {
/* The right packet was available in the packet brigade */
return 0;
}
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
ret = libssh2_sftp_packet_read(sftp, 0);
ret = sftp_packet_read(sftp);
if (ret == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (ret <= 0) {
@@ -318,8 +309,8 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
if (packet_type == ret) {
/* Be lazy, let packet_ask pull it out of the brigade */
return libssh2_sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0);
return sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0);
}
}
@@ -329,36 +320,27 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */
/* {{{ libssh2_sftp_packet_requirev
* Requie one of N possible reponses
/* {{{ sftp_packet_requirev
* Require one of N possible reponses
*/
static int
libssh2_sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
const unsigned char *valid_responses,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
const unsigned char *valid_responses,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
{
int i;
int ret;
/*
* If no timeout is active, start a new one and flush
* any pending packets
*/
/* If no timeout is active, start a new one */
if (sftp->requirev_start == 0) {
_libssh2_debug(sftp->channel->session, LIBSSH2_DBG_SFTP,
"_requirev(): Initialize timeout");
sftp->requirev_start = time(NULL);
/* Flush */
while (libssh2_sftp_packet_read(sftp, 1) > 0);
}
while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
for(i = 0; i < num_valid_responses; i++) {
if (libssh2_sftp_packet_ask
(sftp, valid_responses[i], request_id, data, data_len,
0) == 0) {
if (sftp_packet_ask(sftp, valid_responses[i], request_id,
data, data_len, 0) == 0) {
/*
* Set to zero before all returns to say
* 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)) {
sftp->requirev_start = 0;
return -1;
@@ -534,7 +516,7 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
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) {
LIBSSH2_FREE(session, sftp->partial_packet);
}
@@ -659,8 +641,8 @@ libssh2_sftp_init(LIBSSH2_SESSION * session)
}
/* For initiallization we are requiring blocking, probably reasonable */
rc = libssh2_sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
0, &data, &data_len);
rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
0, &data, &data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from SFTP subsystem",
@@ -744,10 +726,6 @@ libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
LIBSSH2_FREE(sftp->channel->session, sftp->open_packet);
sftp->open_packet = NULL;
}
if (sftp->read_packet) {
LIBSSH2_FREE(sftp->channel->session, sftp->read_packet);
sftp->read_packet = NULL;
}
if (sftp->readdir_packet) {
LIBSSH2_FREE(sftp->channel->session, sftp->readdir_packet);
sftp->readdir_packet = NULL;
@@ -814,7 +792,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
int rc;
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 +
((open_type ==
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);
if (!sftp->open_packet) {
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);
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",
0);
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,
"Unable to send FXP_OPEN or FXP_OPENDIR command", 0);
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) {
rc = libssh2_sftp_packet_requirev(sftp, 2, fopen_responses,
sftp->open_request_id, &data,
&data_len);
rc = sftp_packet_requirev(sftp, 2, fopen_responses,
sftp->open_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for status message", 0);
return NULL;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
sftp->open_state = libssh2_NB_state_idle;
@@ -898,12 +883,38 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
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) {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file", 0);
int badness = 1;
sftp->last_errno = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
return NULL;
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,
"Failed opening remote file", 0);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
sftp->last_errno);
LIBSSH2_FREE(session, data);
return NULL;
}
}
fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
@@ -920,18 +931,11 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
LIBSSH2_SFTP_HANDLE_DIR;
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 */
fp->handle_len = 256;
}
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;
fp->handle_len = SFTP_HANDLE_MAXLEN;
}
memcpy(fp->handle, data + 9, fp->handle_len);
LIBSSH2_FREE(session, data);
@@ -960,8 +964,9 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, request_id;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + length(4) */
unsigned long data_len, request_id = 0;
/* 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;
unsigned char *packet, *s, *data;
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,
"Reading %lu bytes from SFTP handle",
(unsigned long) buffer_maxlen);
packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_CLOSE packet", 0);
return -1;
}
packet = handle->request_packet;
sftp->read_state = libssh2_NB_state_allocated;
} else {
packet = sftp->read_packet;
@@ -996,9 +996,23 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
* So we request data by pieces.
*/
bytes_requested = buffer_maxlen - total_read;
/* 10 = packet_type(1)+request_id(4)+data_length(4)+end_of_line_flag(1) */
if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 10) {
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 10;
/* 10 = packet_type(1) + request_id(4) + data_length(4) +
end_of_line_flag(1)
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
_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);
s += 8;
libssh2_htonu32(s, buffer_maxlen);
libssh2_htonu32(s, bytes_requested);
s += 4;
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;
return PACKET_EAGAIN;
} 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,
"Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
return -1;
@@ -1053,14 +1068,13 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
if (sftp->read_state == libssh2_NB_state_sent) {
retcode =
libssh2_sftp_packet_requirev(sftp, 2, read_responses,
request_id, &data, &data_len);
sftp_packet_requirev(sftp, 2, read_responses,
request_id, &data, &data_len);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
return -1;
@@ -1072,7 +1086,6 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
switch (data[0]) {
case SSH_FXP_STATUS:
retcode = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, data);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
@@ -1089,7 +1102,6 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
case SSH_FXP_DATA:
bytes_read = libssh2_ntohu32(data + 5);
if (bytes_read > (data_len - 9)) {
LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL;
sftp->read_state = libssh2_NB_state_idle;
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_state = libssh2_NB_state_idle;
return total_read;
@@ -1244,9 +1255,9 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
}
retcode =
libssh2_sftp_packet_requirev(sftp, 2, read_responses,
sftp->readdir_request_id, &data,
&data_len);
sftp_packet_requirev(sftp, 2, read_responses,
sftp->readdir_request_id, &data,
&data_len);
if (retcode == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (retcode) {
@@ -1331,7 +1342,8 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
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;
unsigned char *s, *data;
int rc;
@@ -1385,8 +1397,8 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
sftp->write_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -1468,8 +1480,8 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
return PACKET_EAGAIN;
} else if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
setstat ? (char *) "Unable to send FXP_FSETSTAT"
: (char *) "Unable to send FXP_FSTAT command", 0);
(setstat ? "Unable to send FXP_FSETSTAT"
: "Unable to send FXP_FSTAT command"), 0);
LIBSSH2_FREE(session, sftp->fstat_packet);
sftp->fstat_packet = NULL;
sftp->fstat_state = libssh2_NB_state_idle;
@@ -1481,9 +1493,9 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
sftp->fstat_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_requirev(sftp, 2, fstat_responses,
sftp->fstat_request_id, &data,
&data_len);
rc = sftp_packet_requirev(sftp, 2, fstat_responses,
sftp->fstat_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -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
* Return the current read/write pointer's offset
*/
@@ -1537,6 +1560,15 @@ libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
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,9 +1632,9 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
}
if (handle->close_state == libssh2_NB_state_sent) {
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -1640,7 +1672,6 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
handle->close_state = libssh2_NB_state_idle;
LIBSSH2_FREE(session, handle->handle);
LIBSSH2_FREE(session, handle);
return 0;
@@ -1711,12 +1742,13 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
sftp->unlink_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
sftp->unlink_state = libssh2_NB_state_idle;
@@ -1820,9 +1852,9 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
sftp->rename_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -1936,8 +1968,8 @@ libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->mkdir_packet = NULL;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -2023,8 +2055,8 @@ libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->rmdir_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -2133,8 +2165,8 @@ libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->stat_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len);
rc = sftp_packet_requirev(sftp, 2, stat_responses,
sftp->stat_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@@ -2200,8 +2232,8 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
if (!sftp->symlink_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for SYMLINK/READLINK/REALPATH packet",
0);
"Unable to allocate memory for SYMLINK/READLINK"
"/REALPATH packet", 0);
return -1;
}
@@ -2263,12 +2295,13 @@ libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->symlink_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_requirev(sftp, 2, link_responses,
sftp->symlink_request_id, &data,
&data_len);
rc = sftp_packet_requirev(sftp, 2, link_responses,
sftp->symlink_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
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 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 ===============================
* 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 */
if ((nread < 0) && (errno == EAGAIN)) {
session->socket_block_directions =
LIBSSH2_SESSION_BLOCK_INBOUND;
return PACKET_EAGAIN;
}
return PACKET_FAIL;
@@ -527,8 +563,21 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
libssh2_packet_read_point1:
rc = fullpacket(session, encrypted);
if (rc == PACKET_EAGAIN) {
session->readPack_encrypted = encrypted;
session->readPack_state = libssh2_NB_state_jump1;
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_state = libssh2_NB_state_jump1;
}
return PACKET_EAGAIN;
}
@@ -543,8 +592,6 @@ libssh2_packet_read(LIBSSH2_SESSION * session)
/* }}} */
#ifndef OLDSEND
static libssh2pack_t
send_existing(LIBSSH2_SESSION * session, unsigned char *data,
unsigned long data_len, ssize_t * ret)
@@ -587,6 +634,7 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data,
/* send failure! */
return PACKET_FAIL;
}
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
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
* 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.
*
* 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
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 */
if (encrypted && strcmp(session->local.comp->name, "none")) {
if (session->local.comp->
comp(session, 1, &data, &data_len, LIBSSH2_PACKET_MAXCOMP,
&free_data, data, data_len, &session->local.comp_abstract)) {
if (session->local.comp->comp(session, 1, &data, &data_len,
LIBSSH2_PACKET_MAXCOMP,
&free_data, data, data_len,
&session->local.comp_abstract)) {
return PACKET_COMPRESS; /* compression failure */
}
}
@@ -722,8 +775,8 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
The MAC field is not encrypted. */
for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
unsigned char *ptr = &p->outbuf[i];
if (session->local.crypt->
crypt(session, ptr, &session->local.crypt_abstract))
if (session->local.crypt->crypt(session, ptr,
&session->local.crypt_abstract))
return PACKET_FAIL; /* encryption failure */
}
}
@@ -739,6 +792,7 @@ libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
if (ret != total_length) {
if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
/* the whole packet could not be sent, save the rest */
session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
p->odata = orgdata;
p->olen = orgdata_len;
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);
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);
session->userauth_list_data[methods_len] = '\0';
_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,
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] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long pubkeydata_len, sig_len, data_len;
int rc;
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 */
memset(&session->userauth_host_packet_requirev_state, 0,
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) {
unsigned long data_len;
rc = libssh2_packet_requirev_ex(session, reply_codes,
&session->userauth_host_data,
&data_len, 0, NULL, 0,
@@ -822,19 +827,16 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
const char *privatekey,
const char *passphrase)
{
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *pubkeydata, *sig;
unsigned long pubkeydata_len = 0;
unsigned char reply_codes[4] =
{ SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
SSH_MSG_USERAUTH_PK_OK, 0
};
unsigned long pubkeydata_len, sig_len;
int rc;
if (session->userauth_pblc_state == libssh2_NB_state_idle) {
unsigned char *pubkeydata;
/* Zero the whole thing out */
memset(&session->userauth_pblc_packet_requirev_state, 0,
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) {
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,
&session->userauth_pblc_data,
&session->userauth_pblc_data_len, 0,
@@ -1023,6 +1032,10 @@ libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
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) {
unsigned char *newpacket;
/* 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_packet + session->userauth_pblc_packet_len;
session->userauth_pblc_b = NULL;
libssh2_htonu32(session->userauth_pblc_s,
4 + session->userauth_pblc_method_len + 4 + sig_len);

View File

@@ -1,5 +1,8 @@
.deps
.libs
*.gcno
*.gcda
Makefile
Makefile.in
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
if SSHD
noinst_PROGRAMS = ssh2
ssh2_SOURCES = ssh2.c
endif
ctests = simple
TESTS = $(ctests)
if SSHD
TESTS += ssh2.sh
endif
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.
* Author: Simon Josefsson
/* Copyright (C) 2007 The Written Word, Inc.
* Copyright (C) 2008 Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@@ -36,9 +37,36 @@
*/
#include <stdio.h>
#include <stdlib.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[])
{
LIBSSH2_SESSION *session;
@@ -50,6 +78,8 @@ int main(int argc, char *argv[])
return 1;
}
test_libssh2_base64_decode (session);
libssh2_session_free(session);
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_IOCTLSOCKET
/* 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;
}
#define HAVE_SELECT
#ifdef _MSC_VER
#define snprintf _snprintf
#if _MSC_VER < 1500
#define vsnprintf _vsnprintf
#else
#define ssize_t SSIZE_T
#define uint32_t UINT32
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#ifdef __MINGW32__
#define WINSOCK_VERSION MAKEWORD(2,0)
#else
#define strncasecmp strnicmp
#define strcasecmp stricmp
#endif /* __MINGW32__ */
#endif /* _MSC_VER */
/* Compile in zlib support */