Compare commits

..

1 Commits

Author SHA1 Message Date
Sara Golemon
6b40898187 Initial Import. 2004-12-07 21:17:20 +00:00
38 changed files with 584 additions and 8780 deletions

View File

@@ -1,9 +0,0 @@
*.lib
*.pdb
*.dll
*.exe
*.obj
.*.swp
Debug
Release
*.exp

60
INSTALL
View File

@@ -1,60 +0,0 @@
Installing libssh2
==================
* Untar this tarball (which, if you're reading this, you've already done)
* Run: ./configure (passing additional options as desired)
In addition the the standard set of ./configure options (e.g. --prefix)
there are five switches which you may wish to pay attention to:
* --with-openssl=[DIR]
libssh2 requires the OpenSSL library (http://www.openssl.org) for
cipher and hash method implementations.
./configure will attempt to locate OpenSSL in a number of default locations:
/usr/local/ssl /usr/local /usr /usr/local/openssl
If your installation of OpenSSL is in another location, specify it here.
* --with-zlib=[DIR]
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.
* --enable-crypt-none
The SSH2 Transport allows for unencrypted data transmission using the "none" cipher.
Because this is such a huge security hole, it is typically disabled on
SSH2 implementations and is diabled in libssh2 by default as well.
Enabling this option will allow for "none" as a negotiable method,
however it still requires that the method be advertized by the remote end
and that no more-prefferable methods are available.
* --enable-mac-none
The SSH2 Transport also allows implementations to forego a message authentication code.
While this is less of a security risk than using a "none" cipher, it is still not
recommended as disabling MAC hashes removes a layer of security.
Enabling this option will allow for "none" as a negotiable method,
however it still requires that the method be advertized by the remote end
and that no more-prefferable methods are available.
* --disable-gex-new
The diffie-hellman-group-exchange-sha1 (dh-gex) key exchange method originally defined
an exchange negotiation using packet type 30 to request a generation pair based
on a single target value. Later refinement of dh-gex provided for range and target
values. By default libssh2 will use the newer range method.
If you experience trouble connecting to an old SSH server using dh-gex,
try this option to fallback on the older more reliable method.
* Run: make all install

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,

View File

@@ -10,7 +10,7 @@ CC = @CC@
CFLAGS = -c @CFLAGS@ -Iinclude/ -Wall -g CFLAGS = -c @CFLAGS@ -Iinclude/ -Wall -g
LIBS = -lssh2 -Lsrc/ LIBS = -lssh2 -Lsrc/
INSTALL = @INSTALL@ INSTALL = @INSTALL@
VERSION=@PACKAGE_VERSION@ VERSION=0.1-dev
DISTLIB=libssh2-$(VERSION) DISTLIB=libssh2-$(VERSION)
all: all:
@@ -21,14 +21,13 @@ all:
$(CC) -o ssh2_sample.o ssh2_sample.c $(CFLAGS) $(CC) -o ssh2_sample.o ssh2_sample.c $(CFLAGS)
$(CC) -o ssh2_sample ssh2_sample.o $(LIBS) $(CC) -o ssh2_sample ssh2_sample.o $(LIBS)
install: install:
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(incldir) $(top_srcdir)/mkinstalldirs $(incldir)
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(libdir) $(top_srcdir)/mkinstalldirs $(libdir)
@for dir in ${subdirs}; do \ @for dir in ${subdirs}; do \
(cd $$dir && $(MAKE) install) \ (cd $$dir && $(MAKE) install) \
|| case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail" done && test -z "$$fail"
$(INSTALL) -m 644 include/libssh2.h $(DESTDIR)$(incldir)/ $(INSTALL) -m 644 include/libssh2.h $(incldir)/
$(INSTALL) -m 644 include/libssh2_sftp.h $(DESTDIR)$(incldir)/
clean: clean:
@for dir in ${subdirs}; do \ @for dir in ${subdirs}; do \
(cd $$dir && $(MAKE) clean) \ (cd $$dir && $(MAKE) clean) \
@@ -41,24 +40,9 @@ dist:
rm -f $(DISTLIB) rm -f $(DISTLIB)
ln -s . $(DISTLIB) ln -s . $(DISTLIB)
tar -zcf $(DISTLIB).tar.gz \ tar -zcf $(DISTLIB).tar.gz \
$(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \ $(DISTLIB)/configure.in $(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/INSTALL \ $(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/TODO \
$(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh $(DISTLIB)/config.sub $(DISTLIB)/config.guess \ $(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh \
$(DISTLIB)/src/*.c $(DISTLIB)/src/Makefile.in \ $(DISTLIB)/src/*.c $(DISTLIB)/src/Makefile.in \
$(DISTLIB)/include/libssh2.h $(DISTLIB)/include/libssh2_priv.h $(DISTLIB)/include/libssh2_sftp.h \ $(DISTLIB)/include/libssh2.h $(DISTLIB)/include/libssh2_priv.h $(DISTLIB)/include/libssh2_config.h.in
$(DISTLIB)/include/libssh2_config.h.in \
$(DISTLIB)/win32/config.mk $(DISTLIB)/win32/libssh2_config.h $(DISTLIB)/win32/rules.mk \
$(DISTLIB)/win32/libssh2.dsp $(DISTLIB)/win32/libssh2.dsw $(DISTLIB)/win32/ssh2_sample.dsp
rm -f $(DISTLIB) rm -f $(DISTLIB)
dist_nmake:
autoheader
autoconf
rm -f $(DISTLIB)
ln -s . $(DISTLIB)
tar -zcf $(DISTLIB)-win32.tar.gz \
$(DISTLIB)/NMakefile $(DISTLIB)/ssh2_sample.c $(DISTLIB)/src/*.c \
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/TODO $(DISTLIB)/INSTALL \
$(DISTLIB)/include/libssh2.h $(DISTLIB)/include/libssh2_priv.h $(DISTLIB)/include/libssh2_sftp.h \
$(DISTLIB)/win32/config.mk $(DISTLIB)/win32/libssh2_config.h $(DISTLIB)/win32/rules.mk
rm -f $(DISTLIB)

View File

@@ -1,16 +0,0 @@
!include "win32/config.mk"
SUBDIRS=src
all: all-sub ssh2_sample.exe
ssh2_sample.exe: ssh2_sample.c
$(CC) $(CFLAGS) -DWIN32 -o ssh2_sample.exe ssh2_sample.c libssh2$(SUFFIX).lib $(LIBS)
all-sub:
-for %D in ($(SUBDIRS)) do $(MAKE) /nologo /f %D/NMakefile BUILD=$(BUILD) SUBDIR=%D all-sub
clean:
rmdir /s/q $(TARGET)

180
README
View File

@@ -1,184 +1,8 @@
libssh2 - SSH2 library libssh2 - SSH2 library
====================== ======================
Version 0.11 Version 0.1-dev
------------ ---------------
Added libssh2_chnnale_get_exit_status() -- Mikhail
Added libssh2_channel_wait_closed() -- Mikhail
Added libssh2_userauth_keyboard_interactive_ex() -- Mikhail
Added libssh2_channel_receive_window_adjust() to be able to increase the size of the receive window.
Added queueing for small window_adjust packets to avoid unnecessary packet conversation.
Fixed libssh2_sftp_rename_ex() to only send flags parameter if version >= 5 negotiated
(not currently possible, but will be and might as well keep the API consistent).
Version 0.10
------------
Added developer debugging hooks. See --enable-debug-* options to ./configure
Ignore extended data in the SFTP layer. With no other mechanism to deal with that data it'd just fill up and get stuck.
(Re)Fixed channel_write() to provide an opportunity for window space to become available again.
(Re)Fixed SFTP INIT to send the correct SFTP packet length.
Fixed segfault when client and host can't agree on a hostkey/crypt/mac/comp method. (Thanks puudeli)
Fixed major issue with sftp packet buffering mechanism. Using wrong blocking semantics. (No puudeli, YOU the man)
Reduced busy-looping of libssh2_sftp_packet_requirev.
Version 0.9
-----------
Changed blocking_read to only block as much as necessary and not an arbitrary length of time. (Thanks Felix)
Fixed SFTP INIT/VERSION to exclude request_id and send correct maximum version number.
Fixed SFTP to be properly BC with version 1 and 2 servers.
Fixed libssh2_poll() to recognized closed sessions/channels.
Fixed libssh2_channel_write_ex() to fully block when set to blocking mode. Return actual bytes written as well. (Thanks deadem)
Added tests for -lm and -lsocket and add them when necessary.
Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex()
for examining the ssh transport windowing states.
Version 0.8
-----------
Fix potential segfault in compression/decompression.
Fix compatability with older versions of OpenSSL
Swapped order of none,zlib compression modes to prefer no compression by default.
Added sys/uio.h for platforms (FBSD) which need it in order to define struct iovec.
Added libssh2_poll() to check status of sockets/channels/listeners.
Removed unnecessary inclusion of stdio.h (holdover from debugging)
Version 0.7
-----------
Added libssh2_userauth_hostbased_fromfile_ex() for authenticating from hostkey.
Added configure recognition for MacOSX (Darwin) (Thanks Gabe)
Fixed extended data identification in libssh2_channel_read().
Fixed window adjust code. Hadn't acknowledged adjustments correctly.
Removed initial_window_size requirement for sending window adjust packet.
Version 0.6
-----------
Added LIBSSH2_FLAG_SIGPIPE to enable/disable SIGPIPE generated by send()/recv() calls. Default off.
Added libssh2_session_flag() to set optional session flags.
Collapsed exchanging_keys/newkeys/authenticated flags into single state attribute.
Fix zlib compression issue when internal buffer state misses partial sync.
Fix segfault when libssh2_session_methods() is called prior to session_startup().
Fixed client to server channel windowing. Pervent send queue overruns.
Swapped banner send/receive order (send first, then wait for response).
Version 0.5
-----------
*** BC Break ***
Reimplemented libssh2_session_methods() to match libssh2_session_method_pref() style
Fixed libssh2_attr2bin() (effects any setstat style call).
Fixed authenticating with encrypted private key.
Fixed authenticating via ssh-dss public key.
Fixed KEX_INIT cookie and packet padding to use actual random data
Added DESTDIR support to makefiles (Adam Go<47><6F>biowski -- I hope that character set translates right)
Added libssh2_channel_forward_listen_ex(), libssh2_channel_forward_cancel(), and libssh2_channel_forward_accept().
Added ./configure option '--disable-gex-new' to allow using the older group-exchange format
Added MAC methods hmac-md5 and hmac-md5-96.
Version 0.4
-----------
Fixed crash when trying to free sftp_dirhandle data from a filehandle struct.
Fixed leak in sftp_open_ex(), handle->handle not freed in handle_close().
Fixed leak in sftp_symlink_ex(), result for READLINK and REALPATH not freed unless there was an error.
Added libssh2_banner_set(), specify an arbitrary banner to send on introduction.
Version 0.3
-----------
Fixed libssh2_channel_read_ex(). Packet loop initialized BEFORE transport polled for new packets (should have been after).
Fixed blocking issues in scp_send()/scp_recv().
Fixed degree of indirection in macerror callback.
Changed packet read mechanism to use a fixed buffer and avoid unnecessary alloc/free calls. (especially while non-block looping)
Added channel close callback.
Added SFTP support (Using its own header file: libssh2_sftp.h)
Version 0.2
-----------
Changed extended data ignorance mechanism:
libssh2_channel_ignore_extended_data() changed to libssh2_channel_handle_extended_data()
Macro introduced for backward compatability during beta phase.
*** THE LIBSSH2_CHANNEL_IGNORE_EXTENDED_DATA() MACRO WILL BE REMOVED PRIOR TO 1.0 RELEASE ***
libssh2_channel_handle_extended_data() may be passed one of three "ignore_mode" constants
LIBSSH2_CHANNEL_EXTENDED_DATA_NONE Default behavior, queue ED packets and return them with read_ex
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE Equivalent to libssh2_channel_ignore_extended_data()
IGNORE will implicitly flush the extended data stream(s)
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE Calls to channel_read() will check both the standard data stream
and the extended data stream(s) for the first available packet
Changed libssh2_session_disconnect_ex() to return an error code when alloc fails
Added libssh2_channel_flush_ex() and basic macros: ..._flush() ..._flush_stderr()
flush_ex accepts either the streamid (0 for standard data, 1 for stderr) or one of the two following constants:
LIBSSH2_CHANNEL_FLUSH_ALL Flush all streams
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA Flush all streams EXCEPT the standard data stream
Added libssh2_session_callback_set() for setting ignore/debug/disconnect/macerror callbacks
Added libssh2_session_method_pref() to selectively set methods and method preferences.
Added libssh2_session_methods() to determine what methods were negotiated.
Added libssh2_session_abstract() for retreiving &session->abstract
Added libssh2_session_last_error() for retreiving error codes/messages
Version 0.1
-----------
Initial Release: Initial Release:
KEX methods: diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1 KEX methods: diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1

4
TODO Normal file
View File

@@ -0,0 +1,4 @@
* More Crypt Methods
* hmac-md5, hmac-md5-96
* SFTP support
* Review callbacks

1415
config.guess vendored

File diff suppressed because it is too large Load Diff

1510
config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,13 @@
# AC_PREREQ(2.57) # AC_PREREQ(2.57)
AC_INIT(libssh2,0.11,sarag@libssh2.org) AC_INIT(libssh2, 0.1 , pollita@php.net)
AC_CONFIG_SRCDIR([src]) AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([include/libssh2_config.h]) AC_CONFIG_HEADER([include/libssh2_config.h])
# Check for the OS. SHLIB_SUFFIX_NAME="so"
AC_CANONICAL_HOST SHLIB_LDFLAGS="-shared"
case "$host" in
*-cygwin)
SHLIB_SUFFIX_NAME="dll"
SHLIB_LDFLAGS="-shared"
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
;;
*darwin*)
SHLIB_SUFFIX_NAME="dylib"
SHLIB_LDFLAGS="-dynamiclib -flat_namespace"
CFLAGS="$CFLAGS -DLIBSSH2_DARWIN"
;;
*)
SHLIB_SUFFIX_NAME="so"
SHLIB_LDFLAGS="-shared"
;;
esac
AC_CHECK_LIB(socket, socket, [
SHLIB_LDFLAGS="$SHLIB_LDFLAGS -lsocket"
LIBS="$LIBS -lsocket"
])
AC_CHECK_LIB(m, ceil, [ SHLIB_LDFLAGS="$SHLIB_LDFLAGS -lm" ])
AC_SUBST(SHLIB_SUFFIX_NAME) AC_SUBST(SHLIB_SUFFIX_NAME)
AC_SUBST(SHLIB_LDFLAGS) AC_SUBST(SHLIB_LDFLAGS)
AC_SUBST(LIBS)
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
@@ -162,55 +138,9 @@ AC_ARG_ENABLE(mac-none,
AC_HELP_STRING([--enable-mac-none],[Permit "none" MAC -- NOT RECOMMENDED]), AC_HELP_STRING([--enable-mac-none],[Permit "none" MAC -- NOT RECOMMENDED]),
[AC_DEFINE(LIBSSH2_MAC_NONE, 1, [Enable "none" MAC -- NOT RECOMMENDED])]) [AC_DEFINE(LIBSSH2_MAC_NONE, 1, [Enable "none" MAC -- NOT RECOMMENDED])])
AC_ARG_ENABLE(gex-new,
AC_HELP_STRING([--disable-gex-new],[Disable "new" diffie-hellman-group-exchange-sha1 method]),
[GEX_NEW=$enableval])
if test "$GEX_NEW" != "no"; then
AC_DEFINE(LIBSSH2_DH_GEX_NEW, 1, [Enable newer diffie-hellman-group-exchange-sha1 syntax])
fi
#
# Optional debugging -- Meant for developer maintenance only
# When enabled, the relevant debugging information will be written on stderr
#
AC_ARG_ENABLE(debug-transport,
AC_HELP_STRING([--enable-debug-transport],[Output transport layer debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_TRANSPORT, 1, [Output transport layer debugging info to stderr])])
AC_ARG_ENABLE(debug-kex,
AC_HELP_STRING([--enable-debug-kex],[Output Key Exchange debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_KEX, 1, [Output Key Exchange debugging info to stderr])])
AC_ARG_ENABLE(debug-userauth,
AC_HELP_STRING([--enable-debug-userauth],[Output userauth debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_USERAUTH, 1, [Output userauth layer debugging info to stderr])])
AC_ARG_ENABLE(debug-channel,
AC_HELP_STRING([--enable-debug-connection],[Output connection layer debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_CONNECTION, 1, [Output connection layer debugging info to stderr])])
AC_ARG_ENABLE(debug-scp,
AC_HELP_STRING([--enable-debug-scp],[Output scp subsystem debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_SCP, 1, [Output scp subsystem debugging info to stderr])])
AC_ARG_ENABLE(debug-sftp,
AC_HELP_STRING([--enable-debug-sftp],[Output sftp subsystem debugging info to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_SFTP, 1, [Output sftp subsystem debugging info to stderr])])
AC_ARG_ENABLE(debug-errors,
AC_HELP_STRING([--enable-debug-errors],[Output failure events to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_ERRORS, 1, [Output failure events to stderr])])
AC_ARG_ENABLE(debug-all,
AC_HELP_STRING([--enable-debug-all],[Output debugging info for all layers to stderr]),
[
AC_DEFINE(LIBSSH2_DEBUG_TRANSPORT, 1, [Output transport layer debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_KEX, 1, [Output Key Exchange debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_USERAUTH, 1, [Output userauth layer debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_CONNECTION, 1, [Output connection layer debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_SCP, 1, [Output scp subsystem debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_SFTP, 1, [Output sftp subsystem debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_ERRORS, 1, [Output failure events to stderr])
])
# Checks for header files. # Checks for header files.
# AC_HEADER_STDC # AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h sys/select.h]) AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h])
AC_CHECK_FUNCS(poll gettimeofday select)
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST AC_C_CONST

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -38,41 +38,11 @@
#ifndef LIBSSH2_H #ifndef LIBSSH2_H
#define LIBSSH2_H 1 #define LIBSSH2_H 1
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
/* Allow alternate API prefix from CFLAGS or calling app */ #define LIBSSH2_VERSION "0.1dev"
#ifndef LIBSSH2_API
# ifdef LIBSSH2_WIN32
# ifdef LIBSSH2_LIBRARY
# define LIBSSH2_API __declspec(dllexport)
# else
# define LIBSSH2_API __declspec(dllimport)
# endif /* LIBSSH2_LIBRARY */
# else /* !LIBSSH2_WIN32 */
# define LIBSSH2_API
# endif /* LIBSSH2_WIN32 */
#endif /* LIBSSH2_API */
#if defined(LIBSSH2_DARWIN) || (defined(LIBSSH2_WIN32) && !defined(_MSC_VER))
# include <sys/uio.h>
#endif
#if defined(LIBSSH2_WIN32) && _MSC_VER < 1300
typedef unsigned __int64 libssh2_uint64_t;
typedef __int64 libssh2_int64_t;
#else
typedef unsigned long long libssh2_uint64_t;
typedef long long libssh2_int64_t;
#endif
#define LIBSSH2_VERSION "0.11"
#define LIBSSH2_APINO 200507041839
/* Part of every banner, user specified or not */ /* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -81,6 +51,9 @@ typedef long long libssh2_int64_t;
#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER #define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER
#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n" #define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
/* Enable the "new" version of diffie-hellman-group-exchange-sha1 */
#define LIBSSH2_DH_GEX_NEW
/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */ /* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */
#define LIBSSH2_DH_GEX_MINGROUP 1024 #define LIBSSH2_DH_GEX_MINGROUP 1024
#define LIBSSH2_DH_GEX_OPTGROUP 1536 #define LIBSSH2_DH_GEX_OPTGROUP 1536
@@ -98,105 +71,32 @@ typedef long long libssh2_int64_t;
#define LIBSSH2_SOCKET_POLL_MAXLOOPS 120 #define LIBSSH2_SOCKET_POLL_MAXLOOPS 120
/* Maximum size to allow a payload to compress to, plays it safe by falling short of spec limits */ /* Maximum size to allow a payload to compress to, plays it safe by falling short of spec limits */
#define LIBSSH2_PACKET_MAXCOMP 32000 #define LIBSSH2_PACKET_MAXCOMP 32000
/* Maximum size to allow a payload to deccompress to, plays it safe by allowing more than spec requires */ /* Maximum size to allow a payload to deccompress to, plays it safe by allowing more than spec requires */
#define LIBSSH2_PACKET_MAXDECOMP 40000 #define LIBSSH2_PACKET_MAXDECOMP 40000
/* Maximum size for an inbound compressed payload, plays it safe by overshooting spec limits */
#define LIBSSH2_PACKET_MAXPAYLOAD 40000
/* Malloc callbacks */ /* Malloc callbacks */
#define LIBSSH2_ALLOC_FUNC(name) void *name(size_t count, void **abstract) #define LIBSSH2_ALLOC_FUNC(name) void *name(size_t count, void **abstract)
#define LIBSSH2_REALLOC_FUNC(name) void *name(void *ptr, size_t count, void **abstract) #define LIBSSH2_REALLOC_FUNC(name) void *name(void *ptr, size_t count, void **abstract)
#define LIBSSH2_FREE_FUNC(name) void name(void *ptr, void **abstract) #define LIBSSH2_FREE_FUNC(name) void name(void *ptr, void **abstract)
typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT
{
char* text;
unsigned int length;
unsigned char echo;
} LIBSSH2_USERAUTH_KBDINT_PROMPT;
typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
{
char* text;
unsigned int length;
} LIBSSH2_USERAUTH_KBDINT_RESPONSE;
/* 'keyboard-interactive' authentication callback */
#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) void name_(const char* name, int name_len, const char* instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract)
/* Callbacks for special SSH packets */ /* Callbacks for special SSH packets */
#define LIBSSH2_IGNORE_FUNC(name) void name(LIBSSH2_SESSION *session, const char *message, int message_len, void **abstract) #define LIBSSH2_IGNORE_FUNC(name) void name(LIBSSH2_SESSION *session, const char *message, int message_len, void **abstract)
#define LIBSSH2_DEBUG_FUNC(name) void name(LIBSSH2_SESSION *session, int always_display, const char *message, int message_len, const char *language, int language_len,void **abstract) #define LIBSSH2_DEBUG_FUNC(name) void name(LIBSSH2_SESSION *session, int always_display, const char *message, int message_len, const char *language, int language_len,void **abstract)
#define LIBSSH2_DISCONNECT_FUNC(name) void name(LIBSSH2_SESSION *session, int reason, const char *message, int message_len, const char *language, int language_len, void **abstract) #define LIBSSH2_DISCONNECT_FUNC(name) void name(LIBSSH2_SESSION *session, int reason, const char *message, int message_len, const char *language, int language_len, void **abstract)
#define LIBSSH2_PASSWD_CHANGEREQ_FUNC(name) void name(LIBSSH2_SESSION *session, char **newpw, int *newpw_len, void **abstract) #define LIBSSH2_PASSWD_CHANGEREQ_FUNC(name) void name(LIBSSH2_SESSION *session, char **newpw, int *newpw_len, void **abstract)
#define LIBSSH2_MACERROR_FUNC(name) int name(LIBSSH2_SESSION *session, const char *packet, int packet_len, void **abstract) #define LIBSSH2_MACERROR_FUNC(name) int name(LIBSSH2_SESSION *session, const char *packet, int packet_len, void **abstract)
#define LIBSSH2_X11_OPEN_FUNC(name) void name(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, char *shost, int sport, void **abstract)
#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) void name(LIBSSH2_SESSION *session, void **session_abstract, LIBSSH2_CHANNEL *channel, void **channel_abstract)
/* libssh2_session_callback_set() constants */
#define LIBSSH2_CALLBACK_IGNORE 0
#define LIBSSH2_CALLBACK_DEBUG 1
#define LIBSSH2_CALLBACK_DISCONNECT 2
#define LIBSSH2_CALLBACK_MACERROR 3
#define LIBSSH2_CALLBACK_X11 4
/* libssh2_session_method_pref() constants */
#define LIBSSH2_METHOD_KEX 0
#define LIBSSH2_METHOD_HOSTKEY 1
#define LIBSSH2_METHOD_CRYPT_CS 2
#define LIBSSH2_METHOD_CRYPT_SC 3
#define LIBSSH2_METHOD_MAC_CS 4
#define LIBSSH2_METHOD_MAC_SC 5
#define LIBSSH2_METHOD_COMP_CS 6
#define LIBSSH2_METHOD_COMP_SC 7
#define LIBSSH2_METHOD_LANG_CS 8
#define LIBSSH2_METHOD_LANG_SC 9
/* session.flags bits */
#define LIBSSH2_FLAG_SIGPIPE 0x00000001
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL; typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
typedef struct _LIBSSH2_POLLFD { #ifdef WIN_32
unsigned char type; /* LIBSSH2_POLLFD_* below */ #define LIBSSH2_API __declspec(dllexport)
#else
#define LIBSSH2_API
#endif
union {
int socket; /* File descriptors -- examined with system select() call */
LIBSSH2_CHANNEL *channel; /* Examined by checking internal state */
LIBSSH2_LISTENER *listener; /* Read polls only -- are inbound connections waiting to be accepted? */
} fd;
unsigned long events; /* Requested Events */
unsigned long revents; /* Returned Events */
} LIBSSH2_POLLFD;
/* Poll FD Descriptor Types */
#define LIBSSH2_POLLFD_SOCKET 1
#define LIBSSH2_POLLFD_CHANNEL 2
#define LIBSSH2_POLLFD_LISTENER 3
/* Note: Win32 Doesn't actually have a poll() implementation, so some of these values are faked with select() data */
/* Poll FD events/revents -- Match sys/poll.h where possible */
#define LIBSSH2_POLLFD_POLLIN 0x0001 /* Data available to be read or connection available -- All */
#define LIBSSH2_POLLFD_POLLPRI 0x0002 /* Priority data available to be read -- Socket only */
#define LIBSSH2_POLLFD_POLLEXT 0x0002 /* Extended data available to be read -- Channel only */
#define LIBSSH2_POLLFD_POLLOUT 0x0004 /* Can may be written -- Socket/Channel */
/* revents only */
#define LIBSSH2_POLLFD_POLLERR 0x0008 /* Error Condition -- Socket */
#define LIBSSH2_POLLFD_POLLHUP 0x0010 /* HangUp/EOF -- Socket */
#define LIBSSH2_POLLFD_SESSION_CLOSED 0x0010 /* Session Disconnect */
#define LIBSSH2_POLLFD_POLLNVAL 0x0020 /* Invalid request -- Socket Only */
#define LIBSSH2_POLLFD_POLLEX 0x0040 /* Exception Condition -- Socket/Win32 */
#define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel Disconnect */
#define LIBSSH2_POLLFD_LISTENER_CLOSED 0x0080 /* Listener Disconnect */
/* Hash Types */
#define LIBSSH2_HOSTKEY_HASH_MD5 1 #define LIBSSH2_HOSTKEY_HASH_MD5 1
#define LIBSSH2_HOSTKEY_HASH_SHA1 2 #define LIBSSH2_HOSTKEY_HASH_SHA1 2
@@ -248,152 +148,70 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_SCP_PROTOCOL -28 #define LIBSSH2_ERROR_SCP_PROTOCOL -28
#define LIBSSH2_ERROR_ZLIB -29 #define LIBSSH2_ERROR_ZLIB -29
#define LIBSSH2_ERROR_SOCKET_TIMEOUT -30 #define LIBSSH2_ERROR_SOCKET_TIMEOUT -30
#define LIBSSH2_ERROR_SFTP_PROTOCOL -31
#define LIBSSH2_ERROR_REQUEST_DENIED -32
#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED -33
#define LIBSSH2_ERROR_INVAL -34
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
/* Session API */ /* Session API */
LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract); LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract);
#define libssh2_session_init() libssh2_session_init_ex(NULL, NULL, NULL, NULL) #define libssh2_session_init() libssh2_session_init_ex(NULL, NULL, NULL, NULL)
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session);
LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner);
LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket); LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket);
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang); LIBSSH2_API void libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang);
#define libssh2_session_disconnect(session, description) libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, (description), "") #define libssh2_session_disconnect(session, description) libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, (description), "")
LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session); LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session);
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type); LIBSSH2_API char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type);
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, const char *prefs);
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_flag(LIBSSH2_SESSION *session, int flag, int value);
/* Userauth API */ /* Userauth API */
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, int username_len); LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len);
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session); LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, int username_len, const char *password, int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))); LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, char *username, int username_len, char *password, int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)));
#define libssh2_userauth_password(session, username, password) libssh2_userauth_password_ex((session), (username), strlen(username), (password), strlen(password), NULL) #define libssh2_userauth_password(session, username, password) libssh2_userauth_password_ex((session), (username), strlen(username), (password), strlen(password), NULL)
LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, const char *username, int username_len, LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, char *username, int username_len,
const char *publickey, const char *privatekey, char *publickey, char *privatekey,
const char *passphrase); char *passphrase);
#define libssh2_userauth_publickey_fromfile(session, username, publickey, privatekey, passphrase) \ #define libssh2_userauth_publickey_fromfile(session, username, publickey, privatekey, passphrase) \
libssh2_userauth_publickey_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase)) libssh2_userauth_publickey_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase))
LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session, const char *username, int username_len,
const char *publickey, const char *privatekey,
const char *passphrase,
const char *hostname, int hostname_len,
const char *local_username, int local_username_len);
#define libssh2_userauth_hostbased_fromfile(session, username, publickey, privatekey, passphrase, hostname) \
libssh2_userauth_hostbased_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase), (hostname), strlen(hostname), (username), strlen(username))
/*
* response_callback is provided with filled by library prompts array,
* but client must allocate and fill individual responses. Responses
* array is already allocated. Responses data will be freed by libssh2
* after callback return, but before subsequent callback invokation.
*/
LIBSSH2_API int libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION* session, const char *username, int username_len,
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)));
#define libssh2_userauth_keyboard_interactive(session, username, response_callback) \
libssh2_userauth_keyboard_interactive_ex((session), (username), strlen(username), (response_callback))
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
/* Channel API */ /* Channel API */
#define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536 #define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536
#define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384 #define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384
#define LIBSSH2_CHANNEL_MINADJUST 1024
/* Extended Data Handling */ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, char *channel_type, int channel_type_len, int window_size, int packet_size, char *message, int message_len);
#define LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL 0
#define LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE 1
#define LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE 2
#define SSH_EXTENDED_DATA_STDERR 1
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *channel_type, int channel_type_len, int window_size, int packet_size, const char *message, int message_len);
#define libssh2_channel_open_session(session) libssh2_channel_open_ex((session), "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0) #define libssh2_channel_open_session(session) libssh2_channel_open_ex((session), "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0)
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, char *host, int port, char *shost, int sport); LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, char *host, int port, char *shost, int sport);
#define libssh2_channel_direct_tcpip(session, host, port) libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22) #define libssh2_channel_direct_tcpip(session, host, port) libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22)
LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize);
#define libssh2_channel_forward_listen(session, port) libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16)
LIBSSH2_API int libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener);
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener);
LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varname, int varname_len, char *value, int value_len); LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varname, int varname_len, char *value, int value_len);
#define libssh2_channel_setenv(channel, varname, value) libssh2_channel_setenv_ex((channel), (varname), strlen(varname), (value), strlen(value)) #define libssh2_channel_setenv(channel, varname, value) libssh2_channel_setenv_ex((channel), (varname), strlen(varname), (value), strlen(value))
LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *term, int term_len, char *modes, int modes_len, int width, int height, int width_px, int height_px); LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *term, int term_len, char *modes, int modes_len, int width, int height, int width_px, int height_px);
#define libssh2_channel_request_pty(channel, term) libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX) #define libssh2_channel_request_pty(channel, term) libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX)
LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, char *auth_proto, char *auth_cookie, int screen_number); LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, char *request, int request_len, char *message, int message_len);
#define libssh2_channel_x11_req(channel, screen_number) libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number))
LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, const char *request, int request_len, const char *message, int message_len);
#define libssh2_channel_shell(channel) libssh2_channel_process_startup((channel), "shell", sizeof("shell") - 1, NULL, 0) #define libssh2_channel_shell(channel) libssh2_channel_process_startup((channel), "shell", sizeof("shell") - 1, NULL, 0)
#define libssh2_channel_exec(channel, command) libssh2_channel_process_startup((channel), "exec", sizeof("exec") - 1, (command), strlen(command)) #define libssh2_channel_exec(channel, command) libssh2_channel_process_startup((channel), "exec", sizeof("exec") - 1, (command), strlen(command))
#define libssh2_channel_subsystem(channel, subsystem) libssh2_channel_process_startup((channel), "subsystem", sizeof("subsystem") - 1, (subsystem), strlen(subsystem)) #define libssh2_channel_subsystem(channel, subsystem) libssh2_channel_process_startup((channel), "subsystem", sizeof("subsystem") - 1, (subsystem), strlen(subsystem))
#define SSH_EXTENDED_DATA_STDERR 1
LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen); LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen);
#define libssh2_channel_read(channel, buf, buflen) libssh2_channel_read_ex((channel), 0, (buf), (buflen)) #define libssh2_channel_read(channel, buf, buflen) libssh2_channel_read_ex((channel), 0, (buf), (buflen))
#define libssh2_channel_read_stderr(channel, buf, buflen) libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) #define libssh2_channel_read_stderr(channel, buf, buflen) libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended);
LIBSSH2_API unsigned long libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, unsigned long *read_avail, unsigned long *window_size_initial);
#define libssh2_channel_window_read(channel) libssh2_channel_window_read_ex((channel), NULL, NULL)
LIBSSH2_API unsigned long libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, unsigned long adjustment, unsigned char force);
LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen); LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen);
#define libssh2_channel_write(channel, buf, buflen) libssh2_channel_write_ex((channel), 0, (buf), (buflen)) #define libssh2_channel_write(channel, buf, buflen) libssh2_channel_write_ex((channel), 0, (buf), (buflen))
#define libssh2_channel_write_stderr(channel, buf, buflen) libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) #define libssh2_channel_write_stderr(channel, buf, buflen) libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
LIBSSH2_API unsigned long libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, unsigned long *window_size_initial);
#define libssh2_channel_window_write(channel) libssh2_channel_window_write_ex((channel), NULL)
LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking); LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking);
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
/* libssh2_channel_ignore_extended_data() is defined below for BC with version 0.1
* Future uses should use libssh2_channel_handle_extended_data() directly
* if LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read (FIFO) from the standard data channel
*/
/* DEPRECATED */
#define libssh2_channel_ignore_extended_data(channel, ignore) libssh2_channel_handle_extended_data((channel), (ignore) ? LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL )
#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1
#define LIBSSH2_CHANNEL_FLUSH_ALL -2
LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid);
#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0)
#define libssh2_channel_flush_stderr(channel) libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel);
LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel);
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb); LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, char *path, struct stat *sb);
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime); LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char *path, int mode, size_t size, long mtime, long atime);
#define libssh2_scp_send(session, path, mode, size) libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0) #define libssh2_scp_send(session, path, mode, size) libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0)
LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest, int *dest_len, char *src, int src_len); LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest, int *dest_len, char *src, int src_len);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LIBSSH2_H */ #endif /* LIBSSH2_H */

