Compare commits
81 Commits
RELEASE.0.
...
RELEASE.1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
27197bcff3 | ||
![]() |
64b3e5e3f6 | ||
![]() |
ba79d6b52d | ||
![]() |
6b38e21fa7 | ||
![]() |
11330ee6da | ||
![]() |
b3649e86a8 | ||
![]() |
2f32080772 | ||
![]() |
7aac082782 | ||
![]() |
5a35edcb9a | ||
![]() |
079d20aca8 | ||
![]() |
b357379923 | ||
![]() |
62769b438f | ||
![]() |
d602478e87 | ||
![]() |
8eba2961ac | ||
![]() |
962a41e4ec | ||
![]() |
31841e7c74 | ||
![]() |
70f844e57c | ||
![]() |
942a81c8d5 | ||
![]() |
e26956be72 | ||
![]() |
2535c5c2ee | ||
![]() |
197a26ef8c | ||
![]() |
f1dae83d5e | ||
![]() |
bcad67636b | ||
![]() |
fbb25c7ad0 | ||
![]() |
e47bedf17c | ||
![]() |
19f78244de | ||
![]() |
9d5ba0dee2 | ||
![]() |
0934c4b39d | ||
![]() |
cc3a7d8e83 | ||
![]() |
8f860e249e | ||
![]() |
160f89f42e | ||
![]() |
881b01e522 | ||
![]() |
74d33d50ba | ||
![]() |
fcaa810350 | ||
![]() |
1f015d72b1 | ||
![]() |
8c8ba3bc20 | ||
![]() |
9d433d4f80 | ||
![]() |
50a3255dde | ||
![]() |
482072939a | ||
![]() |
f2253aeee9 | ||
![]() |
2b5becfe85 | ||
![]() |
8b25820589 | ||
![]() |
fd0bffdb2e | ||
![]() |
86eaae7886 | ||
![]() |
8e8dc43b0c | ||
![]() |
e45bddb9fd | ||
![]() |
e5a36fb1cf | ||
![]() |
5438cffd9a | ||
![]() |
95b73812e7 | ||
![]() |
85b953d0dd | ||
![]() |
c3447ea29f | ||
![]() |
8896b675f8 | ||
![]() |
b2334b227d | ||
![]() |
88d0ef1f3f | ||
![]() |
006f233361 | ||
![]() |
fa620b2a7b | ||
![]() |
b228f132f7 | ||
![]() |
8c43bc52b1 | ||
![]() |
d26a330483 | ||
![]() |
b4b8c51b32 | ||
![]() |
818e9edfb1 | ||
![]() |
61fda23340 | ||
![]() |
93ae080bbc | ||
![]() |
bd3dfed7e8 | ||
![]() |
99afc66665 | ||
![]() |
903307113e | ||
![]() |
9b31ca67ac | ||
![]() |
3f0d30d1d6 | ||
![]() |
d4aa801f6f | ||
![]() |
f56daac7fe | ||
![]() |
a55e6c10c9 | ||
![]() |
2fcaa00e3a | ||
![]() |
0242a3b6af | ||
![]() |
b310cc3465 | ||
![]() |
092e5f4b44 | ||
![]() |
c1a83abff9 | ||
![]() |
f3c344da22 | ||
![]() |
4600d108ed | ||
![]() |
76e8e81402 | ||
![]() |
d27dd927cd | ||
![]() |
63d863241a |
@@ -7,3 +7,5 @@ edink:Edink Kadribasic
|
||||
jehousley: James Housley
|
||||
gknauf: Guenter Knauf
|
||||
dfandrich: Dan Fandrich
|
||||
yangtse: Yang Tse
|
||||
thomaspu: Paul Thomas
|
||||
|
25
Makefile.am
25
Makefile.am
@@ -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
59
NEWS
@@ -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
54
README
@@ -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
30
TODO
Normal 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
|
217
configure.in
217
configure.in
@@ -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
|
||||
|
||||
|
@@ -1,2 +1,3 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
coverage
|
||||
|
@@ -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
|
||||
|
27
docs/libssh2_base64_decode.3
Normal file
27
docs/libssh2_base64_decode.3
Normal 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.
|
@@ -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>
|
||||
|
||||
|
24
docs/libssh2_channel_wait_closed.3
Normal file
24
docs/libssh2_channel_wait_closed.3
Normal 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)
|
@@ -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
|
||||
|
31
docs/libssh2_session_block_directions.3
Normal file
31
docs/libssh2_session_block_directions.3
Normal 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
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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.
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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)
|
||||
|
@@ -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>
|
||||
|
@@ -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)
|
||||
|
23
docs/libssh2_sftp_tell64.3
Normal file
23
docs/libssh2_sftp_tell64.3
Normal 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)
|
@@ -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>
|
||||
|
@@ -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
35
docs/libssh2_trace.3
Normal 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
|
43
docs/libssh2_userauth_keyboard_interactive_ex.3
Normal file
43
docs/libssh2_userauth_keyboard_interactive_ex.3
Normal 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)
|
@@ -2,8 +2,12 @@ Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
.libs
|
||||
*.gcno
|
||||
*.gcda
|
||||
scp
|
||||
scp_nonblock
|
||||
scp_write
|
||||
scp_write_nonblock
|
||||
sftp
|
||||
sftp_nonblock
|
||||
sftpdir
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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 */
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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))
|
||||
|
||||
|
@@ -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
51
libssh2-style.el
Normal 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
5
m4/.cvsignore
Normal file
@@ -0,0 +1,5 @@
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
@@ -5,6 +5,8 @@
|
||||
*.dll
|
||||
*.exe
|
||||
*.obj
|
||||
*.gcno
|
||||
*.gcda
|
||||
.*.swp
|
||||
Debug
|
||||
Release
|
||||
|
@@ -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)
|
||||
|
272
src/channel.c
272
src/channel.c
@@ -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;
|
||||
}
|
||||
|
||||
|
14
src/kex.c
14
src/kex.c
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
28
src/packet.c
28
src/packet.c
@@ -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;
|
||||
}
|
||||
|
10
src/pem.c
10
src/pem.c
@@ -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;
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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",
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
327
src/sftp.c
327
src/sftp.c
@@ -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
374
src/sshentry.c
Normal 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;
|
||||
}
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -1,5 +1,8 @@
|
||||
.deps
|
||||
.libs
|
||||
*.gcno
|
||||
*.gcda
|
||||
Makefile
|
||||
Makefile.in
|
||||
simple
|
||||
ssh2
|
||||
|
@@ -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
27
tests/etc/host
Normal 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
1
tests/etc/host.pub
Normal 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
3
tests/etc/sshd_config
Normal file
@@ -0,0 +1,3 @@
|
||||
Port 4711
|
||||
Protocol 2
|
||||
AuthorizedKeysFile /home/jas/src/libssh2/tests/etc/user.pub
|
27
tests/etc/user
Normal file
27
tests/etc/user
Normal 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
1
tests/etc/user.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxIgBuZS39D4bFnWminE7svGQLdVKx1aWKnEYEa+XtNU4DKZ/pxUHg0zbEBya+IkX1yqQYWALoiOwI8XhdemLp8g03BX7o+DLSWisfiHpCDVGAuNqRDF7qnFyL/ZBH6e0XKMtsoB51TDuBc4Rxh6p1V2QL/fg8BoHcCrnKkoqN8PSoKUX2lPKJ3JIF/P8cDLbKYCvbSTFOdf56eqg0GJe7jFtSwweE9yz3IWZ3kSS1E/9E6sXaNCu/hUt1bvQthICQyBNoTtQP/igEUJ7n0GMetsnq9wiUSomLzWqIWNqmvOv62aCXRi5sYgpSAR4Zvnm3Cx/Wl0BEPz2rrFkG+G0SQ== jas@mocca
|
@@ -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
170
tests/ssh2.c
Normal 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
39
tests/ssh2.sh
Executable 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
28
tests/sshdwrap
Executable 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
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user