Compare commits
29 Commits
RELEASE.0.
...
RELEASE.0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fe2513a18b | ||
![]() |
ee03669517 | ||
![]() |
22c105332d | ||
![]() |
c9e8f3a1a0 | ||
![]() |
54b852dfc9 | ||
![]() |
308d59910f | ||
![]() |
ecd83df6a7 | ||
![]() |
4191a8c56c | ||
![]() |
c5acc8a901 | ||
![]() |
a119685410 | ||
![]() |
dc4bb1af96 | ||
![]() |
8fe47a609a | ||
![]() |
c070bdacc7 | ||
![]() |
a9af84c51d | ||
![]() |
dfb3b8f0fd | ||
![]() |
c006dd4350 | ||
![]() |
4324a1a1d1 | ||
![]() |
cf8ca63ea0 | ||
![]() |
d1b33840bf | ||
![]() |
eef99ca106 | ||
![]() |
d86bcab2d2 | ||
![]() |
2e02ad041a | ||
![]() |
596b62c027 | ||
![]() |
143c6bf97f | ||
![]() |
371f5de682 | ||
![]() |
d2d8f8ad0b | ||
![]() |
a1e649b507 | ||
![]() |
99795a165e | ||
![]() |
6f13a93be9 |
9
.cvsignore
Normal file
9
.cvsignore
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
*.lib
|
||||||
|
*.pdb
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.obj
|
||||||
|
.*.swp
|
||||||
|
Debug
|
||||||
|
Release
|
||||||
|
*.exp
|
51
INSTALL
51
INSTALL
@@ -5,5 +5,56 @@ Installing libssh2
|
|||||||
|
|
||||||
* Run: ./configure (passing additional options as desired)
|
* 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
|
* Run: make all install
|
||||||
|
|
||||||
|
24
Makefile.in
24
Makefile.in
@@ -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=0.3
|
VERSION=@PACKAGE_VERSION@
|
||||||
DISTLIB=libssh2-$(VERSION)
|
DISTLIB=libssh2-$(VERSION)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@@ -21,14 +21,14 @@ 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 $(incldir)
|
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(incldir)
|
||||||
$(top_srcdir)/mkinstalldirs $(libdir)
|
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(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 $(incldir)/
|
$(INSTALL) -m 644 include/libssh2.h $(DESTDIR)$(incldir)/
|
||||||
$(INSTALL) -m 644 include/libssh2_sftp.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) \
|
||||||
@@ -43,8 +43,20 @@ dist:
|
|||||||
tar -zcf $(DISTLIB).tar.gz \
|
tar -zcf $(DISTLIB).tar.gz \
|
||||||
$(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \
|
$(DISTLIB)/configure $(DISTLIB)/Makefile.in $(DISTLIB)/ssh2_sample.c \
|
||||||
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/TODO $(DISTLIB)/INSTALL \
|
$(DISTLIB)/LICENSE $(DISTLIB)/README $(DISTLIB)/TODO $(DISTLIB)/INSTALL \
|
||||||
$(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh \
|
$(DISTLIB)/mkinstalldirs $(DISTLIB)/install-sh $(DISTLIB)/config.sub $(DISTLIB)/config.guess \
|
||||||
$(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_sftp.h \
|
||||||
$(DISTLIB)/include/libssh2_config.h.in
|
$(DISTLIB)/include/libssh2_config.h.in
|
||||||
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)
|
||||||
|
|
||||||
|
16
NMakefile
Normal file
16
NMakefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
!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)
|
||||||
|
|
||||||
|
|
33
README
33
README
@@ -1,6 +1,39 @@
|
|||||||
libssh2 - SSH2 library
|
libssh2 - SSH2 library
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
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
|
Version 0.3
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
1415
config.guess
vendored
Executable file
1415
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1510
config.sub
vendored
Executable file
1510
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
25
configure.in
25
configure.in
@@ -1,11 +1,21 @@
|
|||||||
# AC_PREREQ(2.57)
|
# AC_PREREQ(2.57)
|
||||||
AC_INIT(libssh2, 0.3 , sarag@libssh2.org)
|
AC_INIT(libssh2,0.5,sarag@libssh2.org)
|
||||||
AC_CONFIG_SRCDIR([src])
|
AC_CONFIG_SRCDIR([src])
|
||||||
AC_CONFIG_HEADER([include/libssh2_config.h])
|
AC_CONFIG_HEADER([include/libssh2_config.h])
|
||||||
|
|
||||||
SHLIB_SUFFIX_NAME="so"
|
# Check for the OS.
|
||||||
SHLIB_LDFLAGS="-shared"
|
AC_CANONICAL_HOST
|
||||||
|
case "$host" in
|
||||||
|
*-cygwin)
|
||||||
|
SHLIB_SUFFIX_NAME="dll"
|
||||||
|
SHLIB_LDFLAGS="-shared"
|
||||||
|
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
SHLIB_SUFFIX_NAME="so"
|
||||||
|
SHLIB_LDFLAGS="-shared"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
AC_SUBST(SHLIB_SUFFIX_NAME)
|
AC_SUBST(SHLIB_SUFFIX_NAME)
|
||||||
AC_SUBST(SHLIB_LDFLAGS)
|
AC_SUBST(SHLIB_LDFLAGS)
|
||||||
|
|
||||||
@@ -138,6 +148,13 @@ 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
|
||||||
|
|
||||||
# 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])
|
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h])
|
||||||
|
@@ -42,8 +42,32 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define LIBSSH2_VERSION "0.3"
|
/* Allow alternate API prefix from CFLAGS or calling app */
|
||||||
#define LIBSSH2_APINO 200412211608
|
#ifndef LIBSSH2_API
|
||||||
|
#ifdef LIBSSH2_WIN32
|
||||||
|
# ifdef LIBSSH2_LIBRARY
|
||||||
|
# define LIBSSH2_API __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define LIBSSH2_API __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# ifndef _MSC_VER
|
||||||
|
# include <sys/uio.h>
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define LIBSSH2_API
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _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.5"
|
||||||
|
#define LIBSSH2_APINO 200412301450
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -97,9 +121,6 @@
|
|||||||
#endif
|
#endif
|
||||||
/* LIBSSH2_MAC_NONE already defined (or not) by ./configure */
|
/* LIBSSH2_MAC_NONE already defined (or not) by ./configure */
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -136,6 +157,7 @@
|
|||||||
#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)
|
#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) void name(LIBSSH2_SESSION *session, void **session_abstract, LIBSSH2_CHANNEL *channel, void **channel_abstract)
|
||||||
|
|
||||||
@@ -144,6 +166,7 @@
|
|||||||
#define LIBSSH2_CALLBACK_DEBUG 1
|
#define LIBSSH2_CALLBACK_DEBUG 1
|
||||||
#define LIBSSH2_CALLBACK_DISCONNECT 2
|
#define LIBSSH2_CALLBACK_DISCONNECT 2
|
||||||
#define LIBSSH2_CALLBACK_MACERROR 3
|
#define LIBSSH2_CALLBACK_MACERROR 3
|
||||||
|
#define LIBSSH2_CALLBACK_X11 4
|
||||||
|
|
||||||
/* libssh2_session_method_pref() constants */
|
/* libssh2_session_method_pref() constants */
|
||||||
#define LIBSSH2_METHOD_KEX 0
|
#define LIBSSH2_METHOD_KEX 0
|
||||||
@@ -159,12 +182,7 @@
|
|||||||
|
|
||||||
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;
|
||||||
#ifdef WIN_32
|
|
||||||
#define LIBSSH2_API __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define LIBSSH2_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LIBSSH2_HOSTKEY_HASH_MD5 1
|
#define LIBSSH2_HOSTKEY_HASH_MD5 1
|
||||||
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
|
#define LIBSSH2_HOSTKEY_HASH_SHA1 2
|
||||||
@@ -218,6 +236,9 @@ typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
|
|||||||
#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_SFTP_PROTOCOL -31
|
||||||
|
#define LIBSSH2_ERROR_REQUEST_DENIED -32
|
||||||
|
#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED -33
|
||||||
|
#define LIBSSH2_ERROR_INVAL -34
|
||||||
|
|
||||||
/* 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);
|
||||||
@@ -225,6 +246,7 @@ LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_all
|
|||||||
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session);
|
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 void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);
|
||||||
|
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, 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, char *description, char *lang);
|
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang);
|
||||||
@@ -234,12 +256,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session);
|
|||||||
LIBSSH2_API 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, char *prefs);
|
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, char *prefs);
|
||||||
LIBSSH2_API void libssh2_session_methods(LIBSSH2_SESSION *session, char **kex, char **hostkey,
|
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
|
||||||
char **crypt_cs, char **crypt_sc,
|
|
||||||
char **mac_cs, char **mac_sc,
|
|
||||||
char **comp_cs, char **comp_sc,
|
|
||||||
char **lang_cs, char **lang_sc);
|
|
||||||
|
|
||||||
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
|
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
|
||||||
|
|
||||||
/* Userauth API */
|
/* Userauth API */
|
||||||
@@ -267,15 +284,26 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
|
|||||||
|
|
||||||
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);
|
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_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);
|
||||||
|
#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, char *request, int request_len, char *message, int message_len);
|
LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, char *request, int request_len, 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))
|
||||||
|
@@ -39,6 +39,9 @@
|
|||||||
/* Enable "none" cipher -- NOT RECOMMENDED */
|
/* Enable "none" cipher -- NOT RECOMMENDED */
|
||||||
#undef LIBSSH2_CRYPT_NONE
|
#undef LIBSSH2_CRYPT_NONE
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
@@ -38,11 +38,13 @@
|
|||||||
#ifndef LIBSSH2_PRIV_H
|
#ifndef LIBSSH2_PRIV_H
|
||||||
#define LIBSSH2_PRIV_H 1
|
#define LIBSSH2_PRIV_H 1
|
||||||
|
|
||||||
/* Definitions shared with the public */
|
#define LIBSSH2_LIBRARY
|
||||||
#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)
|
||||||
@@ -56,6 +58,7 @@
|
|||||||
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)
|
#define LIBSSH2_CHANNEL_CLOSE(session, channel) channel->close_cb((session), &(session)->abstract, (channel), &(channel)->abstract)
|
||||||
|
|
||||||
@@ -123,6 +126,19 @@ 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;
|
||||||
|
|
||||||
@@ -158,6 +174,7 @@ 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;
|
char *kex_prefs;
|
||||||
@@ -202,6 +219,8 @@ 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;
|
||||||
@@ -219,9 +238,6 @@ struct _LIBSSH2_SESSION {
|
|||||||
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);
|
||||||
|
|
||||||
@@ -278,6 +294,9 @@ 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);
|
||||||
@@ -360,9 +379,9 @@ struct _LIBSSH2_MAC_METHOD {
|
|||||||
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);
|
||||||
unsigned long long libssh2_ntohu64(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, unsigned long 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);
|
||||||
@@ -373,6 +392,7 @@ int libssh2_packet_require_ex(LIBSSH2_SESSION *session, unsigned char packet_typ
|
|||||||
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_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 */
|
||||||
|
@@ -82,7 +82,7 @@ struct _LIBSSH2_SFTP_ATTRIBUTES {
|
|||||||
*/
|
*/
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
unsigned long long filesize;
|
libssh2_uint64_t filesize;
|
||||||
unsigned long uid, gid;
|
unsigned long uid, gid;
|
||||||
unsigned long permissions;
|
unsigned long permissions;
|
||||||
unsigned long atime, mtime;
|
unsigned long atime, mtime;
|
||||||
|
9
src/.cvsignore
Normal file
9
src/.cvsignore
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
*.lib
|
||||||
|
*.pdb
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.obj
|
||||||
|
.*.swp
|
||||||
|
Debug
|
||||||
|
Release
|
||||||
|
*.exp
|
@@ -57,7 +57,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@ $(libdir)
|
$(INSTALL) libssh2.@SHLIB_SUFFIX_NAME@ $(DESTDIR)$(libdir)
|
||||||
clean:
|
clean:
|
||||||
rm -f *~ libssh2.a libssh2.@SHLIB_SUFFIX_NAME@ *.o
|
rm -f *~ libssh2.a libssh2.@SHLIB_SUFFIX_NAME@ *.o
|
||||||
|
|
||||||
|
18
src/NMakefile
Normal file
18
src/NMakefile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
!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"
|
||||||
|
|
269
src/channel.c
269
src/channel.c
@@ -36,12 +36,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#ifndef WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* {{{ libssh2_channel_nextid
|
/* {{{ libssh2_channel_nextid
|
||||||
* Determine the next channel ID we can use at our end
|
* Determine the next channel ID we can use at our end
|
||||||
*/
|
*/
|
||||||
static unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session)
|
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
unsigned long id = session->next_channel;
|
unsigned long id = session->next_channel;
|
||||||
LIBSSH2_CHANNEL *channel;
|
LIBSSH2_CHANNEL *channel;
|
||||||
@@ -257,6 +260,191 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *se
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_channel_forward_listen_ex
|
||||||
|
* Bind a port on the remote host and listen for connections
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize)
|
||||||
|
{
|
||||||
|
unsigned char *packet, *s;
|
||||||
|
unsigned long host_len = (host ? strlen(host) : (sizeof("0.0.0.0") - 1));
|
||||||
|
unsigned long packet_len = host_len + (sizeof("tcpip-forward") - 1) + 14;
|
||||||
|
/* packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */
|
||||||
|
|
||||||
|
s = packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
|
if (!packet) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memeory for setenv packet", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(s++) = SSH_MSG_GLOBAL_REQUEST;
|
||||||
|
libssh2_htonu32(s, sizeof("tcpip-forward") - 1); s += 4;
|
||||||
|
memcpy(s, "tcpip-forward", sizeof("tcpip-forward") - 1); s += sizeof("tcpip-forward") - 1;
|
||||||
|
*(s++) = 0xFF; /* want_reply */
|
||||||
|
|
||||||
|
libssh2_htonu32(s, host_len); s += 4;
|
||||||
|
memcpy(s, host ? host : "0.0.0.0", host_len); s += host_len;
|
||||||
|
libssh2_htonu32(s, port); s += 4;
|
||||||
|
|
||||||
|
if (libssh2_packet_write(session, packet, packet_len)) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send global-request packet for forward listen request", 0);
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
|
||||||
|
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||||
|
unsigned char *data;
|
||||||
|
unsigned long data_len;
|
||||||
|
|
||||||
|
if (libssh2_packet_ask(session, SSH_MSG_REQUEST_SUCCESS, &data, &data_len, 1) == 0) {
|
||||||
|
LIBSSH2_LISTENER *listener;
|
||||||
|
|
||||||
|
listener = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_LISTENER));
|
||||||
|
if (!listener) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(listener, 0, sizeof(LIBSSH2_LISTENER));
|
||||||
|
listener->session = session;
|
||||||
|
listener->host = LIBSSH2_ALLOC(session, host_len + 1);
|
||||||
|
if (!listener->host) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
|
||||||
|
LIBSSH2_FREE(session, listener);
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(listener->host, host ? host : "0.0.0.0", host_len);
|
||||||
|
listener->host[host_len] = 0;
|
||||||
|
if (data_len >= 5 && !port) {
|
||||||
|
listener->port = libssh2_ntohu32(data + 1);
|
||||||
|
} else {
|
||||||
|
listener->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->queue_size = 0;
|
||||||
|
listener->queue_maxsize = queue_maxsize;
|
||||||
|
|
||||||
|
listener->next = session->listeners;
|
||||||
|
listener->prev = NULL;
|
||||||
|
if (session->listeners) {
|
||||||
|
session->listeners->prev = listener;
|
||||||
|
}
|
||||||
|
session->listeners = listener;
|
||||||
|
|
||||||
|
if (bound_port) {
|
||||||
|
*bound_port = listener->port;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libssh2_packet_ask(session, SSH_MSG_REQUEST_FAILURE, &data, &data_len, 0) == 0) {
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED, "Unable to complete request for forward-listen", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_channel_forward_cancel
|
||||||
|
* Stop listening on a remote port and free the listener
|
||||||
|
* Toss out any pending (un-accept()ed) connections
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session = listener->session;
|
||||||
|
LIBSSH2_CHANNEL *queued = listener->queue;
|
||||||
|
unsigned char *packet, *s;
|
||||||
|
unsigned long host_len = strlen(listener->host);
|
||||||
|
unsigned long packet_len = host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
|
||||||
|
/* packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */
|
||||||
|
|
||||||
|
s = packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
|
if (!packet) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memeory for setenv packet", 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(s++) = SSH_MSG_GLOBAL_REQUEST;
|
||||||
|
libssh2_htonu32(s, sizeof("cancel-tcpip-forward") - 1); s += 4;
|
||||||
|
memcpy(s, "cancel-tcpip-forward", sizeof("cancel-tcpip-forward") - 1); s += sizeof("cancel-tcpip-forward") - 1;
|
||||||
|
*(s++) = 0x00; /* want_reply */
|
||||||
|
|
||||||
|
libssh2_htonu32(s, host_len); s += 4;
|
||||||
|
memcpy(s, listener->host, host_len); s += host_len;
|
||||||
|
libssh2_htonu32(s, listener->port); s += 4;
|
||||||
|
|
||||||
|
if (libssh2_packet_write(session, packet, packet_len)) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send global-request packet for forward listen request", 0);
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
|
||||||
|
while (queued) {
|
||||||
|
LIBSSH2_CHANNEL *next = queued->next;
|
||||||
|
|
||||||
|
libssh2_channel_free(queued);
|
||||||
|
queued = next;
|
||||||
|
}
|
||||||
|
LIBSSH2_FREE(session, listener->host);
|
||||||
|
|
||||||
|
if (listener->next) {
|
||||||
|
listener->next->prev = listener->prev;
|
||||||
|
}
|
||||||
|
if (listener->prev) {
|
||||||
|
listener->prev->next = listener->next;
|
||||||
|
} else {
|
||||||
|
session->listeners = listener->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBSSH2_FREE(session, listener);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_channel_forward_accept
|
||||||
|
* Accept a connection
|
||||||
|
*/
|
||||||
|
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener)
|
||||||
|
{
|
||||||
|
while (libssh2_packet_read(listener->session, 0) > 0);
|
||||||
|
|
||||||
|
if (listener->queue) {
|
||||||
|
LIBSSH2_SESSION *session = listener->session;
|
||||||
|
LIBSSH2_CHANNEL *channel;
|
||||||
|
|
||||||
|
channel = listener->queue;
|
||||||
|
|
||||||
|
listener->queue = listener->queue->next;
|
||||||
|
if (listener->queue) {
|
||||||
|
listener->queue->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->prev = NULL;
|
||||||
|
channel->next = session->channels.head;
|
||||||
|
session->channels.head = channel;
|
||||||
|
|
||||||
|
if (channel->next) {
|
||||||
|
channel->next->prev = channel;
|
||||||
|
} else {
|
||||||
|
session->channels.tail = channel;
|
||||||
|
}
|
||||||
|
listener->queue_size--;
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_channel_setenv_ex
|
/* {{{ libssh2_channel_setenv_ex
|
||||||
* Set an environment variable prior to requesting a shell/program/subsystem
|
* Set an environment variable prior to requesting a shell/program/subsystem
|
||||||
*/
|
*/
|
||||||
@@ -389,6 +577,85 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* Keep this an even number */
|
||||||
|
#define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
|
||||||
|
/* {{{ libssh2_channel_x11_req_ex
|
||||||
|
* Request X11 forwarding
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, char *auth_proto, char *auth_cookie, int screen_number)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
|
unsigned char *s, *packet;
|
||||||
|
unsigned long proto_len = auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
|
||||||
|
unsigned long cookie_len = auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
|
||||||
|
unsigned long packet_len = proto_len + cookie_len + 41; /* packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + want_reply(1) +
|
||||||
|
single_cnx(4) + proto_len(4) + cookie_len(4) + screen_num(4) */
|
||||||
|
|
||||||
|
s = packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
|
if (!packet) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for pty-request", 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(s++) = SSH_MSG_CHANNEL_REQUEST;
|
||||||
|
libssh2_htonu32(s, channel->remote.id); s += 4;
|
||||||
|
libssh2_htonu32(s, sizeof("x11-req") - 1); s += 4;
|
||||||
|
memcpy(s, "x11-req", sizeof("x11-req") - 1); s += sizeof("x11-req") - 1;
|
||||||
|
|
||||||
|
*(s++) = 0xFF; /* want_reply */
|
||||||
|
*(s++) = single_connection ? 0xFF : 0x00;
|
||||||
|
|
||||||
|
libssh2_htonu32(s, proto_len); s += 4;
|
||||||
|
memcpy(s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1", proto_len);
|
||||||
|
s += proto_len;
|
||||||
|
|
||||||
|
libssh2_htonu32(s, cookie_len);
|
||||||
|
if (auth_cookie) {
|
||||||
|
memcpy(s, auth_cookie, cookie_len);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
char buffer[LIBSSH2_X11_RANDOM_COOKIE_LEN / 2];
|
||||||
|
|
||||||
|
RAND_bytes(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
|
||||||
|
for (i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
|
||||||
|
snprintf(s + (i * 2), 2, "%02X", buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += cookie_len;
|
||||||
|
|
||||||
|
libssh2_htonu32(s, screen_number); s += 4;
|
||||||
|
|
||||||
|
if (libssh2_packet_write(session, packet, packet_len)) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send pty-request packet", 0);
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
unsigned char *data;
|
||||||
|
unsigned long data_len;
|
||||||
|
unsigned char local_channel[4];
|
||||||
|
|
||||||
|
libssh2_htonu32(local_channel, channel->local.id);
|
||||||
|
|
||||||
|
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_SUCCESS, &data, &data_len, 1, local_channel, 4, 1) == 0) {
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_FAILURE, &data, &data_len, 1, local_channel, 4, 1) == 0) {
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel x11-req", 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Never reached, just giving the compiler something to not complain about */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_channel_process_startup
|
/* {{{ libssh2_channel_process_startup
|
||||||
* Primitive for libssh2_channel_(shell|exec|subsystem)
|
* Primitive for libssh2_channel_(shell|exec|subsystem)
|
||||||
*/
|
*/
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#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>
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_RSA
|
#ifndef OPENSSL_NO_RSA
|
||||||
/* ***********
|
/* ***********
|
||||||
@@ -86,7 +87,8 @@ 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)) {
|
||||||
@@ -116,6 +118,14 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsi
|
|||||||
if (!fp) {
|
if (!fp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_algorithms_noconf();
|
||||||
|
}
|
||||||
rsactx = PEM_read_RSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
|
rsactx = PEM_read_RSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
|
||||||
if (!rsactx) {
|
if (!rsactx) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -322,6 +332,14 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsi
|
|||||||
if (!fp) {
|
if (!fp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_algorithms_noconf();
|
||||||
|
}
|
||||||
dsactx = PEM_read_DSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
|
dsactx = PEM_read_DSAPrivateKey(fp, NULL, (void*)libssh2_hostkey_method_ssh_rsadsa_passphrase_cb, passphrase);
|
||||||
if (!dsactx) {
|
if (!dsactx) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -371,16 +389,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);
|
||||||
int ret;
|
DSA_SIG *sig;
|
||||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
SHA_CTX ctx;
|
SHA_CTX ctx;
|
||||||
char *sig;
|
int r_len, s_len, rs_pad;
|
||||||
int sig_len;
|
|
||||||
|
|
||||||
sig_len = DSA_size(dsactx);
|
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
|
||||||
sig = LIBSSH2_ALLOC(session, sig_len);
|
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
||||||
|
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
|
||||||
|
|
||||||
if (!sig) {
|
if (!(*signature)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,14 +406,25 @@ 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);
|
||||||
|
|
||||||
ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
|
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
|
||||||
if (!ret) {
|
if (!sig) {
|
||||||
LIBSSH2_FREE(session, sig);
|
LIBSSH2_FREE(session, *signature);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*signature = sig;
|
r_len = BN_num_bytes(sig->r);
|
||||||
*signature_len = sig_len;
|
s_len = BN_num_bytes(sig->s);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -408,16 +437,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);
|
||||||
int ret, i;
|
DSA_SIG *sig;
|
||||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
SHA_CTX ctx;
|
SHA_CTX ctx;
|
||||||
char *sig;
|
int r_len, s_len, rs_pad, i;
|
||||||
int sig_len;
|
|
||||||
|
|
||||||
sig_len = DSA_size(dsactx);
|
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
|
||||||
sig = LIBSSH2_ALLOC(session, sig_len);
|
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
||||||
|
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
|
||||||
|
|
||||||
if (!sig) {
|
if (!(*signature)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,15 +456,25 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
|
|||||||
}
|
}
|
||||||
SHA1_Final(hash, &ctx);
|
SHA1_Final(hash, &ctx);
|
||||||
|
|
||||||
ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
|
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
|
||||||
|
if (!sig) {
|
||||||
if (!ret) {
|
LIBSSH2_FREE(session, *signature);
|
||||||
LIBSSH2_FREE(session, sig);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*signature = sig;
|
r_len = BN_num_bytes(sig->r);
|
||||||
*signature_len = sig_len;
|
s_len = BN_num_bytes(sig->s);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
17
src/kex.c
17
src/kex.c
@@ -39,6 +39,7 @@
|
|||||||
#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 */
|
||||||
@@ -384,11 +385,11 @@ 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->kex->key_len, "E");
|
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->local.mac->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->kex->key_len);
|
memset(key, 0, session->local.mac->key_len);
|
||||||
LIBSSH2_FREE(session, key);
|
LIBSSH2_FREE(session, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,11 +402,11 @@ 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->kex->key_len, "F");
|
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->remote.mac->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->kex->key_len);
|
memset(key, 0, session->remote.mac->key_len);
|
||||||
LIBSSH2_FREE(session, key);
|
LIBSSH2_FREE(session, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,21 +596,18 @@ 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,
|
||||||
};
|
};
|
||||||
@@ -720,8 +718,7 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
*(s++) = SSH_MSG_KEXINIT;
|
*(s++) = SSH_MSG_KEXINIT;
|
||||||
|
|
||||||
/* TODO: Build a better cookie (and the mice will beat a path to my door...) */
|
RAND_bytes(s, 16);
|
||||||
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 */
|
||||||
@@ -1251,6 +1248,7 @@ LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method
|
|||||||
mlist = NULL;
|
mlist = NULL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1282,6 +1280,7 @@ LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(newprefs) == 0) {
|
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);
|
LIBSSH2_FREE(session, newprefs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
33
src/mac.c
33
src/mac.c
@@ -54,6 +54,7 @@ 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
|
||||||
@@ -98,7 +99,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, session->kex->key_len, EVP_sha1());
|
HMAC_Init(&ctx, *abstract, 20, 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) {
|
||||||
@@ -113,7 +114,8 @@ 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",
|
||||||
SHA_DIGEST_LENGTH,
|
20,
|
||||||
|
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,
|
||||||
@@ -137,13 +139,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",
|
||||||
96 / 8,
|
12,
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
@@ -156,7 +158,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, session->kex->key_len, EVP_md5());
|
HMAC_Init(&ctx, *abstract, 16, 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) {
|
||||||
@@ -171,7 +173,8 @@ 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",
|
||||||
MD5_DIGEST_LENGTH,
|
16,
|
||||||
|
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,
|
||||||
@@ -180,8 +183,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 seqno,
|
static int libssh2_mac_method_hmac_md5_96_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno,
|
||||||
const unsigned char *packet, unsigned packet_len,
|
const unsigned char *packet, unsigned long 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];
|
||||||
@@ -195,12 +198,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",
|
||||||
96 / 8,
|
12,
|
||||||
|
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
|
||||||
@@ -215,7 +218,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, session->kex->key_len, EVP_ripemd160());
|
HMAC_Init(&ctx, *abstract, 20, 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) {
|
||||||
@@ -230,7 +233,8 @@ 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",
|
||||||
160 / 8,
|
20,
|
||||||
|
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,
|
||||||
@@ -238,7 +242,8 @@ 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",
|
||||||
160 / 8,
|
20,
|
||||||
|
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,
|
||||||
@@ -248,10 +253,8 @@ 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,
|
||||||
|
287
src/packet.c
287
src/packet.c
@@ -38,8 +38,236 @@
|
|||||||
#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>
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ 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;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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
|
||||||
@@ -229,6 +457,24 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
|
||||||
@@ -275,8 +521,17 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
|
|||||||
while (bytes_read < count) {
|
while (bytes_read < count) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = read(session->socket_fd, buf + bytes_read, count - bytes_read);
|
ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
#ifdef WIN32
|
||||||
|
switch (WSAGetLastError()) {
|
||||||
|
case WSAEWOULDBLOCK: errno = EAGAIN;
|
||||||
|
case WSAENOTCONN:
|
||||||
|
case WSAENOTSOCK:
|
||||||
|
case WSAECONNABORTED: errno = EBADF;
|
||||||
|
case WSAEINTR: errno = EINTR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
|
if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -315,7 +570,14 @@ 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
|
||||||
|
{
|
||||||
|
u_long non_block = TRUE;
|
||||||
|
ioctlsocket(session->socket_fd, FIONBIO, &non_block);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (session->newkeys) {
|
if (session->newkeys) {
|
||||||
/* Temporary Buffer
|
/* Temporary Buffer
|
||||||
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
|
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
|
||||||
@@ -336,7 +598,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
|
|||||||
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 = read(session->socket_fd, block, 1);
|
read_len = recv(session->socket_fd, block, 1, 0);
|
||||||
if (read_len <= 0) {
|
if (read_len <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -461,7 +723,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 = read(session->socket_fd, buf, 1);
|
buf_len = recv(session->socket_fd, buf, 1, 0);
|
||||||
if (buf_len <= 0) {
|
if (buf_len <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -481,8 +743,13 @@ 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 */
|
||||||
padding_length -= libssh2_blocking_read(session, buf, padding_length);
|
l = 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 */
|
||||||
@@ -589,7 +856,15 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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) {
|
||||||
@@ -627,7 +902,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);
|
||||||
memcpy(encbuf + 5 + data_len, buf + 5, padding_length);
|
RAND_bytes(encbuf + 5 + data_len, padding_length);
|
||||||
if (free_data) {
|
if (free_data) {
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
}
|
}
|
||||||
@@ -648,7 +923,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) == write(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len)) ? 0 : -1;
|
ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, 0)) ? 0 : -1;
|
||||||
|
|
||||||
/* Cleanup environment */
|
/* Cleanup environment */
|
||||||
LIBSSH2_FREE(session, encbuf);
|
LIBSSH2_FREE(session, encbuf);
|
||||||
|
129
src/session.c
129
src/session.c
@@ -37,7 +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>
|
||||||
|
|
||||||
/* {{{ libssh2_default_alloc
|
/* {{{ libssh2_default_alloc
|
||||||
@@ -79,7 +81,7 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
|
|||||||
char c = '\0';
|
char c = '\0';
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = read(session->socket_fd, &c, 1);
|
ret = recv(session->socket_fd, &c, 1, 0);
|
||||||
|
|
||||||
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 */
|
||||||
@@ -124,7 +126,38 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
|
|||||||
banner = session->local.banner;
|
banner = session->local.banner;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (write(session->socket_fd, banner, banner_len) == banner_len) ? 0 : 1;
|
return (send(session->socket_fd, banner, banner_len, 0) == banner_len) ? 0 : 1;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ libssh2_banner_set
|
||||||
|
* Set the local banner
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, 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);
|
||||||
|
session->local.banner[banner_len++] = '\r';
|
||||||
|
session->local.banner[banner_len++] = '\n';
|
||||||
|
session->local.banner[banner_len++] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@@ -189,6 +222,11 @@ LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbt
|
|||||||
session->macerror = callback;
|
session->macerror = callback;
|
||||||
return oldcb;
|
return oldcb;
|
||||||
break;
|
break;
|
||||||
|
case LIBSSH2_CALLBACK_X11:
|
||||||
|
oldcb = session->x11;
|
||||||
|
session->x11 = callback;
|
||||||
|
return oldcb;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -216,7 +254,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_receive(session)) {
|
if (libssh2_banner_receive(session)) {
|
||||||
/* Unable to receive banner from remote */
|
/* Unable to receive banner from remote */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0);
|
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0);
|
||||||
@@ -284,6 +321,10 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (session->listeners) {
|
||||||
|
libssh2_channel_forward_cancel(session->listeners);
|
||||||
|
}
|
||||||
|
|
||||||
if (session->newkeys) {
|
if (session->newkeys) {
|
||||||
/* hostkey */
|
/* hostkey */
|
||||||
if (session->hostkey && session->hostkey->dtor) {
|
if (session->hostkey && session->hostkey->dtor) {
|
||||||
@@ -392,10 +433,6 @@ 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);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
@@ -445,51 +482,57 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
|
|||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_session_methods
|
/* {{{ libssh2_session_methods
|
||||||
* Return the currently active 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
|
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
|
||||||
* Strings should NOT be freed
|
* Strings should NOT be freed
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API void libssh2_session_methods(LIBSSH2_SESSION *session, char **kex, char **hostkey,
|
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type)
|
||||||
char **crypt_cs, char **crypt_sc,
|
|
||||||
char **mac_cs, char **mac_sc,
|
|
||||||
char **comp_cs, char **comp_sc,
|
|
||||||
char **lang_cs, char **lang_sc)
|
|
||||||
{
|
{
|
||||||
if (kex) {
|
char *methodlist = NULL;
|
||||||
*kex = session->kex->name;
|
|
||||||
}
|
switch(method_type) {
|
||||||
if (hostkey) {
|
case LIBSSH2_METHOD_KEX:
|
||||||
*hostkey = session->hostkey->name;
|
methodlist = session->kex->name;
|
||||||
}
|
break;
|
||||||
if (crypt_cs) {
|
case LIBSSH2_METHOD_HOSTKEY:
|
||||||
*crypt_cs = session->local.crypt->name;
|
methodlist = session->hostkey->name;
|
||||||
}
|
break;
|
||||||
if (crypt_sc) {
|
case LIBSSH2_METHOD_CRYPT_CS:
|
||||||
*crypt_sc = session->remote.crypt->name;
|
methodlist = session->local.crypt->name;
|
||||||
}
|
break;
|
||||||
if (mac_cs) {
|
case LIBSSH2_METHOD_CRYPT_SC:
|
||||||
*mac_cs = session->local.mac->name;
|
methodlist = session->remote.crypt->name;
|
||||||
}
|
break;
|
||||||
if (mac_sc) {
|
case LIBSSH2_METHOD_MAC_CS:
|
||||||
*mac_sc = session->remote.mac->name;
|
methodlist = session->local.mac->name;
|
||||||
}
|
break;
|
||||||
if (comp_cs) {
|
case LIBSSH2_METHOD_MAC_SC:
|
||||||
*comp_cs = session->local.comp->name;
|
methodlist = session->remote.mac->name;
|
||||||
}
|
break;
|
||||||
if (comp_sc) {
|
case LIBSSH2_METHOD_COMP_CS:
|
||||||
*comp_sc = session->remote.comp->name;
|
methodlist = session->local.comp->name;
|
||||||
}
|
break;
|
||||||
if (lang_cs) {
|
case LIBSSH2_METHOD_COMP_SC:
|
||||||
*lang_cs = "";
|
methodlist = session->remote.comp->name;
|
||||||
}
|
break;
|
||||||
if (lang_sc) {
|
case LIBSSH2_METHOD_LANG_CS:
|
||||||
*lang_sc = "";
|
methodlist = "";
|
||||||
|
break;
|
||||||
|
case LIBSSH2_METHOD_LANG_SC:
|
||||||
|
methodlist = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
|
||||||
|
methodlist = NULL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return(methodlist);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_session_abstract
|
/* {{{ libssh2_session_abstract
|
||||||
* Retreive a pointer to the abstract property
|
* Retrieve a pointer to the abstract property
|
||||||
*/
|
*/
|
||||||
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session)
|
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
44
src/sftp.c
44
src/sftp.c
@@ -83,7 +83,7 @@ struct _LIBSSH2_SFTP {
|
|||||||
|
|
||||||
LIBSSH2_SFTP_HANDLE *handles;
|
LIBSSH2_SFTP_HANDLE *handles;
|
||||||
|
|
||||||
unsigned long errno;
|
unsigned long last_errno;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIBSSH2_SFTP_HANDLE_FILE 0
|
#define LIBSSH2_SFTP_HANDLE_FILE 0
|
||||||
@@ -100,7 +100,7 @@ struct _LIBSSH2_SFTP_HANDLE {
|
|||||||
|
|
||||||
union _libssh2_sftp_handle_data {
|
union _libssh2_sftp_handle_data {
|
||||||
struct _libssh2_sftp_handle_file_data {
|
struct _libssh2_sftp_handle_file_data {
|
||||||
unsigned long long offset;
|
libssh2_uint64_t offset;
|
||||||
} file;
|
} file;
|
||||||
struct _libssh2_sftp_handle_dir_data {
|
struct _libssh2_sftp_handle_dir_data {
|
||||||
unsigned long names_left;
|
unsigned long names_left;
|
||||||
@@ -318,13 +318,16 @@ static int libssh2_sftp_attrsize(LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
|||||||
static int libssh2_sftp_attr2bin(unsigned char *p, LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
static int libssh2_sftp_attr2bin(unsigned char *p, LIBSSH2_SFTP_ATTRIBUTES *attrs)
|
||||||
{
|
{
|
||||||
unsigned char *s = p;
|
unsigned char *s = p;
|
||||||
|
unsigned long flag_mask = LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
|
||||||
|
|
||||||
|
/* TODO: When we add SFTP4+ functionality flag_mask can get additional bits */
|
||||||
|
|
||||||
if (!attrs) {
|
if (!attrs) {
|
||||||
libssh2_htonu32(s, 0);
|
libssh2_htonu32(s, 0);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
libssh2_htonu32(s, attrs->flags & 0x0000000); s += 4;
|
libssh2_htonu32(s, attrs->flags & flag_mask); s += 4;
|
||||||
|
|
||||||
if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
|
if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
|
||||||
libssh2_htonu64(s, attrs->filesize); s += 8;
|
libssh2_htonu64(s, attrs->filesize); s += 8;
|
||||||
@@ -542,7 +545,7 @@ LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, char *
|
|||||||
|
|
||||||
if (data[0] == SSH_FXP_STATUS) {
|
if (data[0] == SSH_FXP_STATUS) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Failed opening remote file", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Failed opening remote file", 0);
|
||||||
sftp->errno = libssh2_ntohu32(data + 5);
|
sftp->last_errno = libssh2_ntohu32(data + 5);
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -627,7 +630,7 @@ LIBSSH2_API size_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
|||||||
|
|
||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case SSH_FXP_STATUS:
|
case SSH_FXP_STATUS:
|
||||||
sftp->errno = libssh2_ntohu32(data + 5);
|
sftp->last_errno = libssh2_ntohu32(data + 5);
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -722,7 +725,7 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
|||||||
if (retcode == LIBSSH2_FX_EOF) {
|
if (retcode == LIBSSH2_FX_EOF) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -809,7 +812,7 @@ LIBSSH2_API size_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *b
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -865,7 +868,7 @@ LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_
|
|||||||
if (retcode == LIBSSH2_FX_OK) {
|
if (retcode == LIBSSH2_FX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -938,7 +941,7 @@ LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
|
|||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
|
|
||||||
if (retcode != LIBSSH2_FX_OK) {
|
if (retcode != LIBSSH2_FX_OK) {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -950,10 +953,12 @@ LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
|
|||||||
handle->next->prev = NULL;
|
handle->next->prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->u.dir.names_left) {
|
if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) &&
|
||||||
|
handle->u.dir.names_left) {
|
||||||
LIBSSH2_FREE(session, handle->u.dir.names_packet);
|
LIBSSH2_FREE(session, handle->u.dir.names_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBSSH2_FREE(session, handle->handle);
|
||||||
LIBSSH2_FREE(session, handle);
|
LIBSSH2_FREE(session, handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1006,7 +1011,7 @@ LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, char *filename, int f
|
|||||||
if (retcode == LIBSSH2_FX_OK) {
|
if (retcode == LIBSSH2_FX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1064,17 +1069,17 @@ LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, char *source_filenam
|
|||||||
break;
|
break;
|
||||||
case LIBSSH2_FX_FILE_ALREADY_EXISTS:
|
case LIBSSH2_FX_FILE_ALREADY_EXISTS:
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "File already exists and SSH_FXP_RENAME_OVERWRITE not specified", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "File already exists and SSH_FXP_RENAME_OVERWRITE not specified", 0);
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
retcode = -1;
|
retcode = -1;
|
||||||
break;
|
break;
|
||||||
case LIBSSH2_FX_OP_UNSUPPORTED:
|
case LIBSSH2_FX_OP_UNSUPPORTED:
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Operation Not Supported", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Operation Not Supported", 0);
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
retcode = -1;
|
retcode = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
retcode = -1;
|
retcode = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,7 +1134,7 @@ LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_l
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1177,7 +1182,7 @@ LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_l
|
|||||||
if (retcode == LIBSSH2_FX_OK) {
|
if (retcode == LIBSSH2_FX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1243,7 +1248,7 @@ LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, char *path, int path_le
|
|||||||
if (retcode == LIBSSH2_FX_OK) {
|
if (retcode == LIBSSH2_FX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1317,7 +1322,7 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, in
|
|||||||
if (retcode == LIBSSH2_FX_OK) {
|
if (retcode == LIBSSH2_FX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
sftp->errno = retcode;
|
sftp->last_errno = retcode;
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1334,6 +1339,7 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, in
|
|||||||
link_len = target_len;
|
link_len = target_len;
|
||||||
}
|
}
|
||||||
memcpy(target, data + 13, link_len);
|
memcpy(target, data + 13, link_len);
|
||||||
|
LIBSSH2_FREE(session, data);
|
||||||
|
|
||||||
return link_len;
|
return link_len;
|
||||||
}
|
}
|
||||||
@@ -1344,6 +1350,6 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, in
|
|||||||
*/
|
*/
|
||||||
LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
|
LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
|
||||||
{
|
{
|
||||||
return sftp->errno;
|
return sftp->last_errno;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@@ -1,11 +1,17 @@
|
|||||||
#include "libssh2.h"
|
#include "libssh2.h"
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
#ifndef WIN32
|
||||||
|
# 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[]) {
|
||||||
@@ -14,16 +20,26 @@ int main(int argc, char *argv[]) {
|
|||||||
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);
|
||||||
connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in));
|
if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) {
|
||||||
|
fprintf(stderr, "failed to connect!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a session instance and start it up
|
/* 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
|
||||||
@@ -114,8 +130,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
9
win32/.cvsignore
Normal file
9
win32/.cvsignore
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
*.lib
|
||||||
|
*.pdb
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.obj
|
||||||
|
.*.swp
|
||||||
|
Debug
|
||||||
|
Release
|
||||||
|
*.exp
|
29
win32/config.mk
Normal file
29
win32/config.mk
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
# Tweak these for your system
|
||||||
|
OPENSSLINC=\local\php\php_build\include
|
||||||
|
OPENSSLLIB=\local\php\php_build\lib
|
||||||
|
|
||||||
|
ZLIBINC=-DLIBSSH2_HAVE_ZLIB=1 /I\local\php\php_build\include
|
||||||
|
ZLIBLIB=\local\php\php_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)
|
||||||
|
|
||||||
|
|
31
win32/libssh2_config.h
Normal file
31
win32/libssh2_config.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#define WIN32
|
||||||
|
#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
|
||||||
|
|
15
win32/rules.mk
Normal file
15
win32/rules.mk
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
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)\\" $<
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user