View File

@@ -6,21 +6,12 @@
/* Define to 1 if you have the <fcntl.h> header file. */ /* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H #undef HAVE_FCNTL_H
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H #undef HAVE_MEMORY_H
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H #undef HAVE_STDINT_H
@@ -36,48 +27,18 @@
/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H #undef HAVE_STRING_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/stat.h> header file. */ /* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H #undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H #undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
/* Enable "none" cipher -- NOT RECOMMENDED */ /* Enable "none" cipher -- NOT RECOMMENDED */
#undef LIBSSH2_CRYPT_NONE #undef LIBSSH2_CRYPT_NONE
/* Output connection layer debugging info to stderr */
#undef LIBSSH2_DEBUG_CONNECTION
/* Output failure events to stderr */
#undef LIBSSH2_DEBUG_ERRORS
/* Output Key Exchange debugging info to stderr */
#undef LIBSSH2_DEBUG_KEX
/* Output scp subsystem debugging info to stderr */
#undef LIBSSH2_DEBUG_SCP
/* Output sftp subsystem debugging info to stderr */
#undef LIBSSH2_DEBUG_SFTP
/* Output transport layer debugging info to stderr */
#undef LIBSSH2_DEBUG_TRANSPORT
/* Output userauth layer debugging info to stderr */
#undef LIBSSH2_DEBUG_USERAUTH
/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
#undef LIBSSH2_DH_GEX_NEW
/* Compile in zlib support */ /* Compile in zlib support */
#undef LIBSSH2_HAVE_ZLIB #undef LIBSSH2_HAVE_ZLIB

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -38,13 +38,11 @@
#ifndef LIBSSH2_PRIV_H #ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1 #define LIBSSH2_PRIV_H 1
#define LIBSSH2_LIBRARY /* Definitions shared with the public */
#include "libssh2_config.h" #include "libssh2_config.h"
#include "libssh2.h" #include "libssh2.h"
#ifndef WIN32
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <openssl/evp.h> #include <openssl/evp.h>
#define LIBSSH2_ALLOC(session, count) session->alloc((count), &(session)->abstract) #define LIBSSH2_ALLOC(session, count) session->alloc((count), &(session)->abstract)
@@ -57,10 +55,7 @@
#define LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len) \ #define LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len) \
session->ssh_msg_disconnect((session), (reason), (message), (message_len), (language), (language_len), &(session)->abstract) session->ssh_msg_disconnect((session), (reason), (message), (message_len), (language), (language_len), &(session)->abstract)
#define LIBSSH2_MACERROR(session, data, datalen) session->macerror((session), (data), (datalen), &(session)->abstract) #define LIBSSH2_MACERROR(session, data, datalen) session->macerror((session), (data), (datalen), (session)->abstract)
#define LIBSSH2_X11_OPEN(channel, shost, sport) channel->session->x11(((channel)->session), (channel), (shost), (sport), (&(channel)->session->abstract))
#define LIBSSH2_CHANNEL_CLOSE(session, channel) channel->close_cb((session), &(session)->abstract, (channel), &(channel)->abstract)
typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD; typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD; typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
@@ -103,7 +98,7 @@ typedef struct _libssh2_channel_data {
unsigned long window_size_initial, window_size, packet_size; unsigned long window_size_initial, window_size, packet_size;
/* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */ /* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */
char close, eof, extended_data_ignore_mode; int close, eof;
} libssh2_channel_data; } libssh2_channel_data;
struct _LIBSSH2_CHANNEL { struct _LIBSSH2_CHANNEL {
@@ -112,37 +107,17 @@ struct _LIBSSH2_CHANNEL {
int blocking; int blocking;
/* channel's program exit status */
int exit_status;
libssh2_channel_data local, remote; libssh2_channel_data local, remote;
unsigned long adjust_queue; /* Amount of bytes to be refunded to receive window (but not yet sent) */
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *next, *prev; LIBSSH2_CHANNEL *next, *prev;
void *abstract;
LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
}; };
struct _LIBSSH2_CHANNEL_BRIGADE { struct _LIBSSH2_CHANNEL_BRIGADE {
LIBSSH2_CHANNEL *head, *tail; LIBSSH2_CHANNEL *head, *tail;
}; };
struct _LIBSSH2_LISTENER {
LIBSSH2_SESSION *session;
char *host;
int port;
LIBSSH2_CHANNEL *queue;
int queue_size;
int queue_maxsize;
LIBSSH2_LISTENER *prev, *next;
};
typedef struct _libssh2_endpoint_data { typedef struct _libssh2_endpoint_data {
unsigned char *banner; unsigned char *banner;
@@ -160,10 +135,9 @@ typedef struct _libssh2_endpoint_data {
void *comp_abstract; void *comp_abstract;
/* Method Preferences -- NULL yields "load order" */ /* Method Preferences -- NULL yields "load order" */
char *crypt_prefs; LIBSSH2_CRYPT_METHOD **crypt_prefs;
char *mac_prefs; LIBSSH2_MAC_METHOD **mac_prefs;
char *comp_prefs; LIBSSH2_COMP_METHOD **comp_prefs;
char *lang_prefs;
} libssh2_endpoint_data; } libssh2_endpoint_data;
struct _LIBSSH2_SESSION { struct _LIBSSH2_SESSION {
@@ -178,14 +152,14 @@ struct _LIBSSH2_SESSION {
LIBSSH2_DEBUG_FUNC((*ssh_msg_debug)); LIBSSH2_DEBUG_FUNC((*ssh_msg_debug));
LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect)); LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect));
LIBSSH2_MACERROR_FUNC((*macerror)); LIBSSH2_MACERROR_FUNC((*macerror));
LIBSSH2_X11_OPEN_FUNC((*x11));
/* Method preferences -- NULL yields "load order" */ /* Method preferences -- NULL yields "load order" */
char *kex_prefs; LIBSSH2_KEX_METHOD **kex_prefs;
char *hostkey_prefs; LIBSSH2_HOSTKEY_METHOD **hostkey_prefs;
int state; int exchanging_keys;
int flags; int newkeys;
int authenticated;
/* Agreed Key Exchange Method */ /* Agreed Key Exchange Method */
LIBSSH2_KEX_METHOD *kex; LIBSSH2_KEX_METHOD *kex;
@@ -222,8 +196,6 @@ struct _LIBSSH2_SESSION {
LIBSSH2_CHANNEL_BRIGADE channels; LIBSSH2_CHANNEL_BRIGADE channels;
unsigned long next_channel; unsigned long next_channel;
LIBSSH2_LISTENER *listeners;
/* Actual I/O socket */ /* Actual I/O socket */
int socket_fd; int socket_fd;
int socket_block; int socket_block;
@@ -236,26 +208,14 @@ struct _LIBSSH2_SESSION {
int err_code; int err_code;
}; };
/* session.state bits */
#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
#define LIBSSH2_STATE_NEWKEYS 0x00000002
#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
/* session.flag helpers */
#ifdef MSG_NOSIGNAL
#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
#else
/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0
#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
#endif
/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */ /* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
struct _LIBSSH2_KEX_METHOD { struct _LIBSSH2_KEX_METHOD {
char *name; char *name;
/* integrity key length */
unsigned long key_len;
/* Key exchange, populates session->* and returns 0 on success, non-0 on error */ /* Key exchange, populates session->* and returns 0 on success, non-0 on error */
int (*exchange_keys)(LIBSSH2_SESSION *session); int (*exchange_keys)(LIBSSH2_SESSION *session);
@@ -267,7 +227,7 @@ struct _LIBSSH2_HOSTKEY_METHOD {
unsigned long hash_len; unsigned long hash_len;
int (*init)(LIBSSH2_SESSION *session, unsigned char *hostkey_data, unsigned long hostkey_data_len, void **abstract); int (*init)(LIBSSH2_SESSION *session, unsigned char *hostkey_data, unsigned long hostkey_data_len, void **abstract);
int (*initPEM)(LIBSSH2_SESSION *session, unsigned const char *privkeyfile, unsigned const char *passphrase, void **abstract); int (*initPEM)(LIBSSH2_SESSION *session, unsigned char *privkeyfile, unsigned char *passphrase, void **abstract);
int (*sig_verify)(LIBSSH2_SESSION *session, const unsigned char *sig, unsigned long sig_len, const unsigned char *m, unsigned long m_len, void **abstract); int (*sig_verify)(LIBSSH2_SESSION *session, const unsigned char *sig, unsigned long sig_len, const unsigned char *m, unsigned long m_len, void **abstract);
int (*sign)(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, const unsigned char *data, unsigned long data_len, void **abstract); int (*sign)(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, const unsigned char *data, unsigned long data_len, void **abstract);
int (*signv)(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, unsigned long veccount, const struct iovec datavec[], void **abstract); int (*signv)(LIBSSH2_SESSION *session, unsigned char **signature, unsigned long *signature_len, unsigned long veccount, const struct iovec datavec[], void **abstract);
@@ -312,46 +272,12 @@ struct _LIBSSH2_MAC_METHOD {
/* The length of a given MAC packet */ /* The length of a given MAC packet */
int mac_len; int mac_len;
/* integrity key length */
int key_len;
/* Message Authentication Code Hashing algo */ /* Message Authentication Code Hashing algo */
int (*init)(LIBSSH2_SESSION *session, unsigned char *key, int *free_key, void **abstract); int (*init)(LIBSSH2_SESSION *session, unsigned char *key, int *free_key, void **abstract);
int (*hash)(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, const unsigned char *packet, unsigned long packet_len, const unsigned char *addtl, unsigned long addtl_len, void **abstract); int (*hash)(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, const unsigned char *packet, unsigned long packet_len, const unsigned char *addtl, unsigned long addtl_len, void **abstract);
int (*dtor)(LIBSSH2_SESSION *session, void **abstract); int (*dtor)(LIBSSH2_SESSION *session, void **abstract);
}; };
#if defined(LIBSSH2_DEBUG_TRANSPORT) || defined(LIBSSH2_DEBUG_KEX) || defined(LIBSSH2_DEBUG_USERAUTH) || defined(LIBSSH2_DEBUG_CONNECTION) || defined(LIBSSH2_DEBUG_SCP) || defined(LIBSSH2_DEBUG_SFTP) || defined(LIBSSH2_DEBUG_ERRORS)
#define LIBSSH2_DEBUG_ENABLED
/* Internal debugging contexts -- Used with --enable-debug-* */
#define LIBSSH2_DBG_TRANS 1
#define LIBSSH2_DBG_KEX 2
#define LIBSSH2_DBG_AUTH 3
#define LIBSSH2_DBG_CONN 4
#define LIBSSH2_DBG_SCP 5
#define LIBSSH2_DBG_SFTP 6
#define LIBSSH2_DBG_ERROR 7
void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, ...);
#endif /* LIBSSH2_DEBUG_ENABLED */
#ifdef LIBSSH2_DEBUG_ERRORS
#define libssh2_error(session, errcode, errmsg, should_free) \
{ \
if (session->err_msg && session->err_should_free) { \
LIBSSH2_FREE(session, session->err_msg); \
} \
session->err_msg = errmsg; \
session->err_msglen = strlen(errmsg); \
session->err_should_free = should_free; \
session->err_code = errcode; \
_libssh2_debug(session, LIBSSH2_DBG_ERROR, "%d - %s", session->err_code, session->err_msg); \
}
#else /* ! LIBSSH2_DEBUG_ERRORS */
#define libssh2_error(session, errcode, errmsg, should_free) \ #define libssh2_error(session, errcode, errmsg, should_free) \
{ \ { \
if (session->err_msg && session->err_should_free) { \ if (session->err_msg && session->err_should_free) { \
@@ -363,9 +289,6 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, .
session->err_code = errcode; \ session->err_code = errcode; \
} }
#endif /* LIBSSH2_DEBUG_ENABLED */
#define LIBSSH2_SOCKET_UNKNOWN 1 #define LIBSSH2_SOCKET_UNKNOWN 1
#define LIBSSH2_SOCKET_CONNECTED 0 #define LIBSSH2_SOCKET_CONNECTED 0
#define LIBSSH2_SOCKET_DISCONNECTED -1 #define LIBSSH2_SOCKET_DISCONNECTED -1
@@ -410,9 +333,6 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, .
#define SSH_MSG_USERAUTH_PK_OK 60 #define SSH_MSG_USERAUTH_PK_OK 60
/* "password" method */ /* "password" method */
#define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60
/* "keyboard-interactive" method */
#define SSH_MSG_USERAUTH_INFO_REQUEST 60
#define SSH_MSG_USERAUTH_INFO_RESPONSE 61
/* Channels */ /* Channels */
#define SSH_MSG_GLOBAL_REQUEST 80 #define SSH_MSG_GLOBAL_REQUEST 80
@@ -434,26 +354,17 @@ void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, .
void libssh2_session_shutdown(LIBSSH2_SESSION *session); void libssh2_session_shutdown(LIBSSH2_SESSION *session);
unsigned long libssh2_ntohu32(const unsigned char *buf); unsigned long libssh2_ntohu32(const unsigned char *buf);
libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf);
void libssh2_htonu32(unsigned char *buf, unsigned long val); void libssh2_htonu32(unsigned char *buf, unsigned long val);
void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t val);
int libssh2_packet_read(LIBSSH2_SESSION *session, int block); int libssh2_packet_read(LIBSSH2_SESSION *session, int block);
int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket); int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket);
#define libssh2_packet_ask(session, packet_type, data, data_len, poll_socket) \ #define libssh2_packet_ask(session, packet_type, data, data_len, poll_socket) \
libssh2_packet_ask_ex((session), (packet_type), (data), (data_len), 0, NULL, 0, (poll_socket)) libssh2_packet_ask_ex((session), (packet_type), (data), (data_len), 0, NULL, 0, (poll_socket))
int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket);
#define libssh2_packet_askv(session, packet_types, data, data_len, poll_socket) \
libssh2_packet_askv_ex((session), (packet_types), (data), (data_len), 0, NULL, 0, (poll_socket))
int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len); int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len);
#define libssh2_packet_require(session, packet_type, data, data_len) \ #define libssh2_packet_require(session, packet_type, data, data_len) \
libssh2_packet_require_ex((session), (packet_type), (data), (data_len), 0, NULL, 0) libssh2_packet_require_ex((session), (packet_type), (data), (data_len), 0, NULL, 0)
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len);
#define libssh2_packet_requirev(session, packet_types, data, data_len) \
libssh2_packet_requirev_ex((session), (packet_types), (data), (data_len), 0, NULL, 0)
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len); int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len);
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange); int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange);
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session);
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id); LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id);
/* Let crypt.c/hostkey.c/comp.c/mac.c expose their method structs */ /* Let crypt.c/hostkey.c/comp.c/mac.c expose their method structs */

