Compare commits

..

1 Commits

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

View File

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

60
INSTALL
View File

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

View File

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

View File

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

View File

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

83
README
View File

@@ -1,87 +1,8 @@
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
-----------
Fixed libssh2_channel_read_ex(). Packet loop initialized BEFORE transport polled for new packets (should have been after).
Fixed blocking issues in scp_send()/scp_recv().
Fixed degree of indirection in macerror callback.
Changed packet read mechanism to use a fixed buffer and avoid unnecessary alloc/free calls. (especially while non-block looping)
Added channel close callback.
Added SFTP support (Using its own header file: libssh2_sftp.h)
Version 0.2
-----------
Changed extended data ignorance mechanism:
libssh2_channel_ignore_extended_data() changed to libssh2_channel_handle_extended_data()
Macro introduced for backward compatability during beta phase.
*** THE LIBSSH2_CHANNEL_IGNORE_EXTENDED_DATA() MACRO WILL BE REMOVED PRIOR TO 1.0 RELEASE ***
libssh2_channel_handle_extended_data() may be passed one of three "ignore_mode" constants
LIBSSH2_CHANNEL_EXTENDED_DATA_NONE Default behavior, queue ED packets and return them with read_ex
LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE Equivalent to libssh2_channel_ignore_extended_data()
IGNORE will implicitly flush the extended data stream(s)
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE Calls to channel_read() will check both the standard data stream
and the extended data stream(s) for the first available packet
Changed libssh2_session_disconnect_ex() to return an error code when alloc fails
Added libssh2_channel_flush_ex() and basic macros: ..._flush() ..._flush_stderr()
flush_ex accepts either the streamid (0 for standard data, 1 for stderr) or one of the two following constants:
LIBSSH2_CHANNEL_FLUSH_ALL Flush all streams
LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA Flush all streams EXCEPT the standard data stream
Added libssh2_session_callback_set() for setting ignore/debug/disconnect/macerror callbacks
Added libssh2_session_method_pref() to selectively set methods and method preferences.
Added libssh2_session_methods() to determine what methods were negotiated.
Added libssh2_session_abstract() for retreiving &session->abstract
Added libssh2_session_last_error() for retreiving error codes/messages
Version 0.1
-----------
Version 0.1-dev
---------------
Initial Release:
KEX methods: diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1

1
TODO
View File

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

1415
config.guess vendored

File diff suppressed because it is too large Load Diff

1510
config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,11 @@
# AC_PREREQ(2.57)
AC_INIT(libssh2,0.5,sarag@libssh2.org)
AC_INIT(libssh2, 0.1 , pollita@php.net)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([include/libssh2_config.h])
# Check for the OS.
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
SHLIB_SUFFIX_NAME="so"
SHLIB_LDFLAGS="-shared"
AC_SUBST(SHLIB_SUFFIX_NAME)
AC_SUBST(SHLIB_LDFLAGS)
@@ -148,13 +138,6 @@ AC_ARG_ENABLE(mac-none,
AC_HELP_STRING([--enable-mac-none],[Permit "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.
# AC_HEADER_STDC
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h])

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -42,32 +42,7 @@
#include <string.h>
#include <sys/stat.h>
/* Allow alternate API prefix from CFLAGS or calling app */
#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
#define LIBSSH2_VERSION "0.1dev"
/* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@@ -76,50 +51,8 @@ typedef long long libssh2_int64_t;
#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER
#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
/* Capabilities */
#define LIBSSH2_KEX_DH_GROUP1
#define LIBSSH2_KEX_DH_GROUP14
#define LIBSSH2_KEX_DH_GROUP_EXCHANGE
#ifndef OPENSSL_NO_RSA
#define LIBSSH2_HOSTKEY_RSA
#endif
#ifndef OPENSSL_NO_DSA
#define LIBSSH2_HOSTKEY_DSA
#endif
#ifndef OPENSSL_NO_AES
#define LIBSSH2_CRYPT_AES256_CBC
#define LIBSSH2_CRYPT_RIJNDAEL_CBC_LYSATOR_LIU_SE
#define LIBSSH2_CRYPT_AES192_CBC
#define LIBSSH2_CRYPT_AES128_CBC
#endif
#ifndef OPENSSL_NO_BLOWFISH
#define LIBSSH2_CRYPT_BLOWFISH_CBC
#endif
#ifndef OPENSSL_NO_RC4
#define LIBSSH2_CRYPT_ARCFOUR
#endif
#ifndef OPENSSL_NO_CAST
#define LIBSSH2_CRYPT_CAST128_CBC
#endif
#ifndef OPENSSL_NO_DES
#define LIBSSH2_CRYPT_3DES_CBC
#endif
/* LIBSSH2_CRYPT_NONE already defined (or not) by ./configure */
#ifdef LIBSSH2_HAVE_ZLIB
#define LIBSSH2_COMP_ZLIB
#endif
#define LIBSSH2_COMP_NONE
#define LIBSSH2_MAC_SHA1
#define LIBSSH2_MAC_SHA1_96
#ifndef OPENSSL_NO_RIPEMD
#define LIBSSH2_MAC_RIPEMD160
#define LIBSSH2_MAC_RIPEMD160_OPENSSH_COM
#endif
/* 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 */
#define LIBSSH2_DH_GEX_MINGROUP 1024
@@ -138,13 +71,10 @@ typedef long long libssh2_int64_t;
#define LIBSSH2_SOCKET_POLL_MAXLOOPS 120
/* Maximum size to allow a payload to compress to, plays it safe by falling short of spec limits */
#define LIBSSH2_PACKET_MAXCOMP 32000
#define LIBSSH2_PACKET_MAXCOMP 32000
/* Maximum size to allow a payload to deccompress to, plays it safe by allowing more than spec requires */
#define LIBSSH2_PACKET_MAXDECOMP 40000
/* Maximum size for an inbound compressed payload, plays it safe by overshooting spec limits */
#define LIBSSH2_PACKET_MAXPAYLOAD 40000
#define LIBSSH2_PACKET_MAXDECOMP 40000
/* Malloc callbacks */
#define LIBSSH2_ALLOC_FUNC(name) void *name(size_t count, void **abstract)
@@ -157,32 +87,15 @@ typedef long long libssh2_int64_t;
#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_MACERROR_FUNC(name) int name(LIBSSH2_SESSION *session, const char *packet, int packet_len, void **abstract)
#define LIBSSH2_X11_OPEN_FUNC(name) void name(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, char *shost, int sport, void **abstract)
#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) void name(LIBSSH2_SESSION *session, void **session_abstract, LIBSSH2_CHANNEL *channel, void **channel_abstract)
/* libssh2_session_callback_set() constants */
#define LIBSSH2_CALLBACK_IGNORE 0
#define LIBSSH2_CALLBACK_DEBUG 1
#define LIBSSH2_CALLBACK_DISCONNECT 2
#define LIBSSH2_CALLBACK_MACERROR 3
#define LIBSSH2_CALLBACK_X11 4
/* libssh2_session_method_pref() constants */
#define LIBSSH2_METHOD_KEX 0
#define LIBSSH2_METHOD_HOSTKEY 1
#define LIBSSH2_METHOD_CRYPT_CS 2
#define LIBSSH2_METHOD_CRYPT_SC 3
#define LIBSSH2_METHOD_MAC_CS 4
#define LIBSSH2_METHOD_MAC_SC 5
#define LIBSSH2_METHOD_COMP_CS 6
#define LIBSSH2_METHOD_COMP_SC 7
#define LIBSSH2_METHOD_LANG_CS 8
#define LIBSSH2_METHOD_LANG_SC 9
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
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_SHA1 2
@@ -235,30 +148,18 @@ typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
#define LIBSSH2_ERROR_SCP_PROTOCOL -28
#define LIBSSH2_ERROR_ZLIB -29
#define LIBSSH2_ERROR_SOCKET_TIMEOUT -30
#define LIBSSH2_ERROR_SFTP_PROTOCOL -31
#define LIBSSH2_ERROR_REQUEST_DENIED -32
#define LIBSSH2_ERROR_METHOD_NOT_SUPPORTED -33
#define LIBSSH2_ERROR_INVAL -34
/* 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);
#define libssh2_session_init() libssh2_session_init_ex(NULL, NULL, NULL, NULL)
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session);
LIBSSH2_API void *libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback);
LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION *session, char *banner);
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 void libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang);
#define libssh2_session_disconnect(session, description) libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, (description), "")
LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session);
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 char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
/* Userauth API */
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len);
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
@@ -275,40 +176,23 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
#define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536
#define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384
/* Extended Data Handling */
#define LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL 0
#define LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE 1
#define LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE 2
#define SSH_EXTENDED_DATA_STDERR 1
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, 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)
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)
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);
#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);
#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);
#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_subsystem(channel, subsystem) libssh2_channel_process_startup((channel), "subsystem", sizeof("subsystem") - 1, (subsystem), strlen(subsystem))
#define SSH_EXTENDED_DATA_STDERR 1
LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen);
#define libssh2_channel_read(channel, buf, buflen) libssh2_channel_read_ex((channel), 0, (buf), (buflen))
#define libssh2_channel_read_stderr(channel, buf, buflen) libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
@@ -318,19 +202,6 @@ LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id
#define libssh2_channel_write_stderr(channel, buf, buflen) libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking);
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode);
/* libssh2_channel_ignore_extended_data() is defined below for BC with version 0.1
* Future uses should use libssh2_channel_handle_extended_data() directly
* if LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read (FIFO) from the standard data channel
*/
/* DEPRECATED */
#define libssh2_channel_ignore_extended_data(channel, ignore) libssh2_channel_handle_extended_data((channel), (ignore) ? LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL )
#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1
#define LIBSSH2_CHANNEL_FLUSH_ALL -2
LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid);
#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0)
#define libssh2_channel_flush_stderr(channel) libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);