View File

@@ -1,190 +0,0 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_SFTP_H
#define LIBSSH2_SFTP_H 1
/* Note: Version 6 was documented at the time of writing
* However it was marked as "DO NOT IMPLEMENT" due to pending changes
*
* Let's start with Version 3 (The version found in OpenSSH) and go from there
*/
#define LIBSSH2_SFTP_VERSION 3
#define LIBSSH2_SFTP_PACKET_MAXLEN 40000
typedef struct _LIBSSH2_SFTP LIBSSH2_SFTP;
typedef struct _LIBSSH2_SFTP_HANDLE LIBSSH2_SFTP_HANDLE;
typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES;
/* Flags for open_ex() */
#define LIBSSH2_SFTP_OPENFILE 0
#define LIBSSH2_SFTP_OPENDIR 1
/* Flags for rename_ex() */
#define LIBSSH2_SFTP_RENAME_OVERWRITE 0x00000001
#define LIBSSH2_SFTP_RENAME_ATOMIC 0x00000002
#define LIBSSH2_SFTP_RENAME_NATIVE 0x00000004
/* Flags for stat_ex() */
#define LIBSSH2_SFTP_STAT 0
#define LIBSSH2_SFTP_LSTAT 1
#define LIBSSH2_SFTP_SETSTAT 2
/* Flags for symlink_ex() */
#define LIBSSH2_SFTP_SYMLINK 0
#define LIBSSH2_SFTP_READLINK 1
#define LIBSSH2_SFTP_REALPATH 2
/* SFTP attribute flag bits */
#define LIBSSH2_SFTP_ATTR_SIZE 0x00000001
#define LIBSSH2_SFTP_ATTR_UIDGID 0x00000002
#define LIBSSH2_SFTP_ATTR_PERMISSIONS 0x00000004
#define LIBSSH2_SFTP_ATTR_ACMODTIME 0x00000008
#define LIBSSH2_SFTP_ATTR_EXTENDED 0x80000000
struct _LIBSSH2_SFTP_ATTRIBUTES {
/* If flags & ATTR_* bit is set, then the value in this struct will be meaningful
* Otherwise it should be ignored
*/
unsigned long flags;
libssh2_uint64_t filesize;
unsigned long uid, gid;
unsigned long permissions;
unsigned long atime, mtime;
};
/* SFTP filetypes */
#define LIBSSH2_SFTP_TYPE_REGULAR 1
#define LIBSSH2_SFTP_TYPE_DIRECTORY 2
#define LIBSSH2_SFTP_TYPE_SYMLINK 3
#define LIBSSH2_SFTP_TYPE_SPECIAL 4
#define LIBSSH2_SFTP_TYPE_UNKNOWN 5
#define LIBSSH2_SFTP_TYPE_SOCKET 6
#define LIBSSH2_SFTP_TYPE_CHAR_DEVICE 7
#define LIBSSH2_SFTP_TYPE_BLOCK_DEVICE 8
#define LIBSSH2_SFTP_TYPE_FIFO 9
/* SFTP File Transfer Flags -- (e.g. flags parameter to sftp_open())
* Danger will robinson... APPEND doesn't have any effect on OpenSSH servers */
#define LIBSSH2_FXF_READ 0x00000001
#define LIBSSH2_FXF_WRITE 0x00000002
#define LIBSSH2_FXF_APPEND 0x00000004
#define LIBSSH2_FXF_CREAT 0x00000008
#define LIBSSH2_FXF_TRUNC 0x00000010
#define LIBSSH2_FXF_EXCL 0x00000020
/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
#define LIBSSH2_FX_OK 0
#define LIBSSH2_FX_EOF 1
#define LIBSSH2_FX_NO_SUCH_FILE 2
#define LIBSSH2_FX_PERMISSION_DENIED 3
#define LIBSSH2_FX_FAILURE 4
#define LIBSSH2_FX_BAD_MESSAGE 5
#define LIBSSH2_FX_NO_CONNECTION 6
#define LIBSSH2_FX_CONNECTION_LOST 7
#define LIBSSH2_FX_OP_UNSUPPORTED 8
#define LIBSSH2_FX_INVALID_HANDLE 9
#define LIBSSH2_FX_NO_SUCH_PATH 10
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11
#define LIBSSH2_FX_WRITE_PROTECT 12
#define LIBSSH2_FX_NO_MEDIA 13
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14
#define LIBSSH2_FX_QUOTA_EXCEEDED 15
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16
#define LIBSSH2_FX_LOCK_CONFlICT 17
#define LIBSSH2_FX_DIR_NOT_EMPTY 18
#define LIBSSH2_FX_NOT_A_DIRECTORY 19
#define LIBSSH2_FX_INVALID_FILENAME 20
#define LIBSSH2_FX_LINK_LOOP 21
/* SFTP API */
LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session);
LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp);
LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
/* File / Directory Ops */
LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, char *filename, int filename_len, unsigned long flags, long mode, int open_type);
#define libssh2_sftp_open(sftp, filename, flags, mode) libssh2_sftp_open_ex((sftp), (filename), strlen(filename), (flags), (mode), LIBSSH2_SFTP_OPENFILE)
#define libssh2_sftp_opendir(sftp, path) libssh2_sftp_open_ex((sftp), (path), strlen(path), 0, 0, LIBSSH2_SFTP_OPENDIR)
LIBSSH2_API size_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen);
LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
LIBSSH2_API size_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);
LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle)
#define libssh2_sftp_closedir(handle) libssh2_sftp_close_handle(handle)
LIBSSH2_API void libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset);
#define libssh2_sftp_rewind(handle) libssh2_sftp_seek((handle), 0)
LIBSSH2_API size_t libssh2_sftp_tell(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)
#define libssh2_sftp_fsetstat(handle, attrs) libssh2_sftp_fstat_ex((handle), (attrs), 1)
/* Miscellaneous Ops */
LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, char *source_filename, int srouce_filename_len,
char *dest_filename, int dest_filename_len,
long flags);
#define libssh2_sftp_rename(sftp, sourcefile, destfile) libssh2_sftp_rename_ex((sftp), (sourcefile), strlen(sourcefile), (destfile), strlen(destfile), \
LIBSSH2_SFTP_RENAME_OVERWRITE | LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE)
LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, char *filename, int filename_len);
#define libssh2_sftp_unlink(sftp, filename) libssh2_sftp_unlink_ex((sftp), (filename), strlen(filename))
LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_len, long mode);
#define libssh2_sftp_mkdir(sftp, path, mode) libssh2_sftp_mkdir_ex((sftp), (path), strlen(path), (mode))
LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_len);
#define libssh2_sftp_rmdir(sftp, path) libssh2_sftp_rmdir_ex((sftp), (path), strlen(path))
LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, char *path, int path_len, int stat_type, LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_stat(sftp, path, attrs) libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_STAT, (attrs))
#define libssh2_sftp_lstat(sftp, path, attrs) libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_LSTAT, (attrs))
#define libssh2_sftp_setstat(sftp, path, attrs) libssh2_sftp_stat_ex((sftp), (path), strlen(path), LIBSSH2_SFTP_SETSTAT, (attrs))
LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, int path_len, char *target, int target_len, int link_type);
#define libssh2_sftp_symlink(sftp, orig, linkpath) libssh2_sftp_symlink_ex((sftp), (orig), strlen(orig), (linkpath), strlen(linkpath), LIBSSH2_SFTP_SYMLINK)
#define libssh2_sftp_readlink(sftp, path, target, maxlen) libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), LIBSSH2_SFTP_READLINK)
#define libssh2_sftp_realpath(sftp, path, target, maxlen) libssh2_sftp_symlink_ex((sftp), (path), strlen(path), (target), (maxlen), LIBSSH2_SFTP_REALPATH)
#endif /* LIBSSH2_SFTP_H */

View File

@@ -4,7 +4,7 @@
# Created: 1993-05-16 # Created: 1993-05-16
# Public domain # Public domain
# $Id: mkinstalldirs,v 1.1 2004/12/07 21:17:20 sarag Exp $ # $Id: mkinstalldirs,v 1.1.1.1 2004/12/07 21:17:20 sarag Exp $
errstatus=0 errstatus=0

View File

@@ -1,9 +0,0 @@
*.lib
*.pdb
*.dll
*.exe
*.obj
.*.swp
Debug
Release
*.exp

View File

@@ -1,4 +1,4 @@
OBJECTS = channel.o comp.o crypt.o hostkey.o kex.o mac.o misc.o packet.o scp.o session.o sftp.o userauth.o OBJECTS = channel.o comp.o crypt.o hostkey.o kex.o mac.o misc.o packet.o scp.o session.o userauth.o
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
prefix = @prefix@ prefix = @prefix@
@@ -42,9 +42,6 @@ scp.o: scp.c
session.o: session.c session.o: session.c
$(CC) -o session.o session.c $(CFLAGS) $(LIBS) $(CC) -o session.o session.c $(CFLAGS) $(LIBS)
sftp.o: sftp.c
$(CC) -o sftp.o sftp.c $(CFLAGS) $(LIBS)
userauth.o: userauth.c userauth.o: userauth.c
$(CC) -o userauth.o userauth.c $(CFLAGS) $(LIBS) $(CC) -o userauth.o userauth.c $(CFLAGS) $(LIBS)
@@ -57,7 +54,7 @@ libssh2.a: $(OBJECTS)
ar q libssh2.a $(OBJECTS) ar q libssh2.a $(OBJECTS)
@RANLIB@ libssh2.a @RANLIB@ libssh2.a
install: all install: all
$(INSTALL) libssh2.@SHLIB_SUFFIX_NAME@ $(DESTDIR)$(libdir) $(INSTALL) libssh2.@SHLIB_SUFFIX_NAME@ $(libdir)
clean: clean:
rm -f *~ libssh2.a libssh2.@SHLIB_SUFFIX_NAME@ *.o rm -f *~ libssh2.a libssh2.@SHLIB_SUFFIX_NAME@ *.o

View File

@@ -1,18 +0,0 @@
!include "win32/config.mk"
CFLAGS=$(CFLAGS)
OBJECTS = $(INTDIR)\channel.obj $(INTDIR)\comp.obj $(INTDIR)\crypt.obj \
$(INTDIR)\hostkey.obj $(INTDIR)\kex.obj $(INTDIR)\mac.obj \
$(INTDIR)\misc.obj $(INTDIR)\packet.obj $(INTDIR)\scp.obj \
$(INTDIR)\session.obj $(INTDIR)\sftp.obj $(INTDIR)\userauth.obj
DLL=libssh2$(SUFFIX).dll
$(DLL): $(OBJECTS)
$(CC) -o $(DLL) $(DLLFLAGS) $(OBJECTS) $(LIBS)
all: $(DLL)
!include "win32/rules.mk"

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -136,12 +136,12 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
z_stream *strm = *abstract; z_stream *strm = *abstract;
/* A short-term alloc of a full data chunk is better than a series of reallocs */ /* A short-term alloc of a full data chunk is better than a series of reallocs */
char *out; char *out;
int out_maxlen = compress ? (src_len + 4) : (2 * src_len); int out_maxlen = compress ? src_len : (2 * src_len);
int limiter = 0; int limiter = 0;
/* In practice they never come smaller than this */ /* In practice they never come smaller than this */
if (out_maxlen < 25) { if (out_maxlen < 21) {
out_maxlen = 25; out_maxlen = 21;
} }
if (out_maxlen > payload_limit) { if (out_maxlen > payload_limit) {
@@ -166,17 +166,17 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
} }
if (status != Z_OK) { if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0); libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, strm->next_out);
return -1; return -1;
} }
if (strm->avail_in) { if (strm->avail_in) {
unsigned long out_ofs = out_maxlen - strm->avail_out; unsigned long out_ofs = out_maxlen - strm->avail_out;
out_maxlen += compress ? (strm->avail_in + 4) : (2 * strm->avail_in); out_maxlen += compress ? strm->avail_in : (2 * strm->avail_in);
if ((out_maxlen > payload_limit) && !compress && limiter++) { if ((out_maxlen > payload_limit) && !compress && limiter++) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0); libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
LIBSSH2_FREE(session, out); LIBSSH2_FREE(session, strm->next_out);
return -1; return -1;
} }
@@ -186,43 +186,7 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
return -1; return -1;
} }
strm->next_out = out + out_ofs; strm->next_out = out + out_ofs;
strm->avail_out += compress ? (strm->avail_in + 4) : (2 * strm->avail_in); strm->avail_out += compress ? strm->avail_in : (2 * strm->avail_in);
} else while (!strm->avail_out) {
/* Done with input, might be a byte or two in internal buffer during compress
* Or potentially many bytes if it's a decompress
*/
int grow_size = compress ? 8 : 1024;
if (out_maxlen >= payload_limit) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
LIBSSH2_FREE(session, out);
return -1;
}
if (grow_size > (payload_limit - out_maxlen)) {
grow_size = payload_limit - out_maxlen;
}
out_maxlen += grow_size;
strm->avail_out = grow_size;
out = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!out) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand final compress/decompress buffer", 0);
return -1;
}
strm->next_out = out + out_maxlen - grow_size;
if (compress) {
status = deflate(strm, Z_PARTIAL_FLUSH);
} else {
status = inflate(strm, Z_PARTIAL_FLUSH);
}
if (status != Z_OK) {
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
LIBSSH2_FREE(session, out);
return -1;
}
} }
} }
@@ -272,10 +236,10 @@ static LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = {
*********************** */ *********************** */
static LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = { static LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = {
&libssh2_comp_method_none,
#ifdef LIBSSH2_HAVE_ZLIB #ifdef LIBSSH2_HAVE_ZLIB
&libssh2_comp_method_zlib, &libssh2_comp_method_zlib,
#endif /* LIBSSH2_HAVE_ZLIB */ #endif /* LIBSSH2_HAVE_ZLIB */
&libssh2_comp_method_none,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -38,12 +38,6 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/evp.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifndef OPENSSL_NO_RSA #ifndef OPENSSL_NO_RSA
/* *********** /* ***********
@@ -92,8 +86,7 @@ static int libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION *session, unsigne
/* {{{ libssh2_hostkey_method_ssh_rsa_passphrase_cb /* {{{ libssh2_hostkey_method_ssh_rsa_passphrase_cb
* TODO: Optionally call a passphrase callback specified by the calling program * TODO: Optionally call a passphrase callback specified by the calling program
*/ */
static int libssh2_hostkey_method_ssh_rsadsa_passphrase_cb(char *buf, int size, int rwflag, char *passphrase) static int libssh2_hostkey_method_ssh_rsadsa_passphrase_cb(char *buf, int size, int rwflag, char *passphrase){
{
int passphrase_len = strlen(passphrase); int passphrase_len = strlen(passphrase);
if (passphrase_len > (size - 1)) { if (passphrase_len > (size - 1)) {
@@ -109,7 +102,7 @@ static int libssh2_hostkey_method_ssh_rsadsa_passphrase_cb(char *buf, int size,
/* {{{ libssh2_hostkey_method_ssh_rsa_initPEM /* {{{ libssh2_hostkey_method_ssh_rsa_initPEM
* Load a Private Key from a PEM file * Load a Private Key from a PEM file
*/ */
static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsigned const char *privkeyfile, unsigned const char *passphrase, void **abstract) static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsigned char *privkeyfile, unsigned char *passphrase, void **abstract)
{ {
RSA *rsactx; RSA *rsactx;
FILE *fp; FILE *fp;
@@ -123,15 +116,7 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsi
if (!fp) { if (!fp) {
return -1; return -1;
} }
rsactx = PEM_read_RSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
if (!EVP_get_cipherbyname("des")) {
/* If this cipher isn't loaded it's a pretty good indication that none are.
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
* Someone buy me an OpenSSL manual and I'll read up on it.
*/
OpenSSL_add_all_ciphers();
}
rsactx = PEM_read_RSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, (void*)passphrase);
if (!rsactx) { if (!rsactx) {
fclose(fp); fclose(fp);
return -1; return -1;
@@ -323,7 +308,7 @@ static int libssh2_hostkey_method_ssh_dss_init(LIBSSH2_SESSION *session, unsigne
/* {{{ libssh2_hostkey_method_ssh_dss_initPEM /* {{{ libssh2_hostkey_method_ssh_dss_initPEM
* Load a Private Key from a PEM file * Load a Private Key from a PEM file
*/ */
static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsigned const char *privkeyfile, unsigned const char *passphrase, void **abstract) static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsigned char *privkeyfile, unsigned char *passphrase, void **abstract)
{ {
DSA *dsactx; DSA *dsactx;
FILE *fp; FILE *fp;
@@ -337,15 +322,7 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsi
if (!fp) { if (!fp) {
return -1; return -1;
} }
dsactx = PEM_read_DSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
if (!EVP_get_cipherbyname("des")) {
/* If this cipher isn't loaded it's a pretty good indication that none are.
* I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
* Someone buy me an OpenSSL manual and I'll read up on it.
*/
OpenSSL_add_all_ciphers();
}
dsactx = PEM_read_DSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, (void*)passphrase);
if (!dsactx) { if (!dsactx) {
fclose(fp); fclose(fp);
return -1; return -1;
@@ -394,14 +371,16 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
const unsigned char *buf, unsigned long buf_len, void **abstract) const unsigned char *buf, unsigned long buf_len, void **abstract)
{ {
DSA *dsactx = (DSA*)(*abstract); DSA *dsactx = (DSA*)(*abstract);
DSA_SIG *sig; int ret;
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
SHA_CTX ctx; SHA_CTX ctx;
char *sig;
int sig_len;
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH); sig_len = DSA_size(dsactx);
*signature_len = 2 * SHA_DIGEST_LENGTH; sig = LIBSSH2_ALLOC(session, sig_len);
if (!(*signature)) { if (!sig) {
return -1; return -1;
} }
@@ -409,16 +388,14 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
SHA1_Update(&ctx, buf, buf_len); SHA1_Update(&ctx, buf, buf_len);
SHA1_Final(hash, &ctx); SHA1_Final(hash, &ctx);
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
if (!sig) { if (!ret) {
LIBSSH2_FREE(session, *signature); LIBSSH2_FREE(session, sig);
return -1; return -1;
} }
BN_bn2bin(sig->r, *signature); *signature = sig;
BN_bn2bin(sig->s, *signature + SHA_DIGEST_LENGTH); *signature_len = sig_len;
DSA_SIG_free(sig);
return 0; return 0;
} }
@@ -431,16 +408,16 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
unsigned long veccount, const struct iovec datavec[], void **abstract) unsigned long veccount, const struct iovec datavec[], void **abstract)
{ {
DSA *dsactx = (DSA*)(*abstract); DSA *dsactx = (DSA*)(*abstract);
DSA_SIG *sig; int ret, i;
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];
SHA_CTX ctx; SHA_CTX ctx;
int r_len, s_len, rs_pad, i; char *sig;
int sig_len;
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH); sig_len = DSA_size(dsactx);
*signature_len = 2 * SHA_DIGEST_LENGTH; sig = LIBSSH2_ALLOC(session, sig_len);
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
if (!(*signature)) { if (!sig) {
return -1; return -1;
} }
@@ -450,25 +427,15 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
} }
SHA1_Final(hash, &ctx); SHA1_Final(hash, &ctx);
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
if (!sig) {
LIBSSH2_FREE(session, *signature); if (!ret) {
LIBSSH2_FREE(session, sig);
return -1; return -1;
} }
r_len = BN_num_bytes(sig->r); *signature = sig;
s_len = BN_num_bytes(sig->s); *signature_len = sig_len;
rs_pad = (2 * SHA_DIGEST_LENGTH) - (r_len + s_len);
if (rs_pad < 0) {
DSA_SIG_free(sig);
LIBSSH2_FREE(session, *signature);
return -1;
}
BN_bn2bin(sig->r, *signature + rs_pad);
BN_bn2bin(sig->s, *signature + rs_pad + r_len);
DSA_SIG_free(sig);
return 0; return 0;
} }
@@ -518,12 +485,9 @@ LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void)
} }
/* {{{ libssh2_hostkey_hash /* {{{ libssh2_hostkey_hash
* Returns hash signature * Returns NULL terminated hash signature
* Returned buffer should NOT be freed
* Length of buffer is determined by hash type
* i.e. MD5 == 16, SHA1 == 20
*/ */
LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type) LIBSSH2_API char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type)
{ {
switch (hash_type) { switch (hash_type) {
#ifndef OPENSSL_NO_MD5 #ifndef OPENSSL_NO_MD5

438
src/kex.c
View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -39,7 +39,6 @@
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rand.h>
/* TODO: Switch this to an inline and handle alloc() failures */ /* TODO: Switch this to an inline and handle alloc() failures */
/* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */ /* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */
@@ -109,9 +108,6 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
BN_bn2bin(e, e_packet + 6); BN_bn2bin(e, e_packet + 6);
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending KEX packet %d", (int)packet_type_init);
#endif
if (libssh2_packet_write(session, e_packet, e_packet_len)) { if (libssh2_packet_write(session, e_packet, e_packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send KEX init message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send KEX init message", 0);
ret = -11; ret = -11;
@@ -146,18 +142,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
MD5_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); MD5_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
MD5_Final(session->server_hostkey_md5, &fingerprint_ctx); MD5_Final(session->server_hostkey_md5, &fingerprint_ctx);
} }
#ifdef LIBSSH2_DEBUG_KEX #endif
{
char fingerprint[50], *fprint = fingerprint;
int i;
for(i = 0; i < 16; i++, fprint += 3) {
snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
}
*(--fprint) = '\0';
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Server's MD5 Fingerprint: %s", fingerprint);
}
#endif /* LIBSSH2_DEBUG_KEX */
#endif /* ! OPENSSL_NO_MD5 */
#ifndef OPENSSL_NO_SHA #ifndef OPENSSL_NO_SHA
{ {
@@ -167,18 +152,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
SHA1_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len); SHA1_Update(&fingerprint_ctx, session->server_hostkey, session->server_hostkey_len);
SHA1_Final(session->server_hostkey_sha1, &fingerprint_ctx); SHA1_Final(session->server_hostkey_sha1, &fingerprint_ctx);
} }
#ifdef LIBSSH2_DEBUG_KEX #endif
{
char fingerprint[64], *fprint = fingerprint;
int i;
for(i = 0; i < 20; i++, fprint += 3) {
snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
}
*(--fprint) = '\0';
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Server's SHA1 Fingerprint: %s", fingerprint);
}
#endif /* LIBSSH2_DEBUG_KEX */
#endif /* ! OPENSSL_NO_SHA */
if (session->hostkey->init(session, session->server_hostkey, session->server_hostkey_len, &session->server_hostkey_abstract)) { if (session->hostkey->init(session, session->server_hostkey, session->server_hostkey_len, &session->server_hostkey_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, "Unable to initialize hostkey importer", 0); libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, "Unable to initialize hostkey importer", 0);
@@ -186,6 +160,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
goto clean_exit; goto clean_exit;
} }
f_value_len = libssh2_ntohu32(s); s += 4; f_value_len = libssh2_ntohu32(s); s += 4;
f_value = s; s += f_value_len; f_value = s; s += f_value_len;
BN_bin2bn(f_value, f_value_len, f); BN_bin2bn(f_value, f_value_len, f);
@@ -274,9 +249,6 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
goto clean_exit; goto clean_exit;
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending NEWKEYS message");
#endif
c = SSH_MSG_NEWKEYS; c = SSH_MSG_NEWKEYS;
if (libssh2_packet_write(session, &c, 1)) { if (libssh2_packet_write(session, &c, 1)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send NEWKEYS message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send NEWKEYS message", 0);
@@ -290,10 +262,7 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
goto clean_exit; goto clean_exit;
} }
/* The first key exchange has been performed, switch to active crypt/comp/mac mode */ /* The first key exchange has been performed, switch to active crypt/comp/mac mode */
session->state |= LIBSSH2_STATE_NEWKEYS; session->newkeys = 1;
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
#endif
/* This will actually end up being just packet_type(1) for this packet type anyway */ /* This will actually end up being just packet_type(1) for this packet type anyway */
LIBSSH2_FREE(session, tmp); LIBSSH2_FREE(session, tmp);
@@ -306,9 +275,6 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
} }
memcpy(session->session_id, h_sig_comp, SHA_DIGEST_LENGTH); memcpy(session->session_id, h_sig_comp, SHA_DIGEST_LENGTH);
session->session_id_len = SHA_DIGEST_LENGTH; session->session_id_len = SHA_DIGEST_LENGTH;
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "session_id calculated");
#endif
} }
/* Calculate IV/Secret/Key for each direction */ /* Calculate IV/Secret/Key for each direction */
@@ -360,9 +326,6 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
LIBSSH2_FREE(session, secret); LIBSSH2_FREE(session, secret);
} }
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Client to Server IV and Key calculated");
#endif
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
if (session->remote.crypt_abstract) { if (session->remote.crypt_abstract) {
@@ -412,9 +375,6 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
LIBSSH2_FREE(session, secret); LIBSSH2_FREE(session, secret);
} }
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Server to Client IV and Key calculated");
#endif
if (session->local.mac->dtor) { if (session->local.mac->dtor) {
session->local.mac->dtor(session, &session->local.mac_abstract); session->local.mac->dtor(session, &session->local.mac_abstract);
@@ -424,17 +384,14 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
unsigned char *key = NULL; unsigned char *key = NULL;
int free_key = 0; int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->local.mac->key_len, "E"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->kex->key_len, "E");
session->local.mac->init(session, key, &free_key, &session->local.mac_abstract); session->local.mac->init(session, key, &free_key, &session->local.mac_abstract);
if (free_key) { if (free_key) {
memset(key, 0, session->local.mac->key_len); memset(key, 0, session->kex->key_len);
LIBSSH2_FREE(session, key); LIBSSH2_FREE(session, key);
} }
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Client to Server HMAC Key calculated");
#endif
if (session->remote.mac->dtor) { if (session->remote.mac->dtor) {
session->remote.mac->dtor(session, &session->remote.mac_abstract); session->remote.mac->dtor(session, &session->remote.mac_abstract);
@@ -444,17 +401,14 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
unsigned char *key = NULL; unsigned char *key = NULL;
int free_key = 0; int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->remote.mac->key_len, "F"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->kex->key_len, "F");
session->remote.mac->init(session, key, &free_key, &session->remote.mac_abstract); session->remote.mac->init(session, key, &free_key, &session->remote.mac_abstract);
if (free_key) { if (free_key) {
memset(key, 0, session->remote.mac->key_len); memset(key, 0, session->kex->key_len);
LIBSSH2_FREE(session, key); LIBSSH2_FREE(session, key);
} }
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Server to Client HMAC Key calculated");
#endif
clean_exit: clean_exit:
BN_clear_free(x); BN_clear_free(x);
@@ -515,9 +469,6 @@ static int libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SE
BN_set_word(g, 2); BN_set_word(g, 2);
BN_bin2bn(p_value, 128, p); BN_bin2bn(p_value, 128, p);
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group1 Key Exchange");
#endif
ret = libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, g, p, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0); ret = libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, g, p, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0);
BN_clear_free(p); BN_clear_free(p);
@@ -574,9 +525,6 @@ static int libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_S
BN_set_word(g, 2); BN_set_word(g, 2);
BN_bin2bn(p_value, 256, p); BN_bin2bn(p_value, 256, p);
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group14 Key Exchange");
#endif
ret = libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, g, p, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0); ret = libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session, g, p, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, NULL, 0);
BN_clear_free(p); BN_clear_free(p);
@@ -605,16 +553,10 @@ static int libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange(LI
libssh2_htonu32(request + 5, LIBSSH2_DH_GEX_OPTGROUP); libssh2_htonu32(request + 5, LIBSSH2_DH_GEX_OPTGROUP);
libssh2_htonu32(request + 9, LIBSSH2_DH_GEX_MAXGROUP); libssh2_htonu32(request + 9, LIBSSH2_DH_GEX_MAXGROUP);
request_len = 13; request_len = 13;
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group-Exchange (New Method)");
#endif
#else #else
request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD; request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
libssh2_htonu32(request + 1, LIBSSH2_DH_GEX_OPTGROUP); libssh2_htonu32(request + 1, LIBSSH2_DH_GEX_OPTGROUP);
request_len = 5; request_len = 5;
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Initiating Diffie-Hellman Group-Exchange (Old Method)");
#endif
#endif #endif
if (libssh2_packet_write(session, request, request_len)) { if (libssh2_packet_write(session, request, request_len)) {
@@ -653,18 +595,21 @@ static int libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange(LI
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group1_sha1 = { LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group1_sha1 = {
"diffie-hellman-group1-sha1", "diffie-hellman-group1-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange, libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
}; };
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group14_sha1 = { LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group14_sha1 = {
"diffie-hellman-group14-sha1", "diffie-hellman-group14-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange, libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
}; };
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group_exchange_sha1 = { LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group_exchange_sha1 = {
"diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange, libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
}; };
@@ -726,16 +671,16 @@ static size_t libssh2_kex_method_list(unsigned char *buf, size_t list_strlen, LI
} }
/* }}} */ /* }}} */
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) ((prefvar) ? strlen(prefvar) : libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar))) #define LIBSSH2_METHOD_PREFS \
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \ LIBSSH2_KEX_METHOD **kex_prefs = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods; \
if (prefvar) { \ LIBSSH2_HOSTKEY_METHOD **hostkey_prefs = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods(); \
libssh2_htonu32((buf), (prefvarlen)); \ LIBSSH2_CRYPT_METHOD **crypt_cs_prefs = session->local.crypt_prefs ? session->local.crypt_prefs : libssh2_crypt_methods(); \
buf += 4; \ LIBSSH2_CRYPT_METHOD **crypt_sc_prefs = session->remote.crypt_prefs ? session->remote.crypt_prefs : libssh2_crypt_methods(); \
memcpy((buf), (prefvar), (prefvarlen)); \ LIBSSH2_COMP_METHOD **comp_cs_prefs = session->local.comp_prefs ? session->local.comp_prefs : libssh2_comp_methods(); \
buf += (prefvarlen); \ LIBSSH2_COMP_METHOD **comp_sc_prefs = session->remote.comp_prefs ? session->remote.comp_prefs : libssh2_comp_methods(); \
} else { \ LIBSSH2_MAC_METHOD **mac_cs_prefs = session->local.mac_prefs ? session->local.mac_prefs : libssh2_mac_methods(); \
buf += libssh2_kex_method_list((buf), (prefvarlen), (LIBSSH2_COMMON_METHOD**)(defaultvar)); \ LIBSSH2_MAC_METHOD **mac_sc_prefs = session->remote.mac_prefs ? session->remote.mac_prefs : libssh2_mac_methods();
}
/* {{{ libssh2_kexinit /* {{{ libssh2_kexinit
* Send SSH_MSG_KEXINIT packet * Send SSH_MSG_KEXINIT packet
@@ -749,17 +694,18 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
size_t mac_cs_len, mac_sc_len; size_t mac_cs_len, mac_sc_len;
size_t lang_cs_len, lang_sc_len; size_t lang_cs_len, lang_sc_len;
unsigned char *data, *s; unsigned char *data, *s;
LIBSSH2_METHOD_PREFS
kex_len = LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods); kex_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)kex_prefs);
hostkey_len = LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs, libssh2_hostkey_methods()); hostkey_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)hostkey_prefs);
crypt_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs, libssh2_crypt_methods()); crypt_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
crypt_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs, libssh2_crypt_methods()); crypt_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
mac_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs, libssh2_mac_methods()); mac_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
mac_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs, libssh2_mac_methods()); mac_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
comp_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs, libssh2_comp_methods()); comp_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
comp_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs, libssh2_comp_methods()); comp_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
lang_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL); lang_cs_len = 0; /* No langs in this version */
lang_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL); lang_sc_len = 0; /* No langs in this version */
data_len += kex_len + hostkey_len + \ data_len += kex_len + hostkey_len + \
crypt_cs_len + crypt_sc_len + \ crypt_cs_len + crypt_sc_len + \
@@ -775,20 +721,21 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
*(s++) = SSH_MSG_KEXINIT; *(s++) = SSH_MSG_KEXINIT;
RAND_bytes(s, 16); /* TODO: Build a better cookie (and the mice will beat a path to my door...) */
memcpy(s, "mysecretMYSECRET", 16);
s += 16; s += 16;
/* Ennumerating through these lists twice is probably (certainly?) inefficient from a CPU standpoint, but it saves multiple malloc/realloc calls */ /* Ennumerating through these lists twice is probably (certainly?) inefficient from a CPU standpoint, but it saves multiple malloc/realloc calls */
LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs, libssh2_kex_methods); s += libssh2_kex_method_list(s, kex_len, (LIBSSH2_COMMON_METHOD**)kex_prefs);
LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs, libssh2_hostkey_methods()); s += libssh2_kex_method_list(s, hostkey_len, (LIBSSH2_COMMON_METHOD**)hostkey_prefs);
LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs, libssh2_crypt_methods()); s += libssh2_kex_method_list(s, crypt_cs_len, (LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs, libssh2_crypt_methods()); s += libssh2_kex_method_list(s, crypt_sc_len, (LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs, libssh2_mac_methods()); s += libssh2_kex_method_list(s, mac_cs_len, (LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs, libssh2_mac_methods()); s += libssh2_kex_method_list(s, mac_sc_len, (LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs, libssh2_comp_methods()); s += libssh2_kex_method_list(s, comp_cs_len, (LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs, libssh2_comp_methods()); s += libssh2_kex_method_list(s, comp_sc_len, (LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs, NULL); s += libssh2_kex_method_list(s, lang_cs_len, NULL);
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs, NULL); s += libssh2_kex_method_list(s, lang_sc_len, NULL);
/* No optimistic KEX packet follows */ /* No optimistic KEX packet follows */
/* Deal with optimistic packets /* Deal with optimistic packets
@@ -803,23 +750,6 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
*(s++) = 0; *(s++) = 0;
*(s++) = 0; *(s++) = 0;
#ifdef LIBSSH2_DEBUG_KEX
{
/* Funnily enough, they'll all "appear" to be '\0' terminated */
char *p = data + 21; /* type(1) + cookie(16) + len(4) */
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent KEX: %s", p); p += kex_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent HOSTKEY: %s", p); p += hostkey_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_CS: %s", p); p += crypt_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_SC: %s", p); p += crypt_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_CS: %s", p); p += mac_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_SC: %s", p); p += mac_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_CS: %s", p); p += comp_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_SC: %s", p); p += comp_sc_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_CS: %s", p); p += lang_cs_len + 4;
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_SC: %s", p); p += lang_sc_len + 4;
}
#endif /* LIBSSH2_DEBUG_KEX */
if (libssh2_packet_write(session, data, data_len)) { if (libssh2_packet_write(session, data, data_len)) {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send KEXINIT packet to remote host", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send KEXINIT packet to remote host", 0);
@@ -873,62 +803,15 @@ static unsigned char *libssh2_kex_agree_instr(unsigned char *haystack, unsigned
} }
/* }}} */ /* }}} */
/* {{{ libssh2_get_method_by_name
*/
static LIBSSH2_COMMON_METHOD *libssh2_get_method_by_name(char *name, int name_len, LIBSSH2_COMMON_METHOD **methodlist)
{
while (*methodlist) {
if ((strlen((*methodlist)->name) == name_len) &&
(strncmp((*methodlist)->name, name, name_len) == 0)) {
return *methodlist;
}
methodlist++;
}
return NULL;
}
/* }}} */
/* {{{ libssh2_kex_agree_hostkey /* {{{ libssh2_kex_agree_hostkey
* Agree on a Hostkey which works with this kex * Agree on a Hostkey which works with this kex
*/ */
static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex_flags, unsigned char *hostkey, unsigned long hostkey_len) static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex_flags, unsigned char *hostkey, unsigned long hostkey_len)
{ {
LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods(); LIBSSH2_HOSTKEY_METHOD **hostkeyp = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods();
unsigned char *s; unsigned char *s;
if (session->hostkey_prefs) { while ((*hostkeyp)->name) {
s = session->hostkey_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
LIBSSH2_HOSTKEY_METHOD *method = (LIBSSH2_HOSTKEY_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)hostkeyp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
(method->encrypt)) {
/* Either this hostkey can do encryption or this kex just doesn't require it */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == 0) ||
(method->sig_verify)) {
/* Either this hostkey can do signing or this kex just doesn't require it */
session->hostkey = method;
return 0;
}
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (hostkeyp && (*hostkeyp)->name) {
s = libssh2_kex_agree_instr(hostkey, hostkey_len, (*hostkeyp)->name, strlen((*hostkeyp)->name)); s = libssh2_kex_agree_instr(hostkey, hostkey_len, (*hostkeyp)->name, strlen((*hostkeyp)->name));
if (s) { if (s) {
/* So far so good, but does it suit our purposes? (Encrypting vs Signing) */ /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
@@ -956,37 +839,9 @@ static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex
static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char *kex, unsigned long kex_len, static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char *kex, unsigned long kex_len,
unsigned char *hostkey, unsigned long hostkey_len) unsigned char *hostkey, unsigned long hostkey_len)
{ {
LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods; LIBSSH2_KEX_METHOD **kexp = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods;
unsigned char *s; unsigned char *s;
if (session->kex_prefs) {
s = session->kex_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(kex, kex_len, s, method_len)) {
LIBSSH2_KEX_METHOD *method = (LIBSSH2_KEX_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)kexp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
if (libssh2_kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) {
session->kex = method;
return 0;
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*kexp && (*kexp)->name) { while (*kexp && (*kexp)->name) {
s = libssh2_kex_agree_instr(kex, kex_len, (*kexp)->name, strlen((*kexp)->name)); s = libssh2_kex_agree_instr(kex, kex_len, (*kexp)->name, strlen((*kexp)->name));
if (s) { if (s) {
@@ -1009,34 +864,10 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
*/ */
static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *crypt, unsigned long crypt_len) static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *crypt, unsigned long crypt_len)
{ {
LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods(); LIBSSH2_CRYPT_METHOD **cryptp = endpoint->crypt_prefs ? endpoint->crypt_prefs : libssh2_crypt_methods();
unsigned char *s; unsigned char *s;
if (endpoint->crypt_prefs) { while ((*cryptp)->name) {
s = endpoint->crypt_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
LIBSSH2_CRYPT_METHOD *method = (LIBSSH2_CRYPT_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)cryptp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->crypt = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*cryptp && (*cryptp)->name) {
s = libssh2_kex_agree_instr(crypt, crypt_len, (*cryptp)->name, strlen((*cryptp)->name)); s = libssh2_kex_agree_instr(crypt, crypt_len, (*cryptp)->name, strlen((*cryptp)->name));
if (s) { if (s) {
endpoint->crypt = *cryptp; endpoint->crypt = *cryptp;
@@ -1054,34 +885,10 @@ static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_da
*/ */
static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *mac, unsigned long mac_len) static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *mac, unsigned long mac_len)
{ {
LIBSSH2_MAC_METHOD **macp = libssh2_mac_methods(); LIBSSH2_MAC_METHOD **macp = endpoint->mac_prefs ? endpoint->mac_prefs : libssh2_mac_methods();
unsigned char *s; unsigned char *s;
if (endpoint->mac_prefs) { while ((*macp)->name) {
s = endpoint->mac_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
LIBSSH2_MAC_METHOD *method = (LIBSSH2_MAC_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)macp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->mac = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*macp && (*macp)->name) {
s = libssh2_kex_agree_instr(mac, mac_len, (*macp)->name, strlen((*macp)->name)); s = libssh2_kex_agree_instr(mac, mac_len, (*macp)->name, strlen((*macp)->name));
if (s) { if (s) {
endpoint->mac = *macp; endpoint->mac = *macp;
@@ -1099,34 +906,10 @@ static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data
*/ */
static int libssh2_kex_agree_comp(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *comp, unsigned long comp_len) static int libssh2_kex_agree_comp(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *comp, unsigned long comp_len)
{ {
LIBSSH2_COMP_METHOD **compp = libssh2_comp_methods(); LIBSSH2_COMP_METHOD **compp = endpoint->comp_prefs ? endpoint->comp_prefs : libssh2_comp_methods();
unsigned char *s; unsigned char *s;
if (endpoint->comp_prefs) { while ((*compp)->name) {
s = endpoint->comp_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
LIBSSH2_COMP_METHOD *method = (LIBSSH2_COMP_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)compp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->comp = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*compp && (*compp)->name) {
s = libssh2_kex_agree_instr(comp, comp_len, (*compp)->name, strlen((*compp)->name)); s = libssh2_kex_agree_instr(comp, comp_len, (*compp)->name, strlen((*compp)->name));
if (s) { if (s) {
endpoint->comp = *compp; endpoint->comp = *compp;
@@ -1194,19 +977,6 @@ static int libssh2_kex_agree_methods(LIBSSH2_SESSION *session, unsigned char *da
return -1; return -1;
} }
#ifdef LIBSSH2_DEBUG_KEX
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on KEX method: %s", session->kex->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on HOSTKEY method: %s", session->hostkey->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_CS method: %s", session->local.crypt->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_SC method: %s", session->remote.crypt->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_CS method: %s", session->local.mac->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_SC method: %s", session->remote.mac->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_CS method: %s", session->local.comp->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_SC method: %s", session->remote.comp->name);
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_CS method:"); /* None yet */
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_SC method:"); /* None yet */
#endif
/* Initialize compression layer */ /* Initialize compression layer */
if (session->local.comp && session->local.comp->init && if (session->local.comp && session->local.comp->init &&
session->local.comp->init(session, 1, &session->local.comp_abstract)) { session->local.comp->init(session, 1, &session->local.comp_abstract)) {
@@ -1232,7 +1002,7 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
unsigned long data_len; unsigned long data_len;
/* Prevent loop in packet_add() */ /* Prevent loop in packet_add() */
session->state |= LIBSSH2_STATE_EXCHANGING_KEYS; session->exchanging_keys = 1;
if (reexchange) { if (reexchange) {
session->kex = NULL; session->kex = NULL;
@@ -1278,105 +1048,9 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
session->remote.kexinit = NULL; session->remote.kexinit = NULL;
} }
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS; session->exchanging_keys = 0;
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_method_pref
* Set preferred method
*/
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, const char *prefs)
{
char **prefvar, *s, *newprefs;
int prefs_len = strlen(prefs);
LIBSSH2_COMMON_METHOD **mlist;
switch (method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_kex_methods;
break;
case LIBSSH2_METHOD_HOSTKEY:
prefvar = &session->hostkey_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_hostkey_methods();
break;
case LIBSSH2_METHOD_CRYPT_CS:
prefvar = &session->local.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_CRYPT_SC:
prefvar = &session->remote.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_MAC_CS:
prefvar = &session->local.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_MAC_SC:
prefvar = &session->remote.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_COMP_CS:
prefvar = &session->local.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_COMP_SC:
prefvar = &session->remote.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_LANG_CS:
prefvar = &session->local.lang_prefs;
mlist = NULL;
break;
case LIBSSH2_METHOD_LANG_SC:
prefvar = &session->remote.lang_prefs;
mlist = NULL;
break;
default:
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
return -1;
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
if (!newprefs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocated space for method preferences", 0);
return -1;
}
memcpy(s, prefs, prefs_len + 1);
while (s && *s) {
char *p = strchr(s, ',');
int method_len = p ? (p - s) : strlen(s);
if (!libssh2_get_method_by_name(s, method_len, mlist)) {
/* Strip out unsupported method */
if (p) {
memcpy(s, p + 1, strlen(s) - method_len);
} else {
if (s > newprefs) {
*(--s) = '\0';
} else {
*s = '\0';
}
}
}
s = p ? (p + 1) : NULL;
}
if (strlen(newprefs) == 0) {
libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, "The requested method(s) are not currently supported", 0);
LIBSSH2_FREE(session, newprefs);
return -1;
}
if (*prefvar) {
LIBSSH2_FREE(session, *prefvar);
}
*prefvar = newprefs;
return 0;
}
/* }}} */

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -54,7 +54,6 @@ static int libssh2_mac_none_MAC(LIBSSH2_SESSION *session, unsigned char *buf, un
static LIBSSH2_MAC_METHOD libssh2_mac_method_none = { static LIBSSH2_MAC_METHOD libssh2_mac_method_none = {
"none", "none",
0, 0,
0,
NULL, NULL,
libssh2_mac_none_MAC, libssh2_mac_none_MAC,
NULL NULL
@@ -99,7 +98,7 @@ static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned
libssh2_htonu32(seqno_buf, seqno); libssh2_htonu32(seqno_buf, seqno);
HMAC_Init(&ctx, *abstract, 20, EVP_sha1()); HMAC_Init(&ctx, *abstract, session->kex->key_len, EVP_sha1());
HMAC_Update(&ctx, seqno_buf, 4); HMAC_Update(&ctx, seqno_buf, 4);
HMAC_Update(&ctx, packet, packet_len); HMAC_Update(&ctx, packet, packet_len);
if (addtl && addtl_len) { if (addtl && addtl_len) {
@@ -114,8 +113,7 @@ static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = {
"hmac-sha1", "hmac-sha1",
20, SHA_DIGEST_LENGTH,
20,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_sha1_hash, libssh2_mac_method_hmac_sha1_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
@@ -139,13 +137,13 @@ static int libssh2_mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION *session, unsign
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = {
"hmac-sha1-96", "hmac-sha1-96",
12, 96 / 8,
20,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_sha1_96_hash, libssh2_mac_method_hmac_sha1_96_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
}; };
#ifdef WHY_DOESNT_MD5_WORK
/* {{{ libssh2_mac_method_hmac_md5_hash /* {{{ libssh2_mac_method_hmac_md5_hash
* Calculate hash using full md5 value * Calculate hash using full md5 value
*/ */
@@ -158,7 +156,7 @@ static int libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION *session, unsigned c
libssh2_htonu32(seqno_buf, seqno); libssh2_htonu32(seqno_buf, seqno);
HMAC_Init(&ctx, *abstract, 16, EVP_md5()); HMAC_Init(&ctx, *abstract, session->kex->key_len, EVP_md5());
HMAC_Update(&ctx, seqno_buf, 4); HMAC_Update(&ctx, seqno_buf, 4);
HMAC_Update(&ctx, packet, packet_len); HMAC_Update(&ctx, packet, packet_len);
if (addtl && addtl_len) { if (addtl && addtl_len) {
@@ -173,8 +171,7 @@ static int libssh2_mac_method_hmac_md5_hash(LIBSSH2_SESSION *session, unsigned c
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = {
"hmac-md5", "hmac-md5",
16, MD5_DIGEST_LENGTH,
16,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_md5_hash, libssh2_mac_method_hmac_md5_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
@@ -183,8 +180,8 @@ static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = {
/* {{{ libssh2_mac_method_hmac_md5_96_hash /* {{{ libssh2_mac_method_hmac_md5_96_hash
* Calculate hash using first 96 bits of md5 value * Calculate hash using first 96 bits of md5 value
*/ */
static int libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, static int libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned seqno,
const unsigned char *packet, unsigned long packet_len, const unsigned char *packet, unsigned packet_len,
const unsigned char *addtl, unsigned long addtl_len, void **abstract) const unsigned char *addtl, unsigned long addtl_len, void **abstract)
{ {
char temp[MD5_DIGEST_LENGTH]; char temp[MD5_DIGEST_LENGTH];
@@ -198,12 +195,12 @@ static int libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION *session, unsigne
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = {
"hmac-md5-96", "hmac-md5-96",
12, 96 / 8,
16,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_md5_96_hash, libssh2_mac_method_hmac_md5_96_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
}; };
#endif /* WHY_DOESNT_MD5_WORK */
#ifndef OPENSSL_NO_RIPEMD #ifndef OPENSSL_NO_RIPEMD
/* {{{ libssh2_mac_method_hmac_ripemd160_hash /* {{{ libssh2_mac_method_hmac_ripemd160_hash
@@ -218,7 +215,7 @@ static int libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION *session, unsi
libssh2_htonu32(seqno_buf, seqno); libssh2_htonu32(seqno_buf, seqno);
HMAC_Init(&ctx, *abstract, 20, EVP_ripemd160()); HMAC_Init(&ctx, *abstract, session->kex->key_len, EVP_ripemd160());
HMAC_Update(&ctx, seqno_buf, 4); HMAC_Update(&ctx, seqno_buf, 4);
HMAC_Update(&ctx, packet, packet_len); HMAC_Update(&ctx, packet, packet_len);
if (addtl && addtl_len) { if (addtl && addtl_len) {
@@ -233,8 +230,7 @@ static int libssh2_mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION *session, unsi
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = {
"hmac-ripemd160", "hmac-ripemd160",
20, 160 / 8,
20,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_ripemd160_hash, libssh2_mac_method_hmac_ripemd160_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
@@ -242,8 +238,7 @@ static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = {
static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160_openssh_com = { static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160_openssh_com = {
"hmac-ripemd160@openssh.com", "hmac-ripemd160@openssh.com",
20, 160 / 8,
20,
libssh2_mac_method_common_init, libssh2_mac_method_common_init,
libssh2_mac_method_hmac_ripemd160_hash, libssh2_mac_method_hmac_ripemd160_hash,
libssh2_mac_method_common_dtor, libssh2_mac_method_common_dtor,
@@ -253,8 +248,10 @@ static LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160_openssh_com = {
static LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = { static LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = {
&libssh2_mac_method_hmac_sha1, &libssh2_mac_method_hmac_sha1,
&libssh2_mac_method_hmac_sha1_96, &libssh2_mac_method_hmac_sha1_96,
#ifdef WHY_DOESNT_MD5_WORK
&libssh2_mac_method_hmac_md5, &libssh2_mac_method_hmac_md5,
&libssh2_mac_method_hmac_md5_96, &libssh2_mac_method_hmac_md5_96,
#endif /* WHY_DOESNT_MD5_WORK */
#ifndef OPENSSL_NO_RIPEMD #ifndef OPENSSL_NO_RIPEMD
&libssh2_mac_method_hmac_ripemd160, &libssh2_mac_method_hmac_ripemd160,
&libssh2_mac_method_hmac_ripemd160_openssh_com, &libssh2_mac_method_hmac_ripemd160_openssh_com,

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -45,21 +45,6 @@ unsigned long 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)
{
unsigned long msl, lsl;
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;
}
/* }}} */
/* {{{ libssh2_htonu32 /* {{{ libssh2_htonu32
*/ */
void libssh2_htonu32(unsigned char *buf, unsigned long value) void libssh2_htonu32(unsigned char *buf, unsigned long value)
@@ -71,24 +56,6 @@ void libssh2_htonu32(unsigned char *buf, unsigned long value)
} }
/* }}} */ /* }}} */
/* {{{ libssh2_htonu64
*/
void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
{
unsigned long msl = (value / 65536) / 65536;
buf[0] = (msl >> 24) & 0xFF;
buf[1] = (msl >> 16) & 0xFF;
buf[2] = (msl >> 8) & 0xFF;
buf[3] = msl & 0xFF;
buf[4] = (value >> 24) & 0xFF;
buf[5] = (value >> 16) & 0xFF;
buf[6] = (value >> 8) & 0xFF;
buf[7] = value & 0xFF;
}
/* }}} */
/* Base64 Conversion */ /* Base64 Conversion */
/* {{{ */ /* {{{ */
@@ -169,29 +136,3 @@ LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **data, int
} }
/* }}} */ /* }}} */
#ifdef LIBSSH2_DEBUG_ENABLED
/* {{{ _libssh2_debug
* Internal debug logging facility
* Just writes to stderr until a good reason comes up to support anything else
*/
void _libssh2_debug(LIBSSH2_SESSION *session, int context, const char *format, ...)
{
char buffer[1536];
int len;
va_list vargs;
char *contexts[8] = { "Unknown", "Transport", "Key Exhange", "Userauth", "Connection", "scp", "SFTP", "Failure Event" };
if (context < 1 || context > 6) {
context = 0;
}
len = snprintf(buffer, 1535, "[libssh2] %s: ", contexts[context]);
va_start(vargs, format);
len += vsnprintf(buffer + len, 1535 - len, format, vargs);
buffer[len] = '\n';
va_end(vargs);
write(2, buffer, len + 1);
}
/* }}} */
#endif

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -38,275 +38,8 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#ifndef WIN32
#include <unistd.h> #include <unistd.h>
#endif
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rand.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_POLL
# include <sys/poll.h>
#else
# ifdef HAVE_SELECT
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
# include <sys/time.h>
# include <sys/types.h>
# endif
# endif
#endif
/* {{{ libssh2_packet_queue_listener
* Queue a connection request for a listener
*/
inline int libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char *data, unsigned long datalen)
{
/* Look for a matching listener */
unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
unsigned long packet_len = 17 + (sizeof("Forward not requested") - 1);
unsigned char *p, packet[17 + (sizeof("Forward not requested") - 1)];
/* packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
LIBSSH2_LISTENER *l = session->listeners;
char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */
unsigned long sender_channel, initial_window_size, packet_size;
unsigned char *host, *shost;
unsigned long port, sport, host_len, shost_len;
sender_channel = libssh2_ntohu32(s); s += 4;
initial_window_size = libssh2_ntohu32(s); s += 4;
packet_size = libssh2_ntohu32(s); s += 4;
host_len = libssh2_ntohu32(s); s += 4;
host = s; s += host_len;
port = libssh2_ntohu32(s); s += 4;
shost_len = libssh2_ntohu32(s); s += 4;
shost = s; s += shost_len;
sport = libssh2_ntohu32(s); s += 4;
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Remote received connection from %s:%ld to %s:%ld", shost, sport, host, port);
#endif
while (l) {
if ((l->port == port) &&
(strlen(l->host) == host_len) &&
(memcmp(l->host, host, host_len) == 0)) {
/* This is our listener */
LIBSSH2_CHANNEL *channel, *last_queued = l->queue;
if (l->queue_maxsize &&
(l->queue_maxsize <= l->queue_size)) {
/* Queue is full */
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Listener queue full, ignoring");
#endif
break;
}
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
break;
}
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->session = session;
channel->channel_type_len = sizeof("forwarded-tcpip") - 1;
channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1);
if (!channel->channel_type) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
LIBSSH2_FREE(session, channel);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
break;
}
memcpy(channel->channel_type, "forwarded-tcpip", channel->channel_type_len + 1);
channel->remote.id = sender_channel;
channel->remote.window_size_initial = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
channel->local.id = libssh2_channel_nextid(session);
channel->local.window_size_initial = initial_window_size;
channel->local.window_size = initial_window_size;
channel->local.packet_size = packet_size;
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Connection queued: channel %lu/%lu win %lu/%lu packet %lu/%lu",
channel->local.id, channel->remote.id,
channel->local.window_size, channel->remote.window_size,
channel->local.packet_size, channel->remote.packet_size);
#endif
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
libssh2_htonu32(p, channel->remote.id); p += 4;
libssh2_htonu32(p, channel->local.id); p += 4;
libssh2_htonu32(p, channel->remote.window_size_initial); p += 4;
libssh2_htonu32(p, channel->remote.packet_size); p += 4;
if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1;
}
/* Link the channel into the end of the queue list */
if (!last_queued) {
l->queue = channel;
return 0;
}
while (last_queued->next) last_queued = last_queued->next;
last_queued->next = channel;
channel->prev = last_queued;
l->queue_size++;
return 0;
}
l = l->next;
}
/* We're not listening to you */
{
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
libssh2_htonu32(p, sender_channel); p += 4;
libssh2_htonu32(p, failure_code); p += 4;
libssh2_htonu32(p, sizeof("Forward not requested") - 1); p += 4;
memcpy(s, "Forward not requested", sizeof("Forward not requested") - 1); p += sizeof("Forward not requested") - 1;
libssh2_htonu32(p, 0);
if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send open failure", 0);
return -1;
}
return 0;
}
}
/* }}} */
/* {{{ libssh2_packet_x11_open
* Accept a forwarded X11 connection
*/
inline int libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data, unsigned long datalen)
{
int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */
unsigned char *s = data + (sizeof("x11") - 1) + 5;
unsigned long packet_len = 17 + (sizeof("X11 Forward Unavailable") - 1);
unsigned char *p, packet[17 + (sizeof("X11 Forward Unavailable") - 1)];
/* packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
LIBSSH2_CHANNEL *channel;
unsigned long sender_channel, initial_window_size, packet_size;
unsigned char *shost;
unsigned long sport, shost_len;
sender_channel = libssh2_ntohu32(s); s += 4;
initial_window_size = libssh2_ntohu32(s); s += 4;
packet_size = libssh2_ntohu32(s); s += 4;
shost_len = libssh2_ntohu32(s); s += 4;
shost = s; s += shost_len;
sport = libssh2_ntohu32(s); s += 4;
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "X11 Connection Received from %s:%ld on channel %lu", shost, sport, sender_channel);
#endif
if (session->x11) {
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
goto x11_exit;
}
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->session = session;
channel->channel_type_len = sizeof("x11") - 1;
channel->channel_type = LIBSSH2_ALLOC(session, channel->channel_type_len + 1);
if (!channel->channel_type) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate a channel for new connection", 0);
LIBSSH2_FREE(session, channel);
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
goto x11_exit;
}
memcpy(channel->channel_type, "x11", channel->channel_type_len + 1);
channel->remote.id = sender_channel;
channel->remote.window_size_initial = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
channel->local.id = libssh2_channel_nextid(session);
channel->local.window_size_initial = initial_window_size;
channel->local.window_size = initial_window_size;
channel->local.packet_size = packet_size;
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "X11 Connection established: channel %lu/%lu win %lu/%lu packet %lu/%lu",
channel->local.id, channel->remote.id,
channel->local.window_size, channel->remote.window_size,
channel->local.packet_size, channel->remote.packet_size);
#endif
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
libssh2_htonu32(p, channel->remote.id); p += 4;
libssh2_htonu32(p, channel->local.id); p += 4;
libssh2_htonu32(p, channel->remote.window_size_initial); p += 4;
libssh2_htonu32(p, channel->remote.packet_size); p += 4;
if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1;
}
/* Link the channel into the session */
if (session->channels.tail) {
session->channels.tail->next = channel;
channel->prev = session->channels.tail;
} else {
session->channels.head = channel;
channel->prev = NULL;
}
channel->next = NULL;
session->channels.tail = channel;
/* Pass control to the callback, they may turn right around and free the channel, or actually use it */
LIBSSH2_X11_OPEN(channel, shost, sport);
return 0;
} else {
failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
}
x11_exit:
p = packet;
*(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
libssh2_htonu32(p, sender_channel); p += 4;
libssh2_htonu32(p, failure_code); p += 4;
libssh2_htonu32(p, sizeof("X11 Forward Unavailable") - 1); p += 4;
memcpy(s, "X11 Forward Unavailable", sizeof("X11 Forward Unavailable") - 1); p += sizeof("X11 Forward Unavailable") - 1;
libssh2_htonu32(p, 0);
if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send open failure", 0);
return -1;
}
return 0;
}
/* }}} */
/* {{{ libssh2_packet_new /* {{{ libssh2_packet_new
* Create a new packet and attach it to the brigade * Create a new packet and attach it to the brigade
@@ -316,9 +49,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
LIBSSH2_PACKET *packet; LIBSSH2_PACKET *packet;
unsigned long data_head = 0; unsigned long data_head = 0;
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Packet type %d received, length=%d", (int)data[0], (int)datalen);
#endif
if (macstate == LIBSSH2_MAC_INVALID) { if (macstate == LIBSSH2_MAC_INVALID) {
if (session->macerror) { if (session->macerror) {
if (LIBSSH2_MACERROR(session, data, datalen) == 0) { if (LIBSSH2_MACERROR(session, data, datalen) == 0) {
@@ -367,9 +97,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
if (session->ssh_msg_disconnect) { if (session->ssh_msg_disconnect) {
LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len); LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len);
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Disconnect(%d): %s(%s)", reason, message, language);
#endif
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
return -1; return -1;
@@ -410,10 +137,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
if (session->ssh_msg_debug) { if (session->ssh_msg_debug) {
LIBSSH2_DEBUG(session, always_display, message, message_len, language, language_len); LIBSSH2_DEBUG(session, always_display, message, message_len, language, language_len);
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
/* _libssh2_debug will actually truncate this for us so that it's not an inordinate about of data */
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Debug Packet: %s", message);
#endif
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return 0; return 0;
} }
@@ -430,29 +153,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return 0; return 0;
} }
#ifdef LIBSSH2_DEBUG_CONNECTION
{
unsigned long stream_id = 0;
if (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) {
stream_id = libssh2_ntohu32(data + 5);
}
_libssh2_debug(session, LIBSSH2_DBG_CONN, "%d bytes received for channel %lu/%lu stream #%lu", (int)(datalen - data_head), channel->local.id, channel->remote.id, stream_id);
}
#endif
if ((channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
/* Pretend we didn't receive this */
LIBSSH2_FREE(session, data);
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Ignoring extended data and refunding %d bytes", (int)(datalen - 13));
#endif
/* Adjust the window based on the block we just freed */
libssh2_channel_receive_window_adjust(channel, datalen - 13, 0);
return 0;
}
/* REMEMBER! remote means remote as source of data, NOT remote window! */ /* REMEMBER! remote means remote as source of data, NOT remote window! */
if (channel->remote.packet_size < (datalen - data_head)) { if (channel->remote.packet_size < (datalen - data_head)) {
@@ -460,7 +160,7 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, "Packet contains more data than we offered to receive, truncating", 0); libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, "Packet contains more data than we offered to receive, truncating", 0);
datalen = channel->remote.packet_size + data_head; datalen = channel->remote.packet_size + data_head;
} }
if (channel->remote.window_size <= 0) { if (channel->remote.window_size_initial && (channel->remote.window_size <= 0)) {
/* Spec says we MAY ignore bytes sent beyond window_size */ /* Spec says we MAY ignore bytes sent beyond window_size */
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "The current receive window is full, data ignored", 0); libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "The current receive window is full, data ignored", 0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@@ -469,7 +169,7 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
/* Reset EOF status */ /* Reset EOF status */
channel->remote.eof = 0; channel->remote.eof = 0;
if ((datalen - data_head) > channel->remote.window_size) { if (channel->remote.window_size_initial && ((datalen - data_head) > channel->remote.window_size)) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "Remote sent more data than current window allows, truncating", 0); libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, "Remote sent more data than current window allows, truncating", 0);
datalen = channel->remote.window_size + data_head; datalen = channel->remote.window_size + data_head;
} else { } else {
@@ -488,35 +188,12 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0; return 0;
} }
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "EOF received for channel %lu/%lu", channel->local.id, channel->remote.id);
#endif
channel->remote.eof = 1; channel->remote.eof = 1;
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return 0; return 0;
} }
break; break;
case SSH_MSG_CHANNEL_REQUEST:
{
if (libssh2_ntohu32(data+5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9, sizeof("exit-status") - 1)) {
/* we've got "exit-status" packet. Set the session value */
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data+1));
if (channel) {
channel->exit_status = libssh2_ntohu32(data + 9 + sizeof("exit-status"));
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Exit status %lu received for channel %lu/%lu", channel->exit_status, channel->local.id, channel->remote.id);
#endif
}
LIBSSH2_FREE(session, data);
return 0;
}
}
break;
case SSH_MSG_CHANNEL_CLOSE: case SSH_MSG_CHANNEL_CLOSE:
{ {
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1)); LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1));
@@ -526,9 +203,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return 0; return 0;
} }
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Close received for channel %lu/%lu", channel->local.id, channel->remote.id);
#endif
channel->remote.close = 1; channel->remote.close = 1;
/* TODO: Add a callback for this */ /* TODO: Add a callback for this */
@@ -537,40 +211,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0; return 0;
} }
break; break;
case SSH_MSG_CHANNEL_OPEN:
if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
((sizeof("forwarded-tcpip")-1) == libssh2_ntohu32(data + 1)) &&
(memcmp(data + 5, "forwarded-tcpip", sizeof("forwarded-tcpip") - 1) == 0)) {
int retval = libssh2_packet_queue_listener(session, data, datalen);
LIBSSH2_FREE(session, data);
return retval;
}
if ((datalen >= (sizeof("x11") + 4)) &&
((sizeof("x11")-1) == libssh2_ntohu32(data + 1)) &&
(memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) {
int retval = libssh2_packet_x11_open(session, data, datalen);
LIBSSH2_FREE(session, data);
return retval;
}
break;
case SSH_MSG_CHANNEL_WINDOW_ADJUST:
{
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1));
unsigned long bytestoadd = libssh2_ntohu32(data + 5);
if (channel && bytestoadd) {
channel->local.window_size += bytestoadd;
}
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Window adjust received for channel %lu/%lu, adding %lu bytes, new window_size=%lu", channel->local.id, channel->remote.id, bytestoadd, channel->local.window_size);
#endif
LIBSSH2_FREE(session, data);
return 0;
}
break;
} }
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
@@ -593,14 +233,11 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
packet->prev = NULL; packet->prev = NULL;
} }
if (data[0] == SSH_MSG_KEXINIT && !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) { if (data[0] == SSH_MSG_KEXINIT && !session->exchanging_keys) {
/* Remote wants new keys /* Remote wants new keys
* Well, it's already in the brigade, * Well, it's already in the brigade,
* let's just call back into ourselves * let's just call back into ourselves
*/ */
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Renegotiating Keys");
#endif
libssh2_kex_exchange(session, 1); libssh2_kex_exchange(session, 1);
/* 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 */ /* 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 */
} }
@@ -615,66 +252,18 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, size_t count) static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, size_t count)
{ {
size_t bytes_read = 0; size_t bytes_read = 0;
#if !defined(HAVE_POLL) && !defined(HAVE_SELECT)
int polls = 0; int polls = 0;
#endif
#ifndef WIN32
fcntl(session->socket_fd, F_SETFL, 0);
#else
{
u_long block = FALSE;
ioctlsocket(session->socket_fd, FIONBIO, &block);
}
#endif
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking read: %d bytes", (int)count);
#endif
while (bytes_read < count) { while (bytes_read < count) {
int ret; int ret;
ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, LIBSSH2_SOCKET_RECV_FLAGS(session)); ret = read(session->socket_fd, buf + bytes_read, count - bytes_read);
if (ret < 0) { if (ret < 0) {
#ifdef WIN32
switch (WSAGetLastError()) {
case WSAEWOULDBLOCK: errno = EAGAIN; break;
case WSAENOTCONN:
case WSAENOTSOCK:
case WSAECONNABORTED: errno = EBADF; break;
case WSAEINTR: errno = EINTR; break;
}
#endif
if (errno == EAGAIN) { if (errno == EAGAIN) {
#ifdef HAVE_POLL
struct pollfd read_socket;
read_socket.fd = session->socket_fd;
read_socket.events = POLLIN;
if (poll(&read_socket, 1, 30000) <= 0) {
return -1;
}
#elif defined(HAVE_SELECT)
fd_set read_socket;
struct timeval timeout;
FD_ZERO(&read_socket);
FD_SET(session->socket_fd, &read_socket);
timeout.tv_sec = 30;
timeout.tv_usec = 0;
if (select(session->socket_fd + 1, &read_socket, NULL, NULL, &timeout) <= 0) {
return -1;
}
#else
if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) { if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
return -1; return -1;
} }
usleep(LIBSSH2_SOCKET_POLL_UDELAY); usleep(LIBSSH2_SOCKET_POLL_UDELAY);
#endif /* POLL/SELECT/SLEEP */
continue; continue;
} }
if (errno == EINTR) { if (errno == EINTR) {
@@ -690,10 +279,6 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
bytes_read += ret; bytes_read += ret;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking read: %d bytes actually read", (int)bytes_read);
#endif
return bytes_read; return bytes_read;
} }
/* }}} */ /* }}} */
@@ -712,23 +297,9 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return 0; return 0;
} }
#ifndef WIN32
fcntl(session->socket_fd, F_SETFL, O_NONBLOCK); fcntl(session->socket_fd, F_SETFL, O_NONBLOCK);
#else if (session->newkeys) {
{ unsigned char *block, *payload, *s, tmp[6];
u_long non_block = TRUE;
ioctlsocket(session->socket_fd, FIONBIO, &non_block);
}
#endif
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Checking for packet: will%s block", should_block ? "" : " not");
#endif
if (session->state & LIBSSH2_STATE_NEWKEYS) {
/* Temporary Buffer
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
*/
unsigned char block[2 * 32], *payload, *s, tmp[6];
long read_len; long read_len;
unsigned long blocksize = session->remote.crypt->blocksize; unsigned long blocksize = session->remote.crypt->blocksize;
unsigned long packet_len, payload_len; unsigned long packet_len, payload_len;
@@ -738,19 +309,24 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
/* Safely ignored in CUSTOM cipher mode */ /* Safely ignored in CUSTOM cipher mode */
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)session->remote.crypt_abstract; EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)session->remote.crypt_abstract;
/* Temporary Buffer */
block = LIBSSH2_ALLOC(session, 2 * (blocksize > session->remote.mac->mac_len ? blocksize : session->remote.mac->mac_len));
/* Note: If we add any cipher with a blocksize less than 6 we'll need to get more creative with this /* Note: If we add any cipher with a blocksize less than 6 we'll need to get more creative with this
* For now, all blocksize sizes are 8+ * For now, all blocksize sizes are 8+
*/ */
if (should_block) { if (should_block) {
read_len = libssh2_blocking_read(session, block, blocksize); read_len = libssh2_blocking_read(session, block, blocksize);
} else { } else {
read_len = recv(session->socket_fd, block, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); read_len = read(session->socket_fd, block, 1);
if (read_len <= 0) { if (read_len <= 0) {
LIBSSH2_FREE(session, block);
return 0; return 0;
} }
read_len += libssh2_blocking_read(session, block + read_len, blocksize - read_len); read_len += libssh2_blocking_read(session, block + read_len, blocksize - read_len);
} }
if (read_len < blocksize) { if (read_len < blocksize) {
LIBSSH2_FREE(session, block);
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1; return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
} }
@@ -760,27 +336,16 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
} else { } else {
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) { if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0); libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
LIBSSH2_FREE(session, block);
return -1; return -1;
} }
} }
packet_len = libssh2_ntohu32(block); packet_len = libssh2_ntohu32(block);
padding_len = block[4]; padding_len = block[4];
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Processing packet %lu bytes long (with %lu bytes padding)", packet_len, padding_len);
#endif
memcpy(tmp, block, 5); /* Use this for MAC later */ memcpy(tmp, block, 5); /* Use this for MAC later */
payload_len = packet_len - 1; /* padding_len(1) */ payload_len = packet_len - 1; /* padding_len(1) */
/* Sanity Check */
if ((payload_len > LIBSSH2_PACKET_MAXPAYLOAD) ||
((packet_len + 4) % blocksize)) {
/* If something goes horribly wrong during the decryption phase, just bailout and die gracefully */
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
libssh2_error(session, LIBSSH2_ERROR_PROTO, "Fatal protocol error, invalid payload size", 0);
return -1;
}
s = payload = LIBSSH2_ALLOC(session, payload_len); s = payload = LIBSSH2_ALLOC(session, payload_len);
memcpy(s, block + 5, blocksize - 5); memcpy(s, block + 5, blocksize - 5);
s += blocksize - 5; s += blocksize - 5;
@@ -788,6 +353,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
while ((s - payload) < payload_len) { while ((s - payload) < payload_len) {
read_len = libssh2_blocking_read(session, block, blocksize); read_len = libssh2_blocking_read(session, block, blocksize);
if (read_len < blocksize) { if (read_len < blocksize) {
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload); LIBSSH2_FREE(session, payload);
return -1; return -1;
} }
@@ -797,6 +363,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
} else { } else {
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) { if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0); libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload); LIBSSH2_FREE(session, payload);
return -1; return -1;
} }
@@ -808,6 +375,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
read_len = libssh2_blocking_read(session, block, session->remote.mac->mac_len); read_len = libssh2_blocking_read(session, block, session->remote.mac->mac_len);
if (read_len < session->remote.mac->mac_len) { if (read_len < session->remote.mac->mac_len) {
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload); LIBSSH2_FREE(session, payload);
return -1; return -1;
} }
@@ -816,9 +384,13 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
session->remote.mac->hash(session, block + session->remote.mac->mac_len, session->remote.seqno, tmp, 5, payload, payload_len, &session->remote.mac_abstract); session->remote.mac->hash(session, block + session->remote.mac->mac_len, session->remote.seqno, tmp, 5, payload, payload_len, &session->remote.mac_abstract);
macstate = (strncmp(block, block + session->remote.mac->mac_len, session->remote.mac->mac_len) == 0) ? LIBSSH2_MAC_CONFIRMED : LIBSSH2_MAC_INVALID; macstate = (strncmp(block, block + session->remote.mac->mac_len, session->remote.mac->mac_len) == 0) ? LIBSSH2_MAC_CONFIRMED : LIBSSH2_MAC_INVALID;
/* SMG */
if (macstate == LIBSSH2_MAC_INVALID) libssh2_error(session, -255, "EEEK an error!", 0);
session->remote.seqno++; session->remote.seqno++;
LIBSSH2_FREE(session, block);
/* Ignore padding */ /* Ignore padding */
payload_len -= padding_len; payload_len -= padding_len;
@@ -832,9 +404,6 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
LIBSSH2_FREE(session, payload); LIBSSH2_FREE(session, payload);
return -1; return -1;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Payload decompressed: %lu bytes(compressed) to %lu bytes(uncompressed)", data_len, payload_len);
#endif
if (free_payload) { if (free_payload) {
LIBSSH2_FREE(session, payload); LIBSSH2_FREE(session, payload);
payload = data; payload = data;
@@ -854,6 +423,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
payload = LIBSSH2_ALLOC(session, data_len); payload = LIBSSH2_ALLOC(session, data_len);
if (!payload) { if (!payload) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for copy of uncompressed data", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for copy of uncompressed data", 0);
LIBSSH2_FREE(session, block);
return -1; return -1;
} }
memcpy(payload, data, data_len); memcpy(payload, data, data_len);
@@ -875,7 +445,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
if (should_block) { if (should_block) {
buf_len = libssh2_blocking_read(session, buf, 5); buf_len = libssh2_blocking_read(session, buf, 5);
} else { } else {
buf_len = recv(session->socket_fd, buf, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); buf_len = read(session->socket_fd, buf, 1);
if (buf_len <= 0) { if (buf_len <= 0) {
return 0; return 0;
} }
@@ -887,9 +457,6 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
} }
packet_length = libssh2_ntohu32(buf); packet_length = libssh2_ntohu32(buf);
padding_length = buf[4]; padding_length = buf[4];
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Processing plaintext packet %lu bytes long (with %lu bytes padding)", packet_length, padding_length);
#endif
payload_len = packet_length - padding_length - 1; /* padding_length(1) */ payload_len = packet_length - padding_length - 1; /* padding_length(1) */
payload = LIBSSH2_ALLOC(session, payload_len); payload = LIBSSH2_ALLOC(session, payload_len);
@@ -898,13 +465,8 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1; return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
} }
while (padding_length) { while (padding_length) {
int l;
/* Flush padding */ /* Flush padding */
l = libssh2_blocking_read(session, buf, padding_length); padding_length -= libssh2_blocking_read(session, buf, padding_length);
if (l > 0)
padding_length -= l;
else
break;
} }
/* MACs don't exist in non-encrypted mode */ /* MACs don't exist in non-encrypted mode */
@@ -930,9 +492,6 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
return -1; return -1;
} }
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Looking for packet of type: %d", (int)packet_type);
#endif
while (packet) { while (packet) {
if (packet->data[0] == packet_type && if (packet->data[0] == packet_type &&
(packet->data_len >= (match_ofs + match_len)) && (packet->data_len >= (match_ofs + match_len)) &&
@@ -962,27 +521,9 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_askv
* Scan for any of a list of packet types in the brigade, optionally poll the socket for a packet first
*/
int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket)
{
int i, packet_types_len = strlen(packet_types);
for(i = 0; i < packet_types_len; i++) {
if (0 == libssh2_packet_ask_ex(session, packet_types[i], data, data_len, match_ofs, match_buf, match_len, i ? 0 : poll_socket)) {
return 0;
}
}
return -1;
}
/* }}} */
/* {{{ libssh2_packet_require /* {{{ libssh2_packet_require
* Loops libssh2_packet_read() until the packet requested is available * Loops libssh2_packet_read() until the packet requested is available
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout * SSH_DISCONNECT will cause a bailout though
*/ */
int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len) unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len)
@@ -992,9 +533,6 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
return 0; return 0;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet of type %d becomes available", (int)packet_type);
#endif
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
int ret = libssh2_packet_read(session, 1); int ret = libssh2_packet_read(session, 1);
if (ret < 0) { if (ret < 0) {
@@ -1013,39 +551,6 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
} }
/* }}} */ /* }}} */
/* {{{ libssh2_packet_requirev
* Loops libssh2_packet_read() until one of a list of packet types requested is available
* SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
* packet_types is a null terminated list of packet_type numbers
*/
int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len)
{
if (libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0) == 0) {
/* One of the packets listed was available in the packet brigade */
return 0;
}
while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
int ret = libssh2_packet_read(session, 1);
if (ret < 0) {
return -1;
}
if (ret == 0) {
continue;
}
if (strchr(packet_types, ret)) {
/* Be lazy, let packet_ask pull it out of the brigade */
return libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0);
}
}
/* Only reached if the socket died */
return -1;
}
/* }}} */
/* {{{ libssh2_packet_write /* {{{ libssh2_packet_write
* Send a packet, encrypting it and adding a MAC code if necessary * Send a packet, encrypting it and adding a MAC code if necessary
* Returns 0 on success, non-zero on failure * Returns 0 on success, non-zero on failure
@@ -1053,42 +558,22 @@ int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_t
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len) int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len)
{ {
unsigned long packet_length = data_len + 1; unsigned long packet_length = data_len + 1;
unsigned long block_size = (session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->blocksize : 8; unsigned long block_size = (session->newkeys) ? session->local.crypt->blocksize : 8;
/* At this point packet_length doesn't include the packet_len field itself */ /* At this point packet_length doesn't include the packet_len field itself */
unsigned long padding_length; unsigned long padding_length;
int free_data = 0; int free_data = 0;
unsigned char buf[246]; /* 6 byte header plus max padding size(240) */ unsigned char buf[246]; /* 6 byte header plus max padding size(240) */
int i;
#ifdef LIBSSH2_DEBUG_TRANSPORT if (session->newkeys &&
{
/* Show a hint of what's being sent */
char excerpt[32];
int ex_len = 0, db_ofs = 0;
for (; ex_len < 24 && db_ofs < data_len; ex_len += 3, db_ofs++) snprintf(excerpt + ex_len, 4, "%02X ", data[db_ofs]);
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending packet type %d, length=%lu, %s", (int)data[0], data_len, excerpt);
}
#endif
if ((session->state & LIBSSH2_STATE_NEWKEYS) &&
strcmp(session->local.comp->name, "none")) { 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 -1; return -1;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Compressed payload to %lu bytes", data_len);
#endif
} }
#ifndef WIN32
fcntl(session->socket_fd, F_SETFL, 0); fcntl(session->socket_fd, F_SETFL, 0);
#else
{
u_long non_block = FALSE;
ioctlsocket(session->socket_fd, FIONBIO, &non_block);
}
#endif
packet_length = data_len + 1; /* padding_length(1) -- MAC doesn't count -- Padding to be added soon */ packet_length = data_len + 1; /* padding_length(1) -- MAC doesn't count -- Padding to be added soon */
padding_length = block_size - ((packet_length + 4) % block_size); padding_length = block_size - ((packet_length + 4) % block_size);
if (padding_length < 4) { if (padding_length < 4) {
@@ -1099,11 +584,13 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
packet_length += padding_length; packet_length += padding_length;
libssh2_htonu32(buf, packet_length); libssh2_htonu32(buf, packet_length);
buf[4] = padding_length; buf[4] = padding_length;
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending packet with total length %lu (%lu bytes padding)", packet_length, padding_length);
#endif
if (session->state & LIBSSH2_STATE_NEWKEYS) { for (i = 0; i < padding_length; i++) {
/* Make random */
buf[5 + i] = '\0';
}
if (session->newkeys) {
/* Encryption is in effect */ /* Encryption is in effect */
unsigned char *encbuf, *s; unsigned char *encbuf, *s;
int ret; int ret;
@@ -1124,7 +611,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
/* Copy packet to encoding buffer */ /* Copy packet to encoding buffer */
memcpy(encbuf, buf, 5); memcpy(encbuf, buf, 5);
memcpy(encbuf + 5, data, data_len); memcpy(encbuf + 5, data, data_len);
RAND_bytes(encbuf + 5 + data_len, padding_length); memcpy(encbuf + 5 + data_len, buf + 5, padding_length);
if (free_data) { if (free_data) {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
} }
@@ -1145,7 +632,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
session->local.seqno++; session->local.seqno++;
/* Send It */ /* Send It */
ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, LIBSSH2_SOCKET_SEND_FLAGS(session))) ? 0 : -1; ret = ((4 + packet_length + session->local.mac->mac_len) == write(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len)) ? 0 : -1;
/* Cleanup environment */ /* Cleanup environment */
LIBSSH2_FREE(session, encbuf); LIBSSH2_FREE(session, encbuf);

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -37,6 +37,7 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define LIBSSH2_SCP_RESPONSE_BUFLEN 256 #define LIBSSH2_SCP_RESPONSE_BUFLEN 256
@@ -44,7 +45,7 @@
/* {{{ libssh2_scp_recv /* {{{ libssh2_scp_recv
* Open a channel and request a remote file via SCP * Open a channel and request a remote file via SCP
*/ */
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb) LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, char *path, struct stat *sb)
{ {
int path_len = strlen(path); int path_len = strlen(path);
unsigned char *command, response[LIBSSH2_SCP_RESPONSE_BUFLEN]; unsigned char *command, response[LIBSSH2_SCP_RESPONSE_BUFLEN];
@@ -70,16 +71,11 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
command[command_len - 1] = '\0'; command[command_len - 1] = '\0';
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Opening channel for SCP receive");
#endif
/* Allocate a channel */ /* Allocate a channel */
if ((channel = libssh2_channel_open_session(session)) == NULL) { if ((channel = libssh2_channel_open_session(session)) == NULL) {
LIBSSH2_FREE(session, command); LIBSSH2_FREE(session, command);
return NULL; return NULL;
} }
/* Use blocking I/O for negotiation phase */
libssh2_channel_set_blocking(channel, 1);
/* Request SCP for the desired file */ /* Request SCP for the desired file */
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) { if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
@@ -89,9 +85,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
} }
LIBSSH2_FREE(session, command); LIBSSH2_FREE(session, command);
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sending initial wakeup");
#endif
/* SCP ACK */ /* SCP ACK */
response[0] = '\0'; response[0] = '\0';
if (libssh2_channel_write(channel, response, 1) != 1) { if (libssh2_channel_write(channel, response, 1) != 1) {
@@ -203,9 +196,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
libssh2_channel_free(channel); libssh2_channel_free(channel);
return NULL; return NULL;
} }
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "mtime = %ld, atime = %ld", mtime, atime);
#endif
/* We *should* check that atime.usec is valid, but why let that stop use? */ /* We *should* check that atime.usec is valid, but why let that stop use? */
break; break;
@@ -304,9 +294,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
libssh2_channel_free(channel); libssh2_channel_free(channel);
return NULL; return NULL;
} }
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "mod = 0%lo size = %ld", mode, size);
#endif
/* We *should* check that basename is valid, but why let that stop us? */ /* We *should* check that basename is valid, but why let that stop us? */
break; break;
@@ -320,8 +307,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
sb->st_size = size; sb->st_size = size;
sb->st_mode = mode; sb->st_mode = mode;
} }
/* Revert to non-blocking and let the data BEGIN! */ /* Let the data BEGIN! */
libssh2_channel_set_blocking(channel, 0);
return channel; return channel;
} }
@@ -330,12 +316,11 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const ch
/* {{{ libssh2_scp_send_ex /* {{{ libssh2_scp_send_ex
* Send a file using SCP * Send a file using SCP
*/ */
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime) LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char *path, int mode, size_t size, long mtime, long atime)
{ {
int path_len = strlen(path); int path_len = strlen(path);
unsigned char *command, response[LIBSSH2_SCP_RESPONSE_BUFLEN]; unsigned char *command, *base, response[LIBSSH2_SCP_RESPONSE_BUFLEN];
unsigned long response_len, command_len = path_len + sizeof("scp -t "); unsigned long response_len, command_len = path_len + sizeof("scp -t ");
unsigned const char *base;
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
if (mtime || atime) { if (mtime || atime) {
@@ -357,21 +342,14 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const
} }
command[command_len - 1] = '\0'; command[command_len - 1] = '\0';
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Opening channel for SCP send");
#endif
/* Allocate a channel */ /* Allocate a channel */
if ((channel = libssh2_channel_open_session(session)) == NULL) { if ((channel = libssh2_channel_open_session(session)) == NULL) {
/* previous call set libssh2_session_last_error(), pass it through */
LIBSSH2_FREE(session, command); LIBSSH2_FREE(session, command);
return NULL; return NULL;
} }
/* Use blocking I/O for negotiation phase */
libssh2_channel_set_blocking(channel, 1);
/* Request SCP for the desired file */ /* Request SCP for the desired file */
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) { if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
/* previous call set libssh2_session_last_error(), pass it through */
LIBSSH2_FREE(session, command); LIBSSH2_FREE(session, command);
libssh2_channel_free(channel); libssh2_channel_free(channel);
return NULL; return NULL;
@@ -388,9 +366,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const
/* Send mtime and atime to be used for file */ /* Send mtime and atime to be used for file */
if (mtime || atime) { if (mtime || atime) {
response_len = snprintf(response, LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime, atime); response_len = snprintf(response, LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime, atime);
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s", response);
#endif
if (libssh2_channel_write(channel, response, response_len) != response_len) { if (libssh2_channel_write(channel, response, response_len) != response_len) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send time data for SCP file", 0);
libssh2_channel_free(channel); libssh2_channel_free(channel);
@@ -413,9 +388,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const
} }
response_len = snprintf(response, LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode, (unsigned long)size, base); response_len = snprintf(response, LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode, (unsigned long)size, base);
#ifdef LIBSSH2_DEBUG_SCP
_libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s", response);
#endif
if (libssh2_channel_write(channel, response, response_len) != response_len) { if (libssh2_channel_write(channel, response, response_len) != response_len) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send core file data for SCP file", 0);
libssh2_channel_free(channel); libssh2_channel_free(channel);
@@ -428,8 +400,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const
return NULL; return NULL;
} }
/* Ready to start, switch to non-blocking and let calling app send file */ /* Ready to send file */
libssh2_channel_set_blocking(channel, 0);
return channel; return channel;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -37,31 +37,9 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <errno.h> #include <errno.h>
#ifndef WIN32
#include <unistd.h> #include <unistd.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#include <math.h>
#endif
#ifdef HAVE_POLL
# include <sys/poll.h>
#else
# ifdef HAVE_SELECT
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
# include <sys/time.h>
# include <sys/types.h>
# endif
# endif
#endif
/* {{{ libssh2_default_alloc /* {{{ libssh2_default_alloc
*/ */
static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc) static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
@@ -101,7 +79,7 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
char c = '\0'; char c = '\0';
int ret; int ret;
ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); ret = read(session->socket_fd, &c, 1);
if ((ret < 0) && (ret != EAGAIN)) { if ((ret < 0) && (ret != EAGAIN)) {
/* Some kinda error, but don't break for non-blocking issues */ /* Some kinda error, but don't break for non-blocking issues */
@@ -128,9 +106,6 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
memcpy(session->remote.banner, banner, banner_len); memcpy(session->remote.banner, banner, banner_len);
session->remote.banner[banner_len] = '\0'; session->remote.banner[banner_len] = '\0';
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s", session->remote.banner);
#endif
return 0; return 0;
} }
/* }}} */ /* }}} */
@@ -148,59 +123,8 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
banner_len = strlen(session->local.banner); banner_len = strlen(session->local.banner);
banner = session->local.banner; banner = session->local.banner;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
{
/* Hack and slash to avoid sending CRLF in debug output */
char banner_dup[256];
if (banner_len < 256) { return (write(session->socket_fd, banner, banner_len) == banner_len) ? 0 : 1;
memcpy(banner_dup, banner, banner_len - 2);
banner_dup[banner_len - 2] = '\0';
} else {
memcpy(banner_dup, banner, 255);
banner[255] = '\0';
}
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s", banner_dup);
}
#endif
return (send(session->socket_fd, banner, banner_len, LIBSSH2_SOCKET_SEND_FLAGS(session)) == banner_len) ? 0 : 1;
}
/* }}} */
/* {{{ libssh2_banner_set
* Set the local banner
*/
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, const char *banner)
{
int banner_len = banner ? strlen(banner) : 0;
if (session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
session->local.banner = NULL;
}
if (!banner_len) {
return 0;
}
session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
if (!session->local.banner) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner", 0);
return -1;
}
memcpy(session->local.banner, banner, banner_len);
#ifdef LIBSSH2_DEBUG_TRANSPORT
session->local.banner[banner_len] = '\0';
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s", session->local.banner);
#endif
session->local.banner[banner_len++] = '\r';
session->local.banner[banner_len++] = '\n';
session->local.banner[banner_len++] = '\0';
return 0;
} }
/* }}} */ /* }}} */
@@ -231,57 +155,11 @@ LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(
session->free = local_free; session->free = local_free;
session->realloc = local_realloc; session->realloc = local_realloc;
session->abstract = abstract; session->abstract = abstract;
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "New session resource allocated");
#endif
return session; return session;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_callback_set
* Set (or reset) a callback function
* Returns the prior address
*/
LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback)
{
void *oldcb;
switch (cbtype) {
case LIBSSH2_CALLBACK_IGNORE:
oldcb = session->ssh_msg_ignore;
session->ssh_msg_ignore = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_DEBUG:
oldcb = session->ssh_msg_debug;
session->ssh_msg_debug = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_DISCONNECT:
oldcb = session->ssh_msg_disconnect;
session->ssh_msg_disconnect = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_MACERROR:
oldcb = session->macerror;
session->macerror = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_X11:
oldcb = session->x11;
session->x11 = callback;
return oldcb;
break;
}
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting Callback %d", cbtype);
#endif
return NULL;
}
/* }}} */
/* {{{ proto libssh2_session_startup /* {{{ proto libssh2_session_startup
* session: LIBSSH2_SESSION struct allocated and owned by the calling program * session: LIBSSH2_SESSION struct allocated and owned by the calling program
* Returns: 0 on success, or non-zero on failure * Returns: 0 on success, or non-zero on failure
@@ -295,9 +173,6 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
unsigned char service[sizeof("ssh-userauth") + 5 - 1]; unsigned char service[sizeof("ssh-userauth") + 5 - 1];
unsigned long service_length; unsigned long service_length;
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "session_startup for socket %d", socket);
#endif
if (socket <= 0) { if (socket <= 0) {
/* Did we forget something? */ /* Did we forget something? */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE, "No socket provided", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE, "No socket provided", 0);
@@ -306,11 +181,6 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
session->socket_fd = socket; session->socket_fd = socket;
/* TODO: Liveness check */ /* TODO: Liveness check */
if (libssh2_banner_send(session)) {
/* Unable to send banner? */
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND, "Error sending banner to remote host", 0);
return LIBSSH2_ERROR_BANNER_SEND;
}
if (libssh2_banner_receive(session)) { if (libssh2_banner_receive(session)) {
/* Unable to receive banner from remote */ /* Unable to receive banner from remote */
@@ -318,14 +188,17 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
return LIBSSH2_ERROR_BANNER_NONE; return LIBSSH2_ERROR_BANNER_NONE;
} }
if (libssh2_banner_send(session)) {
/* Unable to send banner? */
libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND, "Error sending banner to remote host", 0);
return LIBSSH2_ERROR_BANNER_SEND;
}
if (libssh2_kex_exchange(session, 0)) { if (libssh2_kex_exchange(session, 0)) {
libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0); libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE, "Unable to exchange encryption keys", 0);
return LIBSSH2_ERROR_KEX_FAILURE; return LIBSSH2_ERROR_KEX_FAILURE;
} }
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Requesting userauth service");
#endif
/* Request the userauth service */ /* Request the userauth service */
service[0] = SSH_MSG_SERVICE_REQUEST; service[0] = SSH_MSG_SERVICE_REQUEST;
libssh2_htonu32(service + 1, sizeof("ssh-userauth") - 1); libssh2_htonu32(service + 1, sizeof("ssh-userauth") - 1);
@@ -358,9 +231,6 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
*/ */
LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session) LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
{ {
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource", session->remote.banner);
#endif
while (session->channels.head) { while (session->channels.head) {
LIBSSH2_CHANNEL *tmp = session->channels.head; LIBSSH2_CHANNEL *tmp = session->channels.head;
@@ -379,11 +249,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
} }
} }
while (session->listeners) { if (session->newkeys) {
libssh2_channel_forward_cancel(session->listeners);
}
if (session->state & LIBSSH2_STATE_NEWKEYS) {
/* hostkey */ /* hostkey */
if (session->hostkey && session->hostkey->dtor) { if (session->hostkey && session->hostkey->dtor) {
session->hostkey->dtor(session, &session->server_hostkey_abstract); session->hostkey->dtor(session, &session->server_hostkey_abstract);
@@ -437,7 +303,6 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
} }
} }
/* Free banner(s) */
if (session->remote.banner) { if (session->remote.banner) {
LIBSSH2_FREE(session, session->remote.banner); LIBSSH2_FREE(session, session->remote.banner);
} }
@@ -445,40 +310,6 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, session->local.banner); LIBSSH2_FREE(session, session->local.banner);
} }
/* Free preference(s) */
if (session->kex_prefs) {
LIBSSH2_FREE(session, session->kex_prefs);
}
if (session->hostkey_prefs) {
LIBSSH2_FREE(session, session->hostkey_prefs);
}
if (session->local.crypt_prefs) {
LIBSSH2_FREE(session, session->local.crypt_prefs);
}
if (session->local.mac_prefs) {
LIBSSH2_FREE(session, session->local.mac_prefs);
}
if (session->local.comp_prefs) {
LIBSSH2_FREE(session, session->local.comp_prefs);
}
if (session->local.lang_prefs) {
LIBSSH2_FREE(session, session->local.lang_prefs);
}
if (session->remote.crypt_prefs) {
LIBSSH2_FREE(session, session->remote.crypt_prefs);
}
if (session->remote.mac_prefs) {
LIBSSH2_FREE(session, session->remote.mac_prefs);
}
if (session->remote.comp_prefs) {
LIBSSH2_FREE(session, session->remote.comp_prefs);
}
if (session->remote.lang_prefs) {
LIBSSH2_FREE(session, session->remote.lang_prefs);
}
/* Cleanup any remaining packets */ /* Cleanup any remaining packets */
while (session->packets.head) { while (session->packets.head) {
LIBSSH2_PACKET *tmp = session->packets.head; LIBSSH2_PACKET *tmp = session->packets.head;
@@ -491,20 +322,21 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, tmp); LIBSSH2_FREE(session, tmp);
} }
if (session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
}
LIBSSH2_FREE(session, session); LIBSSH2_FREE(session, session);
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_disconnect_ex /* {{{ libssh2_session_disconnect_ex
*/ */
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang) LIBSSH2_API void libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang)
{ {
unsigned char *s, *data; unsigned char *data;
unsigned long data_len, descr_len = 0, lang_len = 0; unsigned long data_len, descr_len = 0, lang_len = 0;
#ifdef LIBSSH2_DEBUG_TRANSPORT
_libssh2_debug(session, LIBSSH2_DBG_TRANS, "Disconnecting: reason=%d, desc=%s, lang=%s", reason, description, lang);
#endif
if (description) { if (description) {
descr_len = strlen(description); descr_len = strlen(description);
} }
@@ -513,454 +345,28 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
} }
data_len = descr_len + lang_len + 13; /* packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */ data_len = descr_len + lang_len + 13; /* packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len); data = LIBSSH2_ALLOC(session, data_len);
if (!data) { if (data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for disconnect packet", 0); unsigned char *s = data;
return -1;
*(s++) = SSH_MSG_DISCONNECT;
libssh2_htonu32(s, reason); s += 4;
libssh2_htonu32(s, descr_len); s += 4;
if (description) {
memcpy(s, description, descr_len);
s += descr_len;
}
libssh2_htonu32(s, lang_len); s += 4;
if (lang) {
memcpy(s, lang, lang_len);
s += lang_len;
}
libssh2_packet_write(session, data, data_len);
LIBSSH2_FREE(session, data);
} }
*(s++) = SSH_MSG_DISCONNECT;
libssh2_htonu32(s, reason); s += 4;
libssh2_htonu32(s, descr_len); s += 4;
if (description) {
memcpy(s, description, descr_len);
s += descr_len;
}
libssh2_htonu32(s, lang_len); s += 4;
if (lang) {
memcpy(s, lang, lang_len);
s += lang_len;
}
libssh2_packet_write(session, data, data_len);
LIBSSH2_FREE(session, data);
return 0;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_session_methods
* Return the currently active methods for method_type
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
* Strings should NOT be freed
*/
LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type)
{
/* All methods have char *name as their first element */
LIBSSH2_KEX_METHOD *method = NULL;
switch(method_type) {
case LIBSSH2_METHOD_KEX:
method = session->kex;
break;
case LIBSSH2_METHOD_HOSTKEY:
method = (LIBSSH2_KEX_METHOD*)session->hostkey;
break;
case LIBSSH2_METHOD_CRYPT_CS:
method = (LIBSSH2_KEX_METHOD*)session->local.crypt;
break;
case LIBSSH2_METHOD_CRYPT_SC:
method = (LIBSSH2_KEX_METHOD*)session->remote.crypt;
break;
case LIBSSH2_METHOD_MAC_CS:
method = (LIBSSH2_KEX_METHOD*)session->local.mac;
break;
case LIBSSH2_METHOD_MAC_SC:
method = (LIBSSH2_KEX_METHOD*)session->remote.mac;
break;
case LIBSSH2_METHOD_COMP_CS:
method = (LIBSSH2_KEX_METHOD*)session->local.comp;
break;
case LIBSSH2_METHOD_COMP_SC:
method = (LIBSSH2_KEX_METHOD*)session->remote.comp;
break;
case LIBSSH2_METHOD_LANG_CS:
return "";
break;
case LIBSSH2_METHOD_LANG_SC:
return "";
break;
default:
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
return NULL;
break;
}
if (!method) {
libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, "No method negotiated", 0);
return NULL;
}
return method->name;
}
/* }}} */
/* {{{ libssh2_session_abstract
* Retrieve a pointer to the abstract property
*/
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session)
{
return &session->abstract;
}
/* }}} */
/* {{{ libssh2_session_last_error
* Returns error code and populates an error string into errmsg
* If want_buf is non-zero then the string placed into errmsg must be freed by the calling program
* Otherwise it is assumed to be owned by libssh2
*/
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf)
{
/* No error to report */
if (!session->err_code) {
if (errmsg) {
if (want_buf) {
*errmsg = LIBSSH2_ALLOC(session, 1);
if (*errmsg) {
**errmsg = 0;
}
} else {
*errmsg = "";
}
}
if (errmsg_len) {
*errmsg_len = 0;
}
return 0;
}
if (errmsg) {
char *serrmsg = session->err_msg ? session->err_msg : "";
int ownbuf = session->err_msg ? session->err_should_free : 0;
if (want_buf) {
if (ownbuf) {
/* Just give the calling program the buffer */
*errmsg = serrmsg;
session->err_should_free = 0;
} else {
/* Make a copy so the calling program can own it */
*errmsg = LIBSSH2_ALLOC(session, session->err_msglen + 1);
if (*errmsg) {
memcpy(*errmsg, session->err_msg, session->err_msglen);
(*errmsg)[session->err_msglen] = 0;
}
}
} else {
*errmsg = serrmsg;
}
}
if (errmsg_len) {
*errmsg_len = session->err_msglen;
}
return session->err_code;
}
/* }}} */
/* {{{ libssh2_session_flag
* Set/Get session flags
* Passing flag==0 will avoid changing session->flags while still returning its current value
*/
LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value)
{
if (value) {
session->flags |= flag;
} else {
session->flags &= ~flag;
}
return session->flags;
}
/* }}} */
/* {{{ libssh2_poll_channel_read
* Returns 0 if no data is waiting on channel,
* non-0 if data is available
*/
LIBSSH2_API int 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;
}
packet = packet->next;
}
return 0;
}
/* }}} */
/* {{{ libssh2_poll_channel_write
* Returns 0 if writing to channel would block,
* non-0 if data can be written without blocking
*/
inline int libssh2_poll_channel_write(LIBSSH2_CHANNEL *channel)
{
return channel->local.window_size ? 1 : 0;
}
/* }}} */
/* {{{ libssh2_poll_listener_queued
* Returns 0 if no connections are waiting to be accepted
* non-0 if one or more connections are available
*/
inline int libssh2_poll_listener_queued(LIBSSH2_LISTENER *listener)
{
return listener->queue ? 1 : 0;
}
/* }}} */
/* {{{ libssh2_poll
* Poll sockets, channels, and listeners for activity
*/
LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
{
long timeout_remaining;
int i, active_fds;
#ifdef HAVE_POLL
LIBSSH2_SESSION *session = NULL;
struct pollfd sockets[nfds];
/* Setup sockets for polling */
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
sockets[i].fd = fds[i].fd.socket;
sockets[i].events = fds[i].events;
sockets[i].revents = 0;
break;
case LIBSSH2_POLLFD_CHANNEL:
sockets[i].fd = fds[i].fd.channel->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
if (!session) session = fds[i].fd.channel->session;
break;
case LIBSSH2_POLLFD_LISTENER:
sockets[i].fd = fds[i].fd.listener->session->socket_fd;
sockets[i].events = POLLIN;
sockets[i].revents = 0;
if (!session) session = fds[i].fd.listener->session;
break;
default:
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()", 0);
return -1;
}
}
#elif defined(HAVE_SELECT)
LIBSSH2_SESSION *session = NULL;
int maxfd = 0;
fd_set rfds,wfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
if (fds[i].events & LIBSSH2_POLLFD_POLLIN) {
FD_SET(fds[i].fd.socket, &rfds);
if (fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket;
}
if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
FD_SET(fds[i].fd.socket, &wfds);
if (fds[i].fd.socket > maxfd) maxfd = fds[i].fd.socket;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
if (fds[i].fd.channel->session->socket_fd > maxfd) maxfd = fds[i].fd.channel->session->socket_fd;
if (!session) session = fds[i].fd.channel->session;
break;
case LIBSSH2_POLLFD_LISTENER:
FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
if (fds[i].fd.listener->session->socket_fd > maxfd) maxfd = fds[i].fd.listener->session->socket_fd;
if (!session) session = fds[i].fd.listener->session;
break;
default:
if (session) libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE, "Invalid descriptor passed to libssh2_poll()", 0);
return -1;
}
}
#else
/* No select() or poll()
* no sockets sturcture to setup
*/
timeout = 0;
#endif /* HAVE_POLL or HAVE_SELECT */
timeout_remaining = timeout;
do {
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
int sysret;
#endif
active_fds = 0;
for (i = 0; i < nfds; i++) {
if (fds[i].events != fds[i].revents) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_CHANNEL:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 0) ? LIBSSH2_POLLFD_POLLIN : 0;
}
if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */
((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */
fds[i].revents |= libssh2_poll_channel_read(fds[i].fd.channel, 1) ? LIBSSH2_POLLFD_POLLEXT : 0;
}
if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */
((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */
fds[i].revents |= libssh2_poll_channel_write(fds[i].fd.channel) ? LIBSSH2_POLLFD_POLLOUT : 0;
}
if (fds[i].fd.channel->remote.close || fds[i].fd.channel->local.close) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
}
if (fds[i].fd.channel->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
}
break;
case LIBSSH2_POLLFD_LISTENER:
if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */
((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */
fds[i].revents |= libssh2_poll_listener_queued(fds[i].fd.listener) ? LIBSSH2_POLLFD_POLLIN : 0;
}
if (fds[i].fd.listener->session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
}
break;
}
}
if (fds[i].revents) {
active_fds++;
}
}
if (active_fds) {
/* Don't block on the sockets if we have channels/listeners which are ready */
timeout_remaining = 0;
}
#ifdef HAVE_POLL
#ifdef HAVE_GETTIMEOFDAY
{
struct timeval tv_begin, tv_end;
gettimeofday((struct timeval *)&tv_begin, NULL);
sysret = poll(sockets, nfds, timeout_remaining);
gettimeofday((struct timeval *)&tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
timeout_remaining -= ceil((tv_end.tv_usec - tv_begin.tv_usec) / 1000);
}
#else
/* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away
*/
sysret = poll(sockets, nfds, timeout_remaining);
timeout_remaining = 0;
#endif /* HAVE_GETTIMEOFDAY */
if (sysret > 0) {
for (i = 0; i < nfds; i++) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
fds[i].revents = sockets[i].revents;
sockets[i].revents = 0; /* In case we loop again, be nice */
if (fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
if (sockets[i].events & POLLIN) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session, 0) > 0);
}
if (sockets[i].revents & POLLHUP) {
fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
}
sockets[i].revents = 0;
break;
case LIBSSH2_POLLFD_LISTENER:
if (sockets[i].events & POLLIN) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session, 0) > 0);
}
if (sockets[i].revents & POLLHUP) {
fds[i].revents |= LIBSSH2_POLLFD_LISTENER_CLOSED | LIBSSH2_POLLFD_SESSION_CLOSED;
}
sockets[i].revents = 0;
break;
}
}
}
#elif defined(HAVE_SELECT)
tv.tv_sec = timeout_remaining / 1000;
tv.tv_usec = (timeout_remaining % 1000) * 1000;
#ifdef HAVE_GETTIMEOFDAY
{
struct timeval tv_begin, tv_end;
gettimeofday((struct timeval *)&tv_begin, NULL);
sysret = select(maxfd, &rfds, &wfds, NULL, &tv);
gettimeofday((struct timeval *)&tv_end, NULL);
timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
timeout_remaining -= ceil((tv_end.tv_usec - tv_begin.tv_usec) / 1000);
}
#else
/* If the platform doesn't support gettimeofday,
* then just make the call non-blocking and walk away
*/
sysret = select(maxfd, &rfds, &wfds, NULL, &tv);
timeout_remaining = 0;
#endif
if (sysret > 0) {
for (i = 0; i < nfds; i++) {
switch (fds[i].type) {
case LIBSSH2_POLLFD_SOCKET:
if (FD_ISSET(fds[i].fd.socket, &rfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
}
if (FD_ISSET(fds[i].fd.socket, &wfds)) {
fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
}
if (fds[i].revents) {
active_fds++;
}
break;
case LIBSSH2_POLLFD_CHANNEL:
if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.channel->session, 0) > 0);
}
break;
case LIBSSH2_POLLFD_LISTENER:
if (FD_ISSET(fds[i].fd.listener->session->socket_fd, &rfds)) {
/* Spin session until no data available */
while (libssh2_packet_read(fds[i].fd.listener->session, 0) > 0);
}
break;
}
}
}
#endif /* else no select() or poll() -- timeout (and by extension timeout_remaining) will be equal to 0 */
} while ((timeout_remaining > 0) && !active_fds);
return active_fds;
}
/* }}} */