View File

@@ -39,9 +39,6 @@
/* Enable "none" cipher -- NOT RECOMMENDED */
#undef LIBSSH2_CRYPT_NONE
/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
#undef LIBSSH2_DH_GEX_NEW
/* Compile in zlib support */
#undef LIBSSH2_HAVE_ZLIB

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -38,13 +38,11 @@
#ifndef LIBSSH2_PRIV_H
#define LIBSSH2_PRIV_H 1
#define LIBSSH2_LIBRARY
/* Definitions shared with the public */
#include "libssh2_config.h"
#include "libssh2.h"
#ifndef WIN32
#include <sys/socket.h>
#endif
#include <openssl/evp.h>
#define LIBSSH2_ALLOC(session, count) session->alloc((count), &(session)->abstract)
@@ -57,10 +55,7 @@
#define LIBSSH2_DISCONNECT(session, reason, message, message_len, language, language_len) \
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_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_MACERROR(session, data, datalen) session->macerror((session), (data), (datalen), (session)->abstract)
typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
@@ -103,7 +98,7 @@ typedef struct _libssh2_channel_data {
unsigned long window_size_initial, window_size, packet_size;
/* Set to 1 when CHANNEL_CLOSE / CHANNEL_EOF sent/received */
char close, eof, extended_data_ignore_mode;
int close, eof;
} libssh2_channel_data;
struct _LIBSSH2_CHANNEL {
@@ -117,28 +112,12 @@ struct _LIBSSH2_CHANNEL {
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *next, *prev;
void *abstract;
LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
};
struct _LIBSSH2_CHANNEL_BRIGADE {
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 {
unsigned char *banner;
@@ -156,10 +135,9 @@ typedef struct _libssh2_endpoint_data {
void *comp_abstract;
/* Method Preferences -- NULL yields "load order" */
char *crypt_prefs;
char *mac_prefs;
char *comp_prefs;
char *lang_prefs;
LIBSSH2_CRYPT_METHOD **crypt_prefs;
LIBSSH2_MAC_METHOD **mac_prefs;
LIBSSH2_COMP_METHOD **comp_prefs;
} libssh2_endpoint_data;
struct _LIBSSH2_SESSION {
@@ -174,11 +152,10 @@ struct _LIBSSH2_SESSION {
LIBSSH2_DEBUG_FUNC((*ssh_msg_debug));
LIBSSH2_DISCONNECT_FUNC((*ssh_msg_disconnect));
LIBSSH2_MACERROR_FUNC((*macerror));
LIBSSH2_X11_OPEN_FUNC((*x11));
/* Method preferences -- NULL yields "load order" */
char *kex_prefs;
char *hostkey_prefs;
LIBSSH2_KEX_METHOD **kex_prefs;
LIBSSH2_HOSTKEY_METHOD **hostkey_prefs;
int exchanging_keys;
int newkeys;
@@ -219,8 +196,6 @@ struct _LIBSSH2_SESSION {
LIBSSH2_CHANNEL_BRIGADE channels;
unsigned long next_channel;
LIBSSH2_LISTENER *listeners;
/* Actual I/O socket */
int socket_fd;
int socket_block;
@@ -238,6 +213,9 @@ struct _LIBSSH2_SESSION {
struct _LIBSSH2_KEX_METHOD {
char *name;
/* integrity key length */
unsigned long key_len;
/* Key exchange, populates session->* and returns 0 on success, non-0 on error */
int (*exchange_keys)(LIBSSH2_SESSION *session);
@@ -294,9 +272,6 @@ struct _LIBSSH2_MAC_METHOD {
/* The length of a given MAC packet */
int mac_len;
/* integrity key length */
int key_len;
/* Message Authentication Code Hashing algo */
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);
@@ -379,9 +354,7 @@ struct _LIBSSH2_MAC_METHOD {
void libssh2_session_shutdown(LIBSSH2_SESSION *session);
unsigned long libssh2_ntohu32(const unsigned char *buf);
libssh2_uint64_t libssh2_ntohu64(const unsigned char *buf);
void libssh2_htonu32(unsigned char *buf, unsigned long val);
void libssh2_htonu64(unsigned char *buf, libssh2_uint64_t val);
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);
@@ -392,7 +365,6 @@ 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)
int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned long data_len);
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);
/* Let crypt.c/hostkey.c/comp.c/mac.c expose their method structs */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -36,15 +36,12 @@
*/
#include "libssh2_priv.h"
#include <openssl/rand.h>
#ifndef WIN32
#include <unistd.h>
#endif
/* {{{ libssh2_channel_nextid
* Determine the next channel ID we can use at our end
*/
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session)
static unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session)
{
unsigned long id = session->next_channel;
LIBSSH2_CHANNEL *channel;
@@ -75,6 +72,7 @@ unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session)
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id)
{
LIBSSH2_CHANNEL *channel = session->channels.head;
while (channel) {
if (channel->local.id == channel_id) {
return channel;
@@ -106,39 +104,15 @@ LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long
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_CHANNEL *channel = NULL;
LIBSSH2_CHANNEL *channel;
unsigned long local_channel = libssh2_channel_nextid(session);
unsigned char *s, *packet = NULL;
unsigned char *s, *packet;
unsigned long packet_len = channel_type_len + message_len + 17; /* packet_type(1) + channel_type_len(4) + sender_channel(4) +
window_size(4) + packet_size(4) */
unsigned char *data = NULL;
unsigned char *data;
unsigned long data_len;
int polls = 0;
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate space for channel data", 0);
return NULL;
}
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->channel_type_len = channel_type_len;
channel->channel_type = LIBSSH2_ALLOC(session, channel_type_len);
if (!channel->channel_type) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed allocating memory for channel type name", 0);
LIBSSH2_FREE(session, channel);
return NULL;
}
memcpy(channel->channel_type, channel_type, channel_type_len);
/* REMEMBER: local as in locally sourced */
channel->local.id = local_channel;
channel->remote.window_size = window_size;
channel->remote.window_size_initial = window_size;
channel->remote.packet_size = packet_size;
libssh2_channel_add(session, channel);
s = packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate temporary space for packet", 0);
@@ -158,7 +132,8 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
if (libssh2_packet_write(session, packet, packet_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel-open request", 0);
goto channel_error;
LIBSSH2_FREE(session, packet);
return NULL;
}
while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
@@ -171,62 +146,62 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
/* TODO: provide reason code and description */
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Channel open failure", 0);
goto channel_error;
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
return NULL;
}
usleep(LIBSSH2_SOCKET_POLL_UDELAY);
if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
/* Give up waiting */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timed out waiting for response", 0);
goto channel_error;
LIBSSH2_FREE(session, packet);
return NULL;
}
}
LIBSSH2_FREE(session, packet);
channel->remote.id = libssh2_ntohu32(data + 5);
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) {
/* Play nice and close that channel that we're not going to use after all */
data[3] = SSH_MSG_CHANNEL_CLOSE;
libssh2_packet_write(session, data + 3, 5);
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate space for channel data", 0);
LIBSSH2_FREE(session, data);
return NULL;
}
memset(channel, 0, sizeof(LIBSSH2_CHANNEL));
channel->channel_type_len = channel_type_len;
channel->channel_type = LIBSSH2_ALLOC(session, channel_type_len);
if (!channel->channel_type) {
/* Play nice and close that channel that we're not going to use after all */
data[4] = SSH_MSG_CHANNEL_CLOSE;
libssh2_packet_write(session, data + 4, 5);
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Failed allocating memory for channel type name", 0);
LIBSSH2_FREE(session, channel);
return NULL;
}
memcpy(channel->channel_type, channel_type, channel_type_len);
/* REMEMBER: local as in locally sourced */
channel->local.id = local_channel;
channel->local.window_size = libssh2_ntohu32(data + 9);
channel->local.window_size_initial = libssh2_ntohu32(data + 9);
channel->local.packet_size = libssh2_ntohu32(data + 13);
LIBSSH2_FREE(session, packet);
channel->remote.id = libssh2_ntohu32(data + 5);
channel->remote.window_size = window_size;
channel->remote.window_size_initial = window_size;
channel->remote.packet_size = packet_size;
LIBSSH2_FREE(session, data);
libssh2_channel_add(session, channel);
return channel;
channel_error:
if (data) {
LIBSSH2_FREE(session, data);
}
if (packet) {
LIBSSH2_FREE(session, packet);
}
if (channel) {
unsigned char channel_id[4];
LIBSSH2_FREE(session, channel->channel_type);
if (channel->next) {
channel->next->prev = channel->prev;
}
if (channel->prev) {
channel->prev->next = channel->next;
}
if (session->channels.head == channel) {
session->channels.head = channel->next;
}
if (session->channels.tail == channel) {
session->channels.tail = channel->prev;
}
/* Clear out packets meant for this channel */
libssh2_htonu32(channel_id, channel->local.id);
while ((libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_DATA, &data, &data_len, 1, channel_id, 4, 1) >= 0) ||
(libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data, &data_len, 1, channel_id, 4, 1) >= 0)) {
LIBSSH2_FREE(session, data);
}
LIBSSH2_FREE(session, channel);
}
return NULL;
}
/* }}} */
@@ -235,7 +210,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
*/
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, char *host, int port, char *shost, int sport)
{
LIBSSH2_CHANNEL *channel;
unsigned char *message, *s;
unsigned long host_len = strlen(host), shost_len = strlen(shost);
unsigned long message_len = host_len + shost_len + 16; /* host_len(4) + port(4) + shost_len(4) + sport(4) */
@@ -253,195 +227,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *se
memcpy(s, shost, shost_len); s += shost_len;
libssh2_htonu32(s, sport); s += 4;
channel = libssh2_channel_open_ex(session, "direct-tcpip", sizeof("direct-tcpip") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, message, message_len);
LIBSSH2_FREE(session, message);
return channel;
}
/* }}} */
/* {{{ 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;
return libssh2_channel_open_ex(session, "direct-tcpip", sizeof("direct-tcpip") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, message, message_len);
}
/* }}} */
@@ -551,7 +337,6 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
LIBSSH2_FREE(session, packet);
return -1;
}
LIBSSH2_FREE(session, packet);
while (1) {
unsigned char *data;
@@ -577,85 +362,6 @@ 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
* Primitive for libssh2_channel_(shell|exec|subsystem)
*/
@@ -727,83 +433,6 @@ LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int bloc
}
/* }}} */
/* {{{ libssh2_channel_flush_ex
* Flush data from one (or all) stream
* Returns number of bytes flushed, or -1 on failure
*/
LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid)
{
LIBSSH2_PACKET *packet = channel->session->packets.head;
unsigned long refund_bytes = 0, flush_bytes = 0;
while (packet) {
LIBSSH2_PACKET *next = packet->next;
unsigned char packet_type = packet->data[0];
if (((packet_type == SSH_MSG_CHANNEL_DATA) || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) &&
(libssh2_ntohu32(packet->data + 1) == channel->local.id)) {
/* It's our channel at least */
if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) ||
((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA) && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) || (streamid = libssh2_ntohu32(packet->data + 5)))) ||
((packet_type == SSH_MSG_CHANNEL_DATA) && (streamid == 0))) {
/* It's one of the streams we wanted to flush */
refund_bytes += packet->data_len - 13;
flush_bytes += packet->data_len - packet->data_head;
LIBSSH2_FREE(channel->session, packet->data);
if (packet->prev) {
packet->prev->next = packet->next;
} else {
channel->session->packets.head = packet->next;
}
if (packet->next) {
packet->next->prev = packet->prev;
} else {
channel->session->packets.tail = packet->prev;
}
LIBSSH2_FREE(channel->session, packet);
}
}
packet = next;
}
if (refund_bytes && channel->remote.window_size_initial) {
unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
/* Adjust the window based on the block we just freed */
adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
libssh2_htonu32(adjust + 1, channel->remote.id);
libssh2_htonu32(adjust + 5, refund_bytes);
if (libssh2_packet_write(channel->session, adjust, 9)) {
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
return -1;
} else {
channel->remote.window_size += refund_bytes;
}
}
return flush_bytes;
}
/* }}} */
/* {{{ libssh2_channel_handle_extended_data
* How should extended data look to the calling app?
* Keep it in separate channels[_read() _read_stdder()]? (NORMAL)
* Merge the extended data to the standard data? [everything via _read()]? (MERGE)
* Ignore it entirely [toss out packets as they come in]? (IGNORE)
*/
LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
{
channel->remote.extended_data_ignore_mode = ignore_mode;
if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
libssh2_channel_flush_ex(channel, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
}
}
/* }}} */
/* {{{ libssh2_channel_read_ex
* Read data from a channel
*/
@@ -813,23 +442,17 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
int bytes_read = 0, blocking_read = 0;
do {
LIBSSH2_PACKET *packet;
LIBSSH2_PACKET *packet = session->packets.head;
/* Process any waiting packets */
while (libssh2_packet_read(session, blocking_read) > 0) blocking_read = 0;
packet = session->packets.head;
while (packet && (bytes_read < buflen)) {
/* In case packet gets destroyed during this iteration */
LIBSSH2_PACKET *next = packet->next;
/* Either we asked for a specific extended data stream (and data was available),
* or the standard stream (and data was available),
* or the standard stream with extended_data_merge enabled and data was available
*/
if ((stream_id && (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
(!stream_id && (packet->data[0] == SSH_MSG_CHANNEL_DATA) && (channel->local.id == libssh2_ntohu32(packet->data + 1))) ||
(!stream_id && (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (channel->local.id == libssh2_ntohu32(packet->data + 1)) && (channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
(!stream_id && (packet->data[0] == SSH_MSG_CHANNEL_DATA) && (channel->local.id == libssh2_ntohu32(packet->data + 1)))) {
int want = buflen - bytes_read;
int unlink_packet = 0;
@@ -857,18 +480,16 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
}
LIBSSH2_FREE(session, packet->data);
if (channel->remote.window_size_initial) {
/* Adjust the window based on the block we just freed */
adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
libssh2_htonu32(adjust + 1, channel->remote.id);
libssh2_htonu32(adjust + 5, packet->data_len - (stream_id ? 13 : 9));
/* Adjust the window based on the block we just freed */
adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
libssh2_htonu32(adjust + 1, channel->remote.id);
libssh2_htonu32(adjust + 5, packet->data_len - (stream_id ? 13 : 9));
if (libssh2_packet_write(session, adjust, 9)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
}
LIBSSH2_FREE(session, packet);
if (libssh2_packet_write(session, adjust, 9)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
}
LIBSSH2_FREE(session, packet);
}
}
packet = next;
@@ -906,7 +527,7 @@ LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id
/* twiddle our thumbs until there's window space available */
if (libssh2_packet_read(session, 1) < 0) {
/* Error occured, disconnect? */
return -1;
return 0;
}
}
@@ -1001,10 +622,6 @@ LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel)
return 0;
}
if (channel->close_cb) {
LIBSSH2_CHANNEL_CLOSE(session, channel);
}
packet[0] = SSH_MSG_CHANNEL_CLOSE;
libssh2_htonu32(packet + 1, channel->remote.id);
if (libssh2_packet_write(session, packet, 5)) {
@@ -1046,11 +663,6 @@ LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel)
LIBSSH2_FREE(session, data);
}
/* free "channel_type" */
if (channel->channel_type) {
LIBSSH2_FREE(session, channel->channel_type);
}
/* Unlink from channel brigade */
if (channel->prev) {
channel->prev->next = channel->next;

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -38,7 +38,6 @@
#include "libssh2_priv.h"
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#ifndef OPENSSL_NO_RSA
/* ***********
@@ -87,8 +86,7 @@ static int libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION *session, unsigne
/* {{{ libssh2_hostkey_method_ssh_rsa_passphrase_cb
* 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);
if (passphrase_len > (size - 1)) {
@@ -118,14 +116,6 @@ static int libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session, unsi
if (!fp) {
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);
if (!rsactx) {
fclose(fp);
@@ -332,14 +322,6 @@ static int libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session, unsi
if (!fp) {
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);
if (!dsactx) {
fclose(fp);
@@ -389,16 +371,16 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
const unsigned char *buf, unsigned long buf_len, void **abstract)
{
DSA *dsactx = (DSA*)(*abstract);
DSA_SIG *sig;
int ret;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA_CTX ctx;
int r_len, s_len, rs_pad;
char *sig;
int sig_len;
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
*signature_len = 2 * SHA_DIGEST_LENGTH;
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
sig_len = DSA_size(dsactx);
sig = LIBSSH2_ALLOC(session, sig_len);
if (!(*signature)) {
if (!sig) {
return -1;
}
@@ -406,25 +388,14 @@ static int libssh2_hostkey_method_ssh_dss_sign(LIBSSH2_SESSION *session, unsigne
SHA1_Update(&ctx, buf, buf_len);
SHA1_Final(hash, &ctx);
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
if (!sig) {
LIBSSH2_FREE(session, *signature);
ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
if (!ret) {
LIBSSH2_FREE(session, sig);
return -1;
}
r_len = BN_num_bytes(sig->r);
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);
*signature = sig;
*signature_len = sig_len;
return 0;
}
@@ -437,16 +408,16 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
unsigned long veccount, const struct iovec datavec[], void **abstract)
{
DSA *dsactx = (DSA*)(*abstract);
DSA_SIG *sig;
int ret, i;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA_CTX ctx;
int r_len, s_len, rs_pad, i;
char *sig;
int sig_len;
*signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
*signature_len = 2 * SHA_DIGEST_LENGTH;
memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
sig_len = DSA_size(dsactx);
sig = LIBSSH2_ALLOC(session, sig_len);
if (!(*signature)) {
if (!sig) {
return -1;
}
@@ -456,25 +427,15 @@ static int libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION *session, unsign
}
SHA1_Final(hash, &ctx);
sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
if (!sig) {
LIBSSH2_FREE(session, *signature);
ret = DSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sig, &sig_len, dsactx);
if (!ret) {
LIBSSH2_FREE(session, sig);
return -1;
}
r_len = BN_num_bytes(sig->r);
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);
*signature = sig;
*signature_len = sig_len;
return 0;
}
@@ -524,10 +485,7 @@ LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void)
}
/* {{{ libssh2_hostkey_hash
* Returns hash signature
* Returned buffer should NOT be freed
* Length of buffer is determined by hash type
* i.e. MD5 == 16, SHA1 == 20
* Returns NULL terminated hash signature
*/
LIBSSH2_API char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type)
{

331
src/kex.c
View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -39,7 +39,6 @@
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
/* TODO: Switch this to an inline and handle alloc() failures */
/* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */
@@ -385,11 +384,11 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->local.mac->key_len, "E");
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->kex->key_len, "E");
session->local.mac->init(session, key, &free_key, &session->local.mac_abstract);
if (free_key) {
memset(key, 0, session->local.mac->key_len);
memset(key, 0, session->kex->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -402,11 +401,11 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
unsigned char *key = NULL;
int free_key = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->remote.mac->key_len, "F");
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key, session->kex->key_len, "F");
session->remote.mac->init(session, key, &free_key, &session->remote.mac_abstract);
if (free_key) {
memset(key, 0, session->remote.mac->key_len);
memset(key, 0, session->kex->key_len);
LIBSSH2_FREE(session, key);
}
}
@@ -596,18 +595,21 @@ static int libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange(LI
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group1_sha1 = {
"diffie-hellman-group1-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group14_sha1 = {
"diffie-hellman-group14-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group_exchange_sha1 = {
"diffie-hellman-group-exchange-sha1",
SHA_DIGEST_LENGTH,
libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
};
@@ -669,16 +671,16 @@ static size_t libssh2_kex_method_list(unsigned char *buf, size_t list_strlen, LI
}
/* }}} */
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) ((prefvar) ? strlen(prefvar) : libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
if (prefvar) { \
libssh2_htonu32((buf), (prefvarlen)); \
buf += 4; \
memcpy((buf), (prefvar), (prefvarlen)); \
buf += (prefvarlen); \
} else { \
buf += libssh2_kex_method_list((buf), (prefvarlen), (LIBSSH2_COMMON_METHOD**)(defaultvar)); \
}
#define LIBSSH2_METHOD_PREFS \
LIBSSH2_KEX_METHOD **kex_prefs = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods; \
LIBSSH2_HOSTKEY_METHOD **hostkey_prefs = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods(); \
LIBSSH2_CRYPT_METHOD **crypt_cs_prefs = session->local.crypt_prefs ? session->local.crypt_prefs : libssh2_crypt_methods(); \
LIBSSH2_CRYPT_METHOD **crypt_sc_prefs = session->remote.crypt_prefs ? session->remote.crypt_prefs : libssh2_crypt_methods(); \
LIBSSH2_COMP_METHOD **comp_cs_prefs = session->local.comp_prefs ? session->local.comp_prefs : libssh2_comp_methods(); \
LIBSSH2_COMP_METHOD **comp_sc_prefs = session->remote.comp_prefs ? session->remote.comp_prefs : libssh2_comp_methods(); \
LIBSSH2_MAC_METHOD **mac_cs_prefs = session->local.mac_prefs ? session->local.mac_prefs : libssh2_mac_methods(); \
LIBSSH2_MAC_METHOD **mac_sc_prefs = session->remote.mac_prefs ? session->remote.mac_prefs : libssh2_mac_methods();
/* {{{ libssh2_kexinit
* Send SSH_MSG_KEXINIT packet
@@ -692,17 +694,18 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
size_t mac_cs_len, mac_sc_len;
size_t lang_cs_len, lang_sc_len;
unsigned char *data, *s;
LIBSSH2_METHOD_PREFS
kex_len = LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
hostkey_len = LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs, libssh2_hostkey_methods());
crypt_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs, libssh2_crypt_methods());
crypt_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs, libssh2_crypt_methods());
mac_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs, libssh2_mac_methods());
mac_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs, libssh2_mac_methods());
comp_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs, libssh2_comp_methods());
comp_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs, libssh2_comp_methods());
lang_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
lang_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL);
kex_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)kex_prefs);
hostkey_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)hostkey_prefs);
crypt_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
crypt_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
mac_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
mac_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
comp_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
comp_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
lang_cs_len = 0; /* No langs in this version */
lang_sc_len = 0; /* No langs in this version */
data_len += kex_len + hostkey_len + \
crypt_cs_len + crypt_sc_len + \
@@ -718,20 +721,21 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
*(s++) = SSH_MSG_KEXINIT;
RAND_bytes(s, 16);
/* TODO: Build a better cookie (and the mice will beat a path to my door...) */
memcpy(s, "mysecretMYSECRET", 16);
s += 16;
/* Ennumerating through these lists twice is probably (certainly?) inefficient from a CPU standpoint, but it saves multiple malloc/realloc calls */
LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs, libssh2_kex_methods);
LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs, libssh2_hostkey_methods());
LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs, libssh2_crypt_methods());
LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs, libssh2_crypt_methods());
LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs, libssh2_mac_methods());
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs, libssh2_mac_methods());
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs, libssh2_comp_methods());
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs, libssh2_comp_methods());
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs, NULL);
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs, NULL);
s += libssh2_kex_method_list(s, kex_len, (LIBSSH2_COMMON_METHOD**)kex_prefs);
s += libssh2_kex_method_list(s, hostkey_len, (LIBSSH2_COMMON_METHOD**)hostkey_prefs);
s += libssh2_kex_method_list(s, crypt_cs_len, (LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
s += libssh2_kex_method_list(s, crypt_sc_len, (LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
s += libssh2_kex_method_list(s, mac_cs_len, (LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
s += libssh2_kex_method_list(s, mac_sc_len, (LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
s += libssh2_kex_method_list(s, comp_cs_len, (LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
s += libssh2_kex_method_list(s, comp_sc_len, (LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
s += libssh2_kex_method_list(s, lang_cs_len, NULL);
s += libssh2_kex_method_list(s, lang_sc_len, NULL);
/* No optimistic KEX packet follows */
/* Deal with optimistic packets
@@ -799,61 +803,14 @@ static unsigned char *libssh2_kex_agree_instr(unsigned char *haystack, unsigned
}
/* }}} */
/* {{{ libssh2_get_method_by_name
*/
static LIBSSH2_COMMON_METHOD *libssh2_get_method_by_name(char *name, int name_len, LIBSSH2_COMMON_METHOD **methodlist)
{
while (*methodlist) {
if ((strlen((*methodlist)->name) == name_len) &&
(strncmp((*methodlist)->name, name, name_len) == 0)) {
return *methodlist;
}
methodlist++;
}
return NULL;
}
/* }}} */
/* {{{ libssh2_kex_agree_hostkey
* Agree on a Hostkey which works with this kex
*/
static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex_flags, unsigned char *hostkey, unsigned long hostkey_len)
{
LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
LIBSSH2_HOSTKEY_METHOD **hostkeyp = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods();
unsigned char *s;
if (session->hostkey_prefs) {
s = session->hostkey_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
LIBSSH2_HOSTKEY_METHOD *method = (LIBSSH2_HOSTKEY_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)hostkeyp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
(method->encrypt)) {
/* Either this hostkey can do encryption or this kex just doesn't require it */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == 0) ||
(method->sig_verify)) {
/* Either this hostkey can do signing or this kex just doesn't require it */
session->hostkey = method;
return 0;
}
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*hostkeyp)->name) {
s = libssh2_kex_agree_instr(hostkey, hostkey_len, (*hostkeyp)->name, strlen((*hostkeyp)->name));
if (s) {
@@ -882,37 +839,9 @@ static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex
static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char *kex, unsigned long kex_len,
unsigned char *hostkey, unsigned long hostkey_len)
{
LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
LIBSSH2_KEX_METHOD **kexp = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods;
unsigned char *s;
if (session->kex_prefs) {
s = session->kex_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(kex, kex_len, s, method_len)) {
LIBSSH2_KEX_METHOD *method = (LIBSSH2_KEX_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)kexp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
if (libssh2_kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) {
session->kex = method;
return 0;
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*kexp && (*kexp)->name) {
s = libssh2_kex_agree_instr(kex, kex_len, (*kexp)->name, strlen((*kexp)->name));
if (s) {
@@ -935,33 +864,9 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
*/
static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *crypt, unsigned long crypt_len)
{
LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
LIBSSH2_CRYPT_METHOD **cryptp = endpoint->crypt_prefs ? endpoint->crypt_prefs : libssh2_crypt_methods();
unsigned char *s;
if (endpoint->crypt_prefs) {
s = endpoint->crypt_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
LIBSSH2_CRYPT_METHOD *method = (LIBSSH2_CRYPT_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)cryptp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->crypt = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*cryptp)->name) {
s = libssh2_kex_agree_instr(crypt, crypt_len, (*cryptp)->name, strlen((*cryptp)->name));
if (s) {
@@ -980,33 +885,9 @@ static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_da
*/
static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *mac, unsigned long mac_len)
{
LIBSSH2_MAC_METHOD **macp = libssh2_mac_methods();
LIBSSH2_MAC_METHOD **macp = endpoint->mac_prefs ? endpoint->mac_prefs : libssh2_mac_methods();
unsigned char *s;
if (endpoint->mac_prefs) {
s = endpoint->mac_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
LIBSSH2_MAC_METHOD *method = (LIBSSH2_MAC_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)macp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->mac = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*macp)->name) {
s = libssh2_kex_agree_instr(mac, mac_len, (*macp)->name, strlen((*macp)->name));
if (s) {
@@ -1025,33 +906,9 @@ static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data
*/
static int libssh2_kex_agree_comp(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *comp, unsigned long comp_len)
{
LIBSSH2_COMP_METHOD **compp = libssh2_comp_methods();
LIBSSH2_COMP_METHOD **compp = endpoint->comp_prefs ? endpoint->comp_prefs : libssh2_comp_methods();
unsigned char *s;
if (endpoint->comp_prefs) {
s = endpoint->comp_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
LIBSSH2_COMP_METHOD *method = (LIBSSH2_COMP_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)compp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->comp = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*compp)->name) {
s = libssh2_kex_agree_instr(comp, comp_len, (*compp)->name, strlen((*compp)->name));
if (s) {
@@ -1197,99 +1054,3 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
}
/* }}} */
/* {{{ libssh2_session_method_pref
* Set preferred method
*/
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, char *prefs)
{
char **prefvar, *s, *newprefs;
int prefs_len = strlen(prefs);
LIBSSH2_COMMON_METHOD **mlist;
switch (method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_kex_methods;
break;
case LIBSSH2_METHOD_HOSTKEY:
prefvar = &session->hostkey_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_hostkey_methods();
break;
case LIBSSH2_METHOD_CRYPT_CS:
prefvar = &session->local.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_CRYPT_SC:
prefvar = &session->remote.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_MAC_CS:
prefvar = &session->local.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_MAC_SC:
prefvar = &session->remote.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_COMP_CS:
prefvar = &session->local.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_COMP_SC:
prefvar = &session->remote.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_LANG_CS:
prefvar = &session->local.lang_prefs;
mlist = NULL;
break;
case LIBSSH2_METHOD_LANG_SC:
prefvar = &session->remote.lang_prefs;
mlist = NULL;
break;
default:
libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid parameter specified for method_type", 0);
return -1;
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
if (!newprefs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocated space for method preferences", 0);
return -1;
}
memcpy(s, prefs, prefs_len + 1);
while (s && *s) {
char *p = strchr(s, ',');
int method_len = p ? (p - s) : strlen(s);
if (!libssh2_get_method_by_name(s, method_len, mlist)) {
/* Strip out unsupported method */
if (p) {
memcpy(s, p + 1, strlen(s) - method_len);
} else {
if (s > newprefs) {
*(--s) = '\0';
} else {
*s = '\0';
}
}
}
s = p ? (p + 1) : NULL;
}
if (strlen(newprefs) == 0) {
libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, "The requested method(s) are not currently supported", 0);
LIBSSH2_FREE(session, newprefs);
return -1;
}
if (*prefvar) {
LIBSSH2_FREE(session, *prefvar);
}
*prefvar = newprefs;
return 0;
}
/* }}} */

View File

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

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -45,21 +45,6 @@ unsigned long libssh2_ntohu32(const unsigned char *buf)
}
/* }}} */
/* {{{ libssh2_ntohu64
* Note: Some 32-bit platforms have issues with bitops on long longs
* Work around this by doing expensive (but safer) arithmetic ops with optimization defying parentheses
*/
unsigned long long libssh2_ntohu64(const unsigned char *buf)
{
unsigned long msl, lsl;
msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
return ((msl * 65536) * 65536) + lsl;
}
/* }}} */
/* {{{ libssh2_htonu32
*/
void libssh2_htonu32(unsigned char *buf, unsigned long value)
@@ -71,24 +56,6 @@ void libssh2_htonu32(unsigned char *buf, unsigned long value)
}
/* }}} */
/* {{{ libssh2_htonu64
*/
void libssh2_htonu64(unsigned char *buf, unsigned long long value)
{
unsigned long msl = (value / 65536) / 65536;
buf[0] = (msl >> 24) & 0xFF;
buf[1] = (msl >> 16) & 0xFF;
buf[2] = (msl >> 8) & 0xFF;
buf[3] = msl & 0xFF;
buf[4] = (value >> 24) & 0xFF;
buf[5] = (value >> 16) & 0xFF;
buf[6] = (value >> 8) & 0xFF;
buf[7] = value & 0xFF;
}
/* }}} */
/* Base64 Conversion */
/* {{{ */

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -38,236 +38,8 @@
#include "libssh2_priv.h"
#include <errno.h>
#include <fcntl.h>
#ifndef WIN32
#include <unistd.h>
#endif
#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
* Create a new packet and attach it to the brigade
@@ -381,24 +153,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
LIBSSH2_FREE(session, data);
return 0;
}
if ((channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
/* Pretend we didn't receive this */
LIBSSH2_FREE(session, data);
if (channel->remote.window_size_initial) {
/* Adjust the window based on the block we just freed */
unsigned char adjust[9];
adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
libssh2_htonu32(adjust + 1, channel->remote.id);
libssh2_htonu32(adjust + 5, datalen - 13);
if (libssh2_packet_write(channel->session, adjust, 9)) {
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
}
}
return 0;
}
/* REMEMBER! remote means remote as source of data, NOT remote window! */
if (channel->remote.packet_size < (datalen - data_head)) {
@@ -457,24 +211,6 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0;
}
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));
@@ -521,17 +257,8 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s
while (bytes_read < count) {
int ret;
ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, 0);
ret = read(session->socket_fd, buf + bytes_read, count - bytes_read);
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 (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
return -1;
@@ -570,19 +297,9 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return 0;
}
#ifndef WIN32
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) {
/* Temporary Buffer
* The largest blocksize (currently) is 32, the largest MAC (currently) is 20
*/
unsigned char block[2 * 32], *payload, *s, tmp[6];
unsigned char *block, *payload, *s, tmp[6];
long read_len;
unsigned long blocksize = session->remote.crypt->blocksize;
unsigned long packet_len, payload_len;
@@ -592,19 +309,24 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
/* Safely ignored in CUSTOM cipher mode */
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)session->remote.crypt_abstract;
/* Temporary Buffer */
block = LIBSSH2_ALLOC(session, 2 * (blocksize > session->remote.mac->mac_len ? blocksize : session->remote.mac->mac_len));
/* Note: If we add any cipher with a blocksize less than 6 we'll need to get more creative with this
* For now, all blocksize sizes are 8+
*/
if (should_block) {
read_len = libssh2_blocking_read(session, block, blocksize);
} else {
read_len = recv(session->socket_fd, block, 1, 0);
read_len = read(session->socket_fd, block, 1);
if (read_len <= 0) {
LIBSSH2_FREE(session, block);
return 0;
}
read_len += libssh2_blocking_read(session, block + read_len, blocksize - read_len);
}
if (read_len < blocksize) {
LIBSSH2_FREE(session, block);
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
}
@@ -614,6 +336,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
} else {
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
LIBSSH2_FREE(session, block);
return -1;
}
}
@@ -623,15 +346,6 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
memcpy(tmp, block, 5); /* Use this for MAC later */
payload_len = packet_len - 1; /* padding_len(1) */
/* Sanity Check */
if ((payload_len > LIBSSH2_PACKET_MAXPAYLOAD) ||
((packet_len + 4) % blocksize)) {
/* If something goes horribly wrong during the decryption phase, just bailout and die gracefully */
session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
libssh2_error(session, LIBSSH2_ERROR_PROTO, "Fatal protocol error, invalid payload size", 0);
return -1;
}
s = payload = LIBSSH2_ALLOC(session, payload_len);
memcpy(s, block + 5, blocksize - 5);
s += blocksize - 5;
@@ -639,6 +353,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
while ((s - payload) < payload_len) {
read_len = libssh2_blocking_read(session, block, blocksize);
if (read_len < blocksize) {
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload);
return -1;
}
@@ -648,6 +363,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
} else {
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload);
return -1;
}
@@ -659,6 +375,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
read_len = libssh2_blocking_read(session, block, session->remote.mac->mac_len);
if (read_len < session->remote.mac->mac_len) {
LIBSSH2_FREE(session, block);
LIBSSH2_FREE(session, payload);
return -1;
}
@@ -667,9 +384,13 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
session->remote.mac->hash(session, block + session->remote.mac->mac_len, session->remote.seqno, tmp, 5, payload, payload_len, &session->remote.mac_abstract);
macstate = (strncmp(block, block + session->remote.mac->mac_len, session->remote.mac->mac_len) == 0) ? LIBSSH2_MAC_CONFIRMED : LIBSSH2_MAC_INVALID;
/* SMG */
if (macstate == LIBSSH2_MAC_INVALID) libssh2_error(session, -255, "EEEK an error!", 0);
session->remote.seqno++;
LIBSSH2_FREE(session, block);
/* Ignore padding */
payload_len -= padding_len;
@@ -702,6 +423,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
payload = LIBSSH2_ALLOC(session, data_len);
if (!payload) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for copy of uncompressed data", 0);
LIBSSH2_FREE(session, block);
return -1;
}
memcpy(payload, data, data_len);
@@ -723,7 +445,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
if (should_block) {
buf_len = libssh2_blocking_read(session, buf, 5);
} else {
buf_len = recv(session->socket_fd, buf, 1, 0);
buf_len = read(session->socket_fd, buf, 1);
if (buf_len <= 0) {
return 0;
}
@@ -743,13 +465,8 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
}
while (padding_length) {
int l;
/* Flush padding */
l = libssh2_blocking_read(session, buf, padding_length);
if (l > 0)
padding_length -= l;
else
break;
padding_length -= libssh2_blocking_read(session, buf, padding_length);
}
/* MACs don't exist in non-encrypted mode */
@@ -856,15 +573,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
}
}
#ifndef WIN32
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 */
padding_length = block_size - ((packet_length + 4) % block_size);
if (padding_length < 4) {
@@ -902,7 +611,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
/* Copy packet to encoding buffer */
memcpy(encbuf, buf, 5);
memcpy(encbuf + 5, data, data_len);
RAND_bytes(encbuf + 5 + data_len, padding_length);
memcpy(encbuf + 5 + data_len, buf + 5, padding_length);
if (free_data) {
LIBSSH2_FREE(session, data);
}
@@ -923,7 +632,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
session->local.seqno++;
/* Send It */
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;
ret = ((4 + packet_length + session->local.mac->mac_len) == write(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len)) ? 0 : -1;
/* Cleanup environment */
LIBSSH2_FREE(session, encbuf);

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -76,8 +76,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, char *pa
LIBSSH2_FREE(session, command);
return NULL;
}
/* Use blocking I/O for negotiation phase */
libssh2_channel_set_blocking(channel, 1);
/* Request SCP for the desired file */
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
@@ -309,8 +307,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, char *pa
sb->st_size = size;
sb->st_mode = mode;
}
/* Revert to non-blocking and let the data BEGIN! */
libssh2_channel_set_blocking(channel, 0);
/* Let the data BEGIN! */
return channel;
}
@@ -350,8 +347,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char
LIBSSH2_FREE(session, command);
return NULL;
}
/* Use blocking I/O for negotiation phase */
libssh2_channel_set_blocking(channel, 1);
/* Request SCP for the desired file */
if (libssh2_channel_process_startup(channel, "exec", sizeof("exec") - 1, command, command_len)) {
@@ -405,8 +400,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, char
return NULL;
}
/* Ready to start, switch to non-blocking and let calling app send file */
libssh2_channel_set_blocking(channel, 0);
/* Ready to send file */
return channel;
}

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -37,9 +37,7 @@
#include "libssh2_priv.h"
#include <errno.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <stdlib.h>
/* {{{ libssh2_default_alloc
@@ -81,7 +79,7 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session)
char c = '\0';
int ret;
ret = recv(session->socket_fd, &c, 1, 0);
ret = read(session->socket_fd, &c, 1);
if ((ret < 0) && (ret != EAGAIN)) {
/* Some kinda error, but don't break for non-blocking issues */
@@ -126,38 +124,7 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session)
banner = session->local.banner;
}
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;
return (write(session->socket_fd, banner, banner_len) == banner_len) ? 0 : 1;
}
/* }}} */
@@ -193,46 +160,6 @@ LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(
}
/* }}} */
/* {{{ libssh2_session_callback_set
* Set (or reset) a callback function
* Returns the prior address
*/
LIBSSH2_API void* libssh2_session_callback_set(LIBSSH2_SESSION *session, int cbtype, void *callback)
{
void *oldcb;
switch (cbtype) {
case LIBSSH2_CALLBACK_IGNORE:
oldcb = session->ssh_msg_ignore;
session->ssh_msg_ignore = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_DEBUG:
oldcb = session->ssh_msg_debug;
session->ssh_msg_debug = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_DISCONNECT:
oldcb = session->ssh_msg_disconnect;
session->ssh_msg_disconnect = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_MACERROR:
oldcb = session->macerror;
session->macerror = callback;
return oldcb;
break;
case LIBSSH2_CALLBACK_X11:
oldcb = session->x11;
session->x11 = callback;
return oldcb;
break;
}
return NULL;
}
/* }}} */
/* {{{ proto libssh2_session_startup
* session: LIBSSH2_SESSION struct allocated and owned by the calling program
* Returns: 0 on success, or non-zero on failure
@@ -254,6 +181,7 @@ LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int socket)
session->socket_fd = socket;
/* TODO: Liveness check */
if (libssh2_banner_receive(session)) {
/* Unable to receive banner from remote */
libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE, "Timeout waiting for banner", 0);
@@ -321,10 +249,6 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
}
}
while (session->listeners) {
libssh2_channel_forward_cancel(session->listeners);
}
if (session->newkeys) {
/* hostkey */
if (session->hostkey && session->hostkey->dtor) {
@@ -379,7 +303,6 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
}
}
/* Free banner(s) */
if (session->remote.banner) {
LIBSSH2_FREE(session, session->remote.banner);
}
@@ -387,40 +310,6 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, session->local.banner);
}
/* Free preference(s) */
if (session->kex_prefs) {
LIBSSH2_FREE(session, session->kex_prefs);
}
if (session->hostkey_prefs) {
LIBSSH2_FREE(session, session->hostkey_prefs);
}
if (session->local.crypt_prefs) {
LIBSSH2_FREE(session, session->local.crypt_prefs);
}
if (session->local.mac_prefs) {
LIBSSH2_FREE(session, session->local.mac_prefs);
}
if (session->local.comp_prefs) {
LIBSSH2_FREE(session, session->local.comp_prefs);
}
if (session->local.lang_prefs) {
LIBSSH2_FREE(session, session->local.lang_prefs);
}
if (session->remote.crypt_prefs) {
LIBSSH2_FREE(session, session->remote.crypt_prefs);
}
if (session->remote.mac_prefs) {
LIBSSH2_FREE(session, session->remote.mac_prefs);
}
if (session->remote.comp_prefs) {
LIBSSH2_FREE(session, session->remote.comp_prefs);
}
if (session->remote.lang_prefs) {
LIBSSH2_FREE(session, session->remote.lang_prefs);
}
/* Cleanup any remaining packets */
while (session->packets.head) {
LIBSSH2_PACKET *tmp = session->packets.head;
@@ -433,15 +322,19 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, tmp);
}
if (session->local.banner) {
LIBSSH2_FREE(session, session->local.banner);
}
LIBSSH2_FREE(session, session);
}
/* }}} */
/* {{{ libssh2_session_disconnect_ex
*/
LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang)
LIBSSH2_API void libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, char *description, char *lang)
{
unsigned char *s, *data;
unsigned char *data;
unsigned long data_len, descr_len = 0, lang_len = 0;
if (description) {
@@ -452,145 +345,28 @@ LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reas
}
data_len = descr_len + lang_len + 13; /* packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for disconnect packet", 0);
return -1;
}
data = LIBSSH2_ALLOC(session, data_len);
if (data) {
unsigned char *s = data;
*(s++) = SSH_MSG_DISCONNECT;
libssh2_htonu32(s, reason); s += 4;
*(s++) = SSH_MSG_DISCONNECT;
libssh2_htonu32(s, reason); s += 4;
libssh2_htonu32(s, descr_len); s += 4;
if (description) {
memcpy(s, description, descr_len);
s += descr_len;
}
libssh2_htonu32(s, lang_len); s += 4;
if (lang) {
memcpy(s, lang, lang_len);
s += lang_len;
}
libssh2_packet_write(session, data, data_len);
LIBSSH2_FREE(session, data);
return 0;
}
/* }}} */
/* {{{ libssh2_session_methods
* Return the currently active methods for method_type
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
* Strings should NOT be freed
*/
LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type)
{
char *methodlist = NULL;
switch(method_type) {
case LIBSSH2_METHOD_KEX:
methodlist = session->kex->name;
break;
case LIBSSH2_METHOD_HOSTKEY:
methodlist = session->hostkey->name;
break;
case LIBSSH2_METHOD_CRYPT_CS:
methodlist = session->local.crypt->name;
break;
case LIBSSH2_METHOD_CRYPT_SC:
methodlist = session->remote.crypt->name;
break;
case LIBSSH2_METHOD_MAC_CS:
methodlist = session->local.mac->name;
break;
case LIBSSH2_METHOD_MAC_SC:
methodlist = session->remote.mac->name;
break;
case LIBSSH2_METHOD_COMP_CS:
methodlist = session->local.comp->name;
break;
case LIBSSH2_METHOD_COMP_SC:
methodlist = session->remote.comp->name;
break;
case LIBSSH2_METHOD_LANG_CS:
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
* Retrieve a pointer to the abstract property
*/
LIBSSH2_API void **libssh2_session_abstract(LIBSSH2_SESSION *session)
{
return &session->abstract;
}
/* }}} */
/* {{{ libssh2_session_last_error
* Returns error code and populates an error string into errmsg
* If want_buf is non-zero then the string placed into errmsg must be freed by the calling program
* Otherwise it is assumed to be owned by libssh2
*/
LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf)
{
/* No error to report */
if (!session->err_code) {
if (errmsg) {
if (want_buf) {
*errmsg = LIBSSH2_ALLOC(session, 1);
if (*errmsg) {
**errmsg = 0;
}
} else {
*errmsg = "";
}
libssh2_htonu32(s, descr_len); s += 4;
if (description) {
memcpy(s, description, descr_len);
s += descr_len;
}
if (errmsg_len) {
*errmsg_len = 0;
libssh2_htonu32(s, lang_len); s += 4;
if (lang) {
memcpy(s, lang, lang_len);
s += lang_len;
}
return 0;
libssh2_packet_write(session, data, data_len);
LIBSSH2_FREE(session, data);
}
if (errmsg) {
char *serrmsg = session->err_msg ? session->err_msg : "";
int ownbuf = session->err_msg ? session->err_should_free : 0;
if (want_buf) {
if (ownbuf) {
/* Just give the calling program the buffer */
*errmsg = serrmsg;
session->err_should_free = 0;
} else {
/* Make a copy so the calling program can own it */
*errmsg = LIBSSH2_ALLOC(session, session->err_msglen + 1);
if (*errmsg) {
memcpy(*errmsg, session->err_msg, session->err_msglen);
(*errmsg)[session->err_msglen] = 0;
}
}
} else {
*errmsg = serrmsg;
}
}
if (errmsg_len) {
*errmsg_len = session->err_msglen;
}
return session->err_code;
}
/* }}} */

1355
src/sftp.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2004, Sara Golemon <sarag@libssh2.org>
/* Copyright (c) 2004, Sara Golemon <sarag@users.sourceforge.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -300,7 +300,7 @@ static int libssh2_file_read_privatekey(LIBSSH2_SESSION *session, LIBSSH2_HOSTKE
char *method, int method_len,
char *privkeyfile, char *passphrase)
{
LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail = libssh2_hostkey_methods();
LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods();
*hostkey_method = NULL;
*hostkey_abstract = NULL;

View File

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

View File

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

View File

@@ -1,29 +0,0 @@
# 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)

View File

@@ -1,31 +0,0 @@
#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

View File

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