1471
src/sftp.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004-2005, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@@ -36,12 +36,7 @@
*/ */
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <stdio.h>
/* Needed for struct iovec on some platforms */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
/* {{{ proto libssh2_userauth_list /* {{{ proto libssh2_userauth_list
* List authentication methods * List authentication methods
@@ -49,9 +44,8 @@
* Not a common configuration for any SSH server though * Not a common configuration for any SSH server though
* username should be NULL, or a null terminated string * username should be NULL, or a null terminated string
*/ */
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, int username_len) LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len)
{ {
unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long data_len = username_len + 31; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + unsigned long data_len = username_len + 31; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" +
method_len(4) + method(4)"none" */ method_len(4) + method(4)"none" */
unsigned long methods_len; unsigned long methods_len;
@@ -82,23 +76,25 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *us
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) { while (1) {
return NULL; if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
} /* Wow, who'dve thought... */
LIBSSH2_FREE(session, data);
session->authenticated = 1;
return NULL;
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* Wow, who'dve thought... */ /* What we *actually* wanted to happen */
LIBSSH2_FREE(session, data); break;
session->state |= LIBSSH2_STATE_AUTHENTICATED; }
return NULL; /* TODO: Timeout? */
} }
methods_len = libssh2_ntohu32(data + 1); methods_len = libssh2_ntohu32(data + 1);
memcpy(data, data + 5, methods_len); memcpy(data, data + 5, methods_len);
data[methods_len] = '\0'; data[methods_len] = '\0';
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s", data);
#endif
return data; return data;
} }
/* }}} */ /* }}} */
@@ -109,18 +105,18 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *us
*/ */
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session) LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session)
{ {
return session->state & LIBSSH2_STATE_AUTHENTICATED; return session->authenticated;
} }
/* }}} */ /* }}} */
/* {{{ libssh2_userauth_password /* {{{ libssh2_userauth_password
* Plain ol' login * Plain ol' login
*/ */
LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, int username_len, LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, char *username, int username_len,
const char *password, int password_len, char *password, int password_len,
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
{ {
unsigned char *data, *s, reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0 }; unsigned char *data, *s;
unsigned long data_len = username_len + password_len + 40; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + unsigned long data_len = username_len + password_len + 40; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" +
method_len(4) + method(8)"password" + chgpwdbool(1) + password_len(4) */ method_len(4) + method(8)"password" + chgpwdbool(1) + password_len(4) */
@@ -145,9 +141,6 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const cha
libssh2_htonu32(s, password_len); s += 4; libssh2_htonu32(s, password_len); s += 4;
memcpy(s, password, password_len); s += password_len; memcpy(s, password, password_len); s += password_len;
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting to login using password authentication");
#endif
if (libssh2_packet_write(session, data, data_len)) { if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password request", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password request", 0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@@ -155,78 +148,71 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const cha
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
password_response: while (1) {
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
return -1;
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Password authentication successful");
#endif
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (data[0] == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) {
char *newpw = NULL;
int newpw_len = 0;
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Password change required");
#endif
LIBSSH2_FREE(session, data);
if (passwd_change_cb) {
passwd_change_cb(session, &newpw, &newpw_len, &session->abstract);
if (!newpw) {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and callback failed", 0);
return -1;
}
data_len = username_len + password_len + 44 + newpw_len; /* basic data_len + newpw_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth-password-change request", 0);
return -1;
}
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
libssh2_htonu32(s, sizeof("ssh-connection") - 1); s += 4;
memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1); s += sizeof("ssh-connection") - 1;
libssh2_htonu32(s, sizeof("password") - 1); s += 4;
memcpy(s, "password", sizeof("password") - 1); s += sizeof("password") - 1;
*s = 0xFF; s++;
libssh2_htonu32(s, password_len); s += 4;
memcpy(s, password, password_len); s += password_len;
libssh2_htonu32(s, newpw_len); s += 4;
memcpy(s, newpw, newpw_len); s += newpw_len;
if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password-change request", 0);
LIBSSH2_FREE(session, data);
return -1;
}
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, newpw); session->authenticated = 1;
return 0;
}
/* Ugliest use of goto ever. Blame it on the askN => requirev migration. */ if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
goto password_response; LIBSSH2_FREE(session, data);
} else {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback specified", 0);
return -1; return -1;
} }
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, &data, &data_len, 0) == 0) {
char *newpw = NULL;
int newpw_len = 0;
LIBSSH2_FREE(session, data);
if (passwd_change_cb) {
passwd_change_cb(session, &newpw, &newpw_len, &session->abstract);
if (!newpw) {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and callback failed", 0);
return -1;
}
data_len = username_len + password_len + 44 + newpw_len; /* basic data_len + newpw_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth-password-change request", 0);
return -1;
}
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
libssh2_htonu32(s, sizeof("ssh-connection") - 1); s += 4;
memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1); s += sizeof("ssh-connection") - 1;
libssh2_htonu32(s, sizeof("password") - 1); s += 4;
memcpy(s, "password", sizeof("password") - 1); s += sizeof("password") - 1;
*s = 0xFF; s++;
libssh2_htonu32(s, password_len); s += 4;
memcpy(s, password, password_len); s += password_len;
libssh2_htonu32(s, newpw_len); s += 4;
memcpy(s, newpw, newpw_len); s += newpw_len;
if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password-change request", 0);
LIBSSH2_FREE(session, data);
return -1;
}
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, newpw);
/* TODO: Reset timeout? */
} else {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback specified", 0);
return -1;
}
}
/* TODO: Timeout? */
} }
/* FAILURE */ return 0;
LIBSSH2_FREE(session, data);
return -1;
} }
/* }}} */ /* }}} */
@@ -235,15 +221,12 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const cha
*/ */
static int libssh2_file_read_publickey(LIBSSH2_SESSION *session, unsigned char **method, unsigned long *method_len, static int libssh2_file_read_publickey(LIBSSH2_SESSION *session, unsigned char **method, unsigned long *method_len,
unsigned char **pubkeydata, unsigned long *pubkeydata_len, unsigned char **pubkeydata, unsigned long *pubkeydata_len,
const char *pubkeyfile) char *pubkeyfile)
{ {
FILE *fd; FILE *fd;
char *pubkey = NULL, c, *sp1, *sp2, *tmp; char *pubkey = NULL, c, *sp1, *sp2, *tmp;
int pubkey_len = 0, tmp_len; int pubkey_len = 0, tmp_len;
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading public key file: %s", pubkeyfile);
#endif
/* Read Public Key */ /* Read Public Key */
fd = fopen(pubkeyfile, "r"); fd = fopen(pubkeyfile, "r");
if (!fd) { if (!fd) {
@@ -310,18 +293,15 @@ static int libssh2_file_read_publickey(LIBSSH2_SESSION *session, unsigned char *
} }
/* }}} */ /* }}} */
/* {{{ libssh2_file_read_privatekey /* {{{ libssh2_file_read_publickey
* Read a PEM encoded private key from an id_??? style file * Read a PEM encoded private key from an id_??? style file
*/ */
static int libssh2_file_read_privatekey(LIBSSH2_SESSION *session, LIBSSH2_HOSTKEY_METHOD **hostkey_method, void **hostkey_abstract, static int libssh2_file_read_privatekey(LIBSSH2_SESSION *session, LIBSSH2_HOSTKEY_METHOD **hostkey_method, void **hostkey_abstract,
const char *method, int method_len, char *method, int method_len,
const char *privkeyfile, const char *passphrase) char *privkeyfile, char *passphrase)
{ {
LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail = libssh2_hostkey_methods(); LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods();
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading private key file: %s", privkeyfile);
#endif
*hostkey_method = NULL; *hostkey_method = NULL;
*hostkey_abstract = NULL; *hostkey_abstract = NULL;
while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) { while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
@@ -346,151 +326,19 @@ static int libssh2_file_read_privatekey(LIBSSH2_SESSION *session, LIBSSH2_HOSTKE
} }
/* }}} */ /* }}} */
/* {{{ libssh2_userauth_hostbased_fromfile_ex
* Authenticate using a keypair found in the named files
*/
LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session, const char *username, int username_len,
const char *publickey, const char *privatekey,
const char *passphrase,
const char *hostname, int hostname_len,
const char *local_username, int local_username_len)
{
LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract;
unsigned char buf[5];
struct iovec datavec[4];
unsigned char *method, *pubkeydata, *packet, *s, *sig, *data, reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long method_len, pubkeydata_len, packet_len, sig_len, data_len;
if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) {
return -1;
}
packet_len = username_len + method_len + hostname_len + local_username_len + pubkeydata_len + 48;
/* packet_type(1) + username_len(4) + servicename_len(4) + service_name(14)"ssh-connection" +
* authmethod_len(4) + authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) +
* local_username_len(4)
*/
/* Preallocate space for an overall length, method name again,
* and the signature, which won't be any larger than the size of the publickeydata itself */
s = packet = LIBSSH2_ALLOC(session, packet_len + 4 + (4 + method_len) + (4 + pubkeydata_len));
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
libssh2_htonu32(s, 14); s += 4;
memcpy(s, "ssh-connection", 14); s += 14;
libssh2_htonu32(s, 9); s += 4;
memcpy(s, "hostbased", 9); s += 9;
libssh2_htonu32(s, method_len); s += 4;
memcpy(s, method, method_len); s += method_len;
libssh2_htonu32(s, pubkeydata_len); s += 4;
memcpy(s, pubkeydata, pubkeydata_len); s += pubkeydata_len;
libssh2_htonu32(s, hostname_len); s += 4;
memcpy(s, hostname, hostname_len); s += hostname_len;
libssh2_htonu32(s, local_username_len); s += 4;
memcpy(s, local_username, local_username_len); s += local_username_len;
if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract, method, method_len, privatekey, passphrase)) {
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, packet);
return -1;
}
libssh2_htonu32(buf, session->session_id_len);
datavec[0].iov_base = buf;
datavec[0].iov_len = 4;
datavec[1].iov_base = session->session_id;
datavec[1].iov_len = session->session_id_len;
datavec[2].iov_base = packet;
datavec[2].iov_len = packet_len;
if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) {
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, packet);
if (privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
return -1;
}
if (privkeyobj->dtor) {
privkeyobj->dtor(session, &abstract);
}
if (sig_len > pubkeydata_len ) {
/* Should *NEVER* happen, but...well.. better safe than sorry */
packet = LIBSSH2_REALLOC(session, packet, packet_len + 4 + (4 + method_len) + (4 + sig_len)); /* PK sigblob */
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed allocating additional space for userauth-hostbased packet", 0);
LIBSSH2_FREE(session, method);
return -1;
}
}
s = packet + packet_len;
libssh2_htonu32(s, 4 + method_len + 4 + sig_len); s += 4;
libssh2_htonu32(s, method_len); s += 4;
memcpy(s, method, method_len); s += method_len;
LIBSSH2_FREE(session, method);
libssh2_htonu32(s, sig_len); s += 4;
memcpy(s, sig, sig_len); s += sig_len;
LIBSSH2_FREE(session, sig);
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting hostbased authentication");
#endif
if (libssh2_packet_write(session, packet, s - packet)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-hostbased request", 0);
LIBSSH2_FREE(session, packet);
return -1;
}
LIBSSH2_FREE(session, packet);
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
return -1;
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Hostbased authentication successful");
#endif
/* We are us and we've proved it. */
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
}
/* }}} */
/* {{{ libssh2_userauth_publickey_fromfile_ex /* {{{ libssh2_userauth_publickey_fromfile_ex
* Authenticate using a keypair found in the named files * Authenticate using a keypair found in the named files
*/ */
LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, const char *username, int username_len, LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, char *username, int username_len,
const char *publickey, const char *privatekey, char *publickey, char *privatekey,
const char *passphrase) char *passphrase)
{ {
LIBSSH2_HOSTKEY_METHOD *privkeyobj; LIBSSH2_HOSTKEY_METHOD *privkeyobj;
void *abstract; void *abstract;
unsigned char buf[5]; unsigned char buf[5];
struct iovec datavec[4]; struct iovec datavec[4];
unsigned char *method, *pubkeydata, *packet, *s, *b, *sig, *data; unsigned char *method, *pubkeydata, *packet, *s, *b, *sig;
unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PK_OK, 0 }; unsigned long method_len, pubkeydata_len, packet_len, sig_len;
unsigned long method_len, pubkeydata_len, packet_len, sig_len, data_len;
if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) { if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) {
return -1; return -1;
@@ -523,9 +371,6 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
libssh2_htonu32(s, pubkeydata_len); s += 4; libssh2_htonu32(s, pubkeydata_len); s += 4;
memcpy(s, pubkeydata, pubkeydata_len); s += pubkeydata_len; memcpy(s, pubkeydata, pubkeydata_len); s += pubkeydata_len;
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting publickey authentication");
#endif
if (libssh2_packet_write(session, packet, packet_len)) { if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-publickey request", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-publickey request", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
@@ -534,38 +379,45 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
return -1; return -1;
} }
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) { while (1) {
LIBSSH2_FREE(session, packet); unsigned char *data;
LIBSSH2_FREE(session, method); unsigned long data_len;
LIBSSH2_FREE(session, pubkeydata);
return -1;
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
#ifdef LIBSSH2_DEBUG_USERAUTH /* God help any SSH server that allows an UNVERIFIED public key to validate the user */
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Pubkey authentication prematurely successful"); LIBSSH2_FREE(session, data);
#endif LIBSSH2_FREE(session, packet);
/* God help any SSH server that allows an UNVERIFIED public key to validate the user */ LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, pubkeydata);
LIBSSH2_FREE(session, packet); session->authenticated = 1;
LIBSSH2_FREE(session, method); return 0;
LIBSSH2_FREE(session, pubkeydata); }
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (data[0] == SSH_MSG_USERAUTH_FAILURE) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* This public key is not allowed for this user on this server */ /* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method); LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata); LIBSSH2_FREE(session, pubkeydata);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED, "Username/PublicKey combination invalid", 0); libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED, "Username/PublicKey combination invalid", 0);
return -1; return -1;
} }
/* Semi-Success! */ if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_PK_OK, &data, &data_len, 0) == 0) {
LIBSSH2_FREE(session, data); /* Semi-Success! */
if ((libssh2_ntohu32(data + 1) != method_len) ||
strncmp(data + 5, method, method_len) ||
(libssh2_ntohu32(data + 5 + method_len) != pubkeydata_len) ||
strncmp(data + 5 + method_len + 4, pubkeydata, pubkeydata_len)) {
/* Unlikely but possible, the server has responded to a different userauth public key request */
LIBSSH2_FREE(session, data);
continue;
}
LIBSSH2_FREE(session, data);
break;
}
/* TODO: Timeout? */
}
LIBSSH2_FREE(session, pubkeydata); LIBSSH2_FREE(session, pubkeydata);
if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract, method, method_len, privatekey, passphrase)) { if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract, method, method_len, privatekey, passphrase)) {
@@ -619,9 +471,6 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
memcpy(s, sig, sig_len); s += sig_len; memcpy(s, sig, sig_len); s += sig_len;
LIBSSH2_FREE(session, sig); LIBSSH2_FREE(session, sig);
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting publickey authentication -- phase 2");
#endif
if (libssh2_packet_write(session, packet, s - packet)) { if (libssh2_packet_write(session, packet, s - packet)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-publickey request", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-publickey request", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
@@ -629,227 +478,26 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
/* PK_OK is no longer valid */ while (1) {
reply_codes[2] = 0; unsigned char *data;
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
return -1;
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Publickey authentication successful");
#endif
/* We are us and we've proved it. */
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
}
/* }}} */
/* {{{ libssh2_userauth_keyboard_interactive
* Authenticate using a challenge-response authentication
*/
LIBSSH2_API int libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session, const char *username, int username_len,
LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
{
unsigned char *s, *data; /* packet */
unsigned long packet_len;
packet_len = 1 /* byte SSH_MSG_USERAUTH_REQUEST */
+ 4 + username_len /* string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) */
+ 4 + 14 /* string service name (US-ASCII) */
+ 4 + 20 /* string "keyboard-interactive" (US-ASCII) */
+ 4 + 0 /* string language tag (as defined in [RFC-3066]) */
+ 4 + 0 /* string submethods (ISO-10646 UTF-8) */
;
if (!(data = s = LIBSSH2_ALLOC(session, packet_len))) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive authentication", 0);
return -1;
}
*s++ = SSH_MSG_USERAUTH_REQUEST;
/* user name */
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
/* service name */
libssh2_htonu32(s, sizeof("ssh-connection") - 1); s += 4;
memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1); s += sizeof("ssh-connection") - 1;
/* "keyboard-interactive" */
libssh2_htonu32(s, sizeof("keyboard-interactive") - 1); s += 4;
memcpy(s, "keyboard-interactive", sizeof("keyboard-interactive") - 1); s += sizeof("keyboard-interactive") - 1;
/* language tag */
libssh2_htonu32(s, 0); s += 4;
/* submethods */
libssh2_htonu32(s, 0); s += 4;
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Attempting keyboard-interactive authentication");
#endif
if (libssh2_packet_write(session, data, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send keyboard-interactive request", 0);
LIBSSH2_FREE(session, data);
return -1;
}
LIBSSH2_FREE(session, data);
for (;;) {
unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0 };
unsigned int auth_name_len;
char* auth_name = NULL;
unsigned auth_instruction_len;
char* auth_instruction = NULL;
unsigned int language_tag_len;
unsigned long data_len; unsigned long data_len;
unsigned int num_prompts = 0;
unsigned int i;
int auth_failure = 1;
LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts = NULL;
LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses = NULL;
if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
return -1; /* We are us and we've proved it. */
}
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Keyboard-interactive authentication successful");
#endif
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED; session->authenticated = 1;
return 0; return 0;
} }
if (data[0] == SSH_MSG_USERAUTH_FAILURE) { if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1; return -1;
} }
/* TODO: Timeout? */
/* server requested PAM-like conversation */
s = data + 1;
/* string name (ISO-10646 UTF-8) */
auth_name_len = libssh2_ntohu32(s); s += 4;
if (!(auth_name = LIBSSH2_ALLOC(session, auth_name_len))) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive 'name' request field", 0);
goto cleanup;
}
memcpy(auth_name, s, auth_name_len); s += auth_name_len;
/* string instruction (ISO-10646 UTF-8) */
auth_instruction_len = libssh2_ntohu32(s); s += 4;
if (!(auth_instruction = LIBSSH2_ALLOC(session, auth_instruction_len))) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive 'instruction' request field", 0);
goto cleanup;
}
memcpy(auth_instruction, s, auth_instruction_len); s += auth_instruction_len;
/* string language tag (as defined in [RFC-3066]) */
language_tag_len = libssh2_ntohu32(s); s += 4;
/* ignoring this field as deprecated */ s += language_tag_len;
/* int num-prompts */
num_prompts = libssh2_ntohu32(s); s += 4;
prompts = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) * num_prompts);
if (!prompts) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive prompts array", 0);
goto cleanup;
}
memset(prompts, 0, sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) * num_prompts);
responses = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) * num_prompts);
if (!responses) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive responses array", 0);
goto cleanup;
}
memset(responses, 0, sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) * num_prompts);
for(i = 0; i != num_prompts; ++i) {
/* string prompt[1] (ISO-10646 UTF-8) */
prompts[i].length = libssh2_ntohu32(s); s += 4;
if (!(prompts[i].text = LIBSSH2_ALLOC(session, prompts[i].length))) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive prompt message", 0);
goto cleanup;
}
memcpy(prompts[i].text, s, prompts[i].length); s += prompts[i].length;
/* boolean echo[1] */
prompts[i].echo = *s++;
}
response_callback(auth_name, auth_name_len, auth_instruction, auth_instruction_len, num_prompts, prompts, responses, &session->abstract);
#ifdef LIBSSH2_DEBUG_USERAUTH
_libssh2_debug(session, LIBSSH2_DBG_AUTH, "Keyboard-interactive response callback function invoked");
#endif
packet_len = 1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */
+ 4 /* int num-responses */
;
for (i = 0; i != num_prompts; ++i) {
packet_len += 4 + responses[i].length; /* string response[1] (ISO-10646 UTF-8) */
}
if (!(data = s = LIBSSH2_ALLOC(session, packet_len))) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for keyboard-interactive response packet", 0);
goto cleanup;
}
*s = SSH_MSG_USERAUTH_INFO_RESPONSE; s++;
libssh2_htonu32(s, num_prompts); s += 4;
for (i = 0; i != num_prompts; ++i) {
libssh2_htonu32(s, responses[i].length); s += 4;
memcpy(s, responses[i].text, responses[i].length); s += responses[i].length;
}
if (libssh2_packet_write(session, data, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-keyboard-interactive request", 0);
goto cleanup;
}
auth_failure = 0;
cleanup:
/* It's safe to clean all the data here, because unallocated pointers
* are filled by zeroes
*/
LIBSSH2_FREE(session, data);
if (prompts) {
for (i = 0; i != num_prompts; ++i) {
LIBSSH2_FREE(session, prompts[i].text);
}
}
if (responses) {
for (i = 0; i != num_prompts; ++i) {
LIBSSH2_FREE(session, responses[i].text);
}
}
LIBSSH2_FREE(session, prompts);
LIBSSH2_FREE(session, responses);
if (auth_failure) {
return -1;
}
} }
return 0;
} }
/* }}} */ /* }}} */

View File

@@ -1,45 +1,29 @@
#include "libssh2.h" #include "libssh2.h"
#include <netinet/in.h>
#ifndef WIN32 #include <sys/socket.h>
# include <netinet/in.h>
# include <sys/socket.h>
# include <unistd.h>
#else
# include <winsock2.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <ctype.h> #include <ctype.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int sock, i, auth_pw = 1; int sock, i, auth_pw = 1;
struct sockaddr_in sin; struct sockaddr_in sin;
const char *fingerprint; char *fingerprint;
LIBSSH2_SESSION *session; LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel; LIBSSH2_CHANNEL *channel;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(WINSOCK_VERSION, &wsadata);
#endif
/* Ultra basic "connect to port 22 on localhost" /* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the connection * Your code is responsible for creating the socket establishing the connection
*/ */
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
#ifndef WIN32
fcntl(sock, F_SETFL, 0); fcntl(sock, F_SETFL, 0);
#endif
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = htons(22); sin.sin_port = htons(22);
sin.sin_addr.s_addr = htonl(0x7F000001); sin.sin_addr.s_addr = htonl(0x7F000001);
if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in));
fprintf(stderr, "failed to connect!\n");
return -1;
}
/* Create a session instance and start it up /* Create a session instance and start it up
* This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers * This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers
@@ -130,13 +114,8 @@ int main(int argc, char *argv[]) {
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session); libssh2_session_free(session);
#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1); sleep(1);
close(sock); close(sock);
#endif
printf("all done\n");
return 0; return 0;
} }

View File

@@ -1,12 +0,0 @@
*.lib
*.pdb
*.dll
*.exe
*.obj
.*.swp
Debug
Release
*.exp
*.ncb
*.opt
*.plg

View File

@@ -1,29 +0,0 @@
# Tweak these for your system
OPENSSLINC=..\libssh2_build\include
OPENSSLLIB=..\libssh2_build\lib
ZLIBINC=-DLIBSSH2_HAVE_ZLIB=1 /I..\libssh2_build\include
ZLIBLIB=..\libssh2_build\lib
!if "$(TARGET)" == ""
TARGET=Release
!endif
!if "$(TARGET)" == "Debug"
SUFFIX=_debug
CPPFLAGS=/Od /MDd
DLLFLAGS=/DEBUG /LDd
!else
CPPFLAGS=/Og /Oi /O2 /Oy /GF /Y- /MD /DNDEBUG
DLLFLAGS=/DEBUG /LD
!endif
CPPFLAGS=/nologo /GL /Zi /EHsc $(CPPFLAGS) /Iwin32 /Iinclude /I$(OPENSSLINC) $(ZLIBINC) -DLIBSSH2_WIN32
CFLAGS=$(CPPFLAGS)
DLLFLAGS=$(CFLAGS) $(DLLFLAGS)
LIBS=$(OPENSSLLIB)\libeay32.lib $(OPENSSLLIB)\ssleay32.lib ws2_32.lib $(ZLIBLIB)\zlib.lib
INTDIR=$(TARGET)\$(SUBDIR)

View File

@@ -1,156 +0,0 @@
# Microsoft Developer Studio Project File - Name="libssh2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=libssh2 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "libssh2.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "libssh2.mak" CFG="libssh2 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "libssh2 - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "libssh2 - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "libssh2 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "libssh2___Win32_Release"
# PROP BASE Intermediate_Dir "libssh2___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /I "..\win32" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "libssh2 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\win32" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"Debug\libssh2d.lib"
!ENDIF
# Begin Target
# Name "libssh2 - Win32 Release"
# Name "libssh2 - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\src\channel.c
# End Source File
# Begin Source File
SOURCE=..\src\comp.c
# End Source File
# Begin Source File
SOURCE=..\src\crypt.c
# End Source File
# Begin Source File
SOURCE=..\src\hostkey.c
# End Source File
# Begin Source File
SOURCE=..\src\kex.c
# End Source File
# Begin Source File
SOURCE=..\src\mac.c
# End Source File
# Begin Source File
SOURCE=..\src\misc.c
# End Source File
# Begin Source File
SOURCE=..\src\packet.c
# End Source File
# Begin Source File
SOURCE=..\src\scp.c
# End Source File
# Begin Source File
SOURCE=..\src\session.c
# End Source File
# Begin Source File
SOURCE=..\src\sftp.c
# End Source File
# Begin Source File
SOURCE=..\src\userauth.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\include\libssh2.h
# End Source File
# Begin Source File
SOURCE=.\libssh2_config.h
# End Source File
# Begin Source File
SOURCE=..\include\libssh2_priv.h
# End Source File
# Begin Source File
SOURCE=..\include\libssh2_sftp.h
# End Source File
# End Group
# End Target
# End Project

View File

@@ -1,41 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "libssh2"=.\libssh2.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "ssh2_sample"=.\ssh2_sample.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -1,38 +0,0 @@
#ifndef WIN32
#define WIN32
#endif
#include <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
/* 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 snprintf _snprintf
/* Compile in zlib support */
#define LIBSSH2_HAVE_ZLIB 1
/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
#define LIBSSH2_DH_GEX_NEW 1

View File

@@ -1,15 +0,0 @@
all-sub: $(INTDIR) all
clean-sub: clean
$(INTDIR):
!if "$(SRCDIR)" == ""
@if not exist $(TARGET) mkdir $(TARGET)
!endif
@if not exist $(INTDIR) mkdir $(INTDIR)
{$(SUBDIR)}.c{$(INTDIR)}.obj::
$(CC) -c $(CFLAGS) /Fo"$(INTDIR)\\" $<

View File

@@ -1,102 +0,0 @@
# Microsoft Developer Studio Project File - Name="ssh2_sample" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=ssh2_sample - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ssh2_sample.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ssh2_sample.mak" CFG="ssh2_sample - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ssh2_sample - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "ssh2_sample - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "ssh2_sample - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ssh2_sample___Win32_Release"
# PROP BASE Intermediate_Dir "ssh2_sample___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /I "..\win32" /D "WIN32" /D "NDEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBSSH2_LIBRARY" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libeay32.lib ssleay32.lib ws2_32.lib zlib.lib libssh2.lib /nologo /subsystem:console /machine:I386 /libpath:"Release"
!ELSEIF "$(CFG)" == "ssh2_sample - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "ssh2_sample___Win32_Debug"
# PROP BASE Intermediate_Dir "ssh2_sample___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\win32" /D "WIN32" /D "_DEBUG" /D "LIBSSH2_WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBSSH2_LIBRARY" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libeay32.lib ssleay32.lib ws2_32.lib zlib.lib libssh2d.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept /libpath:"Debug"
!ENDIF
# Begin Target
# Name "ssh2_sample - Win32 Release"
# Name "ssh2_sample - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\ssh2_sample.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project