+++ /dev/null
-Index: config.w32
-===================================================================
---- config.w32 (.../tags/RELEASE_0_11_0)
-+++ config.w32 (.../trunk)
-@@ -0,0 +1,37 @@
-+// $Id$
-+// vim:ft=javascript
-+
-+ARG_WITH("ssh2", "SSH2 support", "no");
-+
-+if (PHP_SSH2 != "no") {
-+ if ((((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib", "ssh2", PHP_SSH2) || CHECK_LIB("zlib.lib", "ssh2", PHP_SSH2))) ||
-+ (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "ssh2", PHP_SSH2)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) &&
-+ CHECK_LIB("libeay32.lib", "ssh2", PHP_SSH2) &&
-+ CHECK_LIB("ssleay32.lib", "ssh2", PHP_SSH2) &&
-+ CHECK_LIB("ws2_32.lib", "ssh2", PHP_SSH2)) {
-+
-+ // Use bundled lib if none installed, even if it is outdated.
-+ if (!(CHECK_LIB("libssh2_a.lib;libssh2.lib", "ssh2", PHP_SSH2) &&
-+ CHECK_HEADER_ADD_INCLUDE("libssh2.h", "CFLAGS_SSH2", PHP_PHP_BUILD + "\\include\\libssh2"))) {
-+ FSO.CopyFile(configure_module_dirname + "\\libssh2\\src\\libssh2_config.h.in.w32",
-+ configure_module_dirname + "\\libssh2\\src\\libssh2_config.h");
-+
-+ ADD_FLAG('CFLAGS_SSH2', '/DLIBSSH2_WIN32=1 /DLIBSSH2_API= /I ' +
-+ configure_module_dirname + '/libssh2/include');
-+ }
-+
-+ AC_DEFINE('HAVE_SSH2LIB', 1);
-+ AC_DEFINE('PHP_SSH2_REMOTE_FORWARDING', 1);
-+ AC_DEFINE('PHP_SSH2_HOSTBASED_AUTH', 1);
-+ AC_DEFINE('PHP_SSH2_POLL', 1);
-+ AC_DEFINE('PHP_SSH2_PUBLICKEY_SUBSYSTEM', 1);
-+
-+ EXTENSION("ssh2", "ssh2.c ssh2_fopen_wrappers.c ssh2_sftp.c");
-+
-+ ADD_SOURCES(configure_module_dirname + "/libssh2/src", "channel.c comp.c crypt.c \
-+ hostkey.c kex.c mac.c misc.c openssl.c packet.c pem.c publickey.c scp.c \
-+ session.c sftp.c transport.c userauth.c", "ssh2");
-+ } else {
-+ WARNING("ssh2 not enabled: libraries or headers not found");
-+ }
-+}
-
-Property changes on: config.w32
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.11
-
-Index: ssh2.c
-===================================================================
---- ssh2.c (.../tags/RELEASE_0_11_0)
-+++ ssh2.c (.../trunk)
-@@ -47,14 +47,9 @@
- int le_ssh2_pkey_subsys;
- #endif
-
--#ifdef ZEND_ENGINE_2
--static
-- ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
-- ZEND_ARG_PASS_INFO(1)
-- ZEND_END_ARG_INFO()
--#else
--static unsigned char php_ssh2_first_arg_force_ref[] = { 1, BYREF_FORCE };
--#endif
-+ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
-+ ZEND_ARG_PASS_INFO(1)
-+ZEND_END_ARG_INFO()
-
- /* *************
- * Callbacks *
-@@ -248,7 +243,7 @@
- /* {{{ php_ssh2_set_callback
- * Try to set a method if it's passed in with the hash table
- */
--static int php_ssh2_set_callback(LIBSSH2_SESSION *session, HashTable *ht, char *callback, int callback_len, int callback_type, php_ssh2_session_data *data)
-+static int php_ssh2_set_callback(LIBSSH2_SESSION *session, HashTable *ht, char *callback, int callback_len, int callback_type, php_ssh2_session_data *data TSRMLS_DC)
- {
- zval **handler, *copyval;
- void *internal_handler;
-@@ -257,7 +252,7 @@
- return 0;
- }
-
-- if (!handler || !*handler || !zend_is_callable(*handler, 0, NULL)) {
-+ if (!handler || !*handler || !zend_is_callable(*handler, 0, NULL ZEND_IS_CALLABLE_TSRMLS_CC)) {
- return -1;
- }
-
-@@ -358,7 +353,7 @@
- if (!session) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to initialize SSH2 session");
- efree(data);
-- close(socket);
-+ closesocket(socket);
- return NULL;
- }
- libssh2_banner_set(session, LIBSSH2_SSH_DEFAULT_BANNER " PHP");
-@@ -411,19 +406,19 @@
- if (callbacks) {
- /* ignore debug disconnect macerror */
-
-- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "ignore", sizeof("ignore") - 1, LIBSSH2_CALLBACK_IGNORE, data)) {
-+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "ignore", sizeof("ignore") - 1, LIBSSH2_CALLBACK_IGNORE, data TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting IGNORE callback");
- }
-
-- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "debug", sizeof("debug") - 1, LIBSSH2_CALLBACK_DEBUG, data)) {
-+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "debug", sizeof("debug") - 1, LIBSSH2_CALLBACK_DEBUG, data TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DEBUG callback");
- }
-
-- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "macerror", sizeof("macerror") - 1, LIBSSH2_CALLBACK_MACERROR, data)) {
-+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "macerror", sizeof("macerror") - 1, LIBSSH2_CALLBACK_MACERROR, data TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting MACERROR callback");
- }
-
-- if (php_ssh2_set_callback(session, HASH_OF(callbacks), "disconnect", sizeof("disconnect") - 1, LIBSSH2_CALLBACK_DISCONNECT, data)) {
-+ if (php_ssh2_set_callback(session, HASH_OF(callbacks), "disconnect", sizeof("disconnect") - 1, LIBSSH2_CALLBACK_DISCONNECT, data TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed setting DISCONNECT callback");
- }
- }
-@@ -434,7 +429,7 @@
-
- last_error = libssh2_session_last_error(session, &error_msg, NULL, 0);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error starting up SSH connection(%d): %s", last_error, error_msg);
-- close(socket);
-+ closesocket(socket);
- libssh2_session_free(session);
- efree(data);
- return NULL;
-@@ -1148,7 +1143,7 @@
- zval_ptr_dtor(&(*data)->disconnect_cb);
- }
-
-- close((*data)->socket);
-+ closesocket((*data)->socket);
-
- efree(*data);
- *data = NULL;
-@@ -1274,7 +1269,7 @@
-
- /* {{{ ssh2_functions[]
- */
--function_entry ssh2_functions[] = {
-+zend_function_entry ssh2_functions[] = {
- PHP_FE(ssh2_connect, NULL)
- PHP_FE(ssh2_methods_negotiated, NULL)
- PHP_FE(ssh2_fingerprint, NULL)
-
-Property changes on: ssh2.c
-___________________________________________________________________
-Modified: cvs2svn:cvs-rev
- - 1.22
- + 1.25
-
-Index: libssh2/include/libssh2_publickey.h
-===================================================================
---- libssh2/include/libssh2_publickey.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/include/libssh2_publickey.h (.../trunk)
-@@ -0,0 +1,101 @@
-+/* Copyright (c) 2004-2006, 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.
-+ */
-+
-+/* Note: This include file is only needed for using the
-+ * publickey SUBSYSTEM which is not the same as publickey
-+ * authentication. For authentication you only need libssh2.h
-+ *
-+ * For more information on the publickey subsystem,
-+ * refer to IETF draft: secsh-publickey
-+ */
-+
-+#ifndef LIBSSH2_PUBLICKEY_H
-+#define LIBSSH2_PUBLICKEY_H 1
-+
-+typedef struct _LIBSSH2_PUBLICKEY LIBSSH2_PUBLICKEY;
-+
-+typedef struct _libssh2_publickey_attribute {
-+ const char *name;
-+ unsigned long name_len;
-+ const char *value;
-+ unsigned long value_len;
-+ char mandatory;
-+} libssh2_publickey_attribute;
-+
-+typedef struct _libssh2_publickey_list {
-+ unsigned char *packet; /* For freeing */
-+
-+ const unsigned char *name;
-+ unsigned long name_len;
-+ const unsigned char *blob;
-+ unsigned long blob_len;
-+ unsigned long num_attrs;
-+ libssh2_publickey_attribute *attrs; /* free me */
-+} libssh2_publickey_list;
-+
-+/* Generally use the first macro here, but if both name and value are string literals, you can use _fast() to take advantage of preprocessing */
-+#define libssh2_publickey_attribute(name, value, mandatory) { (name), strlen(name), (value), strlen(value), (mandatory) },
-+#define libssh2_publickey_attribute_fast(name, value, mandatory) { (name), sizeof(name) - 1, (value), sizeof(value) - 1, (mandatory) },
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* Publickey Subsystem */
-+LIBSSH2_API LIBSSH2_PUBLICKEY *libssh2_publickey_init(LIBSSH2_SESSION *session);
-+
-+LIBSSH2_API int libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len,
-+ const unsigned char *blob, unsigned long blob_len, char overwrite,
-+ unsigned long num_attrs, const libssh2_publickey_attribute attrs[]);
-+#define libssh2_publickey_add(pkey, name, blob, blob_len, overwrite, num_attrs, attrs) \
-+ libssh2_publickey_add_ex((pkey), (name), strlen(name), (blob), (blob_len), (overwrite), (num_attrs), (attrs))
-+
-+LIBSSH2_API int libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, unsigned long name_len,
-+ const unsigned char *blob, unsigned long blob_len);
-+#define libssh2_publickey_remove(pkey, name, blob, blob_len) \
-+ libssh2_publickey_remove_ex((pkey), (name), strlen(name), (blob), (blob_len))
-+
-+LIBSSH2_API int libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY *pkey, unsigned long *num_keys, libssh2_publickey_list **pkey_list);
-+LIBSSH2_API void libssh2_publickey_list_free(LIBSSH2_PUBLICKEY *pkey, libssh2_publickey_list *pkey_list);
-+
-+LIBSSH2_API int libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY *pkey);
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* ndef: LIBSSH2_PUBLICKEY_H */
-
-Property changes on: libssh2/include/libssh2_publickey.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/include/libssh2_sftp.h
-===================================================================
---- libssh2/include/libssh2_sftp.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/include/libssh2_sftp.h (.../trunk)
-@@ -0,0 +1,251 @@
-+/* Copyright (c) 2004-2008, 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
-+
-+#ifndef WIN32
-+#include <unistd.h>
-+#endif
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* 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
-+
-+/*
-+ * Reproduce the POSIX file modes here for systems that are not
-+ * POSIX compliant.
-+ *
-+ * These is used in "permissions" of "struct _LIBSSH2_SFTP_ATTRIBUTES"
-+ */
-+/* File type */
-+#define LIBSSH2_SFTP_S_IFMT 0170000 /* type of file mask */
-+#define LIBSSH2_SFTP_S_IFIFO 0010000 /* named pipe (fifo) */
-+#define LIBSSH2_SFTP_S_IFCHR 0020000 /* character special */
-+#define LIBSSH2_SFTP_S_IFDIR 0040000 /* directory */
-+#define LIBSSH2_SFTP_S_IFBLK 0060000 /* block special */
-+#define LIBSSH2_SFTP_S_IFREG 0100000 /* regular */
-+#define LIBSSH2_SFTP_S_IFLNK 0120000 /* symbolic link */
-+#define LIBSSH2_SFTP_S_IFSOCK 0140000 /* socket */
-+
-+/* File mode */
-+/* Read, write, execute/search by owner */
-+#define LIBSSH2_SFTP_S_IRWXU 0000700 /* RWX mask for owner */
-+#define LIBSSH2_SFTP_S_IRUSR 0000400 /* R for owner */
-+#define LIBSSH2_SFTP_S_IWUSR 0000200 /* W for owner */
-+#define LIBSSH2_SFTP_S_IXUSR 0000100 /* X for owner */
-+/* Read, write, execute/search by group */
-+#define LIBSSH2_SFTP_S_IRWXG 0000070 /* RWX mask for group */
-+#define LIBSSH2_SFTP_S_IRGRP 0000040 /* R for group */
-+#define LIBSSH2_SFTP_S_IWGRP 0000020 /* W for group */
-+#define LIBSSH2_SFTP_S_IXGRP 0000010 /* X for group */
-+/* Read, write, execute/search by others */
-+#define LIBSSH2_SFTP_S_IRWXO 0000007 /* RWX mask for other */
-+#define LIBSSH2_SFTP_S_IROTH 0000004 /* R for other */
-+#define LIBSSH2_SFTP_S_IWOTH 0000002 /* W for other */
-+#define LIBSSH2_SFTP_S_IXOTH 0000001 /* X for other */
-+
-+/* 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 /* Initial mis-spelling */
-+#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16
-+#define LIBSSH2_FX_LOCK_CONFlICT 17 /* Initial mis-spelling */
-+#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
-+
-+/* Returned by any function that would block during a read/write opperation */
-+#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
-+
-+/* 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, const char *filename, unsigned 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 ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen);
-+
-+LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen,
-+ char *longentry, size_t longentry_maxlen,
-+ LIBSSH2_SFTP_ATTRIBUTES *attrs);
-+#define libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs) \
-+ libssh2_sftp_readdir_ex((handle), (buffer), (buffer_maxlen), NULL, 0, (attrs))
-+
-+LIBSSH2_API ssize_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);
-+LIBSSH2_API void libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset);
-+#define libssh2_sftp_rewind(handle) libssh2_sftp_seek64((handle), 0)
-+
-+LIBSSH2_API size_t libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle);
-+LIBSSH2_API libssh2_uint64_t libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle);
-+
-+LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat);
-+#define libssh2_sftp_fstat(handle, attrs) libssh2_sftp_fstat_ex((handle), (attrs), 0)
-+#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, const char *source_filename, unsigned int srouce_filename_len,
-+ const char *dest_filename, unsigned 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, const char *filename, unsigned 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, const char *path, unsigned 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, const char *path, unsigned 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, const char *path, unsigned 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, unsigned int path_len, char *target, unsigned 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)
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* LIBSSH2_SFTP_H */
-
-Property changes on: libssh2/include/libssh2_sftp.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/include/libssh2.h
-===================================================================
---- libssh2/include/libssh2.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/include/libssh2.h (.../trunk)
-@@ -0,0 +1,489 @@
-+/* Copyright (c) 2004-2008, 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_H
-+#define LIBSSH2_H 1
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include <stddef.h>
-+#include <string.h>
-+#include <sys/stat.h>
-+#include <sys/types.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 /* LIBSSH2_LIBRARY */
-+# else /* !LIBSSH2_WIN32 */
-+# define LIBSSH2_API
-+# endif /* LIBSSH2_WIN32 */
-+#endif /* LIBSSH2_API */
-+
-+#if defined(LIBSSH2_DARWIN) || (defined(LIBSSH2_WIN32) && !defined(_MSC_VER) && !defined(__MINGW32__))
-+# include <sys/uio.h>
-+#endif
-+
-+#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
-+# include <sys/bsdskt.h>
-+typedef unsigned int uint32_t;
-+#endif
-+
-+#if defined(LIBSSH2_WIN32) && defined(_MSC_VER) && (_MSC_VER <= 1400)
-+typedef unsigned __int64 libssh2_uint64_t;
-+typedef __int64 libssh2_int64_t;
-+typedef unsigned int uint32_t;
-+#ifndef _SSIZE_T_DEFINED
-+typedef int ssize_t;
-+#define _SSIZE_T_DEFINED
-+#endif
-+#else
-+typedef unsigned long long libssh2_uint64_t;
-+typedef long long libssh2_int64_t;
-+#endif
-+
-+/* We use underscore instead of dash when appending CVS in dev versions just
-+ to make the BANNER define (used by src/session.c) be a valid SSH
-+ banner. Release versions have no appended strings and may of coruse not
-+ have dashes either. */
-+#define LIBSSH2_VERSION "1.0"
-+
-+/* The numeric version number is also available "in parts" by using these
-+ defines: */
-+#define LIBSSH2_VERSION_MAJOR 1
-+#define LIBSSH2_VERSION_MINOR 0
-+#define LIBSSH2_VERSION_PATCH
-+
-+/* This is the numeric version of the libssh2 version number, meant for easier
-+ parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
-+ always follow this syntax:
-+
-+ 0xXXYYZZ
-+
-+ Where XX, YY and ZZ are the main version, release and patch numbers in
-+ hexadecimal (using 8 bits each). All three numbers are always represented
-+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
-+ appears as "0x090b07".
-+
-+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
-+ and it is always a greater number in a more recent release. It makes
-+ comparisons with greater than and less than work.
-+*/
-+#define LIBSSH2_VERSION_NUM 0x010000
-+
-+/*
-+ * This is the date and time when the full source package was created. The
-+ * timestamp is not stored in CVS, as the timestamp is properly set in the
-+ * tarballs by the maketgz script.
-+ *
-+ * The format of the date should follow this template:
-+ *
-+ * "Mon Feb 12 11:35:33 UTC 2007"
-+ */
-+#define LIBSSH2_TIMESTAMP "Fri Dec 26 21:35:07 UTC 2008"
-+
-+/* Part of every banner, user specified or not */
-+#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
-+
-+/* We *could* add a comment here if we so chose */
-+#define LIBSSH2_SSH_DEFAULT_BANNER LIBSSH2_SSH_BANNER
-+#define LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF LIBSSH2_SSH_DEFAULT_BANNER "\r\n"
-+
-+/* Default generate and safe prime sizes for diffie-hellman-group-exchange-sha1 */
-+#define LIBSSH2_DH_GEX_MINGROUP 1024
-+#define LIBSSH2_DH_GEX_OPTGROUP 1536
-+#define LIBSSH2_DH_GEX_MAXGROUP 2048
-+
-+/* Defaults for pty requests */
-+#define LIBSSH2_TERM_WIDTH 80
-+#define LIBSSH2_TERM_HEIGHT 24
-+#define LIBSSH2_TERM_WIDTH_PX 0
-+#define LIBSSH2_TERM_HEIGHT_PX 0
-+
-+/* 1/4 second */
-+#define LIBSSH2_SOCKET_POLL_UDELAY 250000
-+/* 0.25 * 120 == 30 seconds */
-+#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
-+
-+/* 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
-+
-+/* Malloc callbacks */
-+#define LIBSSH2_ALLOC_FUNC(name) void *name(size_t count, void **abstract)
-+#define LIBSSH2_REALLOC_FUNC(name) void *name(void *ptr, size_t count, void **abstract)
-+#define LIBSSH2_FREE_FUNC(name) void name(void *ptr, void **abstract)
-+
-+typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT
-+{
-+ char* text;
-+ unsigned int length;
-+ unsigned char echo;
-+} LIBSSH2_USERAUTH_KBDINT_PROMPT;
-+
-+typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE
-+{
-+ char* text;
-+ unsigned int length;
-+} LIBSSH2_USERAUTH_KBDINT_RESPONSE;
-+
-+/* 'keyboard-interactive' authentication callback */
-+#define LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC(name_) void name_(const char* name, int name_len, const char* instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract)
-+
-+/* Callbacks for special SSH packets */
-+#define LIBSSH2_IGNORE_FUNC(name) void name(LIBSSH2_SESSION *session, const char *message, int message_len, void **abstract)
-+#define LIBSSH2_DEBUG_FUNC(name) void name(LIBSSH2_SESSION *session, int always_display, const char *message, int message_len, const char *language, int language_len,void **abstract)
-+#define LIBSSH2_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, const char *shost, int sport, void **abstract)
-+
-+#define LIBSSH2_CHANNEL_CLOSE_FUNC(name) void name(LIBSSH2_SESSION *session, void **session_abstract, LIBSSH2_CHANNEL *channel, void **channel_abstract)
-+
-+/* libssh2_session_callback_set() constants */
-+#define LIBSSH2_CALLBACK_IGNORE 0
-+#define LIBSSH2_CALLBACK_DEBUG 1
-+#define LIBSSH2_CALLBACK_DISCONNECT 2
-+#define LIBSSH2_CALLBACK_MACERROR 3
-+#define LIBSSH2_CALLBACK_X11 4
-+
-+/* libssh2_session_method_pref() constants */
-+#define LIBSSH2_METHOD_KEX 0
-+#define LIBSSH2_METHOD_HOSTKEY 1
-+#define LIBSSH2_METHOD_CRYPT_CS 2
-+#define LIBSSH2_METHOD_CRYPT_SC 3
-+#define LIBSSH2_METHOD_MAC_CS 4
-+#define LIBSSH2_METHOD_MAC_SC 5
-+#define LIBSSH2_METHOD_COMP_CS 6
-+#define LIBSSH2_METHOD_COMP_SC 7
-+#define LIBSSH2_METHOD_LANG_CS 8
-+#define LIBSSH2_METHOD_LANG_SC 9
-+
-+/* session.flags bits */
-+#define LIBSSH2_FLAG_SIGPIPE 0x00000001
-+
-+typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
-+typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
-+typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER;
-+
-+typedef struct _LIBSSH2_POLLFD {
-+ unsigned char type; /* LIBSSH2_POLLFD_* below */
-+
-+ union {
-+ int socket; /* File descriptors -- examined with system select() call */
-+ LIBSSH2_CHANNEL *channel; /* Examined by checking internal state */
-+ LIBSSH2_LISTENER *listener; /* Read polls only -- are inbound connections waiting to be accepted? */
-+ } fd;
-+
-+ unsigned long events; /* Requested Events */
-+ unsigned long revents; /* Returned Events */
-+} LIBSSH2_POLLFD;
-+
-+/* Poll FD Descriptor Types */
-+#define LIBSSH2_POLLFD_SOCKET 1
-+#define LIBSSH2_POLLFD_CHANNEL 2
-+#define LIBSSH2_POLLFD_LISTENER 3
-+
-+/* Note: Win32 Doesn't actually have a poll() implementation, so some of these values are faked with select() data */
-+/* Poll FD events/revents -- Match sys/poll.h where possible */
-+#define LIBSSH2_POLLFD_POLLIN 0x0001 /* Data available to be read or connection available -- All */
-+#define LIBSSH2_POLLFD_POLLPRI 0x0002 /* Priority data available to be read -- Socket only */
-+#define LIBSSH2_POLLFD_POLLEXT 0x0002 /* Extended data available to be read -- Channel only */
-+#define LIBSSH2_POLLFD_POLLOUT 0x0004 /* Can may be written -- Socket/Channel */
-+/* revents only */
-+#define LIBSSH2_POLLFD_POLLERR 0x0008 /* Error Condition -- Socket */
-+#define LIBSSH2_POLLFD_POLLHUP 0x0010 /* HangUp/EOF -- Socket */
-+#define LIBSSH2_POLLFD_SESSION_CLOSED 0x0010 /* Session Disconnect */
-+#define LIBSSH2_POLLFD_POLLNVAL 0x0020 /* Invalid request -- Socket Only */
-+#define LIBSSH2_POLLFD_POLLEX 0x0040 /* Exception Condition -- Socket/Win32 */
-+#define LIBSSH2_POLLFD_CHANNEL_CLOSED 0x0080 /* Channel Disconnect */
-+#define LIBSSH2_POLLFD_LISTENER_CLOSED 0x0080 /* Listener Disconnect */
-+
-+#define HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
-+/* Block Direction Types */
-+#define LIBSSH2_SESSION_BLOCK_INBOUND 0x0001
-+#define LIBSSH2_SESSION_BLOCK_OUTBOUND 0x0002
-+
-+/* Hash Types */
-+#define LIBSSH2_HOSTKEY_HASH_MD5 1
-+#define LIBSSH2_HOSTKEY_HASH_SHA1 2
-+
-+/* Disconnect Codes (defined by SSH protocol) */
-+#define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
-+#define SSH_DISCONNECT_PROTOCOL_ERROR 2
-+#define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3
-+#define SSH_DISCONNECT_RESERVED 4
-+#define SSH_DISCONNECT_MAC_ERROR 5
-+#define SSH_DISCONNECT_COMPRESSION_ERROR 6
-+#define SSH_DISCONNECT_SERVICE_NOT_AVAILABLE 7
-+#define SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
-+#define SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
-+#define SSH_DISCONNECT_CONNECTION_LOST 10
-+#define SSH_DISCONNECT_BY_APPLICATION 11
-+#define SSH_DISCONNECT_TOO_MANY_CONNECTIONS 12
-+#define SSH_DISCONNECT_AUTH_CANCELLED_BY_USER 13
-+#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
-+#define SSH_DISCONNECT_ILLEGAL_USER_NAME 15
-+
-+/* Error Codes (defined by libssh2) */
-+#define LIBSSH2_ERROR_NONE 0
-+#define LIBSSH2_ERROR_SOCKET_NONE -1
-+#define LIBSSH2_ERROR_BANNER_NONE -2
-+#define LIBSSH2_ERROR_BANNER_SEND -3
-+#define LIBSSH2_ERROR_INVALID_MAC -4
-+#define LIBSSH2_ERROR_KEX_FAILURE -5
-+#define LIBSSH2_ERROR_ALLOC -6
-+#define LIBSSH2_ERROR_SOCKET_SEND -7
-+#define LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE -8
-+#define LIBSSH2_ERROR_TIMEOUT -9
-+#define LIBSSH2_ERROR_HOSTKEY_INIT -10
-+#define LIBSSH2_ERROR_HOSTKEY_SIGN -11
-+#define LIBSSH2_ERROR_DECRYPT -12
-+#define LIBSSH2_ERROR_SOCKET_DISCONNECT -13
-+#define LIBSSH2_ERROR_PROTO -14
-+#define LIBSSH2_ERROR_PASSWORD_EXPIRED -15
-+#define LIBSSH2_ERROR_FILE -16
-+#define LIBSSH2_ERROR_METHOD_NONE -17
-+#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED -18
-+#define LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED -19
-+#define LIBSSH2_ERROR_CHANNEL_OUTOFORDER -20
-+#define LIBSSH2_ERROR_CHANNEL_FAILURE -21
-+#define LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED -22
-+#define LIBSSH2_ERROR_CHANNEL_UNKNOWN -23
-+#define LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED -24
-+#define LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED -25
-+#define LIBSSH2_ERROR_CHANNEL_CLOSED -26
-+#define LIBSSH2_ERROR_CHANNEL_EOF_SENT -27
-+#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
-+#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
-+#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36
-+#define LIBSSH2_ERROR_EAGAIN -37
-+
-+/* 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, const char *banner);
-+
-+LIBSSH2_API int libssh2_session_startup(LIBSSH2_SESSION *session, int sock);
-+LIBSSH2_API int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang);
-+#define libssh2_session_disconnect(session, description) libssh2_session_disconnect_ex((session), SSH_DISCONNECT_BY_APPLICATION, (description), "")
-+LIBSSH2_API int libssh2_session_free(LIBSSH2_SESSION *session);
-+
-+LIBSSH2_API const char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type);
-+
-+LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, const char *prefs);
-+LIBSSH2_API const char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type);
-+LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf);
-+LIBSSH2_API int libssh2_session_last_errno(LIBSSH2_SESSION *session);
-+LIBSSH2_API int libssh2_session_block_directions(LIBSSH2_SESSION *session);
-+
-+LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value);
-+
-+/* Userauth API */
-+LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len);
-+LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);
-+LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)));
-+#define libssh2_userauth_password(session, username, password) libssh2_userauth_password_ex((session), (username), strlen(username), (password), strlen(password), NULL)
-+
-+LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len,
-+ const char *publickey, const char *privatekey,
-+ const char *passphrase);
-+#define libssh2_userauth_publickey_fromfile(session, username, publickey, privatekey, passphrase) \
-+ libssh2_userauth_publickey_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase))
-+LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len,
-+ const char *publickey, const char *privatekey,
-+ const char *passphrase,
-+ const char *hostname, unsigned int hostname_len,
-+ const char *local_username, unsigned int local_username_len);
-+#define libssh2_userauth_hostbased_fromfile(session, username, publickey, privatekey, passphrase, hostname) \
-+ libssh2_userauth_hostbased_fromfile_ex((session), (username), strlen(username), (publickey), (privatekey), (passphrase), (hostname), strlen(hostname), (username), strlen(username))
-+
-+/*
-+ * response_callback is provided with filled by library prompts array,
-+ * but client must allocate and fill individual responses. Responses
-+ * array is already allocated. Responses data will be freed by libssh2
-+ * after callback return, but before subsequent callback invokation.
-+ */
-+LIBSSH2_API int libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION* session, const char *username, unsigned int username_len,
-+ LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)));
-+#define libssh2_userauth_keyboard_interactive(session, username, response_callback) \
-+ libssh2_userauth_keyboard_interactive_ex((session), (username), strlen(username), (response_callback))
-+
-+LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout);
-+
-+/* Channel API */
-+#define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536
-+#define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384
-+#define LIBSSH2_CHANNEL_MINADJUST 1024
-+
-+/* 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
-+
-+/* Returned by any function that would block during a read/write opperation */
-+#define LIBSSH2CHANNEL_EAGAIN LIBSSH2_ERROR_EAGAIN
-+
-+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *channel_type, unsigned int channel_type_len, unsigned int window_size, unsigned int packet_size, const char *message, unsigned 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, const char *host, int port, const 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, const 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, const char *varname, unsigned int varname_len, const char *value, unsigned 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, const char *term, unsigned int term_len, const char *modes, unsigned int modes_len, int width, int height, int width_px, int height_px);
-+#define libssh2_channel_request_pty(channel, term) libssh2_channel_request_pty_ex((channel), (term), strlen(term), NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX)
-+
-+LIBSSH2_API int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel, int width, int height, int width_px, int height_px);
-+#define libssh2_channel_request_pty_size(channel, width, height) libssh2_channel_request_pty_size_ex( (channel), (width), (height), 0, 0)
-+
-+LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, const char *auth_proto, const char *auth_cookie, int screen_number);
-+#define libssh2_channel_x11_req(channel, screen_number) libssh2_channel_x11_req_ex((channel), 0, NULL, NULL, (screen_number))
-+
-+LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, const char *request, unsigned int request_len, const char *message, unsigned 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))
-+
-+LIBSSH2_API ssize_t 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))
-+
-+LIBSSH2_API int libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended);
-+
-+LIBSSH2_API unsigned long libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, unsigned long *read_avail, unsigned long *window_size_initial);
-+#define libssh2_channel_window_read(channel) \
-+ libssh2_channel_window_read_ex((channel), NULL, NULL)
-+
-+LIBSSH2_API unsigned long libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, unsigned long adjustment, unsigned char force);
-+
-+LIBSSH2_API ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen);
-+
-+#define libssh2_channel_write(channel, buf, buflen) \
-+ libssh2_channel_write_ex((channel), 0, (buf), (buflen))
-+#define libssh2_channel_write_stderr(channel, buf, buflen) \
-+ libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen))
-+
-+LIBSSH2_API unsigned long libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, unsigned long *window_size_initial);
-+#define libssh2_channel_window_write(channel) libssh2_channel_window_write_ex((channel), NULL)
-+
-+LIBSSH2_API void libssh2_session_set_blocking(LIBSSH2_SESSION* session, int blocking);
-+LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session);
-+
-+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_API int libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, int ignore_mode);
-+/* libssh2_channel_ignore_extended_data() is defined below for BC with version 0.1
-+ * Future uses should use libssh2_channel_handle_extended_data() directly
-+ * if LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE is passed, extended data will be read (FIFO) from the standard data channel
-+ */
-+/* DEPRECATED */
-+#define libssh2_channel_ignore_extended_data(channel, ignore) libssh2_channel_handle_extended_data((channel), (ignore) ? LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL )
-+
-+#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1
-+#define LIBSSH2_CHANNEL_FLUSH_ALL -2
-+LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid);
-+#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0)
-+#define libssh2_channel_flush_stderr(channel) libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
-+LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel);
-+
-+LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
-+LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
-+LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel);
-+LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel);
-+LIBSSH2_API int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
-+LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel);
-+
-+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat *sb);
-+LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime);
-+#define libssh2_scp_send(session, path, mode, size) libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0)
-+
-+LIBSSH2_API int libssh2_base64_decode(LIBSSH2_SESSION *session, char **dest, unsigned int *dest_len, const char *src, unsigned int src_len);
-+
-+/* NOTE NOTE NOTE
-+ libssh2_trace() has no function in builds that aren't built with debug
-+ enabled
-+ */
-+LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask);
-+#define LIBSSH2_TRACE_TRANS (1<<1)
-+#define LIBSSH2_TRACE_KEX (1<<2)
-+#define LIBSSH2_TRACE_AUTH (1<<3)
-+#define LIBSSH2_TRACE_CONN (1<<4)
-+#define LIBSSH2_TRACE_SCP (1<<5)
-+#define LIBSSH2_TRACE_SFTP (1<<6)
-+#define LIBSSH2_TRACE_ERROR (1<<7)
-+#define LIBSSH2_TRACE_PUBLICKEY (1<<8)
-+
-+#ifdef __cplusplus
-+} /* extern "C" */
-+#endif
-+
-+#endif /* LIBSSH2_H */
-
-Property changes on: libssh2/include/libssh2.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.3
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/comp.c
-===================================================================
---- libssh2/src/comp.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/comp.c (.../trunk)
-@@ -0,0 +1,340 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#ifdef LIBSSH2_HAVE_ZLIB
-+# include <zlib.h>
-+#endif
-+
-+/* ********
-+ * none *
-+ ******** */
-+
-+/* {{{ libssh2_comp_method_none_comp
-+ * Minimalist compression: Absolutely none
-+ */
-+static int
-+libssh2_comp_method_none_comp(LIBSSH2_SESSION * session,
-+ int compress,
-+ unsigned char **dest,
-+ unsigned long *dest_len,
-+ unsigned long payload_limit,
-+ int *free_dest,
-+ const unsigned char *src,
-+ unsigned long src_len, void **abstract)
-+{
-+ (void) session;
-+ (void) compress;
-+ (void) payload_limit;
-+ (void) abstract;
-+ *dest = (unsigned char *) src;
-+ *dest_len = src_len;
-+
-+ *free_dest = 0;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_COMP_METHOD libssh2_comp_method_none = {
-+ "none",
-+ NULL,
-+ libssh2_comp_method_none_comp,
-+ NULL
-+};
-+
-+#ifdef LIBSSH2_HAVE_ZLIB
-+/* ********
-+ * zlib *
-+ ******** */
-+
-+/* {{{ Memory management wrappers
-+ * Yes, I realize we're doing a callback to a callback,
-+ * Deal...
-+ */
-+
-+static voidpf
-+libssh2_comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size)
-+{
-+ LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
-+
-+ return (voidpf) LIBSSH2_ALLOC(session, items * size);
-+}
-+
-+static void
-+libssh2_comp_method_zlib_free(voidpf opaque, voidpf address)
-+{
-+ LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
-+
-+ LIBSSH2_FREE(session, address);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_comp_method_zlib_init
-+ * All your bandwidth are belong to us (so save some)
-+ */
-+static int
-+libssh2_comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
-+ void **abstract)
-+{
-+ z_stream *strm;
-+ int status;
-+
-+ strm = LIBSSH2_ALLOC(session, sizeof(z_stream));
-+ if (!strm) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for zlib compression/decompression",
-+ 0);
-+ return -1;
-+ }
-+ memset(strm, 0, sizeof(z_stream));
-+
-+ strm->opaque = (voidpf) session;
-+ strm->zalloc = (alloc_func) libssh2_comp_method_zlib_alloc;
-+ strm->zfree = (free_func) libssh2_comp_method_zlib_free;
-+ if (compress) {
-+ /* deflate */
-+ status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
-+ } else {
-+ /* inflate */
-+ status = inflateInit(strm);
-+ }
-+
-+ if (status != Z_OK) {
-+ LIBSSH2_FREE(session, strm);
-+ return -1;
-+ }
-+ *abstract = strm;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_comp_method_zlib_comp
-+ * zlib, a compression standard for all occasions
-+ */
-+static int
-+libssh2_comp_method_zlib_comp(LIBSSH2_SESSION * session,
-+ int compress,
-+ unsigned char **dest,
-+ unsigned long *dest_len,
-+ unsigned long payload_limit,
-+ int *free_dest,
-+ const unsigned char *src,
-+ unsigned long src_len, void **abstract)
-+{
-+ z_stream *strm = *abstract;
-+ /* A short-term alloc of a full data chunk is better than a series of
-+ reallocs */
-+ char *out;
-+ int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
-+ int limiter = 0;
-+
-+ /* In practice they never come smaller than this */
-+ if (out_maxlen < 25) {
-+ out_maxlen = 25;
-+ }
-+
-+ if (out_maxlen > (int) payload_limit) {
-+ out_maxlen = payload_limit;
-+ }
-+
-+ strm->next_in = (unsigned char *) src;
-+ strm->avail_in = src_len;
-+ strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
-+ out = (char *) strm->next_out;
-+ strm->avail_out = out_maxlen;
-+ if (!strm->next_out) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate compression/decompression buffer",
-+ 0);
-+ return -1;
-+ }
-+ while (strm->avail_in) {
-+ int status;
-+
-+ if (compress) {
-+ status = deflate(strm, Z_PARTIAL_FLUSH);
-+ } else {
-+ status = inflate(strm, Z_PARTIAL_FLUSH);
-+ }
-+ if (status != Z_OK) {
-+ libssh2_error(session, LIBSSH2_ERROR_ZLIB,
-+ "compress/decompression failure", 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+ if (strm->avail_in) {
-+ unsigned long out_ofs = out_maxlen - strm->avail_out;
-+ char *newout;
-+
-+ out_maxlen +=
-+ compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
-+
-+ if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
-+ libssh2_error(session, LIBSSH2_ERROR_ZLIB,
-+ "Excessive growth in decompression phase", 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+
-+ newout = LIBSSH2_REALLOC(session, out, out_maxlen);
-+ if (!newout) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to expand compress/decompression buffer",
-+ 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+ out = newout;
-+ strm->next_out = (unsigned char *) out + out_ofs;
-+ strm->avail_out +=
-+ compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
-+ } else
-+ while (!strm->avail_out) {
-+ /* Done with input, might be a byte or two in internal buffer during compress
-+ * Or potentially many bytes if it's a decompress
-+ */
-+ int grow_size = compress ? 8 : 1024;
-+ char *newout;
-+
-+ if (out_maxlen >= (int) payload_limit) {
-+ libssh2_error(session, LIBSSH2_ERROR_ZLIB,
-+ "Excessive growth in decompression phase",
-+ 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+
-+ if (grow_size > (int) (payload_limit - out_maxlen)) {
-+ grow_size = payload_limit - out_maxlen;
-+ }
-+
-+ out_maxlen += grow_size;
-+ strm->avail_out = grow_size;
-+
-+ newout = LIBSSH2_REALLOC(session, out, out_maxlen);
-+ if (!newout) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to expand final compress/decompress buffer",
-+ 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+ out = newout;
-+ strm->next_out = (unsigned char *) out + out_maxlen -
-+ grow_size;
-+
-+ if (compress) {
-+ status = deflate(strm, Z_PARTIAL_FLUSH);
-+ } else {
-+ status = inflate(strm, Z_PARTIAL_FLUSH);
-+ }
-+ if (status != Z_OK) {
-+ libssh2_error(session, LIBSSH2_ERROR_ZLIB,
-+ "compress/decompression failure", 0);
-+ LIBSSH2_FREE(session, out);
-+ return -1;
-+ }
-+ }
-+ }
-+
-+ *dest = (unsigned char *) out;
-+ *dest_len = out_maxlen - strm->avail_out;
-+ *free_dest = 1;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_comp_method_zlib_dtor
-+ * All done, no more compression for you
-+ */
-+static int
-+libssh2_comp_method_zlib_dtor(LIBSSH2_SESSION * session, int compress,
-+ void **abstract)
-+{
-+ z_stream *strm = *abstract;
-+
-+ if (strm) {
-+ if (compress) {
-+ /* deflate */
-+ deflateEnd(strm);
-+ } else {
-+ /* inflate */
-+ inflateEnd(strm);
-+ }
-+
-+ LIBSSH2_FREE(session, strm);
-+ }
-+
-+ *abstract = NULL;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_COMP_METHOD libssh2_comp_method_zlib = {
-+ "zlib",
-+ libssh2_comp_method_zlib_init,
-+ libssh2_comp_method_zlib_comp,
-+ libssh2_comp_method_zlib_dtor,
-+};
-+#endif /* LIBSSH2_HAVE_ZLIB */
-+
-+/* ***********************
-+ * Compression Methods *
-+ *********************** */
-+
-+static const LIBSSH2_COMP_METHOD *_libssh2_comp_methods[] = {
-+ &libssh2_comp_method_none,
-+#ifdef LIBSSH2_HAVE_ZLIB
-+ &libssh2_comp_method_zlib,
-+#endif /* LIBSSH2_HAVE_ZLIB */
-+ NULL
-+};
-+
-+const LIBSSH2_COMP_METHOD **
-+libssh2_comp_methods(void)
-+{
-+ return _libssh2_comp_methods;
-+}
-
-Property changes on: libssh2/src/comp.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/libgcrypt.c
-===================================================================
---- libssh2/src/libgcrypt.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/libgcrypt.c (.../trunk)
-@@ -0,0 +1,560 @@
-+/* Copyright (C) 2006, 2007, The Written Word, Inc.
-+ * Copyright (C) 2008, Simon Josefsson
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms,
-+ * with or without modification, are permitted provided
-+ * 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <string.h>
-+
-+int
-+_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
-+ const unsigned char *edata,
-+ unsigned long elen,
-+ const unsigned char *ndata,
-+ unsigned long nlen,
-+ const unsigned char *ddata,
-+ unsigned long dlen,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *e1data,
-+ unsigned long e1len,
-+ const unsigned char *e2data,
-+ unsigned long e2len,
-+ const unsigned char *coeffdata, unsigned long coefflen)
-+{
-+ int rc;
-+ (void) e1data;
-+ (void) e1len;
-+ (void) e2data;
-+ (void) e2len;
-+
-+ if (ddata) {
-+ rc = gcry_sexp_build
-+ (rsa, NULL,
-+ "(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))",
-+ nlen, ndata, elen, edata, dlen, ddata, plen, pdata,
-+ qlen, qdata, coefflen, coeffdata);
-+ } else {
-+ rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
-+ nlen, ndata, elen, edata);
-+ }
-+ if (rc) {
-+ *rsa = NULL;
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m, unsigned long m_len)
-+{
-+ unsigned char hash[SHA_DIGEST_LENGTH];
-+ gcry_sexp_t s_sig, s_hash;
-+ int rc = -1;
-+
-+ libssh2_sha1(m, m_len, hash);
-+
-+ rc = gcry_sexp_build(&s_hash, NULL,
-+ "(data (flags pkcs1) (hash sha1 %b))",
-+ SHA_DIGEST_LENGTH, hash);
-+ if (rc != 0) {
-+ return -1;
-+ }
-+
-+ rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
-+ if (rc != 0) {
-+ gcry_sexp_release(s_hash);
-+ return -1;
-+ }
-+
-+ rc = gcry_pk_verify(s_sig, s_hash, rsa);
-+ gcry_sexp_release(s_sig);
-+ gcry_sexp_release(s_hash);
-+
-+ return (rc == 0) ? 0 : -1;
-+}
-+
-+int
-+_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
-+ const unsigned char *p,
-+ unsigned long p_len,
-+ const unsigned char *q,
-+ unsigned long q_len,
-+ const unsigned char *g,
-+ unsigned long g_len,
-+ const unsigned char *y,
-+ unsigned long y_len,
-+ const unsigned char *x, unsigned long x_len)
-+{
-+ int rc;
-+
-+ if (x_len) {
-+ rc = gcry_sexp_build
-+ (dsactx, NULL,
-+ "(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))",
-+ p_len, p, q_len, q, g_len, g, y_len, y, x_len, x);
-+ } else {
-+ rc = gcry_sexp_build(dsactx, NULL,
-+ "(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
-+ p_len, p, q_len, q, g_len, g, y_len, y);
-+ }
-+
-+ if (rc) {
-+ *dsactx = NULL;
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase)
-+{
-+ unsigned char *data, *save_data;
-+ unsigned int datalen;
-+ int ret;
-+ unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
-+ unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
-+
-+ (void) passphrase;
-+
-+ ret = _libssh2_pem_parse(session,
-+ "-----BEGIN RSA PRIVATE KEY-----",
-+ "-----END RSA PRIVATE KEY-----",
-+ fp, &data, &datalen);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ save_data = data;
-+
-+ if (_libssh2_pem_decode_sequence(&data, &datalen)) {
-+ ret = -1;
-+ goto fail;
-+ }
-+/* First read Version field (should be 0). */
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
-+ if (ret != 0 || (nlen != 1 && *n != '\0')) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &n, &nlen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &e, &elen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &d, &dlen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &e1, &e1len);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &e2, &e2len);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &coeff, &coefflen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ if (_libssh2_rsa_new(rsa, e, elen, n, nlen, d, dlen, p, plen,
-+ q, qlen, e1, e1len, e2, e2len, coeff, coefflen)) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = 0;
-+
-+ fail:
-+ LIBSSH2_FREE(session, save_data);
-+ return ret;
-+}
-+
-+int
-+_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase)
-+{
-+ unsigned char *data, *save_data;
-+ unsigned int datalen;
-+ int ret;
-+ unsigned char *p, *q, *g, *y, *x;
-+ unsigned int plen, qlen, glen, ylen, xlen;
-+
-+ (void) passphrase;
-+
-+ ret = _libssh2_pem_parse(session,
-+ "-----BEGIN DSA PRIVATE KEY-----",
-+ "-----END DSA PRIVATE KEY-----",
-+ fp, &data, &datalen);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ save_data = data;
-+
-+ if (_libssh2_pem_decode_sequence(&data, &datalen)) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+/* First read Version field (should be 0). */
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
-+ if (ret != 0 || (plen != 1 && *p != '\0')) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &p, &plen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &q, &qlen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &g, &glen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &y, &ylen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = _libssh2_pem_decode_integer(&data, &datalen, &x, &xlen);
-+ if (ret != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ if (datalen != 0) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ if (_libssh2_dsa_new(dsa, p, plen, q, qlen, g, glen, y, ylen, x, xlen)) {
-+ ret = -1;
-+ goto fail;
-+ }
-+
-+ ret = 0;
-+
-+ fail:
-+ LIBSSH2_FREE(session, save_data);
-+ return ret;
-+}
-+
-+int
-+_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
-+ libssh2_dsa_ctx * rsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len,
-+ unsigned char **signature, unsigned long *signature_len)
-+{
-+ gcry_sexp_t sig_sexp;
-+ gcry_sexp_t data;
-+ int rc;
-+ const char *tmp;
-+ size_t size;
-+
-+ if (hash_len != SHA_DIGEST_LENGTH) {
-+ return -1;
-+ }
-+
-+ if (gcry_sexp_build(&data, NULL,
-+ "(data (flags pkcs1) (hash sha1 %b))",
-+ hash_len, hash)) {
-+ return -1;
-+ }
-+
-+ rc = gcry_pk_sign(&sig_sexp, data, rsactx);
-+
-+ gcry_sexp_release(data);
-+
-+ if (rc != 0) {
-+ return -1;
-+ }
-+
-+ data = gcry_sexp_find_token(sig_sexp, "s", 0);
-+ if (!data) {
-+ return -1;
-+ }
-+
-+ tmp = gcry_sexp_nth_data(data, 1, &size);
-+ if (!tmp) {
-+ return -1;
-+ }
-+
-+ if (tmp[0] == '\0') {
-+ tmp++;
-+ size--;
-+ }
-+
-+ *signature = LIBSSH2_ALLOC(session, size);
-+ memcpy(*signature, tmp, size);
-+ *signature_len = size;
-+
-+ return rc;
-+}
-+
-+int
-+_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len, unsigned char *sig)
-+{
-+ unsigned char zhash[SHA_DIGEST_LENGTH + 1];
-+ gcry_sexp_t sig_sexp;
-+ gcry_sexp_t data;
-+ int ret;
-+ const char *tmp;
-+ size_t size;
-+
-+ if (hash_len != SHA_DIGEST_LENGTH) {
-+ return -1;
-+ }
-+
-+ memcpy(zhash + 1, hash, hash_len);
-+ zhash[0] = 0;
-+
-+ if (gcry_sexp_build(&data, NULL, "(data (value %b))", hash_len + 1, zhash)) {
-+ return -1;
-+ }
-+
-+ ret = gcry_pk_sign(&sig_sexp, data, dsactx);
-+
-+ gcry_sexp_release(data);
-+
-+ if (ret != 0) {
-+ return -1;
-+ }
-+
-+/* Extract R. */
-+
-+ data = gcry_sexp_find_token(sig_sexp, "r", 0);
-+ if (!data) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ tmp = gcry_sexp_nth_data(data, 1, &size);
-+ if (!tmp) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ if (tmp[0] == '\0') {
-+ tmp++;
-+ size--;
-+ }
-+
-+ if (size != 20) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ memcpy(sig, tmp, 20);
-+
-+ gcry_sexp_release(data);
-+
-+/* Extract S. */
-+
-+ data = gcry_sexp_find_token(sig_sexp, "s", 0);
-+ if (!data) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ tmp = gcry_sexp_nth_data(data, 1, &size);
-+ if (!tmp) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ if (tmp[0] == '\0') {
-+ tmp++;
-+ size--;
-+ }
-+
-+ if (size != 20) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ memcpy(sig + 20, tmp, 20);
-+
-+ ret = 0;
-+ out:
-+ if (sig_sexp) {
-+ gcry_sexp_release(sig_sexp);
-+ }
-+ if (data) {
-+ gcry_sexp_release(data);
-+ }
-+ return ret;
-+}
-+
-+int
-+_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *sig,
-+ const unsigned char *m, unsigned long m_len)
-+{
-+ unsigned char hash[SHA_DIGEST_LENGTH + 1];
-+ gcry_sexp_t s_sig, s_hash;
-+ int rc = -1;
-+
-+ libssh2_sha1(m, m_len, hash + 1);
-+ hash[0] = 0;
-+
-+ if (gcry_sexp_build(&s_hash, NULL, "(data(flags raw)(value %b))",
-+ SHA_DIGEST_LENGTH + 1, hash)) {
-+ return -1;
-+ }
-+
-+ if (gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
-+ 20, sig, 20, sig + 20)) {
-+ gcry_sexp_release(s_hash);
-+ return -1;
-+ }
-+
-+ rc = gcry_pk_verify(s_sig, s_hash, dsactx);
-+ gcry_sexp_release(s_sig);
-+ gcry_sexp_release(s_hash);
-+
-+ return (rc == 0) ? 0 : -1;
-+}
-+
-+int
-+_libssh2_cipher_init(_libssh2_cipher_ctx * h,
-+ _libssh2_cipher_type(algo),
-+ unsigned char *iv, unsigned char *secret, int encrypt)
-+{
-+ int mode = 0, ret;
-+ int keylen = gcry_cipher_get_algo_keylen(algo);
-+
-+ (void) encrypt;
-+
-+ if (algo != GCRY_CIPHER_ARCFOUR) {
-+ mode = GCRY_CIPHER_MODE_CBC;
-+ }
-+
-+ ret = gcry_cipher_open(h, algo, mode, 0);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ ret = gcry_cipher_setkey(*h, secret, keylen);
-+ if (ret) {
-+ gcry_cipher_close(*h);
-+ return -1;
-+ }
-+
-+ if (algo != GCRY_CIPHER_ARCFOUR) {
-+ int blklen = gcry_cipher_get_algo_blklen(algo);
-+ ret = gcry_cipher_setiv(*h, iv, blklen);
-+ if (ret) {
-+ gcry_cipher_close(*h);
-+ return -1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
-+ _libssh2_cipher_type(algo),
-+ int encrypt, unsigned char *block)
-+{
-+ size_t blklen = gcry_cipher_get_algo_blklen(algo);
-+ int ret;
-+ if (blklen == 1) {
-+/* Hack for arcfour. */
-+ blklen = 8;
-+ }
-+
-+ if (encrypt) {
-+ ret = gcry_cipher_encrypt(*ctx, block, blklen, block, blklen);
-+ } else {
-+ ret = gcry_cipher_decrypt(*ctx, block, blklen, block, blklen);
-+ }
-+ return ret;
-+}
-
-Property changes on: libssh2/src/libgcrypt.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/userauth.c
-===================================================================
---- libssh2/src/userauth.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/userauth.c (.../trunk)
-@@ -0,0 +1,1473 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+#include <ctype.h>
-+#include <stdio.h>
-+
-+/* Needed for struct iovec on some platforms */
-+#ifdef HAVE_SYS_UIO_H
-+#include <sys/uio.h>
-+#endif
-+
-+
-+/* {{{ proto libssh2_userauth_list
-+ * List authentication methods
-+ * Will yield successful login if "none" happens to be allowable for this user
-+ * Not a common configuration for any SSH server though
-+ * username should be NULL, or a null terminated string
-+ */
-+LIBSSH2_API char *
-+libssh2_userauth_list(LIBSSH2_SESSION * session, const char *username,
-+ unsigned int username_len)
-+{
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
-+ /* packet_type(1) + username_len(4) + service_len(4) +
-+ service(14)"ssh-connection" + method_len(4) + method(4)"none" */
-+ unsigned long methods_len;
-+ unsigned char *s;
-+ int rc;
-+
-+ if (session->userauth_list_state == libssh2_NB_state_idle) {
-+ /* Zero the whole thing out */
-+ memset(&session->userauth_list_packet_requirev_state, 0,
-+ sizeof(session->userauth_list_packet_requirev_state));
-+
-+ session->userauth_list_data_len = username_len + 31;
-+
-+ s = session->userauth_list_data =
-+ LIBSSH2_ALLOC(session, session->userauth_list_data_len);
-+ if (!session->userauth_list_data) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for userauth_list", 0);
-+ return NULL;
-+ }
-+
-+ *(s++) = SSH_MSG_USERAUTH_REQUEST;
-+ libssh2_htonu32(s, username_len);
-+ s += 4;
-+ if (username) {
-+ memcpy(s, username, username_len);
-+ s += username_len;
-+ }
-+
-+ libssh2_htonu32(s, 14);
-+ s += 4;
-+ memcpy(s, "ssh-connection", 14);
-+ s += 14;
-+
-+ libssh2_htonu32(s, 4);
-+ s += 4;
-+ memcpy(s, "none", 4);
-+ s += 4;
-+
-+ session->userauth_list_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->userauth_list_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->userauth_list_data,
-+ session->userauth_list_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block requesting userauth list", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-none request", 0);
-+ LIBSSH2_FREE(session, session->userauth_list_data);
-+ session->userauth_list_data = NULL;
-+ session->userauth_list_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_list_data);
-+ session->userauth_list_data = NULL;
-+
-+ session->userauth_list_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->userauth_list_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_list_data,
-+ &session->userauth_list_data_len, 0,
-+ NULL, 0,
-+ &session->
-+ userauth_list_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block requesting userauth list", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_NONE, "No error", 0);
-+ session->userauth_list_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+
-+ if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ /* Wow, who'dve thought... */
-+ libssh2_error(session, LIBSSH2_ERROR_NONE, "No error", 0);
-+ LIBSSH2_FREE(session, session->userauth_list_data);
-+ session->userauth_list_data = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_list_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+
-+ methods_len = libssh2_ntohu32(session->userauth_list_data + 1);
-+
-+ /* Do note that the memory areas overlap! */
-+ memmove(session->userauth_list_data, session->userauth_list_data + 5,
-+ methods_len);
-+ session->userauth_list_data[methods_len] = '\0';
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH, "Permitted auth methods: %s",
-+ session->userauth_list_data);
-+ }
-+
-+ session->userauth_list_state = libssh2_NB_state_idle;
-+ return (char *) session->userauth_list_data;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_userauth_authenticated
-+ * 0 if not yet authenticated
-+ * non-zero is already authenticated
-+ */
-+LIBSSH2_API int
-+libssh2_userauth_authenticated(LIBSSH2_SESSION * session)
-+{
-+ return session->state & LIBSSH2_STATE_AUTHENTICATED;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_userauth_password
-+ * Plain ol' login
-+ */
-+LIBSSH2_API int
-+libssh2_userauth_password_ex(LIBSSH2_SESSION * session, const char *username,
-+ unsigned int username_len, const char *password,
-+ unsigned int password_len,
-+ LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
-+{
-+ unsigned char *s;
-+ static const unsigned char reply_codes[4] =
-+ { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
-+ SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0
-+ };
-+ int rc;
-+
-+ if (session->userauth_pswd_state == libssh2_NB_state_idle) {
-+ /* Zero the whole thing out */
-+ memset(&session->userauth_pswd_packet_requirev_state, 0,
-+ sizeof(session->userauth_pswd_packet_requirev_state));
-+
-+ /*
-+ * 40 = acket_type(1) + username_len(4) + service_len(4) +
-+ * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
-+ * chgpwdbool(1) + password_len(4) */
-+ session->userauth_pswd_data_len = username_len + password_len + 40;
-+
-+ session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
-+
-+ s = session->userauth_pswd_data =
-+ LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
-+ if (!session->userauth_pswd_data) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for userauth-password request",
-+ 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_USERAUTH_REQUEST;
-+ libssh2_htonu32(s, username_len);
-+ s += 4;
-+ memcpy(s, username, username_len);
-+ s += username_len;
-+
-+ libssh2_htonu32(s, sizeof("ssh-connection") - 1);
-+ s += 4;
-+ memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1);
-+ s += sizeof("ssh-connection") - 1;
-+
-+ libssh2_htonu32(s, sizeof("password") - 1);
-+ s += 4;
-+ memcpy(s, "password", sizeof("password") - 1);
-+ s += sizeof("password") - 1;
-+
-+ *s = '\0';
-+ s++;
-+
-+ libssh2_htonu32(s, password_len);
-+ s += 4;
-+ memcpy(s, password, password_len);
-+ s += password_len;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Attempting to login using password authentication");
-+
-+ session->userauth_pswd_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->userauth_pswd_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->userauth_pswd_data,
-+ session->userauth_pswd_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-password request", 0);
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ session->userauth_pswd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+
-+ session->userauth_pswd_state = libssh2_NB_state_sent;
-+ }
-+
-+ password_response:
-+
-+ if ((session->userauth_pswd_state == libssh2_NB_state_sent)
-+ || (session->userauth_pswd_state == libssh2_NB_state_sent1)
-+ || (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
-+ if (session->userauth_pswd_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_pswd_data,
-+ &session->userauth_pswd_data_len,
-+ 0, NULL, 0,
-+ &session->
-+ userauth_pswd_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ session->userauth_pswd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Password authentication successful");
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_pswd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ session->userauth_pswd_newpw = NULL;
-+ session->userauth_pswd_newpw_len = 0;
-+
-+ session->userauth_pswd_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if ((session->userauth_pswd_data[0] ==
-+ SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
-+ || (session->userauth_pswd_data0 ==
-+ SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) {
-+ session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;
-+
-+ if ((session->userauth_pswd_state == libssh2_NB_state_sent1) ||
-+ (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
-+ if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Password change required");
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ }
-+ if (passwd_change_cb) {
-+ if (session->userauth_pswd_state == libssh2_NB_state_sent1) {
-+ passwd_change_cb(session,
-+ &session->userauth_pswd_newpw,
-+ &session->userauth_pswd_newpw_len,
-+ &session->abstract);
-+ if (!session->userauth_pswd_newpw) {
-+ libssh2_error(session,
-+ LIBSSH2_ERROR_PASSWORD_EXPIRED,
-+ "Password expired, and callback failed",
-+ 0);
-+ return -1;
-+ }
-+
-+ /* basic data_len + newpw_len(4) */
-+ session->userauth_pswd_data_len =
-+ username_len + password_len + 44 +
-+ session->userauth_pswd_newpw_len;
-+
-+ s = session->userauth_pswd_data =
-+ LIBSSH2_ALLOC(session,
-+ session->userauth_pswd_data_len);
-+ if (!session->userauth_pswd_data) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for userauth-password-change request",
-+ 0);
-+ LIBSSH2_FREE(session,
-+ session->userauth_pswd_newpw);
-+ session->userauth_pswd_newpw = NULL;
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_USERAUTH_REQUEST;
-+ libssh2_htonu32(s, username_len);
-+ s += 4;
-+ memcpy(s, username, username_len);
-+ s += username_len;
-+
-+ libssh2_htonu32(s, sizeof("ssh-connection") - 1);
-+ s += 4;
-+ memcpy(s, "ssh-connection",
-+ sizeof("ssh-connection") - 1);
-+ s += sizeof("ssh-connection") - 1;
-+
-+ libssh2_htonu32(s, sizeof("password") - 1);
-+ s += 4;
-+ memcpy(s, "password", sizeof("password") - 1);
-+ s += sizeof("password") - 1;
-+
-+ *s = 0x01;
-+ s++;
-+
-+ libssh2_htonu32(s, password_len);
-+ s += 4;
-+ memcpy(s, password, password_len);
-+ s += password_len;
-+
-+ libssh2_htonu32(s, session->userauth_pswd_newpw_len);
-+ s += 4;
-+ memcpy(s, session->userauth_pswd_newpw,
-+ session->userauth_pswd_newpw_len);
-+ s += session->userauth_pswd_newpw_len;
-+
-+ session->userauth_pswd_state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (session->userauth_pswd_state == libssh2_NB_state_sent2) {
-+ rc = libssh2_packet_write(session,
-+ session->userauth_pswd_data,
-+ session->
-+ userauth_pswd_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-password-change request",
-+ 0);
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ LIBSSH2_FREE(session,
-+ session->userauth_pswd_newpw);
-+ session->userauth_pswd_newpw = NULL;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pswd_newpw);
-+ session->userauth_pswd_newpw = NULL;
-+
-+ /*
-+ * Ugliest use of goto ever. Blame it on the
-+ * askN => requirev migration.
-+ */
-+ session->userauth_pswd_state = libssh2_NB_state_sent;
-+ goto password_response;
-+ }
-+ }
-+ } else {
-+ libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED,
-+ "Password Expired, and no callback specified",
-+ 0);
-+ session->userauth_pswd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ }
-+ }
-+
-+ /* FAILURE */
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ session->userauth_pswd_data = NULL;
-+ session->userauth_pswd_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_file_read_publickey
-+ * Read a public key from an id_???.pub style file
-+ */
-+static int
-+libssh2_file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
-+ unsigned long *method_len,
-+ unsigned char **pubkeydata,
-+ unsigned long *pubkeydata_len,
-+ const char *pubkeyfile)
-+{
-+ FILE *fd;
-+ char c;
-+ unsigned char *pubkey = NULL, *sp1, *sp2, *tmp;
-+ size_t pubkey_len = 0;
-+ unsigned int tmp_len;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading public key file: %s",
-+ pubkeyfile);
-+ /* Read Public Key */
-+ fd = fopen(pubkeyfile, "r");
-+ if (!fd) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE,
-+ "Unable to open public key file", 0);
-+ return -1;
-+ }
-+ while (!feof(fd) && (c = fgetc(fd)) != '\r' && c != '\n')
-+ pubkey_len++;
-+ if (feof(fd)) {
-+ /* the last character was EOF */
-+ pubkey_len--;
-+ }
-+ rewind(fd);
-+
-+ if (pubkey_len <= 1) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE,
-+ "Invalid data in public key file", 0);
-+ fclose(fd);
-+ return -1;
-+ }
-+
-+ pubkey = LIBSSH2_ALLOC(session, pubkey_len);
-+ if (!pubkey) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for public key data", 0);
-+ fclose(fd);
-+ return -1;
-+ }
-+ if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE,
-+ "Unable to read public key from file", 0);
-+ LIBSSH2_FREE(session, pubkey);
-+ fclose(fd);
-+ return -1;
-+ }
-+ fclose(fd);
-+ /*
-+ * Remove trailing whitespace
-+ */
-+ while (pubkey_len && isspace(pubkey[pubkey_len - 1]))
-+ pubkey_len--;
-+
-+ if (!pubkey_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE, "Missing public key data",
-+ 0);
-+ LIBSSH2_FREE(session, pubkey);
-+ return -1;
-+ }
-+
-+ if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid public key data",
-+ 0);
-+ LIBSSH2_FREE(session, pubkey);
-+ return -1;
-+ }
-+ /* Wasting some bytes here (okay, more than some),
-+ * but since it's likely to be freed soon anyway,
-+ * we'll just avoid the extra free/alloc and call it a wash */
-+ *method = pubkey;
-+ *method_len = sp1 - pubkey;
-+
-+ sp1++;
-+
-+ if ((sp2 = memchr(sp1, ' ', pubkey_len - *method_len)) == NULL) {
-+ /* Assume that the id string is missing, but that it's okay */
-+ sp2 = pubkey + pubkey_len;
-+ }
-+
-+ if (libssh2_base64_decode
-+ (session, (char **) &tmp, &tmp_len, (char *) sp1, sp2 - sp1)) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE,
-+ "Invalid key data, not base64 encoded", 0);
-+ LIBSSH2_FREE(session, pubkey);
-+ return -1;
-+ }
-+ *pubkeydata = tmp;
-+ *pubkeydata_len = tmp_len;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_file_read_privatekey
-+ * Read a PEM encoded private key from an id_??? style file
-+ */
-+static int
-+libssh2_file_read_privatekey(LIBSSH2_SESSION * session,
-+ const LIBSSH2_HOSTKEY_METHOD ** hostkey_method,
-+ void **hostkey_abstract,
-+ const unsigned char *method, int method_len,
-+ const char *privkeyfile, const char *passphrase)
-+{
-+ const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
-+ libssh2_hostkey_methods();
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH, "Loading private key file: %s",
-+ privkeyfile);
-+ *hostkey_method = NULL;
-+ *hostkey_abstract = NULL;
-+ while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
-+ if ((*hostkey_methods_avail)->initPEM
-+ && strncmp((*hostkey_methods_avail)->name, (const char *) method,
-+ method_len) == 0) {
-+ *hostkey_method = *hostkey_methods_avail;
-+ break;
-+ }
-+ hostkey_methods_avail++;
-+ }
-+ if (!*hostkey_method) {
-+ libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
-+ "No handler for specified private key", 0);
-+ return -1;
-+ }
-+
-+ if ((*hostkey_method)->
-+ initPEM(session, privkeyfile, (unsigned char *) passphrase,
-+ hostkey_abstract)) {
-+ libssh2_error(session, LIBSSH2_ERROR_FILE,
-+ "Unable to initialize private key from file", 0);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_userauth_hostbased_fromfile_ex
-+ * Authenticate using a keypair found in the named files
-+ */
-+LIBSSH2_API int
-+libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION * session,
-+ const char *username,
-+ unsigned int username_len,
-+ const char *publickey,
-+ const char *privatekey,
-+ const char *passphrase,
-+ const char *hostname,
-+ unsigned int hostname_len,
-+ const char *local_username,
-+ unsigned int local_username_len)
-+{
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
-+ int rc;
-+
-+ if (session->userauth_host_state == libssh2_NB_state_idle) {
-+ const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
-+ unsigned char *pubkeydata, *sig;
-+ unsigned long pubkeydata_len;
-+ unsigned long sig_len;
-+ void *abstract;
-+ unsigned char buf[5];
-+ struct iovec datavec[4];
-+
-+ /* Zero the whole thing out */
-+ memset(&session->userauth_host_packet_requirev_state, 0,
-+ sizeof(session->userauth_host_packet_requirev_state));
-+
-+ if (libssh2_file_read_publickey
-+ (session, &session->userauth_host_method,
-+ &session->userauth_host_method_len, &pubkeydata, &pubkeydata_len,
-+ publickey)) {
-+ return -1;
-+ }
-+
-+ /*
-+ * 48 = packet_type(1) + username_len(4) + servicename_len(4) +
-+ * service_name(14)"ssh-connection" + authmethod_len(4) +
-+ * authmethod(9)"hostbased" + method_len(4) + pubkeydata_len(4) +
-+ * local_username_len(4)
-+ */
-+ session->userauth_host_packet_len =
-+ username_len + session->userauth_host_method_len + hostname_len +
-+ local_username_len + pubkeydata_len + 48;
-+
-+ /*
-+ * Preallocate space for an overall length, method name again,
-+ * and the signature, which won't be any larger than the size of
-+ * the publickeydata itself
-+ */
-+ session->userauth_host_s = session->userauth_host_packet =
-+ LIBSSH2_ALLOC(session,
-+ session->userauth_host_packet_len + 4 + (4 +
-+ session->
-+ userauth_host_method_len)
-+ + (4 + pubkeydata_len));
-+ if (!session->userauth_host_packet) {
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ session->userauth_host_method = NULL;
-+ return -1;
-+ }
-+
-+ *(session->userauth_host_s++) = SSH_MSG_USERAUTH_REQUEST;
-+ libssh2_htonu32(session->userauth_host_s, username_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, username, username_len);
-+ session->userauth_host_s += username_len;
-+
-+ libssh2_htonu32(session->userauth_host_s, 14);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, "ssh-connection", 14);
-+ session->userauth_host_s += 14;
-+
-+ libssh2_htonu32(session->userauth_host_s, 9);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, "hostbased", 9);
-+ session->userauth_host_s += 9;
-+
-+ libssh2_htonu32(session->userauth_host_s,
-+ session->userauth_host_method_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, session->userauth_host_method,
-+ session->userauth_host_method_len);
-+ session->userauth_host_s += session->userauth_host_method_len;
-+
-+ libssh2_htonu32(session->userauth_host_s, pubkeydata_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, pubkeydata, pubkeydata_len);
-+ session->userauth_host_s += pubkeydata_len;
-+
-+ libssh2_htonu32(session->userauth_host_s, hostname_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, hostname, hostname_len);
-+ session->userauth_host_s += hostname_len;
-+
-+ libssh2_htonu32(session->userauth_host_s, local_username_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, local_username, local_username_len);
-+ session->userauth_host_s += local_username_len;
-+
-+ if (libssh2_file_read_privatekey
-+ (session, &privkeyobj, &abstract, session->userauth_host_method,
-+ session->userauth_host_method_len, privatekey, passphrase)) {
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ session->userauth_host_method = NULL;
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ session->userauth_host_packet = NULL;
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(buf, session->session_id_len);
-+ datavec[0].iov_base = buf;
-+ datavec[0].iov_len = 4;
-+ datavec[1].iov_base = session->session_id;
-+ datavec[1].iov_len = session->session_id_len;
-+ datavec[2].iov_base = session->userauth_host_packet;
-+ datavec[2].iov_len = session->userauth_host_packet_len;
-+
-+ if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) {
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ session->userauth_host_method = NULL;
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ session->userauth_host_packet = NULL;
-+ if (privkeyobj->dtor) {
-+ privkeyobj->dtor(session, &abstract);
-+ }
-+ return -1;
-+ }
-+
-+ if (privkeyobj->dtor) {
-+ privkeyobj->dtor(session, &abstract);
-+ }
-+
-+ if (sig_len > pubkeydata_len) {
-+ unsigned char *newpacket;
-+ /* Should *NEVER* happen, but...well.. better safe than sorry */
-+ newpacket = LIBSSH2_REALLOC(session, session->userauth_host_packet, session->userauth_host_packet_len + 4 + (4 + session->userauth_host_method_len) + (4 + sig_len)); /* PK sigblob */
-+ if (!newpacket) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Failed allocating additional space for userauth-hostbased packet",
-+ 0);
-+ LIBSSH2_FREE(session, sig);
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ session->userauth_host_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ session->userauth_host_method = NULL;
-+ return -1;
-+ }
-+ session->userauth_host_packet = newpacket;
-+ }
-+
-+ session->userauth_host_s =
-+ session->userauth_host_packet + session->userauth_host_packet_len;
-+
-+ libssh2_htonu32(session->userauth_host_s,
-+ 4 + session->userauth_host_method_len + 4 + sig_len);
-+ session->userauth_host_s += 4;
-+
-+ libssh2_htonu32(session->userauth_host_s,
-+ session->userauth_host_method_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, session->userauth_host_method,
-+ session->userauth_host_method_len);
-+ session->userauth_host_s += session->userauth_host_method_len;
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ session->userauth_host_method = NULL;
-+
-+ libssh2_htonu32(session->userauth_host_s, sig_len);
-+ session->userauth_host_s += 4;
-+ memcpy(session->userauth_host_s, sig, sig_len);
-+ session->userauth_host_s += sig_len;
-+ LIBSSH2_FREE(session, sig);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Attempting hostbased authentication");
-+
-+ session->userauth_host_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->userauth_host_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->userauth_host_packet,
-+ session->userauth_host_s -
-+ session->userauth_host_packet);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-hostbased request", 0);
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ session->userauth_host_packet = NULL;
-+ session->userauth_host_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ session->userauth_host_packet = NULL;
-+
-+ session->userauth_host_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->userauth_host_state == libssh2_NB_state_sent) {
-+ unsigned long data_len;
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_host_data,
-+ &data_len, 0, NULL, 0,
-+ &session->
-+ userauth_host_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ session->userauth_host_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Hostbased authentication successful");
-+ /* We are us and we've proved it. */
-+ LIBSSH2_FREE(session, session->userauth_host_data);
-+ session->userauth_host_data = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_host_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+
-+ /* This public key is not allowed for this user on this server */
-+ LIBSSH2_FREE(session, session->userauth_host_data);
-+ session->userauth_host_data = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
-+ "Invalid signature for supplied public key, or bad username/public key combination",
-+ 0);
-+ session->userauth_host_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_userauth_publickey_fromfile_ex
-+ * Authenticate using a keypair found in the named files
-+ */
-+LIBSSH2_API int
-+libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION * session,
-+ const char *username,
-+ unsigned int username_len,
-+ const char *publickey,
-+ const char *privatekey,
-+ const char *passphrase)
-+{
-+ unsigned long pubkeydata_len = 0;
-+ unsigned char reply_codes[4] =
-+ { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
-+ SSH_MSG_USERAUTH_PK_OK, 0
-+ };
-+ int rc;
-+
-+ if (session->userauth_pblc_state == libssh2_NB_state_idle) {
-+ unsigned char *pubkeydata;
-+
-+ /* Zero the whole thing out */
-+ memset(&session->userauth_pblc_packet_requirev_state, 0,
-+ sizeof(session->userauth_pblc_packet_requirev_state));
-+
-+ if (libssh2_file_read_publickey
-+ (session, &session->userauth_pblc_method,
-+ &session->userauth_pblc_method_len, &pubkeydata, &pubkeydata_len,
-+ publickey)) {
-+ return -1;
-+ }
-+
-+ /*
-+ * 45 = packet_type(1) + username_len(4) + servicename_len(4) +
-+ * service_name(14)"ssh-connection" + authmethod_len(4) +
-+ * authmethod(9)"publickey" + sig_included(1)'\0' + algmethod_len(4) +
-+ * publickey_len(4)
-+ */
-+ session->userauth_pblc_packet_len =
-+ username_len + session->userauth_pblc_method_len + pubkeydata_len +
-+ 45;
-+
-+ /*
-+ * Preallocate space for an overall length, method name again, and
-+ * the signature, which won't be any larger than the size of the
-+ * publickeydata itself
-+ */
-+ session->userauth_pblc_s = session->userauth_pblc_packet =
-+ LIBSSH2_ALLOC(session,
-+ session->userauth_pblc_packet_len + 4 + (4 +
-+ session->
-+ userauth_pblc_method_len)
-+ + (4 + pubkeydata_len));
-+ if (!session->userauth_pblc_packet) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ LIBSSH2_FREE(session, pubkeydata);
-+ return -1;
-+ }
-+
-+ *(session->userauth_pblc_s++) = SSH_MSG_USERAUTH_REQUEST;
-+ libssh2_htonu32(session->userauth_pblc_s, username_len);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, username, username_len);
-+ session->userauth_pblc_s += username_len;
-+
-+ libssh2_htonu32(session->userauth_pblc_s, 14);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, "ssh-connection", 14);
-+ session->userauth_pblc_s += 14;
-+
-+ libssh2_htonu32(session->userauth_pblc_s, 9);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, "publickey", 9);
-+ session->userauth_pblc_s += 9;
-+
-+ session->userauth_pblc_b = session->userauth_pblc_s;
-+ /* Not sending signature with *this* packet */
-+ *(session->userauth_pblc_s++) = 0;
-+
-+ libssh2_htonu32(session->userauth_pblc_s,
-+ session->userauth_pblc_method_len);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, session->userauth_pblc_method,
-+ session->userauth_pblc_method_len);
-+ session->userauth_pblc_s += session->userauth_pblc_method_len;
-+
-+ libssh2_htonu32(session->userauth_pblc_s, pubkeydata_len);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, pubkeydata, pubkeydata_len);
-+ session->userauth_pblc_s += pubkeydata_len;
-+ LIBSSH2_FREE(session, pubkeydata);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Attempting publickey authentication");
-+
-+ session->userauth_pblc_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->userauth_pblc_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->userauth_pblc_packet,
-+ session->userauth_pblc_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-publickey request", 0);
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ session->userauth_pblc_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->userauth_pblc_state == libssh2_NB_state_sent) {
-+ const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
-+ void *abstract;
-+ unsigned char buf[5];
-+ struct iovec datavec[4];
-+ unsigned char *sig;
-+ unsigned long sig_len;
-+
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_pblc_data,
-+ &session->userauth_pblc_data_len, 0,
-+ NULL, 0,
-+ &session->
-+ userauth_pblc_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Pubkey authentication prematurely successful");
-+ /*
-+ * God help any SSH server that allows an UNVERIFIED
-+ * public key to validate the user
-+ */
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ session->userauth_pblc_data = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_FAILURE) {
-+ /* This public key is not allowed for this user on this server */
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ session->userauth_pblc_data = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED,
-+ "Username/PublicKey combination invalid", 0);
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ /* Semi-Success! */
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ session->userauth_pblc_data = NULL;
-+
-+ if (libssh2_file_read_privatekey
-+ (session, &privkeyobj, &abstract, session->userauth_pblc_method,
-+ session->userauth_pblc_method_len, privatekey, passphrase)) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ *session->userauth_pblc_b = 0x01;
-+
-+ libssh2_htonu32(buf, session->session_id_len);
-+ datavec[0].iov_base = buf;
-+ datavec[0].iov_len = 4;
-+ datavec[1].iov_base = session->session_id;
-+ datavec[1].iov_len = session->session_id_len;
-+ datavec[2].iov_base = session->userauth_pblc_packet;
-+ datavec[2].iov_len = session->userauth_pblc_packet_len;
-+
-+ if (privkeyobj->signv(session, &sig, &sig_len, 3, datavec, &abstract)) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ if (privkeyobj->dtor) {
-+ privkeyobj->dtor(session, &abstract);
-+ }
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (privkeyobj->dtor) {
-+ privkeyobj->dtor(session, &abstract);
-+ }
-+
-+ /*
-+ * If this function was restarted, pubkeydata_len might still be 0
-+ * which will cause an unnecessary but harmless realloc here.
-+ */
-+ if (sig_len > pubkeydata_len) {
-+ unsigned char *newpacket;
-+ /* Should *NEVER* happen, but...well.. better safe than sorry */
-+ newpacket = LIBSSH2_REALLOC(session, session->userauth_pblc_packet, session->userauth_pblc_packet_len + 4 + (4 + session->userauth_pblc_method_len) + (4 + sig_len)); /* PK sigblob */
-+ if (!newpacket) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Failed allocating additional space for userauth-publickey packet",
-+ 0);
-+ LIBSSH2_FREE(session, sig);
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ session->userauth_pblc_packet = newpacket;
-+ }
-+
-+ session->userauth_pblc_s =
-+ session->userauth_pblc_packet + session->userauth_pblc_packet_len;
-+ session->userauth_pblc_b = NULL;
-+
-+ libssh2_htonu32(session->userauth_pblc_s,
-+ 4 + session->userauth_pblc_method_len + 4 + sig_len);
-+ session->userauth_pblc_s += 4;
-+
-+ libssh2_htonu32(session->userauth_pblc_s,
-+ session->userauth_pblc_method_len);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, session->userauth_pblc_method,
-+ session->userauth_pblc_method_len);
-+ session->userauth_pblc_s += session->userauth_pblc_method_len;
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ session->userauth_pblc_method = NULL;
-+
-+ libssh2_htonu32(session->userauth_pblc_s, sig_len);
-+ session->userauth_pblc_s += 4;
-+ memcpy(session->userauth_pblc_s, sig, sig_len);
-+ session->userauth_pblc_s += sig_len;
-+ LIBSSH2_FREE(session, sig);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Attempting publickey authentication -- phase 2");
-+
-+ session->userauth_pblc_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->userauth_pblc_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_packet_write(session, session->userauth_pblc_packet,
-+ session->userauth_pblc_s -
-+ session->userauth_pblc_packet);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-publickey request", 0);
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ session->userauth_pblc_packet = NULL;
-+
-+ session->userauth_pblc_state = libssh2_NB_state_sent2;
-+ }
-+
-+ /* PK_OK is no longer valid */
-+ reply_codes[2] = 0;
-+
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_pblc_data,
-+ &session->userauth_pblc_data_len, 0, NULL,
-+ 0,
-+ &session->
-+ userauth_pblc_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Publickey authentication successful");
-+ /* We are us and we've proved it. */
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ session->userauth_pblc_data = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ /* This public key is not allowed for this user on this server */
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ session->userauth_pblc_data = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
-+ "Invalid signature for supplied public key, or bad username/public key combination",
-+ 0);
-+ session->userauth_pblc_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_userauth_keyboard_interactive
-+ * Authenticate using a challenge-response authentication
-+ */
-+LIBSSH2_API int
-+libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION * session,
-+ const char *username,
-+ unsigned int username_len,
-+ LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)))
-+{
-+ unsigned char *s;
-+ int rc;
-+
-+ static const unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS,
-+ SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_INFO_REQUEST, 0
-+ };
-+ unsigned int language_tag_len;
-+ unsigned int i;
-+
-+ if (session->userauth_kybd_state == libssh2_NB_state_idle) {
-+ session->userauth_kybd_auth_name = NULL;
-+ session->userauth_kybd_auth_instruction = NULL;
-+ session->userauth_kybd_num_prompts = 0;
-+ session->userauth_kybd_auth_failure = 1;
-+ session->userauth_kybd_prompts = NULL;
-+ session->userauth_kybd_responses = NULL;
-+
-+ /* Zero the whole thing out */
-+ memset(&session->userauth_kybd_packet_requirev_state, 0,
-+ sizeof(session->userauth_kybd_packet_requirev_state));
-+
-+ session->userauth_kybd_packet_len = 1 /* byte SSH_MSG_USERAUTH_REQUEST */
-+ + 4 + username_len /* string user name (ISO-10646 UTF-8, as defined in [RFC-3629]) */
-+ + 4 + 14 /* string service name (US-ASCII) */
-+ + 4 + 20 /* string "keyboard-interactive" (US-ASCII) */
-+ + 4 + 0 /* string language tag (as defined in [RFC-3066]) */
-+ + 4 + 0 /* string submethods (ISO-10646 UTF-8) */
-+ ;
-+
-+ session->userauth_kybd_data = s =
-+ LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
-+ if (!s) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive authentication",
-+ 0);
-+ return -1;
-+ }
-+
-+ *s++ = SSH_MSG_USERAUTH_REQUEST;
-+
-+ /* user name */
-+ libssh2_htonu32(s, username_len);
-+ s += 4;
-+ memcpy(s, username, username_len);
-+ s += username_len;
-+
-+ /* service name */
-+ libssh2_htonu32(s, sizeof("ssh-connection") - 1);
-+ s += 4;
-+ memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1);
-+ s += sizeof("ssh-connection") - 1;
-+
-+ /* "keyboard-interactive" */
-+ libssh2_htonu32(s, sizeof("keyboard-interactive") - 1);
-+ s += 4;
-+ memcpy(s, "keyboard-interactive", sizeof("keyboard-interactive") - 1);
-+ s += sizeof("keyboard-interactive") - 1;
-+
-+ /* language tag */
-+ libssh2_htonu32(s, 0);
-+ s += 4;
-+
-+ /* submethods */
-+ libssh2_htonu32(s, 0);
-+ s += 4;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Attempting keyboard-interactive authentication");
-+
-+ session->userauth_kybd_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->userauth_kybd_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->userauth_kybd_data,
-+ session->userauth_kybd_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send keyboard-interactive request", 0);
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ session->userauth_kybd_data = NULL;
-+ session->userauth_kybd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ session->userauth_kybd_data = NULL;
-+
-+ session->userauth_kybd_state = libssh2_NB_state_sent;
-+ }
-+
-+ for(;;) {
-+ if (session->userauth_kybd_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->userauth_kybd_data,
-+ &session->userauth_kybd_data_len,
-+ 0, NULL, 0,
-+ &session->
-+ userauth_kybd_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ session->userauth_kybd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Keyboard-interactive authentication successful");
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ session->userauth_kybd_data = NULL;
-+ session->state |= LIBSSH2_STATE_AUTHENTICATED;
-+ session->userauth_kybd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_FAILURE) {
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ session->userauth_kybd_data = NULL;
-+ session->userauth_kybd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ /* server requested PAM-like conversation */
-+
-+ s = session->userauth_kybd_data + 1;
-+
-+ /* string name (ISO-10646 UTF-8) */
-+ session->userauth_kybd_auth_name_len = libssh2_ntohu32(s);
-+ s += 4;
-+ session->userauth_kybd_auth_name =
-+ LIBSSH2_ALLOC(session, session->userauth_kybd_auth_name_len);
-+ if (!session->userauth_kybd_auth_name) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive 'name' request field",
-+ 0);
-+ goto cleanup;
-+ }
-+ memcpy(session->userauth_kybd_auth_name, s,
-+ session->userauth_kybd_auth_name_len);
-+ s += session->userauth_kybd_auth_name_len;
-+
-+ /* string instruction (ISO-10646 UTF-8) */
-+ session->userauth_kybd_auth_instruction_len = libssh2_ntohu32(s);
-+ s += 4;
-+ session->userauth_kybd_auth_instruction =
-+ LIBSSH2_ALLOC(session,
-+ session->userauth_kybd_auth_instruction_len);
-+ if (!session->userauth_kybd_auth_instruction) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive 'instruction' request field",
-+ 0);
-+ goto cleanup;
-+ }
-+ memcpy(session->userauth_kybd_auth_instruction, s,
-+ session->userauth_kybd_auth_instruction_len);
-+ s += session->userauth_kybd_auth_instruction_len;
-+
-+ /* string language tag (as defined in [RFC-3066]) */
-+ language_tag_len = libssh2_ntohu32(s);
-+ s += 4;
-+ /* ignoring this field as deprecated */
-+ s += language_tag_len;
-+
-+ /* int num-prompts */
-+ session->userauth_kybd_num_prompts = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ session->userauth_kybd_prompts =
-+ LIBSSH2_ALLOC(session,
-+ sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) *
-+ session->userauth_kybd_num_prompts);
-+ if (!session->userauth_kybd_prompts) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive prompts array",
-+ 0);
-+ goto cleanup;
-+ }
-+ memset(session->userauth_kybd_prompts, 0,
-+ sizeof(LIBSSH2_USERAUTH_KBDINT_PROMPT) *
-+ session->userauth_kybd_num_prompts);
-+
-+ session->userauth_kybd_responses =
-+ LIBSSH2_ALLOC(session,
-+ sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) *
-+ session->userauth_kybd_num_prompts);
-+ if (!session->userauth_kybd_responses) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive responses array",
-+ 0);
-+ goto cleanup;
-+ }
-+ memset(session->userauth_kybd_responses, 0,
-+ sizeof(LIBSSH2_USERAUTH_KBDINT_RESPONSE) *
-+ session->userauth_kybd_num_prompts);
-+
-+ for(i = 0; i != session->userauth_kybd_num_prompts; ++i) {
-+ /* string prompt[1] (ISO-10646 UTF-8) */
-+ session->userauth_kybd_prompts[i].length = libssh2_ntohu32(s);
-+ s += 4;
-+ session->userauth_kybd_prompts[i].text =
-+ LIBSSH2_ALLOC(session,
-+ session->userauth_kybd_prompts[i].length);
-+ if (!session->userauth_kybd_prompts[i].text) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive prompt message",
-+ 0);
-+ goto cleanup;
-+ }
-+ memcpy(session->userauth_kybd_prompts[i].text, s,
-+ session->userauth_kybd_prompts[i].length);
-+ s += session->userauth_kybd_prompts[i].length;
-+
-+ /* boolean echo[1] */
-+ session->userauth_kybd_prompts[i].echo = *s++;
-+ }
-+
-+ response_callback(session->userauth_kybd_auth_name,
-+ session->userauth_kybd_auth_name_len,
-+ session->userauth_kybd_auth_instruction,
-+ session->userauth_kybd_auth_instruction_len,
-+ session->userauth_kybd_num_prompts,
-+ session->userauth_kybd_prompts,
-+ session->userauth_kybd_responses,
-+ &session->abstract);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_AUTH,
-+ "Keyboard-interactive response callback function invoked");
-+
-+ session->userauth_kybd_packet_len = 1 /* byte SSH_MSG_USERAUTH_INFO_RESPONSE */
-+ + 4 /* int num-responses */
-+ ;
-+
-+ for(i = 0; i != session->userauth_kybd_num_prompts; ++i) {
-+ /* string response[1] (ISO-10646 UTF-8) */
-+ session->userauth_kybd_packet_len +=
-+ 4 + session->userauth_kybd_responses[i].length;
-+ }
-+
-+ session->userauth_kybd_data = s =
-+ LIBSSH2_ALLOC(session, session->userauth_kybd_packet_len);
-+ if (!s) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for keyboard-interactive response packet",
-+ 0);
-+ goto cleanup;
-+ }
-+
-+ *s = SSH_MSG_USERAUTH_INFO_RESPONSE;
-+ s++;
-+ libssh2_htonu32(s, session->userauth_kybd_num_prompts);
-+ s += 4;
-+
-+ for(i = 0; i != session->userauth_kybd_num_prompts; ++i) {
-+ libssh2_htonu32(s, session->userauth_kybd_responses[i].length);
-+ s += 4;
-+ memcpy(s, session->userauth_kybd_responses[i].text,
-+ session->userauth_kybd_responses[i].length);
-+ s += session->userauth_kybd_responses[i].length;
-+ }
-+
-+ session->userauth_kybd_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->userauth_kybd_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_packet_write(session, session->userauth_kybd_data,
-+ session->userauth_kybd_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send userauth-keyboard-interactive request",
-+ 0);
-+ goto cleanup;
-+ }
-+
-+ session->userauth_kybd_auth_failure = 0;
-+ }
-+
-+ cleanup:
-+ /*
-+ * It's safe to clean all the data here, because unallocated pointers
-+ * are filled by zeroes
-+ */
-+
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ session->userauth_kybd_data = NULL;
-+
-+ if (session->userauth_kybd_prompts) {
-+ for(i = 0; i != session->userauth_kybd_num_prompts; ++i) {
-+ LIBSSH2_FREE(session, session->userauth_kybd_prompts[i].text);
-+ session->userauth_kybd_prompts[i].text = NULL;
-+ }
-+ }
-+
-+ if (session->userauth_kybd_responses) {
-+ for(i = 0; i != session->userauth_kybd_num_prompts; ++i) {
-+ LIBSSH2_FREE(session,
-+ session->userauth_kybd_responses[i].text);
-+ session->userauth_kybd_responses[i].text = NULL;
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, session->userauth_kybd_prompts);
-+ session->userauth_kybd_prompts = NULL;
-+ LIBSSH2_FREE(session, session->userauth_kybd_responses);
-+ session->userauth_kybd_responses = NULL;
-+
-+ if (session->userauth_kybd_auth_failure) {
-+ session->userauth_kybd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ session->userauth_kybd_state = libssh2_NB_state_sent;
-+ }
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/userauth.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/mac.c
-===================================================================
---- libssh2/src/mac.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/mac.c (.../trunk)
-@@ -0,0 +1,311 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+#ifdef LIBSSH2_MAC_NONE
-+/* {{{ libssh2_mac_none_MAC
-+ * Minimalist MAC: No MAC
-+ */
-+static int
-+libssh2_mac_none_MAC(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)
-+{
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+
-+static LIBSSH2_MAC_METHOD libssh2_mac_method_none = {
-+ "none",
-+ 0,
-+ 0,
-+ NULL,
-+ libssh2_mac_none_MAC,
-+ NULL
-+};
-+#endif /* LIBSSH2_MAC_NONE */
-+
-+/* {{{ libssh2_mac_method_common_init
-+ * Initialize simple mac methods
-+ */
-+static int
-+libssh2_mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key,
-+ int *free_key, void **abstract)
-+{
-+ *abstract = key;
-+ *free_key = 0;
-+ (void) session;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_mac_method_common_dtor
-+ * Cleanup simple mac methods
-+ */
-+static int
-+libssh2_mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract)
-+{
-+ if (*abstract) {
-+ LIBSSH2_FREE(session, *abstract);
-+ }
-+ *abstract = NULL;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_mac_method_hmac_sha1_hash
-+ * Calculate hash using full sha1 value
-+ */
-+static int
-+libssh2_mac_method_hmac_sha1_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)
-+{
-+ libssh2_hmac_ctx ctx;
-+ unsigned char seqno_buf[4];
-+ (void) session;
-+
-+ libssh2_htonu32(seqno_buf, seqno);
-+
-+ libssh2_hmac_sha1_init(&ctx, *abstract, 20);
-+ libssh2_hmac_update(ctx, seqno_buf, 4);
-+ libssh2_hmac_update(ctx, packet, packet_len);
-+ if (addtl && addtl_len) {
-+ libssh2_hmac_update(ctx, addtl, addtl_len);
-+ }
-+ libssh2_hmac_final(ctx, buf);
-+ libssh2_hmac_cleanup(&ctx);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1 = {
-+ "hmac-sha1",
-+ 20,
-+ 20,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_sha1_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+
-+/* {{{ libssh2_mac_method_hmac_sha1_96_hash
-+ * Calculate hash using first 96 bits of sha1 value
-+ */
-+static int
-+libssh2_mac_method_hmac_sha1_96_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)
-+{
-+ unsigned char temp[SHA_DIGEST_LENGTH];
-+
-+ libssh2_mac_method_hmac_sha1_hash(session, temp, seqno, packet, packet_len,
-+ addtl, addtl_len, abstract);
-+ memcpy(buf, (char *) temp, 96 / 8);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_sha1_96 = {
-+ "hmac-sha1-96",
-+ 12,
-+ 20,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_sha1_96_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+
-+/* {{{ libssh2_mac_method_hmac_md5_hash
-+ * Calculate hash using full md5 value
-+ */
-+static int
-+libssh2_mac_method_hmac_md5_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)
-+{
-+ libssh2_hmac_ctx ctx;
-+ unsigned char seqno_buf[4];
-+ (void) session;
-+
-+ libssh2_htonu32(seqno_buf, seqno);
-+
-+ libssh2_hmac_md5_init(&ctx, *abstract, 16);
-+ libssh2_hmac_update(ctx, seqno_buf, 4);
-+ libssh2_hmac_update(ctx, packet, packet_len);
-+ if (addtl && addtl_len) {
-+ libssh2_hmac_update(ctx, addtl, addtl_len);
-+ }
-+ libssh2_hmac_final(ctx, buf);
-+ libssh2_hmac_cleanup(&ctx);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5 = {
-+ "hmac-md5",
-+ 16,
-+ 16,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_md5_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+
-+/* {{{ 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,
-+ const unsigned char *addtl,
-+ unsigned long addtl_len, void **abstract)
-+{
-+ unsigned char temp[MD5_DIGEST_LENGTH];
-+
-+ libssh2_mac_method_hmac_md5_hash(session, temp, seqno, packet, packet_len,
-+ addtl, addtl_len, abstract);
-+ memcpy(buf, (char *) temp, 96 / 8);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_md5_96 = {
-+ "hmac-md5-96",
-+ 12,
-+ 16,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_md5_96_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+
-+#if LIBSSH2_HMAC_RIPEMD
-+/* {{{ libssh2_mac_method_hmac_ripemd160_hash
-+ * Calculate hash using ripemd160 value
-+ */
-+static int
-+libssh2_mac_method_hmac_ripemd160_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)
-+{
-+ libssh2_hmac_ctx ctx;
-+ unsigned char seqno_buf[4];
-+ (void) session;
-+
-+ libssh2_htonu32(seqno_buf, seqno);
-+
-+ libssh2_hmac_ripemd160_init(&ctx, *abstract, 20);
-+ libssh2_hmac_update(ctx, seqno_buf, 4);
-+ libssh2_hmac_update(ctx, packet, packet_len);
-+ if (addtl && addtl_len) {
-+ libssh2_hmac_update(ctx, addtl, addtl_len);
-+ }
-+ libssh2_hmac_final(ctx, buf);
-+ libssh2_hmac_cleanup(&ctx);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160 = {
-+ "hmac-ripemd160",
-+ 20,
-+ 20,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_ripemd160_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+
-+static const LIBSSH2_MAC_METHOD libssh2_mac_method_hmac_ripemd160_openssh_com = {
-+ "hmac-ripemd160@openssh.com",
-+ 20,
-+ 20,
-+ libssh2_mac_method_common_init,
-+ libssh2_mac_method_hmac_ripemd160_hash,
-+ libssh2_mac_method_common_dtor,
-+};
-+#endif /* LIBSSH2_HMAC_RIPEMD */
-+
-+static const LIBSSH2_MAC_METHOD *_libssh2_mac_methods[] = {
-+ &libssh2_mac_method_hmac_sha1,
-+ &libssh2_mac_method_hmac_sha1_96,
-+ &libssh2_mac_method_hmac_md5,
-+ &libssh2_mac_method_hmac_md5_96,
-+#if LIBSSH2_HMAC_RIPEMD
-+ &libssh2_mac_method_hmac_ripemd160,
-+ &libssh2_mac_method_hmac_ripemd160_openssh_com,
-+#endif /* LIBSSH2_HMAC_RIPEMD */
-+#ifdef LIBSSH2_MAC_NONE
-+ &libssh2_mac_method_none,
-+#endif /* LIBSSH2_MAC_NONE */
-+ NULL
-+};
-+
-+const LIBSSH2_MAC_METHOD **
-+libssh2_mac_methods(void)
-+{
-+ return _libssh2_mac_methods;
-+}
-
-Property changes on: libssh2/src/mac.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/crypt.c
-===================================================================
---- libssh2/src/crypt.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/crypt.c (.../trunk)
-@@ -0,0 +1,256 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+#ifdef LIBSSH2_CRYPT_NONE
-+/* {{{ libssh2_crypt_none_crypt
-+ * Minimalist cipher: VERY secure *wink*
-+ */
-+static int
-+libssh2_crypt_none_crypt(LIBSSH2_SESSION * session, unsigned char *buf,
-+ void **abstract)
-+{
-+ /* Do nothing to the data! */
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
-+ "none",
-+ 8, /* blocksize (SSH2 defines minimum blocksize as 8) */
-+ 0, /* iv_len */
-+ 0, /* secret_len */
-+ 0, /* flags */
-+ NULL,
-+ libssh2_crypt_none_crypt,
-+ NULL
-+};
-+#endif /* LIBSSH2_CRYPT_NONE */
-+
-+struct crypt_ctx
-+{
-+ int encrypt;
-+ _libssh2_cipher_type(algo);
-+ _libssh2_cipher_ctx h;
-+};
-+
-+static int
-+_libssh2_init(LIBSSH2_SESSION * session,
-+ const LIBSSH2_CRYPT_METHOD * method,
-+ unsigned char *iv, int *free_iv,
-+ unsigned char *secret, int *free_secret,
-+ int encrypt, void **abstract)
-+{
-+ struct crypt_ctx *ctx = LIBSSH2_ALLOC(session,
-+ sizeof(struct crypt_ctx));
-+ if (!ctx) {
-+ return -1;
-+ }
-+ ctx->encrypt = encrypt;
-+ ctx->algo = method->algo;
-+ if (_libssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
-+ LIBSSH2_FREE(session, ctx);
-+ return -1;
-+ }
-+ *abstract = ctx;
-+ *free_iv = 1;
-+ *free_secret = 1;
-+ return 0;
-+}
-+
-+static int
-+_libssh2_encrypt(LIBSSH2_SESSION * session, unsigned char *block,
-+ void **abstract)
-+{
-+ struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract;
-+ (void) session;
-+ return _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block);
-+}
-+
-+static int
-+_libssh2_dtor(LIBSSH2_SESSION * session, void **abstract)
-+{
-+ struct crypt_ctx **cctx = (struct crypt_ctx **) abstract;
-+ if (cctx && *cctx) {
-+ _libssh2_cipher_dtor(&(*cctx)->h);
-+ LIBSSH2_FREE(session, *cctx);
-+ *abstract = NULL;
-+ }
-+ return 0;
-+}
-+
-+#if LIBSSH2_AES
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
-+ "aes128-cbc",
-+ 16, /* blocksize */
-+ 16, /* initial value length */
-+ 16, /* secret length -- 16*8 == 128bit */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_aes128
-+};
-+
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
-+ "aes192-cbc",
-+ 16, /* blocksize */
-+ 16, /* initial value length */
-+ 24, /* secret length -- 24*8 == 192bit */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_aes192
-+};
-+
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
-+ "aes256-cbc",
-+ 16, /* blocksize */
-+ 16, /* initial value length */
-+ 32, /* secret length -- 32*8 == 256bit */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_aes256
-+};
-+
-+/* rijndael-cbc@lysator.liu.se == aes256-cbc */
-+static const LIBSSH2_CRYPT_METHOD
-+ libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
-+ "rijndael-cbc@lysator.liu.se",
-+ 16, /* blocksize */
-+ 16, /* initial value length */
-+ 32, /* secret length -- 32*8 == 256bit */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_aes256
-+};
-+#endif /* LIBSSH2_AES */
-+
-+#if LIBSSH2_BLOWFISH
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
-+ "blowfish-cbc",
-+ 8, /* blocksize */
-+ 8, /* initial value length */
-+ 16, /* secret length */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_blowfish
-+};
-+#endif /* LIBSSH2_BLOWFISH */
-+
-+#if LIBSSH2_RC4
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
-+ "arcfour",
-+ 8, /* blocksize */
-+ 8, /* initial value length */
-+ 16, /* secret length */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_arcfour
-+};
-+#endif /* LIBSSH2_RC4 */
-+
-+#if LIBSSH2_CAST
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
-+ "cast128-cbc",
-+ 8, /* blocksize */
-+ 8, /* initial value length */
-+ 16, /* secret length */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_cast5
-+};
-+#endif /* LIBSSH2_CAST */
-+
-+#if LIBSSH2_3DES
-+static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
-+ "3des-cbc",
-+ 8, /* blocksize */
-+ 8, /* initial value length */
-+ 24, /* secret length */
-+ 0, /* flags */
-+ &_libssh2_init,
-+ &_libssh2_encrypt,
-+ &_libssh2_dtor,
-+ _libssh2_cipher_3des
-+};
-+#endif
-+
-+static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
-+#if LIBSSH2_AES
-+ &libssh2_crypt_method_aes256_cbc,
-+ &libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */
-+ &libssh2_crypt_method_aes192_cbc,
-+ &libssh2_crypt_method_aes128_cbc,
-+#endif /* LIBSSH2_AES */
-+#if LIBSSH2_BLOWFISH
-+ &libssh2_crypt_method_blowfish_cbc,
-+#endif /* LIBSSH2_BLOWFISH */
-+#if LIBSSH2_RC4
-+ &libssh2_crypt_method_arcfour,
-+#endif /* LIBSSH2_RC4 */
-+#if LIBSSH2_CAST
-+ &libssh2_crypt_method_cast128_cbc,
-+#endif /* LIBSSH2_CAST */
-+#if LIBSSH2_3DES
-+ &libssh2_crypt_method_3des_cbc,
-+#endif /* LIBSSH2_DES */
-+#ifdef LIBSSH2_CRYPT_NONE
-+ &libssh2_crypt_method_none,
-+#endif
-+ NULL
-+};
-+
-+/* Expose to kex.c */
-+const LIBSSH2_CRYPT_METHOD **
-+libssh2_crypt_methods(void)
-+{
-+ return _libssh2_crypt_methods;
-+}
-
-Property changes on: libssh2/src/crypt.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/libgcrypt.h
-===================================================================
---- libssh2/src/libgcrypt.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/libgcrypt.h (.../trunk)
-@@ -0,0 +1,187 @@
-+/* Copyright (C) 2006, 2007, The Written Word, Inc.
-+ * Copyright (C) 2008, Simon Josefsson
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms,
-+ * with or without modification, are permitted provided
-+ * 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.
-+ */
-+
-+#include <gcrypt.h>
-+
-+#define LIBSSH2_MD5 1
-+
-+#define LIBSSH2_HMAC_RIPEMD 1
-+
-+#define LIBSSH2_AES 1
-+#define LIBSSH2_BLOWFISH 1
-+#define LIBSSH2_RC4 1
-+#define LIBSSH2_CAST 1
-+#define LIBSSH2_3DES 1
-+
-+#define LIBSSH2_RSA 1
-+#define LIBSSH2_DSA 1
-+
-+#define MD5_DIGEST_LENGTH 16
-+#define SHA_DIGEST_LENGTH 20
-+
-+#define libssh2_random(buf, len) \
-+ (gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
-+
-+#define libssh2_sha1_ctx gcry_md_hd_t
-+#define libssh2_sha1_init(ctx) gcry_md_open (ctx, GCRY_MD_SHA1, 0);
-+#define libssh2_sha1_update(ctx, data, len) gcry_md_write (ctx, data, len)
-+#define libssh2_sha1_final(ctx, out) \
-+ memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
-+#define libssh2_sha1(message, len, out) \
-+ gcry_md_hash_buffer (GCRY_MD_SHA1, out, message, len)
-+
-+#define libssh2_md5_ctx gcry_md_hd_t
-+#define libssh2_md5_init(ctx) gcry_md_open (ctx, GCRY_MD_MD5, 0);
-+#define libssh2_md5_update(ctx, data, len) gcry_md_write (ctx, data, len)
-+#define libssh2_md5_final(ctx, out) \
-+ memcpy (out, gcry_md_read (ctx, 0), 20), gcry_md_close (ctx)
-+#define libssh2_md5(message, len, out) \
-+ gcry_md_hash_buffer (GCRY_MD_MD5, out, message, len)
-+
-+#define libssh2_hmac_ctx gcry_md_hd_t
-+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
-+ gcry_md_open (ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC), \
-+ gcry_md_setkey (*ctx, key, keylen)
-+#define libssh2_hmac_md5_init(ctx, key, keylen) \
-+ gcry_md_open (ctx, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC), \
-+ gcry_md_setkey (*ctx, key, keylen)
-+#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
-+ gcry_md_open (ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \
-+ gcry_md_setkey (*ctx, key, keylen)
-+#define libssh2_hmac_update(ctx, data, datalen) \
-+ gcry_md_write (ctx, data, datalen)
-+#define libssh2_hmac_final(ctx, data) \
-+ memcpy (data, gcry_md_read (ctx, 0), \
-+ gcry_md_get_algo_dlen (gcry_md_get_algo (ctx)))
-+#define libssh2_hmac_cleanup(ctx) gcry_md_close (*ctx);
-+
-+#define libssh2_crypto_init() gcry_control (GCRYCTL_DISABLE_SECMEM)
-+
-+#define libssh2_rsa_ctx struct gcry_sexp
-+
-+int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
-+ const unsigned char *edata,
-+ unsigned long elen,
-+ const unsigned char *ndata,
-+ unsigned long nlen,
-+ const unsigned char *ddata,
-+ unsigned long dlen,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *e1data,
-+ unsigned long e1len,
-+ const unsigned char *e2data,
-+ unsigned long e2len,
-+ const unsigned char *coeffdata, unsigned long coefflen);
-+int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase);
-+int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m, unsigned long m_len);
-+int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
-+ libssh2_rsa_ctx * rsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len,
-+ unsigned char **signature,
-+ unsigned long *signature_len);
-+
-+#define _libssh2_rsa_free(rsactx) gcry_sexp_release (rsactx)
-+
-+#define libssh2_dsa_ctx struct gcry_sexp
-+
-+int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *gdata,
-+ unsigned long glen,
-+ const unsigned char *ydata,
-+ unsigned long ylen,
-+ const unsigned char *x, unsigned long x_len);
-+int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase);
-+int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsa,
-+ const unsigned char *sig,
-+ const unsigned char *m, unsigned long m_len);
-+int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len, unsigned char *sig);
-+
-+#define _libssh2_dsa_free(dsactx) gcry_sexp_release (dsactx)
-+
-+#define _libssh2_cipher_type(name) int name
-+#define _libssh2_cipher_ctx gcry_cipher_hd_t
-+
-+#define _libssh2_cipher_aes256 GCRY_CIPHER_AES256
-+#define _libssh2_cipher_aes192 GCRY_CIPHER_AES192
-+#define _libssh2_cipher_aes128 GCRY_CIPHER_AES128
-+#define _libssh2_cipher_blowfish GCRY_CIPHER_BLOWFISH
-+#define _libssh2_cipher_arcfour GCRY_CIPHER_ARCFOUR
-+#define _libssh2_cipher_cast5 GCRY_CIPHER_CAST5
-+#define _libssh2_cipher_3des GCRY_CIPHER_3DES
-+
-+int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
-+ _libssh2_cipher_type(algo),
-+ unsigned char *iv,
-+ unsigned char *secret, int encrypt);
-+
-+int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
-+ _libssh2_cipher_type(algo),
-+ int encrypt, unsigned char *block);
-+
-+#define _libssh2_cipher_dtor(ctx) gcry_cipher_close(*(ctx))
-+
-+#define _libssh2_bn struct gcry_mpi
-+#define _libssh2_bn_ctx int
-+#define _libssh2_bn_ctx_new() 0
-+#define _libssh2_bn_ctx_free(bnctx) ((void)0)
-+#define _libssh2_bn_init() gcry_mpi_new(0)
-+#define _libssh2_bn_rand(bn, bits, top, bottom) gcry_mpi_randomize (bn, bits, GCRY_WEAK_RANDOM)
-+#define _libssh2_bn_mod_exp(r, a, p, m, ctx) gcry_mpi_powm (r, a, p, m)
-+#define _libssh2_bn_set_word(bn, val) gcry_mpi_set_ui(bn, val)
-+#define _libssh2_bn_from_bin(bn, len, val) gcry_mpi_scan(&((bn)), GCRYMPI_FMT_USG, val, len, NULL)
-+#define _libssh2_bn_to_bin(bn, val) gcry_mpi_print (GCRYMPI_FMT_USG, val, _libssh2_bn_bytes(bn), NULL, bn)
-+#define _libssh2_bn_bytes(bn) (gcry_mpi_get_nbits (bn) / 8 + ((gcry_mpi_get_nbits (bn) % 8 == 0) ? 0 : 1))
-+#define _libssh2_bn_bits(bn) gcry_mpi_get_nbits (bn)
-+#define _libssh2_bn_free(bn) gcry_mpi_release(bn)
-
-Property changes on: libssh2/src/libgcrypt.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/packet.c
-===================================================================
---- libssh2/src/packet.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/packet.c (.../trunk)
-@@ -0,0 +1,1270 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <errno.h>
-+#include <fcntl.h>
-+
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+
-+#ifdef HAVE_SYS_TIME_H
-+#include <sys/time.h>
-+#endif
-+
-+#ifdef HAVE_INTTYPES_H
-+#include <inttypes.h>
-+#endif
-+
-+/* Needed for struct iovec on some platforms */
-+#ifdef HAVE_SYS_UIO_H
-+#include <sys/uio.h>
-+#endif
-+
-+#include <sys/types.h>
-+
-+/* {{{ libssh2_packet_queue_listener
-+ * Queue a connection request for a listener
-+ */
-+static inline int
-+libssh2_packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned long datalen,
-+ packet_queue_listener_state_t * listen_state)
-+{
-+ /*
-+ * Look for a matching listener
-+ */
-+ unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
-+ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
-+ unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1);
-+ unsigned char *p;
-+ LIBSSH2_LISTENER *listen = session->listeners;
-+ char failure_code = 1; /* SSH_OPEN_ADMINISTRATIVELY_PROHIBITED */
-+ int rc;
-+
-+ (void) datalen;
-+
-+ if (listen_state->state == libssh2_NB_state_idle) {
-+ listen_state->sender_channel = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ listen_state->initial_window_size = libssh2_ntohu32(s);
-+ s += 4;
-+ listen_state->packet_size = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ listen_state->host_len = libssh2_ntohu32(s);
-+ s += 4;
-+ listen_state->host = s;
-+ s += listen_state->host_len;
-+ listen_state->port = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ listen_state->shost_len = libssh2_ntohu32(s);
-+ s += 4;
-+ listen_state->shost = s;
-+ s += listen_state->shost_len;
-+ listen_state->sport = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Remote received connection from %s:%ld to %s:%ld",
-+ listen_state->shost, listen_state->sport,
-+ listen_state->host, listen_state->port);
-+
-+ listen_state->state = libssh2_NB_state_allocated;
-+ }
-+
-+ if (listen_state->state != libssh2_NB_state_sent) {
-+ while (listen) {
-+ if ((listen->port == (int) listen_state->port) &&
-+ (strlen(listen->host) == listen_state->host_len) &&
-+ (memcmp
-+ (listen->host, listen_state->host,
-+ listen_state->host_len) == 0)) {
-+ /* This is our listener */
-+ LIBSSH2_CHANNEL *channel, *last_queued = listen->queue;
-+
-+ last_queued = listen->queue;
-+ if (listen_state->state == libssh2_NB_state_allocated) {
-+ if (listen->queue_maxsize &&
-+ (listen->queue_maxsize <= listen->queue_size)) {
-+ /* Queue is full */
-+ failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Listener queue full, ignoring");
-+ listen_state->state = libssh2_NB_state_sent;
-+ 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 */
-+ listen_state->state = libssh2_NB_state_sent;
-+ 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 */
-+ listen_state->state = libssh2_NB_state_sent;
-+ break;
-+ }
-+ memcpy(channel->channel_type, "forwarded-tcpip",
-+ channel->channel_type_len + 1);
-+
-+ channel->remote.id = listen_state->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 =
-+ listen_state->initial_window_size;
-+ channel->local.window_size =
-+ listen_state->initial_window_size;
-+ channel->local.packet_size = listen_state->packet_size;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Connection queued: channel %lu/%lu win %lu/%lu packet %lu/%lu",
-+ channel->local.id, channel->remote.id,
-+ channel->local.window_size,
-+ channel->remote.window_size,
-+ channel->local.packet_size,
-+ channel->remote.packet_size);
-+
-+ p = listen_state->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;
-+
-+ listen_state->state = libssh2_NB_state_created;
-+ }
-+
-+ if (listen_state->state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, listen_state->packet,
-+ 17);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel open confirmation",
-+ 0);
-+ listen_state->state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ /* Link the channel into the end of the queue list */
-+
-+ if (!last_queued) {
-+ listen->queue = channel;
-+ listen_state->state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ while (last_queued->next) {
-+ last_queued = last_queued->next;
-+ }
-+
-+ last_queued->next = channel;
-+ channel->prev = last_queued;
-+
-+ listen->queue_size++;
-+
-+ listen_state->state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+
-+ listen = listen->next;
-+ }
-+
-+ listen_state->state = libssh2_NB_state_sent;
-+ }
-+
-+ /* We're not listening to you */
-+ {
-+ p = listen_state->packet;
-+ *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
-+ libssh2_htonu32(p, listen_state->sender_channel);
-+ p += 4;
-+ libssh2_htonu32(p, failure_code);
-+ p += 4;
-+ libssh2_htonu32(p, sizeof(FwdNotReq) - 1);
-+ p += 4;
-+ memcpy(s, FwdNotReq, sizeof(FwdNotReq) - 1);
-+ p += sizeof(FwdNotReq) - 1;
-+ libssh2_htonu32(p, 0);
-+
-+ rc = libssh2_packet_write(session, listen_state->packet, packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send open failure", 0);
-+ listen_state->state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ listen_state->state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_packet_x11_open
-+ * Accept a forwarded X11 connection
-+ */
-+static inline int
-+libssh2_packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned long datalen,
-+ packet_x11_open_state_t * x11open_state)
-+{
-+ int failure_code = 2; /* SSH_OPEN_CONNECT_FAILED */
-+ unsigned char *s = data + (sizeof("x11") - 1) + 5;
-+ /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
-+ unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
-+ unsigned char *p;
-+ LIBSSH2_CHANNEL *channel;
-+ int rc;
-+
-+ (void) datalen;
-+
-+ if (x11open_state->state == libssh2_NB_state_idle) {
-+ x11open_state->sender_channel = libssh2_ntohu32(s);
-+ s += 4;
-+ x11open_state->initial_window_size = libssh2_ntohu32(s);
-+ s += 4;
-+ x11open_state->packet_size = libssh2_ntohu32(s);
-+ s += 4;
-+ x11open_state->shost_len = libssh2_ntohu32(s);
-+ s += 4;
-+ x11open_state->shost = s;
-+ s += x11open_state->shost_len;
-+ x11open_state->sport = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "X11 Connection Received from %s:%ld on channel %lu",
-+ x11open_state->shost, x11open_state->sport,
-+ x11open_state->sender_channel);
-+
-+ x11open_state->state = libssh2_NB_state_allocated;
-+ }
-+
-+ if (session->x11) {
-+ if (x11open_state->state == libssh2_NB_state_allocated) {
-+ 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 = x11open_state->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 =
-+ x11open_state->initial_window_size;
-+ channel->local.window_size = x11open_state->initial_window_size;
-+ channel->local.packet_size = x11open_state->packet_size;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "X11 Connection established: channel %lu/%lu win %lu/%lu packet %lu/%lu",
-+ channel->local.id, channel->remote.id,
-+ channel->local.window_size,
-+ channel->remote.window_size,
-+ channel->local.packet_size,
-+ channel->remote.packet_size);
-+ p = x11open_state->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;
-+
-+ x11open_state->state = libssh2_NB_state_created;
-+ }
-+
-+ if (x11open_state->state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, x11open_state->packet, 17);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel open confirmation", 0);
-+ x11open_state->state = libssh2_NB_state_idle;
-+ 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, (char *) x11open_state->shost,
-+ x11open_state->sport);
-+
-+ x11open_state->state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ } else {
-+ failure_code = 4; /* SSH_OPEN_RESOURCE_SHORTAGE */
-+ }
-+
-+ x11_exit:
-+ p = x11open_state->packet;
-+ *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
-+ libssh2_htonu32(p, x11open_state->sender_channel);
-+ p += 4;
-+ libssh2_htonu32(p, failure_code);
-+ p += 4;
-+ libssh2_htonu32(p, sizeof(X11FwdUnAvil) - 1);
-+ p += 4;
-+ memcpy(s, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
-+ p += sizeof(X11FwdUnAvil) - 1;
-+ libssh2_htonu32(p, 0);
-+
-+ rc = libssh2_packet_write(session, x11open_state->packet, packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send open failure", 0);
-+ x11open_state->state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ x11open_state->state = libssh2_NB_state_idle;
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_packet_new
-+ * Create a new packet and attach it to the brigade
-+ */
-+int
-+libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
-+ size_t datalen, int macstate)
-+{
-+ int rc;
-+
-+ if (session->packAdd_state == libssh2_NB_state_idle) {
-+ session->packAdd_data_head = 0;
-+
-+ /* Zero the whole thing out */
-+ memset(&session->packAdd_key_state, 0,
-+ sizeof(session->packAdd_key_state));
-+
-+ /* Zero the whole thing out */
-+ memset(&session->packAdd_Qlstn_state, 0,
-+ sizeof(session->packAdd_Qlstn_state));
-+
-+ /* Zero the whole thing out */
-+ memset(&session->packAdd_x11open_state, 0,
-+ sizeof(session->packAdd_x11open_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Packet type %d received, length=%d",
-+ (int) data[0], (int) datalen);
-+ if (macstate == LIBSSH2_MAC_INVALID) {
-+ if (session->macerror) {
-+ if (LIBSSH2_MACERROR(session, (char *) data, datalen) == 0) {
-+ /* Calling app has given the OK, Process it anyway */
-+ macstate = LIBSSH2_MAC_CONFIRMED;
-+ } else {
-+ libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
-+ "Invalid Message Authentication Code received",
-+ 0);
-+ if (session->ssh_msg_disconnect) {
-+ LIBSSH2_DISCONNECT(session, SSH_DISCONNECT_MAC_ERROR,
-+ "Invalid MAC received",
-+ sizeof("Invalid MAC received") - 1,
-+ "", 0);
-+ }
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+ } else {
-+ libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
-+ "Invalid Message Authentication Code received",
-+ 0);
-+ if (session->ssh_msg_disconnect) {
-+ LIBSSH2_DISCONNECT(session, SSH_DISCONNECT_MAC_ERROR,
-+ "Invalid MAC received",
-+ sizeof("Invalid MAC received") - 1,
-+ "", 0);
-+ }
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+ }
-+
-+ session->packAdd_state = libssh2_NB_state_allocated;
-+ }
-+
-+ /*
-+ * =============================== NOTE ===============================
-+ * I know this is very ugly and not a really good use of "goto", but
-+ * this case statement would be even uglier to do it any other way
-+ */
-+ if (session->packAdd_state == libssh2_NB_state_jump1) {
-+ goto libssh2_packet_add_jump_point1;
-+ } else if (session->packAdd_state == libssh2_NB_state_jump2) {
-+ goto libssh2_packet_add_jump_point2;
-+ } else if (session->packAdd_state == libssh2_NB_state_jump3) {
-+ goto libssh2_packet_add_jump_point3;
-+ }
-+
-+ if (session->packAdd_state == libssh2_NB_state_allocated) {
-+ /* A couple exceptions to the packet adding rule: */
-+ switch (data[0]) {
-+ case SSH_MSG_DISCONNECT:
-+ {
-+ char *message, *language;
-+ int reason, message_len, language_len;
-+
-+ reason = libssh2_ntohu32(data + 1);
-+ message_len = libssh2_ntohu32(data + 5);
-+ /* 9 = packet_type(1) + reason(4) + message_len(4) */
-+ message = (char *) data + 9;
-+ language_len = libssh2_ntohu32(data + 9 + message_len);
-+ /*
-+ * This is where we hack on the data a little,
-+ * Use the MSB of language_len to to a terminating NULL
-+ * (In all liklihood it is already)
-+ * Shift the language tag back a byte (In all likelihood
-+ * it's zero length anyway)
-+ * Store a NULL in the last byte of the packet to terminate
-+ * the language string
-+ * With the lengths passed this isn't *REALLY* necessary,
-+ * but it's "kind"
-+ */
-+ message[message_len] = '\0';
-+ language = (char *) data + 9 + message_len + 3;
-+ if (language_len) {
-+ memcpy(language, language + 1, language_len);
-+ }
-+ language[language_len] = '\0';
-+
-+ if (session->ssh_msg_disconnect) {
-+ LIBSSH2_DISCONNECT(session, reason, message,
-+ message_len, language, language_len);
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Disconnect(%d): %s(%s)", reason,
-+ message, language);
-+ LIBSSH2_FREE(session, data);
-+ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ break;
-+
-+ case SSH_MSG_IGNORE:
-+ /* As with disconnect, back it up one and add a trailing NULL */
-+ memcpy(data + 4, data + 5, datalen - 5);
-+ data[datalen] = '\0';
-+ if (session->ssh_msg_ignore) {
-+ LIBSSH2_IGNORE(session, (char *) data + 4, datalen - 5);
-+ }
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ break;
-+
-+ case SSH_MSG_DEBUG:
-+ {
-+ int always_display = data[0];
-+ char *message, *language;
-+ int message_len, language_len;
-+
-+ message_len = libssh2_ntohu32(data + 2);
-+ /* 6 = packet_type(1) + display(1) + message_len(4) */
-+ message = (char *) data + 6;
-+ language_len = libssh2_ntohu32(data + 6 + message_len);
-+ /*
-+ * This is where we hack on the data a little,
-+ * Use the MSB of language_len to to a terminating NULL
-+ * (In all liklihood it is already)
-+ * Shift the language tag back a byte (In all likelihood
-+ * it's zero length anyway)
-+ * Store a NULL in the last byte of the packet to terminate
-+ * the language string
-+ * With the lengths passed this isn't *REALLY* necessary,
-+ * but it's "kind"
-+ */
-+ message[message_len] = '\0';
-+ language = (char *) data + 6 + message_len + 3;
-+ if (language_len) {
-+ memcpy(language, language + 1, language_len);
-+ }
-+ language[language_len] = '\0';
-+
-+ if (session->ssh_msg_debug) {
-+ LIBSSH2_DEBUG(session, always_display, message,
-+ message_len, language, language_len);
-+ }
-+ /*
-+ * _libssh2_debug will actually truncate this for us so
-+ * that it's not an inordinate about of data
-+ */
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Debug Packet: %s", message);
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ break;
-+
-+ case SSH_MSG_CHANNEL_EXTENDED_DATA:
-+ /* streamid(4) */
-+ session->packAdd_data_head += 4;
-+ case SSH_MSG_CHANNEL_DATA:
-+ /* packet_type(1) + channelno(4) + datalen(4) */
-+ session->packAdd_data_head += 9;
-+ {
-+ session->packAdd_channel = libssh2_channel_locate(session,
-+ libssh2_ntohu32
-+ (data + 1));
-+
-+ if (!session->packAdd_channel) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
-+ "Packet received for unknown channel, ignoring",
-+ 0);
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+#ifdef LIBSSH2DEBUG
-+ {
-+ unsigned long stream_id = 0;
-+
-+ if (data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) {
-+ stream_id = libssh2_ntohu32(data + 5);
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "%d bytes received for channel %lu/%lu stream #%lu",
-+ (int) (datalen -
-+ session->packAdd_data_head),
-+ session->packAdd_channel->local.id,
-+ session->packAdd_channel->remote.id,
-+ stream_id);
-+ }
-+#endif
-+ if ((session->packAdd_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);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Ignoring extended data and refunding %d bytes",
-+ (int) (datalen - 13));
-+ /* Adjust the window based on the block we just freed */
-+ libssh2_packet_add_jump_point1:
-+ session->packAdd_state = libssh2_NB_state_jump1;
-+ rc = libssh2_channel_receive_window_adjust(session->
-+ packAdd_channel,
-+ datalen - 13,
-+ 0);
-+ if (rc == PACKET_EAGAIN) {
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ return PACKET_EAGAIN;
-+ }
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ /*
-+ * REMEMBER! remote means remote as source of data,
-+ * NOT remote window!
-+ */
-+ if (session->packAdd_channel->remote.packet_size <
-+ (datalen - session->packAdd_data_head)) {
-+ /*
-+ * Spec says we MAY ignore bytes sent beyond
-+ * packet_size
-+ */
-+ libssh2_error(session,
-+ LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
-+ "Packet contains more data than we offered to receive, truncating",
-+ 0);
-+ datalen =
-+ session->packAdd_channel->remote.packet_size +
-+ session->packAdd_data_head;
-+ }
-+ if (session->packAdd_channel->remote.window_size <= 0) {
-+ /*
-+ * Spec says we MAY ignore bytes sent beyond
-+ * window_size
-+ */
-+ libssh2_error(session,
-+ LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
-+ "The current receive window is full, data ignored",
-+ 0);
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ /* Reset EOF status */
-+ session->packAdd_channel->remote.eof = 0;
-+
-+ if ((datalen - session->packAdd_data_head) >
-+ session->packAdd_channel->remote.window_size) {
-+ libssh2_error(session,
-+ LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
-+ "Remote sent more data than current window allows, truncating",
-+ 0);
-+ datalen =
-+ session->packAdd_channel->remote.window_size +
-+ session->packAdd_data_head;
-+ } else {
-+ /* Now that we've received it, shrink our window */
-+ session->packAdd_channel->remote.window_size -=
-+ datalen - session->packAdd_data_head;
-+ }
-+ }
-+ break;
-+
-+ case SSH_MSG_CHANNEL_EOF:
-+ {
-+ session->packAdd_channel = libssh2_channel_locate(session,
-+ libssh2_ntohu32
-+ (data + 1));
-+
-+ if (!session->packAdd_channel) {
-+ /* We may have freed already, just quietly ignore this... */
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ _libssh2_debug(session,
-+ LIBSSH2_DBG_CONN,
-+ "EOF received for channel %lu/%lu",
-+ session->packAdd_channel->local.id,
-+ session->packAdd_channel->remote.id);
-+ session->packAdd_channel->remote.eof = 1;
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ break;
-+
-+ case SSH_MSG_CHANNEL_REQUEST:
-+ {
-+ if (libssh2_ntohu32(data + 5) == sizeof("exit-status") - 1
-+ && !memcmp("exit-status", data + 9,
-+ sizeof("exit-status") - 1)) {
-+
-+ /* we've got "exit-status" packet. Set the session value */
-+ session->packAdd_channel =
-+ libssh2_channel_locate(session,
-+ libssh2_ntohu32(data + 1));
-+
-+ if (session->packAdd_channel) {
-+ session->packAdd_channel->exit_status =
-+ libssh2_ntohu32(data + 9 + sizeof("exit-status"));
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Exit status %lu received for channel %lu/%lu",
-+ session->packAdd_channel->exit_status,
-+ session->packAdd_channel->local.id,
-+ session->packAdd_channel->remote.id);
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+ break;
-+
-+ case SSH_MSG_CHANNEL_CLOSE:
-+ {
-+ session->packAdd_channel = libssh2_channel_locate(session,
-+ libssh2_ntohu32
-+ (data + 1));
-+
-+ if (!session->packAdd_channel) {
-+ /* We may have freed already, just quietly ignore this... */
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Close received for channel %lu/%lu",
-+ session->packAdd_channel->local.id,
-+ session->packAdd_channel->remote.id);
-+
-+ session->packAdd_channel->remote.close = 1;
-+ session->packAdd_channel->remote.eof = 1;
-+ /* TODO: Add a callback for this */
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ 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)) {
-+
-+ libssh2_packet_add_jump_point2:
-+ session->packAdd_state = libssh2_NB_state_jump2;
-+ rc = libssh2_packet_queue_listener(session, data, datalen,
-+ &session->
-+ packAdd_Qlstn_state);
-+ if (rc == PACKET_EAGAIN) {
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ return PACKET_EAGAIN;
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return rc;
-+ }
-+ if ((datalen >= (sizeof("x11") + 4)) &&
-+ ((sizeof("x11") - 1) == libssh2_ntohu32(data + 1)) &&
-+ (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) {
-+
-+ libssh2_packet_add_jump_point3:
-+ session->packAdd_state = libssh2_NB_state_jump3;
-+ rc = libssh2_packet_x11_open(session, data, datalen,
-+ &session->packAdd_x11open_state);
-+ if (rc == PACKET_EAGAIN) {
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ return PACKET_EAGAIN;
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return rc;
-+ }
-+ break;
-+
-+ case SSH_MSG_CHANNEL_WINDOW_ADJUST:
-+ {
-+ unsigned long bytestoadd = libssh2_ntohu32(data + 5);
-+ session->packAdd_channel = libssh2_channel_locate(session,
-+ libssh2_ntohu32
-+ (data + 1));
-+
-+ if (session->packAdd_channel && bytestoadd) {
-+ session->packAdd_channel->local.window_size += bytestoadd;
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Window adjust received for channel %lu/%lu, adding %lu bytes, new window_size=%lu",
-+ session->packAdd_channel->local.id,
-+ session->packAdd_channel->remote.id,
-+ bytestoadd,
-+ session->packAdd_channel->local.window_size);
-+
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ break;
-+ }
-+
-+ session->packAdd_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->packAdd_state == libssh2_NB_state_sent) {
-+ session->packAdd_packet =
-+ LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
-+ if (!session->packAdd_packet) {
-+ _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for LIBSSH2_PACKET");
-+ LIBSSH2_FREE(session, data);
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ memset(session->packAdd_packet, 0, sizeof(LIBSSH2_PACKET));
-+
-+ session->packAdd_packet->data = data;
-+ session->packAdd_packet->data_len = datalen;
-+ session->packAdd_packet->data_head = session->packAdd_data_head;
-+ session->packAdd_packet->mac = macstate;
-+ session->packAdd_packet->brigade = &session->packets;
-+ session->packAdd_packet->next = NULL;
-+
-+ if (session->packets.tail) {
-+ session->packAdd_packet->prev = session->packets.tail;
-+ session->packAdd_packet->prev->next = session->packAdd_packet;
-+ session->packets.tail = session->packAdd_packet;
-+ } else {
-+ session->packets.head = session->packAdd_packet;
-+ session->packets.tail = session->packAdd_packet;
-+ session->packAdd_packet->prev = NULL;
-+ }
-+
-+ session->packAdd_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if ((data[0] == SSH_MSG_KEXINIT &&
-+ !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
-+ (session->packAdd_state == libssh2_NB_state_sent2)) {
-+ if (session->packAdd_state == libssh2_NB_state_sent1) {
-+ /*
-+ * Remote wants new keys
-+ * Well, it's already in the brigade,
-+ * let's just call back into ourselves
-+ */
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Renegotiating Keys");
-+
-+ session->packAdd_state = libssh2_NB_state_sent2;
-+ }
-+
-+ /*
-+ * The KEXINIT message has been added to the queue.
-+ * The packAdd and readPack states need to be reset
-+ * because libssh2_kex_exchange (eventually) calls upon
-+ * libssh2_packet_read to read the rest of the key exchange
-+ * conversation.
-+ */
-+ session->readPack_state = libssh2_NB_state_idle;
-+ session->packet.total_num = 0;
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ session->fullpacket_state = libssh2_NB_state_idle;
-+
-+ /*
-+ * Also, don't use packAdd_key_state for key re-exchange,
-+ * as it will be wiped out in the middle of the exchange.
-+ * How about re-using the startup_key_state?
-+ */
-+ memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
-+
-+ /*
-+ * If there was a key reexchange failure, let's just hope we didn't
-+ * send NEWKEYS yet, otherwise remote will drop us like a rock
-+ */
-+ rc = libssh2_kex_exchange(session, 1, &session->startup_key_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+
-+ session->packAdd_state = libssh2_NB_state_idle;
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_packet_ask
-+ * Scan the brigade for a matching packet type, optionally poll the socket for
-+ * a packet first
-+ */
-+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)
-+{
-+ LIBSSH2_PACKET *packet = session->packets.head;
-+
-+ if (poll_socket) {
-+ /*
-+ * XXX CHECK ***
-+ * When "poll_socket" is "1" libhss2_packet_read() can return
-+ * PACKET_EAGAIN. I am not sure what should happen, but internally
-+ * there is only one location that might do so, libssh2_packet_askv_ex()
-+ */
-+ libssh2pack_t rc = libssh2_packet_read(session);
-+ if ((rc < 0) && !packet) {
-+ return rc;
-+ }
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Looking for packet of type: %d", (int) packet_type);
-+
-+ while (packet) {
-+ if (packet->data[0] == packet_type
-+ && (packet->data_len >= (match_ofs + match_len)) && (!match_buf
-+ ||
-+ (memcmp
-+ (packet->
-+ data +
-+ match_ofs,
-+ match_buf,
-+ match_len)
-+ == 0))) {
-+ *data = packet->data;
-+ *data_len = packet->data_len;
-+
-+ if (packet->prev) {
-+ packet->prev->next = packet->next;
-+ } else {
-+ session->packets.head = packet->next;
-+ }
-+
-+ if (packet->next) {
-+ packet->next->prev = packet->prev;
-+ } else {
-+ session->packets.tail = packet->prev;
-+ }
-+
-+ LIBSSH2_FREE(session, packet);
-+
-+ return 0;
-+ }
-+ packet = packet->next;
-+ }
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_packet_askv
-+ * Scan for any of a list of packet types in the brigade, optionally poll the
-+ * socket for a packet first
-+ */
-+int
-+libssh2_packet_askv_ex(LIBSSH2_SESSION * session,
-+ const unsigned char *packet_types,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len, int poll_socket)
-+{
-+ int i, packet_types_len = strlen((char *) packet_types);
-+
-+ for(i = 0; i < packet_types_len; i++) {
-+ /*
-+ * XXX CHECK XXX
-+ * When "poll_socket" is "1" libssh2_packet_ask_ex() could
-+ * return PACKET_EAGAIN. Not sure the correct action, I
-+ * think it is right as is.
-+ */
-+ if (0 == libssh2_packet_ask_ex(session, packet_types[i], data,
-+ data_len, match_ofs, match_buf,
-+ match_len, i ? 0 : poll_socket)) {
-+ return 0;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ waitsocket
-+ * Returns
-+ * negative on error
-+ * >0 on incoming data
-+ * 0 on timeout
-+ *
-+ * FIXME: convert to use poll on systems that have it.
-+ */
-+int
-+libssh2_waitsocket(LIBSSH2_SESSION * session, long seconds)
-+{
-+ struct timeval timeout;
-+ int rc;
-+ fd_set fd;
-+
-+ timeout.tv_sec = seconds;
-+ timeout.tv_usec = 0;
-+
-+ FD_ZERO(&fd);
-+
-+ FD_SET(session->socket_fd, &fd);
-+
-+ rc = select(session->socket_fd + 1, &fd, NULL, NULL, &timeout);
-+
-+ return rc;
-+}
-+
-+/* {{{ libssh2_packet_require
-+ * Loops libssh2_packet_read() until the packet requested is available
-+ * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
-+ *
-+ * Returns negative on error
-+ * Returns 0 when it has taken care of the requested packet.
-+ */
-+int
-+libssh2_packet_require_ex(LIBSSH2_SESSION * session, unsigned char packet_type,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len,
-+ packet_require_state_t * state)
-+{
-+ if (state->start == 0) {
-+ if (libssh2_packet_ask_ex
-+ (session, packet_type, data, data_len, match_ofs, match_buf,
-+ match_len, 0) == 0) {
-+ /* A packet was available in the packet brigade */
-+ return 0;
-+ }
-+
-+ state->start = time(NULL);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "May block until packet of type %d becomes available",
-+ (int) packet_type);
-+ }
-+
-+ while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
-+ libssh2pack_t ret = libssh2_packet_read(session);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if ((ret == 0) && (!session->socket_block)) {
-+ /* If we are in non-blocking and there is no data, return that */
-+ return PACKET_EAGAIN;
-+ } else if (ret < 0) {
-+ state->start = 0;
-+ /* an error which is not just because of blocking */
-+ return ret;
-+ } else if (ret == packet_type) {
-+ /* Be lazy, let packet_ask pull it out of the brigade */
-+ ret =
-+ libssh2_packet_ask_ex(session, packet_type, data, data_len,
-+ match_ofs, match_buf, match_len, 0);
-+ state->start = 0;
-+ return ret;
-+ } else if (ret == 0) {
-+ /* nothing available, wait until data arrives or we time out */
-+ long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
-+
-+ if ((left <= 0) || (libssh2_waitsocket(session, left) <= 0)) {
-+ state->start = 0;
-+ return PACKET_TIMEOUT;
-+ }
-+ }
-+ }
-+
-+ /* Only reached if the socket died */
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_packet_burn
-+ * Loops libssh2_packet_read() until any packet is available and promptly
-+ * discards it
-+ * Used during KEX exchange to discard badly guessed KEX_INIT packets
-+ */
-+int
-+libssh2_packet_burn(LIBSSH2_SESSION * session,
-+ libssh2_nonblocking_states * state)
-+{
-+ unsigned char *data;
-+ unsigned long data_len;
-+ unsigned char all_packets[255];
-+ int i;
-+ int ret;
-+
-+ if (*state == libssh2_NB_state_idle) {
-+ for(i = 1; i < 256; i++) {
-+ all_packets[i - 1] = i;
-+ }
-+
-+ if (libssh2_packet_askv_ex
-+ (session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) {
-+ i = data[0];
-+ /* A packet was available in the packet brigade, burn it */
-+ LIBSSH2_FREE(session, data);
-+ return i;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Blocking until packet becomes available to burn");
-+ *state = libssh2_NB_state_created;
-+ }
-+
-+ while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
-+ if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (ret < 0) {
-+ *state = libssh2_NB_state_idle;
-+ return ret;
-+ } else if (ret == 0) {
-+ /* FIXME: this might busyloop */
-+ continue;
-+ }
-+
-+ /* Be lazy, let packet_ask pull it out of the brigade */
-+ if (0 ==
-+ libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0,
-+ 0)) {
-+ /* Smoke 'em if you got 'em */
-+ LIBSSH2_FREE(session, data);
-+ *state = libssh2_NB_state_idle;
-+ return ret;
-+ }
-+ }
-+
-+ /* Only reached if the socket died */
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/*
-+ * {{{ libssh2_packet_requirev
-+ *
-+ * Loops libssh2_packet_read() until one of a list of packet types requested is
-+ * available
-+ * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
-+ * packet_types is a null terminated list of packet_type numbers
-+ */
-+
-+int
-+libssh2_packet_requirev_ex(LIBSSH2_SESSION * session,
-+ const unsigned char *packet_types,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len,
-+ packet_requirev_state_t * state)
-+{
-+ if (libssh2_packet_askv_ex
-+ (session, packet_types, data, data_len, match_ofs, match_buf,
-+ match_len, 0) == 0) {
-+ /* One of the packets listed was available in the packet
-+ brigade */
-+ state->start = 0;
-+ return 0;
-+ }
-+
-+ if (state->start == 0) {
-+ state->start = time(NULL);
-+ }
-+
-+ while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
-+ int ret = libssh2_packet_read(session);
-+ if ((ret < 0) && (ret != PACKET_EAGAIN)) {
-+ state->start = 0;
-+ return ret;
-+ }
-+ if (ret <= 0) {
-+ long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);
-+
-+ if ((left <= 0) || (libssh2_waitsocket(session, left) <= 0)) {
-+ state->start = 0;
-+ return PACKET_TIMEOUT;
-+ } else if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+
-+ if (strchr((char *) packet_types, ret)) {
-+ /* Be lazy, let packet_ask pull it out of the brigade */
-+ return libssh2_packet_askv_ex(session, packet_types, data,
-+ data_len, match_ofs, match_buf,
-+ match_len, 0);
-+ }
-+ }
-+
-+ /* Only reached if the socket died */
-+ state->start = 0;
-+ return -1;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/packet.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/channel.c
-===================================================================
---- libssh2/src/channel.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/channel.c (.../trunk)
-@@ -0,0 +1,2260 @@
-+/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
-+ * Copyright (c) 2008 by Daniel Stenberg
-+ *
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms,
-+ * 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+#include <fcntl.h>
-+#ifdef HAVE_INTTYPES_H
-+#include <inttypes.h>
-+#endif
-+
-+
-+/* {{{ libssh2_channel_nextid
-+ * Determine the next channel ID we can use at our end
-+ */
-+unsigned long
-+libssh2_channel_nextid(LIBSSH2_SESSION * session)
-+{
-+ unsigned long id = session->next_channel;
-+ LIBSSH2_CHANNEL *channel;
-+
-+ channel = session->channels.head;
-+
-+ while (channel) {
-+ if (channel->local.id > id) {
-+ id = channel->local.id;
-+ }
-+ channel = channel->next;
-+ }
-+
-+ /* This is a shortcut to avoid waiting for close packets on channels we've
-+ * forgotten about, This *could* be a problem if we request and close 4
-+ * billion or so channels in too rapid succession for the remote end to
-+ * respond, but the worst case scenario is that some data meant for
-+ * another channel Gets picked up by the new one.... Pretty unlikely all
-+ * told...
-+ */
-+ session->next_channel = id + 1;
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN, "Allocated new channel ID#%lu",
-+ id);
-+ return id;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_locate
-+ * Locate a channel pointer by number
-+ */
-+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;
-+ }
-+ channel = channel->next;
-+ }
-+
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+#define CHANNEL_ADD(session, channel) \
-+{ \
-+ 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); \
-+ (channel)->session = (session); \
-+}
-+
-+/* {{{ libssh2_channel_open_ex
-+ * Establish a generic session channel
-+ */
-+LIBSSH2_API LIBSSH2_CHANNEL *
-+libssh2_channel_open_ex(LIBSSH2_SESSION * session, const char *channel_type,
-+ unsigned int channel_type_len,
-+ unsigned int window_size, unsigned int packet_size,
-+ const char *message, unsigned int message_len)
-+{
-+ static const unsigned char reply_codes[3] = {
-+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
-+ SSH_MSG_CHANNEL_OPEN_FAILURE,
-+ 0
-+ };
-+ unsigned char *s;
-+ int rc;
-+
-+ if (session->open_state == libssh2_NB_state_idle) {
-+ session->open_channel = NULL;
-+ session->open_packet = NULL;
-+ session->open_data = NULL;
-+ /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
-+ * window_size(4) + packet_size(4) */
-+ session->open_packet_len = channel_type_len + message_len + 17;
-+ session->open_local_channel = libssh2_channel_nextid(session);
-+
-+ /* Zero the whole thing out */
-+ memset(&session->open_packet_requirev_state, 0,
-+ sizeof(session->open_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Opening Channel - win %d pack %d", window_size,
-+ packet_size);
-+ session->open_channel =
-+ LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
-+ if (!session->open_channel) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate space for channel data", 0);
-+ return NULL;
-+ }
-+ memset(session->open_channel, 0, sizeof(LIBSSH2_CHANNEL));
-+
-+ session->open_channel->channel_type_len = channel_type_len;
-+ session->open_channel->channel_type =
-+ LIBSSH2_ALLOC(session, channel_type_len);
-+ if (!session->open_channel->channel_type) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Failed allocating memory for channel type name", 0);
-+ LIBSSH2_FREE(session, session->open_channel);
-+ session->open_channel = NULL;
-+ return NULL;
-+ }
-+ memcpy(session->open_channel->channel_type, channel_type,
-+ channel_type_len);
-+
-+ /* REMEMBER: local as in locally sourced */
-+ session->open_channel->local.id = session->open_local_channel;
-+ session->open_channel->remote.window_size = window_size;
-+ session->open_channel->remote.window_size_initial = window_size;
-+ session->open_channel->remote.packet_size = packet_size;
-+
-+ CHANNEL_ADD(session, session->open_channel);
-+
-+ s = session->open_packet =
-+ LIBSSH2_ALLOC(session, session->open_packet_len);
-+ if (!session->open_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate temporary space for packet", 0);
-+ goto channel_error;
-+ }
-+ *(s++) = SSH_MSG_CHANNEL_OPEN;
-+ libssh2_htonu32(s, channel_type_len);
-+ s += 4;
-+
-+ memcpy(s, channel_type, channel_type_len);
-+ s += channel_type_len;
-+
-+ libssh2_htonu32(s, session->open_local_channel);
-+ s += 4;
-+
-+ libssh2_htonu32(s, window_size);
-+ s += 4;
-+
-+ libssh2_htonu32(s, packet_size);
-+ s += 4;
-+
-+ if (message && message_len) {
-+ memcpy(s, message, message_len);
-+ s += message_len;
-+ }
-+
-+ session->open_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->open_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->open_packet,
-+ session->open_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending channel-open request", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel-open request", 0);
-+ goto channel_error;
-+ }
-+
-+ session->open_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->open_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes,
-+ &session->open_data,
-+ &session->open_data_len, 1,
-+ session->open_packet + 5 +
-+ channel_type_len, 4,
-+ &session->open_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block", 0);
-+ return NULL;
-+ } else if (rc) {
-+ goto channel_error;
-+ }
-+
-+ if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
-+ session->open_channel->remote.id =
-+ libssh2_ntohu32(session->open_data + 5);
-+ session->open_channel->local.window_size =
-+ libssh2_ntohu32(session->open_data + 9);
-+ session->open_channel->local.window_size_initial =
-+ libssh2_ntohu32(session->open_data + 9);
-+ session->open_channel->local.packet_size =
-+ libssh2_ntohu32(session->open_data + 13);
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Connection Established - ID: %lu/%lu win: %lu/%lu"
-+ " pack: %lu/%lu",
-+ session->open_channel->local.id,
-+ session->open_channel->remote.id,
-+ session->open_channel->local.window_size,
-+ session->open_channel->remote.window_size,
-+ session->open_channel->local.packet_size,
-+ session->open_channel->remote.packet_size);
-+ LIBSSH2_FREE(session, session->open_packet);
-+ session->open_packet = NULL;
-+ LIBSSH2_FREE(session, session->open_data);
-+ session->open_data = NULL;
-+
-+ session->open_state = libssh2_NB_state_idle;
-+ return session->open_channel;
-+ }
-+
-+ if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
-+ "Channel open failure", 0);
-+ }
-+ }
-+
-+ channel_error:
-+
-+ if (session->open_data) {
-+ LIBSSH2_FREE(session, session->open_data);
-+ session->open_data = NULL;
-+ }
-+ if (session->open_packet) {
-+ LIBSSH2_FREE(session, session->open_packet);
-+ session->open_packet = NULL;
-+ }
-+ if (session->open_channel) {
-+ unsigned char channel_id[4];
-+ LIBSSH2_FREE(session, session->open_channel->channel_type);
-+
-+ if (session->open_channel->next) {
-+ session->open_channel->next->prev = session->open_channel->prev;
-+ }
-+ if (session->open_channel->prev) {
-+ session->open_channel->prev->next = session->open_channel->next;
-+ }
-+ if (session->channels.head == session->open_channel) {
-+ session->channels.head = session->open_channel->next;
-+ }
-+ if (session->channels.tail == session->open_channel) {
-+ session->channels.tail = session->open_channel->prev;
-+ }
-+
-+ /* Clear out packets meant for this channel */
-+ libssh2_htonu32(channel_id, session->open_channel->local.id);
-+ while ((libssh2_packet_ask_ex
-+ (session, SSH_MSG_CHANNEL_DATA, &session->open_data,
-+ &session->open_data_len, 1, channel_id, 4, 0) >= 0)
-+ ||
-+ (libssh2_packet_ask_ex
-+ (session, SSH_MSG_CHANNEL_EXTENDED_DATA, &session->open_data,
-+ &session->open_data_len, 1, channel_id, 4, 0) >= 0)) {
-+ LIBSSH2_FREE(session, session->open_data);
-+ session->open_data = NULL;
-+ }
-+
-+ /* Free any state variables still holding data */
-+ if (session->open_channel->write_packet) {
-+ LIBSSH2_FREE(session, session->open_channel->write_packet);
-+ session->open_channel->write_packet = NULL;
-+ }
-+
-+ LIBSSH2_FREE(session, session->open_channel);
-+ session->open_channel = NULL;
-+ }
-+
-+ session->open_state = libssh2_NB_state_idle;
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_direct_tcpip_ex
-+ * Tunnel TCP/IP connect through the SSH session to direct host/port
-+ */
-+LIBSSH2_API LIBSSH2_CHANNEL *
-+libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION * session, const char *host,
-+ int port, const char *shost, int sport)
-+{
-+ LIBSSH2_CHANNEL *channel;
-+ unsigned char *s;
-+
-+ if (session->direct_state == libssh2_NB_state_idle) {
-+ session->direct_host_len = strlen(host);
-+ session->direct_shost_len = strlen(shost);
-+ /* host_len(4) + port(4) + shost_len(4) + sport(4) */
-+ session->direct_message_len =
-+ session->direct_host_len + session->direct_shost_len + 16;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Requesting direct-tcpip session to from %s:%d to %s:%d",
-+ shost, sport, host, port);
-+
-+ s = session->direct_message =
-+ LIBSSH2_ALLOC(session, session->direct_message_len);
-+ if (!session->direct_message) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for direct-tcpip connection",
-+ 0);
-+ return NULL;
-+ }
-+ libssh2_htonu32(s, session->direct_host_len);
-+ s += 4;
-+ memcpy(s, host, session->direct_host_len);
-+ s += session->direct_host_len;
-+ libssh2_htonu32(s, port);
-+ s += 4;
-+
-+ libssh2_htonu32(s, session->direct_shost_len);
-+ s += 4;
-+ memcpy(s, shost, session->direct_shost_len);
-+ s += session->direct_shost_len;
-+ libssh2_htonu32(s, sport);
-+ s += 4;
-+
-+ session->direct_state = libssh2_NB_state_created;
-+ }
-+
-+ channel =
-+ libssh2_channel_open_ex(session, "direct-tcpip",
-+ sizeof("direct-tcpip") - 1,
-+ LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-+ LIBSSH2_CHANNEL_PACKET_DEFAULT,
-+ (char *) session->direct_message,
-+ session->direct_message_len);
-+ if (!channel) {
-+ if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
-+ /* The error code is still set to LIBSSH2_ERROR_EAGAIN */
-+ return NULL;
-+ } else {
-+ LIBSSH2_FREE(session, session->direct_message);
-+ session->direct_message = NULL;
-+ return NULL;
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, session->direct_message);
-+ session->direct_message = NULL;
-+
-+ 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, const char *host,
-+ int port, int *bound_port, int queue_maxsize)
-+{
-+ unsigned char *s, *data;
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
-+ unsigned long data_len;
-+ int rc;
-+
-+ if (session->fwdLstn_state == libssh2_NB_state_idle) {
-+ session->fwdLstn_host_len =
-+ (host ? strlen(host) : (sizeof("0.0.0.0") - 1));
-+ /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
-+ + port(4) */
-+ session->fwdLstn_packet_len =
-+ session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14;
-+
-+ /* Zero the whole thing out */
-+ memset(&session->fwdLstn_packet_requirev_state, 0,
-+ sizeof(session->fwdLstn_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Requesting tcpip-forward session for %s:%d", host,
-+ port);
-+
-+ s = session->fwdLstn_packet =
-+ LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
-+ if (!session->fwdLstn_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++) = 0x01; /* want_reply */
-+
-+ libssh2_htonu32(s, session->fwdLstn_host_len);
-+ s += 4;
-+ memcpy(s, host ? host : "0.0.0.0", session->fwdLstn_host_len);
-+ s += session->fwdLstn_host_len;
-+ libssh2_htonu32(s, port);
-+ s += 4;
-+
-+ session->fwdLstn_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->fwdLstn_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, session->fwdLstn_packet,
-+ session->fwdLstn_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending global-request packet for "
-+ "forward listen request",
-+ 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send global-request packet for forward "
-+ "listen request",
-+ 0);
-+ LIBSSH2_FREE(session, session->fwdLstn_packet);
-+ session->fwdLstn_packet = NULL;
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ LIBSSH2_FREE(session, session->fwdLstn_packet);
-+ session->fwdLstn_packet = NULL;
-+
-+ session->fwdLstn_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->fwdLstn_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len,
-+ 0, NULL, 0,
-+ &session->
-+ fwdLstn_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown", 0);
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+
-+ if (data[0] == SSH_MSG_REQUEST_SUCCESS) {
-+ 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);
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ memset(listener, 0, sizeof(LIBSSH2_LISTENER));
-+ listener->session = session;
-+ listener->host =
-+ LIBSSH2_ALLOC(session, session->fwdLstn_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);
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ memcpy(listener->host, host ? host : "0.0.0.0",
-+ session->fwdLstn_host_len);
-+ listener->host[session->fwdLstn_host_len] = 0;
-+ if (data_len >= 5 && !port) {
-+ listener->port = libssh2_ntohu32(data + 1);
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Dynamic tcpip-forward port allocated: %d",
-+ listener->port);
-+ } 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);
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return listener;
-+ }
-+
-+ if (data[0] == SSH_MSG_REQUEST_FAILURE) {
-+ LIBSSH2_FREE(session, data);
-+ libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
-+ "Unable to complete request for forward-listen", 0);
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ }
-+
-+ session->fwdLstn_state = libssh2_NB_state_idle;
-+
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_forward_cancel
-+ * Stop listening on a remote port and free the listener
-+ * Toss out any pending (un-accept()ed) connections
-+ *
-+ * Return 0 on success, PACKET_EAGAIN if would block, -1 on error
-+ */
-+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);
-+ /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
-+ port(4) */
-+ unsigned long packet_len =
-+ host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
-+ int rc;
-+
-+ if (listener->chanFwdCncl_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Cancelling tcpip-forward session for %s:%d",
-+ listener->host, listener->port);
-+
-+ 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;
-+
-+ listener->chanFwdCncl_state = libssh2_NB_state_created;
-+ } else {
-+ packet = listener->chanFwdCncl_data;
-+ }
-+
-+ if (listener->chanFwdCncl_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, packet, packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ listener->chanFwdCncl_data = packet;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send global-request packet for forward "
-+ "listen request",
-+ 0);
-+ LIBSSH2_FREE(session, packet);
-+ listener->chanFwdCncl_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, packet);
-+
-+ listener->chanFwdCncl_state = libssh2_NB_state_sent;
-+ }
-+
-+ while (queued) {
-+ LIBSSH2_CHANNEL *next = queued->next;
-+
-+ rc = libssh2_channel_free(queued);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ 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);
-+
-+ listener->chanFwdCncl_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_forward_accept
-+ * Accept a connection
-+ */
-+LIBSSH2_API LIBSSH2_CHANNEL *
-+libssh2_channel_forward_accept(LIBSSH2_LISTENER * listener)
-+{
-+ libssh2pack_t rc;
-+
-+ do {
-+ rc = libssh2_packet_read(listener->session);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for packet", 0);
-+ return NULL;
-+ }
-+ } while (rc > 0);
-+
-+ if (listener->queue) {
-+ LIBSSH2_SESSION *session = listener->session;
-+ LIBSSH2_CHANNEL *channel;
-+
-+ channel = listener->queue;
-+
-+ listener->queue = listener->queue->next;
-+ if (listener->queue) {
-+ listener->queue->prev = NULL;
-+ }
-+
-+ channel->prev = NULL;
-+ channel->next = session->channels.head;
-+ session->channels.head = channel;
-+
-+ if (channel->next) {
-+ channel->next->prev = channel;
-+ } else {
-+ session->channels.tail = channel;
-+ }
-+ listener->queue_size--;
-+
-+ return channel;
-+ }
-+
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_setenv_ex
-+ * Set an environment variable prior to requesting a shell/program/subsystem
-+ */
-+LIBSSH2_API int
-+libssh2_channel_setenv_ex(LIBSSH2_CHANNEL * channel, const char *varname,
-+ unsigned int varname_len, const char *value,
-+ unsigned int value_len)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char *s, *data;
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
-+ unsigned long data_len;
-+ int rc;
-+
-+ if (channel->setenv_state == libssh2_NB_state_idle) {
-+ /* 21 = packet_type(1) + channel_id(4) + request_len(4) +
-+ * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
-+ channel->setenv_packet_len = varname_len + value_len + 21;
-+
-+ /* Zero the whole thing out */
-+ memset(&channel->setenv_packet_requirev_state, 0,
-+ sizeof(channel->setenv_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Setting remote environment variable: %s=%s on "
-+ "channel %lu/%lu",
-+ varname, value, channel->local.id, channel->remote.id);
-+
-+ s = channel->setenv_packet =
-+ LIBSSH2_ALLOC(session, channel->setenv_packet_len);
-+ if (!channel->setenv_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memeory for setenv packet", 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_CHANNEL_REQUEST;
-+ libssh2_htonu32(s, channel->remote.id);
-+ s += 4;
-+ libssh2_htonu32(s, sizeof("env") - 1);
-+ s += 4;
-+ memcpy(s, "env", sizeof("env") - 1);
-+ s += sizeof("env") - 1;
-+
-+ *(s++) = 0x01;
-+
-+ libssh2_htonu32(s, varname_len);
-+ s += 4;
-+ memcpy(s, varname, varname_len);
-+ s += varname_len;
-+
-+ libssh2_htonu32(s, value_len);
-+ s += 4;
-+ memcpy(s, value, value_len);
-+ s += value_len;
-+
-+ channel->setenv_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->setenv_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->setenv_packet,
-+ channel->setenv_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel-request packet for "
-+ "setenv request",
-+ 0);
-+ LIBSSH2_FREE(session, channel->setenv_packet);
-+ channel->setenv_packet = NULL;
-+ channel->setenv_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, channel->setenv_packet);
-+ channel->setenv_packet = NULL;
-+
-+ libssh2_htonu32(channel->setenv_local_channel, channel->local.id);
-+
-+ channel->setenv_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (channel->setenv_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len,
-+ 1, channel->setenv_local_channel, 4,
-+ &channel->
-+ setenv_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (rc) {
-+ channel->setenv_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
-+ LIBSSH2_FREE(session, data);
-+ channel->setenv_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ }
-+
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
-+ "Unable to complete request for channel-setenv", 0);
-+ channel->setenv_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_request_pty_ex
-+ * Duh... Request a PTY
-+ */
-+LIBSSH2_API int
-+libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL * channel, const char *term,
-+ unsigned int term_len, const char *modes,
-+ unsigned int modes_len, int width, int height,
-+ int width_px, int height_px)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char *s, *data;
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
-+ unsigned long data_len;
-+ int rc;
-+
-+ if (channel->reqPTY_state == libssh2_NB_state_idle) {
-+ /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
-+ * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
-+ * height_px(4) + modes_len(4) */
-+ channel->reqPTY_packet_len = term_len + modes_len + 41;
-+
-+ /* Zero the whole thing out */
-+ memset(&channel->reqPTY_packet_requirev_state, 0,
-+ sizeof(channel->reqPTY_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Allocating tty on channel %lu/%lu", channel->local.id,
-+ channel->remote.id);
-+
-+ s = channel->reqPTY_packet =
-+ LIBSSH2_ALLOC(session, channel->reqPTY_packet_len);
-+ if (!channel->reqPTY_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for pty-request", 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_CHANNEL_REQUEST;
-+ libssh2_htonu32(s, channel->remote.id);
-+ s += 4;
-+ libssh2_htonu32(s, sizeof("pty-req") - 1);
-+ s += 4;
-+ memcpy(s, "pty-req", sizeof("pty-req") - 1);
-+ s += sizeof("pty-req") - 1;
-+
-+ *(s++) = 0x01;
-+
-+ libssh2_htonu32(s, term_len);
-+ s += 4;
-+ if (term) {
-+ memcpy(s, term, term_len);
-+ s += term_len;
-+ }
-+
-+ libssh2_htonu32(s, width);
-+ s += 4;
-+ libssh2_htonu32(s, height);
-+ s += 4;
-+ libssh2_htonu32(s, width_px);
-+ s += 4;
-+ libssh2_htonu32(s, height_px);
-+ s += 4;
-+
-+ libssh2_htonu32(s, modes_len);
-+ s += 4;
-+ if (modes) {
-+ memcpy(s, modes, modes_len);
-+ s += modes_len;
-+ }
-+
-+ channel->reqPTY_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->reqPTY_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->reqPTY_packet,
-+ channel->reqPTY_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send pty-request packet", 0);
-+ LIBSSH2_FREE(session, channel->reqPTY_packet);
-+ channel->reqPTY_packet = NULL;
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, channel->reqPTY_packet);
-+ channel->reqPTY_packet = NULL;
-+
-+ libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
-+
-+ channel->reqPTY_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (channel->reqPTY_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len,
-+ 1, channel->reqPTY_local_channel, 4,
-+ &channel->
-+ reqPTY_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
-+ LIBSSH2_FREE(session, data);
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
-+ "Unable to complete request for channel request-pty", 0);
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+LIBSSH2_API int
-+libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel, int width,
-+ int height, int width_px, int height_px)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char *s;
-+ int rc;
-+
-+ if (channel->reqPTY_state == libssh2_NB_state_idle) {
-+ channel->reqPTY_packet_len = 39;
-+
-+ /* Zero the whole thing out */
-+ memset(&channel->reqPTY_packet_requirev_state, 0,
-+ sizeof(channel->reqPTY_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "changing tty size on channel %lu/%lu",
-+ channel->local.id,
-+ channel->remote.id);
-+
-+ s = channel->reqPTY_packet =
-+ LIBSSH2_ALLOC(session, channel->reqPTY_packet_len);
-+
-+ if (!channel->reqPTY_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for pty-request", 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_CHANNEL_REQUEST;
-+ libssh2_htonu32(s, channel->remote.id);
-+ s += 4;
-+ libssh2_htonu32(s, sizeof("window-change") - 1);
-+ s += 4;
-+ memcpy(s, "window-change", sizeof("window-change") - 1);
-+ s += sizeof("window-change") - 1;
-+
-+ *(s++) = 0x00; /* Don't reply */
-+ libssh2_htonu32(s, width);
-+ s += 4;
-+ libssh2_htonu32(s, height);
-+ s += 4;
-+ libssh2_htonu32(s, width_px);
-+ s += 4;
-+ libssh2_htonu32(s, height_px);
-+ s += 4;
-+
-+ channel->reqPTY_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->reqPTY_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->reqPTY_packet,
-+ channel->reqPTY_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send window-change packet", 0);
-+ LIBSSH2_FREE(session, channel->reqPTY_packet);
-+ channel->reqPTY_packet = NULL;
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, channel->reqPTY_packet);
-+ channel->reqPTY_packet = NULL;
-+ libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
-+ channel->reqPTY_state = libssh2_NB_state_sent;
-+
-+ return 0;
-+ }
-+
-+ channel->reqPTY_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* Keep this an even number */
-+#define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
-+
-+/* {{{ libssh2_channel_x11_req_ex
-+ * Request X11 forwarding
-+ */
-+LIBSSH2_API int
-+libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL * channel, int single_connection,
-+ const char *auth_proto, const char *auth_cookie,
-+ int screen_number)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char *s, *data;
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
-+ unsigned long data_len;
-+ 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;
-+ int rc;
-+
-+ if (channel->reqX11_state == libssh2_NB_state_idle) {
-+ /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
-+ * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
-+ * screen_num(4) */
-+ channel->reqX11_packet_len = proto_len + cookie_len + 30;
-+
-+ /* Zero the whole thing out */
-+ memset(&channel->reqX11_packet_requirev_state, 0,
-+ sizeof(channel->reqX11_packet_requirev_state));
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Requesting x11-req for channel %lu/%lu: single=%d "
-+ "proto=%s cookie=%s screen=%d",
-+ channel->local.id, channel->remote.id,
-+ single_connection,
-+ auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
-+ auth_cookie ? auth_cookie : "<random>", screen_number);
-+
-+ s = channel->reqX11_packet =
-+ LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
-+ if (!channel->reqX11_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++) = 0x01; /* want_reply */
-+ *(s++) = single_connection ? 0x01 : 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);
-+ s += 4;
-+ if (auth_cookie) {
-+ memcpy(s, auth_cookie, cookie_len);
-+ } else {
-+ int i;
-+ unsigned char buffer[LIBSSH2_X11_RANDOM_COOKIE_LEN / 2];
-+
-+ libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
-+ for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
-+ snprintf((char *) s + (i * 2), 2, "%02X", buffer[i]);
-+ }
-+ }
-+ s += cookie_len;
-+
-+ libssh2_htonu32(s, screen_number);
-+ s += 4;
-+
-+ channel->reqX11_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->reqX11_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->reqX11_packet,
-+ channel->reqX11_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send x11-req packet", 0);
-+ LIBSSH2_FREE(session, channel->reqX11_packet);
-+ channel->reqX11_packet = NULL;
-+ channel->reqX11_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, channel->reqX11_packet);
-+ channel->reqX11_packet = NULL;
-+
-+ libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
-+
-+ channel->reqX11_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (channel->reqX11_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len,
-+ 1, channel->reqX11_local_channel, 4,
-+ &channel->
-+ reqX11_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ channel->reqX11_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
-+ LIBSSH2_FREE(session, data);
-+ channel->reqX11_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
-+ "Unable to complete request for channel x11-req", 0);
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_process_startup
-+ * Primitive for libssh2_channel_(shell|exec|subsystem)
-+ */
-+LIBSSH2_API int
-+libssh2_channel_process_startup(LIBSSH2_CHANNEL * channel, const char *request,
-+ unsigned int request_len, const char *message,
-+ unsigned int message_len)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char *s, *data;
-+ static const unsigned char reply_codes[3] =
-+ { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
-+ unsigned long data_len;
-+ libssh2pack_t rc;
-+
-+ if (channel->process_state == libssh2_NB_state_idle) {
-+ /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
-+ channel->process_packet_len = request_len + 10;
-+
-+ /* Zero the whole thing out */
-+ memset(&channel->process_packet_requirev_state, 0,
-+ sizeof(channel->process_packet_requirev_state));
-+
-+ if (message) {
-+ channel->process_packet_len += message_len + 4;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "starting request(%s) on channel %lu/%lu, message=%s",
-+ request, channel->local.id, channel->remote.id,
-+ message);
-+ s = channel->process_packet =
-+ LIBSSH2_ALLOC(session, channel->process_packet_len);
-+ if (!channel->process_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for channel-process request",
-+ 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_CHANNEL_REQUEST;
-+ libssh2_htonu32(s, channel->remote.id);
-+ s += 4;
-+ libssh2_htonu32(s, request_len);
-+ s += 4;
-+ memcpy(s, request, request_len);
-+ s += request_len;
-+
-+ *(s++) = 0x01;
-+
-+ if (message) {
-+ libssh2_htonu32(s, message_len);
-+ s += 4;
-+ memcpy(s, message, message_len);
-+ s += message_len;
-+ }
-+
-+ channel->process_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->process_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->process_packet,
-+ channel->process_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel request", 0);
-+ LIBSSH2_FREE(session, channel->process_packet);
-+ channel->process_packet = NULL;
-+ channel->process_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, channel->process_packet);
-+ channel->process_packet = NULL;
-+
-+ libssh2_htonu32(channel->process_local_channel, channel->local.id);
-+
-+ channel->process_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (channel->process_state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len,
-+ 1, channel->process_local_channel, 4,
-+ &channel->
-+ process_packet_requirev_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ channel->process_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
-+ LIBSSH2_FREE(session, data);
-+ channel->process_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, data);
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
-+ "Unable to complete request for channel-process-startup", 0);
-+ channel->process_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_set_blocking
-+ * Set a channel's blocking mode on or off, similar to a socket's
-+ * fcntl(fd, F_SETFL, O_NONBLOCK); type command
-+ */
-+LIBSSH2_API void
-+libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
-+{
-+ (void) _libssh2_session_set_blocking(channel->session, blocking);
-+}
-+
-+/* }}} */
-+
-+/* {{{ 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;
-+
-+ if (channel->flush_state == libssh2_NB_state_idle) {
-+ channel->flush_refund_bytes = 0;
-+ channel->flush_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 */
-+ long packet_stream_id =
-+ (packet_type ==
-+ SSH_MSG_CHANNEL_DATA) ? 0 : libssh2_ntohu32(packet->data +
-+ 5);
-+ if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
-+ || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
-+ && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
-+ || (streamid == packet_stream_id)))
-+ || ((packet_type == SSH_MSG_CHANNEL_DATA)
-+ && (streamid == 0))) {
-+ int bytes_to_flush = packet->data_len - packet->data_head;
-+
-+ _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
-+ "Flushing %d bytes of data from stream "
-+ "%lu on channel %lu/%lu",
-+ bytes_to_flush, packet_stream_id,
-+ channel->local.id, channel->remote.id);
-+
-+ /* It's one of the streams we wanted to flush */
-+ channel->flush_refund_bytes += packet->data_len - 13;
-+ channel->flush_flush_bytes += bytes_to_flush;
-+
-+ 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;
-+ }
-+
-+ channel->flush_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->flush_refund_bytes) {
-+ int rc;
-+
-+ rc = libssh2_channel_receive_window_adjust(channel,
-+ channel->flush_refund_bytes,
-+ 0);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+
-+ channel->flush_state = libssh2_NB_state_idle;
-+
-+ return channel->flush_flush_bytes;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_get_exit_status
-+ * Return the channel's program exit status
-+ */
-+LIBSSH2_API int
-+libssh2_channel_get_exit_status(LIBSSH2_CHANNEL * channel)
-+{
-+ return channel->exit_status;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_receive_window_adjust
-+ * Adjust the receive window for a channel by adjustment bytes
-+ * If the amount to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and
-+ * force is 0 the adjustment amount will be queued for a later packet
-+ *
-+ * Returns the new size of the receive window (as understood by remote end)
-+ */
-+LIBSSH2_API unsigned long
-+libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
-+ unsigned long adjustment,
-+ unsigned char force)
-+{
-+ int rc;
-+
-+ if (channel->adjust_state == libssh2_NB_state_idle) {
-+ if (!force
-+ && (adjustment + channel->adjust_queue <
-+ LIBSSH2_CHANNEL_MINADJUST)) {
-+ _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
-+ "Queueing %lu bytes for receive window adjustment "
-+ "for channel %lu/%lu",
-+ adjustment, channel->local.id, channel->remote.id);
-+ channel->adjust_queue += adjustment;
-+ return channel->remote.window_size;
-+ }
-+
-+ if (!adjustment && !channel->adjust_queue) {
-+ return channel->remote.window_size;
-+ }
-+
-+ adjustment += channel->adjust_queue;
-+ channel->adjust_queue = 0;
-+
-+
-+ /* Adjust the window based on the block we just freed */
-+ channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
-+ libssh2_htonu32(channel->adjust_adjust + 1, channel->remote.id);
-+ libssh2_htonu32(channel->adjust_adjust + 5, adjustment);
-+ _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
-+ "Adjusting window %lu bytes for data flushed from "
-+ "channel %lu/%lu",
-+ adjustment, channel->local.id, channel->remote.id);
-+
-+ channel->adjust_state = libssh2_NB_state_created;
-+ }
-+
-+ rc = libssh2_packet_write(channel->session, channel->adjust_adjust, 9);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send transfer-window adjustment packet, "
-+ "deferring",
-+ 0);
-+ channel->adjust_queue = adjustment;
-+ channel->adjust_state = libssh2_NB_state_idle;
-+ } else {
-+ channel->adjust_state = libssh2_NB_state_idle;
-+ channel->remote.window_size += adjustment;
-+ }
-+
-+ return channel->remote.window_size;
-+}
-+
-+/* }}} */
-+
-+/* {{{ 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)
-+{
-+ while (libssh2_channel_handle_extended_data2(channel, ignore_mode) ==
-+ PACKET_EAGAIN);
-+}
-+
-+LIBSSH2_API int
-+libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL * channel,
-+ int ignore_mode)
-+{
-+ if (channel->extData2_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(channel->session, LIBSSH2_DBG_CONN,
-+ "Setting channel %lu/%lu handle_extended_data mode to %d",
-+ channel->local.id, channel->remote.id, ignore_mode);
-+ channel->remote.extended_data_ignore_mode = ignore_mode;
-+
-+ channel->extData2_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->extData2_state == libssh2_NB_state_idle) {
-+ if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
-+ if (libssh2_channel_flush_ex
-+ (channel,
-+ LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+ }
-+
-+ channel->extData2_state = libssh2_NB_state_idle;
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/*
-+ * {{{ libssh2_channel_read_ex
-+ * Read data from a channel blocking or non-blocking depending on set state
-+ *
-+ * When this is done non-blocking, it is important to not return 0 until the
-+ * currently read channel is complete. If we read stuff from the wire but it
-+ * was no payload data to fill in the buffer with, we MUST make sure to return
-+ * PACKET_EAGAIN.
-+ */
-+LIBSSH2_API ssize_t
-+libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel, int stream_id, char *buf,
-+ size_t buflen)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ libssh2pack_t rc = 0;
-+
-+ if (channel->read_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Attempting to read %d bytes from channel %lu/%lu stream #%d",
-+ (int) buflen, channel->local.id, channel->remote.id,
-+ stream_id);
-+
-+ /* process all incoming packets */
-+ do {
-+ if (libssh2_waitsocket(session, 0) > 0) {
-+ rc = libssh2_packet_read(session);
-+ } else {
-+ /* Set for PACKET_EAGAIN so we continue */
-+ rc = PACKET_EAGAIN;
-+ }
-+ } while (rc > 0);
-+
-+ if ((rc < 0) && (rc != PACKET_EAGAIN)) {
-+ return rc;
-+ }
-+ channel->read_bytes_read = 0;
-+
-+ channel->read_packet = session->packets.head;
-+ channel->read_state = libssh2_NB_state_created;
-+ }
-+
-+ /*
-+ * =============================== NOTE ===============================
-+ * I know this is very ugly and not a really good use of "goto", but
-+ * this case statement would be even uglier to do it any other way
-+ */
-+ if (channel->read_state == libssh2_NB_state_jump1) {
-+ goto channel_read_ex_point1;
-+ }
-+
-+ rc = 0;
-+ channel->read_block = 0;
-+
-+ do {
-+ if (channel->read_block) {
-+ /* in the second lap and onwards, do this...
-+ * If we haven't yet filled our buffer, try to read more
-+ * data. */
-+ if ( channel->read_bytes_read < (int) buflen) {
-+ rc = libssh2_packet_read(session);
-+
-+ /* If we didn't find any more data to read */
-+ if (rc < 0) {
-+ if ( channel->read_bytes_read > 0){
-+ break; /* finish processing and return */
-+ }
-+
-+ /* no packets available, no data read. */
-+ channel->read_state = libssh2_NB_state_idle;
-+ return rc;
-+ }
-+ /* We read more data, restart our processing at the beginning
-+ * of our packet list. */
-+ channel->read_packet = session->packets.head;
-+ }
-+ else { /* The read buffer is full, finish processing and return */
-+ break;
-+ }
-+ }
-+
-+ while (channel->read_packet
-+ && (channel->read_bytes_read < (int) buflen)) {
-+ /* In case packet gets destroyed during this iteration */
-+ channel->read_next = channel->read_packet->next;
-+
-+ channel->read_local_id =
-+ libssh2_ntohu32(channel->read_packet->data + 1);
-+
-+ /*
-+ * 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
-+ && (channel->read_packet->data[0] ==
-+ SSH_MSG_CHANNEL_EXTENDED_DATA)
-+ && (channel->local.id == channel->read_local_id)
-+ && (stream_id ==
-+ (int) libssh2_ntohu32(channel->read_packet->data + 5)))
-+ || (!stream_id
-+ && (channel->read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
-+ && (channel->local.id == channel->read_local_id))
-+ || (!stream_id
-+ && (channel->read_packet->data[0] ==
-+ SSH_MSG_CHANNEL_EXTENDED_DATA)
-+ && (channel->local.id == channel->read_local_id)
-+ && (channel->remote.extended_data_ignore_mode ==
-+ LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
-+
-+ channel->read_want = buflen - channel->read_bytes_read;
-+ channel->read_unlink_packet = 0;
-+
-+ if (channel->read_want >=
-+ (int) (channel->read_packet->data_len -
-+ channel->read_packet->data_head)) {
-+ channel->read_want =
-+ channel->read_packet->data_len -
-+ channel->read_packet->data_head;
-+ channel->read_unlink_packet = 1;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Reading %d of buffered data from %lu/%lu/%d",
-+ channel->read_want, channel->local.id,
-+ channel->remote.id, stream_id);
-+ memcpy(buf + channel->read_bytes_read,
-+ channel->read_packet->data +
-+ channel->read_packet->data_head, channel->read_want);
-+ channel->read_packet->data_head += channel->read_want;
-+ channel->read_bytes_read += channel->read_want;
-+
-+ if (channel->read_unlink_packet) {
-+ if (channel->read_packet->prev) {
-+ channel->read_packet->prev->next =
-+ channel->read_packet->next;
-+ } else {
-+ session->packets.head = channel->read_packet->next;
-+ }
-+ if (channel->read_packet->next) {
-+ channel->read_packet->next->prev =
-+ channel->read_packet->prev;
-+ } else {
-+ session->packets.tail = channel->read_packet->prev;
-+ }
-+ LIBSSH2_FREE(session, channel->read_packet->data);
-+
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Unlinking empty packet buffer from "
-+ "channel %lu/%lu",
-+ channel->local.id, channel->remote.id);
-+ channel_read_ex_point1:
-+ channel->read_state = libssh2_NB_state_jump1;
-+ rc = libssh2_channel_receive_window_adjust(channel,
-+ channel->
-+ read_packet->
-+ data_len -
-+ (stream_id ? 13
-+ : 9), 0);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ channel->read_state = libssh2_NB_state_created;
-+ LIBSSH2_FREE(session, channel->read_packet);
-+ channel->read_packet = NULL;
-+ }
-+ }
-+ channel->read_packet = channel->read_next;
-+ }
-+ channel->read_block = 1;
-+ } while ((channel->read_bytes_read == 0) && !channel->remote.close);
-+
-+ channel->read_state = libssh2_NB_state_idle;
-+ if (channel->read_bytes_read == 0) {
-+ if (channel->session->socket_block) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
-+ "Remote end has closed this channel", 0);
-+ } else {
-+ /*
-+ * when non-blocking, we must return PACKET_EAGAIN if we haven't
-+ * completed reading the channel
-+ */
-+ if (!libssh2_channel_eof(channel)) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+ }
-+
-+ channel->read_state = libssh2_NB_state_idle;
-+ return channel->read_bytes_read;
-+}
-+
-+/* }}} */
-+
-+/*
-+ * {{{ libssh2_channel_packet_data_len
-+ * Return the size of the data block of the current packet, or 0 if there
-+ * isn't a packet.
-+ */
-+unsigned long
-+libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_PACKET *read_packet;
-+ uint32_t read_local_id;
-+
-+ if ((read_packet = session->packets.head) == NULL) {
-+ return 0;
-+ }
-+
-+ while (read_packet) {
-+ read_local_id = libssh2_ntohu32(read_packet->data + 1);
-+
-+ /*
-+ * 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
-+ && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
-+ && (channel->local.id == read_local_id)
-+ && (stream_id == (int) libssh2_ntohu32(read_packet->data + 5)))
-+ || (!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
-+ && (channel->local.id == read_local_id)) ||
-+ (!stream_id
-+ && (read_packet->
-+ data[0] ==
-+ SSH_MSG_CHANNEL_EXTENDED_DATA)
-+ && (channel->
-+ local.id ==
-+ read_local_id)
-+ && (channel->
-+ remote.
-+ extended_data_ignore_mode
-+ ==
-+ LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE)))
-+ {
-+ return (read_packet->data_len - read_packet->data_head);
-+ }
-+ read_packet = read_packet->next;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_write_ex
-+ * Send data to a channel
-+ */
-+LIBSSH2_API ssize_t
-+libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel, int stream_id,
-+ const char *buf, size_t buflen)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ libssh2pack_t rc;
-+
-+ if (channel->write_state == libssh2_NB_state_idle) {
-+ channel->write_bufwrote = 0;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Writing %d bytes on channel %lu/%lu, stream #%d",
-+ (int) buflen, channel->local.id, channel->remote.id,
-+ stream_id);
-+
-+ if (channel->local.close) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED,
-+ "We've already closed this channel", 0);
-+ return -1;
-+ }
-+
-+ if (channel->local.eof) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_EOF_SENT,
-+ "EOF has already been sight, data might be ignored",
-+ 0);
-+ }
-+
-+ /* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] +
-+ buflen(4) */
-+ channel->write_packet_len = buflen + (stream_id ? 13 : 9);
-+ channel->write_packet =
-+ LIBSSH2_ALLOC(session, channel->write_packet_len);
-+ if (!channel->write_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocte space for data transmission packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ channel->write_state = libssh2_NB_state_allocated;
-+ }
-+
-+ while (buflen > 0) {
-+ if (channel->write_state == libssh2_NB_state_allocated) {
-+ channel->write_bufwrite = buflen;
-+ channel->write_s = channel->write_packet;
-+
-+ *(channel->write_s++) =
-+ stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
-+ SSH_MSG_CHANNEL_DATA;
-+ libssh2_htonu32(channel->write_s, channel->remote.id);
-+ channel->write_s += 4;
-+ if (stream_id) {
-+ libssh2_htonu32(channel->write_s, stream_id);
-+ channel->write_s += 4;
-+ }
-+
-+ /* twiddle our thumbs until there's window space available */
-+ while (channel->local.window_size <= 0) {
-+ /* Don't worry -- This is never hit unless it's a
-+ blocking channel anyway */
-+ rc = libssh2_packet_read(session);
-+
-+ if (rc < 0) {
-+ /* Error or EAGAIN occurred, disconnect? */
-+ if (rc != PACKET_EAGAIN) {
-+ channel->write_state = libssh2_NB_state_idle;
-+ }
-+ return rc;
-+ }
-+
-+ if ((rc == 0) && (session->socket_block == 0)) {
-+ /*
-+ * if rc == 0 and in non-blocking, then fake EAGAIN
-+ * to prevent busyloops until data arriaves on the network
-+ * which seemed like a very bad idea
-+ */
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+
-+ /* Don't exceed the remote end's limits */
-+ /* REMEMBER local means local as the SOURCE of the data */
-+ if (channel->write_bufwrite > channel->local.window_size) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Splitting write block due to %lu byte "
-+ "window_size on %lu/%lu/%d",
-+ channel->local.window_size, channel->local.id,
-+ channel->remote.id, stream_id);
-+ channel->write_bufwrite = channel->local.window_size;
-+ }
-+ if (channel->write_bufwrite > channel->local.packet_size) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Splitting write block due to %lu byte "
-+ "packet_size on %lu/%lu/%d",
-+ channel->local.packet_size, channel->local.id,
-+ channel->remote.id, stream_id);
-+ channel->write_bufwrite = channel->local.packet_size;
-+ }
-+ libssh2_htonu32(channel->write_s, channel->write_bufwrite);
-+ channel->write_s += 4;
-+ memcpy(channel->write_s, buf, channel->write_bufwrite);
-+ channel->write_s += channel->write_bufwrite;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Sending %d bytes on channel %lu/%lu, stream_id=%d",
-+ (int) channel->write_bufwrite, channel->local.id,
-+ channel->remote.id, stream_id);
-+
-+ channel->write_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->write_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, channel->write_packet,
-+ channel->write_s -
-+ channel->write_packet);
-+ if (rc == PACKET_EAGAIN) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "libssh2_packet_write returned EAGAIN");
-+ return PACKET_EAGAIN;
-+ }
-+ else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send channel data", 0);
-+ LIBSSH2_FREE(session, channel->write_packet);
-+ channel->write_packet = NULL;
-+ channel->write_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ /* Shrink local window size */
-+ channel->local.window_size -= channel->write_bufwrite;
-+
-+ /* Adjust buf for next iteration */
-+ buflen -= channel->write_bufwrite;
-+ buf += channel->write_bufwrite;
-+ channel->write_bufwrote += channel->write_bufwrite;
-+
-+ channel->write_state = libssh2_NB_state_allocated;
-+
-+ /*
-+ * Not sure this is still wanted
-+ if (!channel->session->socket_block) {
-+ break;
-+ }
-+ */
-+ }
-+ }
-+
-+ LIBSSH2_FREE(session, channel->write_packet);
-+ channel->write_packet = NULL;
-+
-+ channel->write_state = libssh2_NB_state_idle;
-+
-+ return channel->write_bufwrote;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_send_eof
-+ * Send EOF on channel
-+ */
-+LIBSSH2_API int
-+libssh2_channel_send_eof(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char packet[5]; /* packet_type(1) + channelno(4) */
-+ int rc;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN, "Sending EOF on channel %lu/%lu",
-+ channel->local.id, channel->remote.id);
-+ packet[0] = SSH_MSG_CHANNEL_EOF;
-+ libssh2_htonu32(packet + 1, channel->remote.id);
-+ rc = libssh2_packet_write(session, packet, 5);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send EOF on channel", 0);
-+ return -1;
-+ }
-+ channel->local.eof = 1;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_eof
-+ * Read channel's eof status
-+ */
-+LIBSSH2_API int
-+libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_PACKET *packet = session->packets.head;
-+
-+ while (packet) {
-+ if (((packet->data[0] == SSH_MSG_CHANNEL_DATA)
-+ || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
-+ && (channel->local.id == libssh2_ntohu32(packet->data + 1))) {
-+ /* There's data waiting to be read yet, mask the EOF status */
-+ return 0;
-+ }
-+ packet = packet->next;
-+ }
-+
-+ return channel->remote.eof;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_wait_eof
-+* Awaiting channel EOF
-+*/
-+LIBSSH2_API int
-+libssh2_channel_wait_eof(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ int rc;
-+
-+ if (channel->wait_eof_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Awaiting close of channel %lu/%lu", channel->local.id,
-+ channel->remote.id);
-+
-+ channel->wait_eof_state = libssh2_NB_state_created;
-+ }
-+
-+ /*
-+ * While channel is not eof, read more packets from the network.
-+ * Either the EOF will be set or network timeout will occur.
-+ */
-+ do {
-+ if (channel->remote.eof) {
-+ break;
-+ }
-+ rc = libssh2_packet_read(session);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc < 0) {
-+ channel->wait_eof_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ } while (1);
-+
-+ channel->wait_eof_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+
-+/* {{{ libssh2_channel_close
-+ * Close a channel
-+ */
-+LIBSSH2_API int
-+libssh2_channel_close(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ int rc = 0;
-+ int retcode;
-+
-+ if (channel->local.close) {
-+ /* Already closed, act like we sent another close,
-+ * even though we didn't... shhhhhh */
-+ channel->close_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ if (channel->close_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN, "Closing channel %lu/%lu",
-+ channel->local.id, channel->remote.id);
-+
-+ if (channel->close_cb) {
-+ LIBSSH2_CHANNEL_CLOSE(session, channel);
-+ }
-+ channel->local.close = 1;
-+
-+ channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
-+ libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
-+
-+ channel->close_state = libssh2_NB_state_created;
-+ }
-+
-+ if (channel->close_state == libssh2_NB_state_created) {
-+ retcode = libssh2_packet_write(session, channel->close_packet, 5);
-+ if (retcode == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send close-channel request", 0);
-+ channel->close_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ channel->close_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (channel->close_state == libssh2_NB_state_sent) {
-+ /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
-+ if (!channel->remote.close) {
-+ libssh2pack_t ret;
-+
-+ do {
-+ ret = libssh2_packet_read(session);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (ret < 0) {
-+ rc = -1;
-+ }
-+ } while ((ret != SSH_MSG_CHANNEL_CLOSE) && (rc == 0));
-+ }
-+ }
-+
-+ channel->close_state = libssh2_NB_state_idle;
-+
-+ return rc;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_wait_closed
-+ * Awaiting channel close after EOF
-+ */
-+LIBSSH2_API int
-+libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ int rc;
-+
-+ if (!libssh2_channel_eof(channel)) {
-+ libssh2_error(session, LIBSSH2_ERROR_INVAL,
-+ "libssh2_channel_wait_closed() invoked when channel is "
-+ "not in EOF state",
-+ 0);
-+ return -1;
-+ }
-+
-+ if (channel->wait_closed_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Awaiting close of channel %lu/%lu", channel->local.id,
-+ channel->remote.id);
-+
-+ channel->wait_closed_state = libssh2_NB_state_created;
-+ }
-+
-+ /*
-+ * While channel is not closed, read more packets from the network.
-+ * Either the channel will be closed or network timeout will occur.
-+ */
-+ do {
-+ if (!channel->remote.close) {
-+ break;
-+ }
-+ rc = libssh2_packet_read(session);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc <= 0) {
-+ break;
-+ }
-+ } while (1);
-+
-+ channel->wait_closed_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+
-+/* {{{ libssh2_channel_free
-+ * Make sure a channel is closed, then remove the channel from the session
-+ * and free its resource(s)
-+ *
-+ * Returns 0 on success, -1 on failure
-+ */
-+LIBSSH2_API int
-+libssh2_channel_free(LIBSSH2_CHANNEL * channel)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char channel_id[4];
-+ unsigned char *data;
-+ unsigned long data_len;
-+ int rc;
-+
-+ if (channel->free_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Freeing channel %lu/%lu resources", channel->local.id,
-+ channel->remote.id);
-+
-+ channel->free_state = libssh2_NB_state_created;
-+ }
-+
-+ /* Allow channel freeing even when the socket has lost its connection */
-+ if (!channel->local.close
-+ && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
-+ while ((rc = libssh2_channel_close(channel)) == PACKET_EAGAIN);
-+ if (rc) {
-+ channel->free_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ }
-+
-+ channel->free_state = libssh2_NB_state_idle;
-+
-+ /*
-+ * channel->remote.close *might* not be set yet, Well...
-+ * We've sent the close packet, what more do you want?
-+ * Just let packet_add ignore it when it finally arrives
-+ */
-+
-+ /* 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,
-+ 0) >= 0)
-+ ||
-+ (libssh2_packet_ask_ex
-+ (session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data, &data_len, 1,
-+ channel_id, 4, 0) >= 0)) {
-+ 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;
-+ } else {
-+ session->channels.head = channel->next;
-+ }
-+ if (channel->next) {
-+ channel->next->prev = channel->prev;
-+ } else {
-+ session->channels.tail = channel->prev;
-+ }
-+
-+ /*
-+ * Make sure all memory used in the state variables are free
-+ */
-+ if (channel->setenv_packet) {
-+ LIBSSH2_FREE(session, channel->setenv_packet);
-+ }
-+ if (channel->reqPTY_packet) {
-+ LIBSSH2_FREE(session, channel->reqPTY_packet);
-+ }
-+ if (channel->reqX11_packet) {
-+ LIBSSH2_FREE(session, channel->reqX11_packet);
-+ }
-+ if (channel->process_packet) {
-+ LIBSSH2_FREE(session, channel->process_packet);
-+ }
-+ if (channel->write_packet) {
-+ LIBSSH2_FREE(session, channel->write_packet);
-+ }
-+
-+ LIBSSH2_FREE(session, channel);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_window_read_ex
-+ *
-+ * Check the status of the read window. Returns the number of bytes which the
-+ * remote end may send without overflowing the window limit read_avail (if
-+ * passed) will be populated with the number of bytes actually available to be
-+ * read window_size_initial (if passed) will be populated with the
-+ * window_size_initial as defined by the channel_open request
-+ */
-+LIBSSH2_API unsigned long
-+libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,
-+ unsigned long *read_avail,
-+ unsigned long *window_size_initial)
-+{
-+ if (window_size_initial) {
-+ *window_size_initial = channel->remote.window_size_initial;
-+ }
-+
-+ if (read_avail) {
-+ unsigned long bytes_queued = 0;
-+ LIBSSH2_PACKET *packet = channel->session->packets.head;
-+
-+ while (packet) {
-+ 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)) {
-+ bytes_queued += packet->data_len - packet->data_head;
-+ }
-+
-+ packet = packet->next;
-+ }
-+
-+ *read_avail = bytes_queued;
-+ }
-+
-+ return channel->remote.window_size;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_channel_window_write_ex
-+ *
-+ * Check the status of the write window Returns the number of bytes which may
-+ * be safely writen on the channel without blocking window_size_initial (if
-+ * passed) will be populated with the size of the initial window as defined by
-+ * the channel_open request
-+ */
-+LIBSSH2_API unsigned long
-+libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel,
-+ unsigned long *window_size_initial)
-+{
-+ if (window_size_initial) {
-+ /* For locally initiated channels this is very often 0, so it's not
-+ * *that* useful as information goes */
-+ *window_size_initial = channel->local.window_size_initial;
-+ }
-+
-+ return channel->local.window_size;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/channel.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/libssh2_priv.h
-===================================================================
---- libssh2/src/libssh2_priv.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/libssh2_priv.h (.../trunk)
-@@ -0,0 +1,1211 @@
-+/* Copyright (c) 2004-2008, 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_PRIV_H
-+#define LIBSSH2_PRIV_H 1
-+
-+#define LIBSSH2_LIBRARY
-+#include "libssh2_config.h"
-+
-+#ifdef HAVE_WINDOWS_H
-+#include <windows.h>
-+#endif
-+
-+#ifdef HAVE_WS2TCPIP_H
-+#include <ws2tcpip.h>
-+#endif
-+
-+#include <stdio.h>
-+#include <time.h>
-+
-+/* The following CPP block should really only be in session.c and
-+ packet.c. However, AIX have #define's for 'events' and 'revents'
-+ and we are using those names in libssh2.h, so we need to include
-+ the AIX headers first, to make sure all code is compiled with
-+ consistent names of these fields. While arguable the best would to
-+ change libssh2.h to use other names, that would break backwards
-+ compatibility. For more information, see:
-+ http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00003.html
-+ http://www.mail-archive.com/libssh2-devel%40lists.sourceforge.net/msg00224.html
-+*/
-+#ifdef HAVE_POLL
-+# include <sys/poll.h>
-+#else
-+# if defined(HAVE_SELECT) && !defined(WIN32)
-+# ifdef HAVE_SYS_SELECT_H
-+# include <sys/select.h>
-+# else
-+# include <sys/time.h>
-+# include <sys/types.h>
-+# endif
-+# endif
-+#endif
-+
-+#include "libssh2.h"
-+#include "libssh2_publickey.h"
-+#include "libssh2_sftp.h"
-+
-+/* Provide iovec / writev on WIN32 platform. */
-+#ifdef WIN32
-+
-+/* same as WSABUF */
-+struct iovec {
-+ u_long iov_len;
-+ char *iov_base;
-+};
-+
-+#define inline __inline
-+
-+static inline int writev(int sock, struct iovec *iov, int nvecs)
-+{
-+ DWORD ret;
-+ if (WSASend(sock, (LPWSABUF)iov, nvecs, &ret, 0, NULL, NULL) == 0) {
-+ return ret;
-+ }
-+ return -1;
-+}
-+
-+#endif /* WIN32 */
-+
-+/* Needed for struct iovec on some platforms */
-+#ifdef HAVE_SYS_UIO_H
-+#include <sys/uio.h>
-+#endif
-+
-+#ifdef HAVE_SYS_SOCKET_H
-+# include <sys/socket.h>
-+#endif
-+#ifdef HAVE_SYS_IOCTL_H
-+# include <sys/ioctl.h>
-+#endif
-+#ifdef HAVE_INTTYPES_H
-+#include <inttypes.h>
-+#endif
-+
-+#ifdef LIBSSH2_LIBGCRYPT
-+#include "libgcrypt.h"
-+#else
-+#include "openssl.h"
-+#endif
-+
-+#ifdef HAVE_WINSOCK2_H
-+
-+#include <winsock2.h>
-+#include <mswsock.h>
-+#include <ws2tcpip.h>
-+
-+#ifdef _MSC_VER
-+/* "inline" keyword is valid only with C++ engine! */
-+#define inline __inline
-+#endif
-+
-+/* not really usleep, but safe for the way we use it in this lib */
-+static inline int usleep(int udelay)
-+{
-+ Sleep(udelay / 1000);
-+ return 0;
-+}
-+
-+#endif
-+
-+/* RFC4253 section 6.1 Maximum Packet Length says:
-+ *
-+ * "All implementations MUST be able to process packets with
-+ * uncompressed payload length of 32768 bytes or less and
-+ * total packet size of 35000 bytes or less (including length,
-+ * padding length, payload, padding, and MAC.)."
-+ */
-+#define MAX_SSH_PACKET_LEN 35000
-+
-+#define LIBSSH2_ALLOC(session, count) session->alloc((count), &(session)->abstract)
-+#define LIBSSH2_REALLOC(session, ptr, count) ((ptr) ? session->realloc((ptr), (count), &(session)->abstract) : session->alloc((count), &(session)->abstract))
-+#define LIBSSH2_FREE(session, ptr) session->free((ptr), &(session)->abstract)
-+
-+#define LIBSSH2_IGNORE(session, data, datalen) session->ssh_msg_ignore((session), (data), (datalen), &(session)->abstract)
-+#define LIBSSH2_DEBUG(session, always_display, message, message_len, language, language_len) \
-+ session->ssh_msg_disconnect((session), (always_display), (message), (message_len), (language), (language_len), &(session)->abstract)
-+#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)
-+
-+typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD;
-+typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD;
-+typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD;
-+typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD;
-+typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD;
-+
-+typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET;
-+typedef struct _LIBSSH2_PACKET_BRIGADE LIBSSH2_PACKET_BRIGADE;
-+typedef struct _LIBSSH2_CHANNEL_BRIGADE LIBSSH2_CHANNEL_BRIGADE;
-+
-+typedef int libssh2pack_t;
-+
-+typedef enum
-+{
-+ libssh2_NB_state_idle = 0,
-+ libssh2_NB_state_allocated,
-+ libssh2_NB_state_created,
-+ libssh2_NB_state_sent,
-+ libssh2_NB_state_sent1,
-+ libssh2_NB_state_sent2,
-+ libssh2_NB_state_sent3,
-+ libssh2_NB_state_sent4,
-+ libssh2_NB_state_sent5,
-+ libssh2_NB_state_sent6,
-+ libssh2_NB_state_sent7,
-+ libssh2_NB_state_jump1,
-+ libssh2_NB_state_jump2,
-+ libssh2_NB_state_jump3
-+} libssh2_nonblocking_states;
-+
-+typedef struct packet_require_state_t
-+{
-+ libssh2_nonblocking_states state;
-+ time_t start;
-+} packet_require_state_t;
-+
-+typedef struct packet_requirev_state_t
-+{
-+ time_t start;
-+} packet_requirev_state_t;
-+
-+typedef struct kmdhgGPsha1kex_state_t
-+{
-+ libssh2_nonblocking_states state;
-+ unsigned char *e_packet;
-+ unsigned char *s_packet;
-+ unsigned char *tmp;
-+ unsigned char h_sig_comp[SHA_DIGEST_LENGTH];
-+ unsigned char c;
-+ unsigned long e_packet_len;
-+ unsigned long s_packet_len;
-+ unsigned long tmp_len;
-+ _libssh2_bn_ctx *ctx;
-+ _libssh2_bn *x;
-+ _libssh2_bn *e;
-+ _libssh2_bn *f;
-+ _libssh2_bn *k;
-+ unsigned char *s;
-+ unsigned char *f_value;
-+ unsigned char *k_value;
-+ unsigned char *h_sig;
-+ unsigned long f_value_len;
-+ unsigned long k_value_len;
-+ unsigned long h_sig_len;
-+ libssh2_sha1_ctx exchange_hash;
-+ packet_require_state_t req_state;
-+ libssh2_nonblocking_states burn_state;
-+} kmdhgGPsha1kex_state_t;
-+
-+typedef struct key_exchange_state_low_t
-+{
-+ libssh2_nonblocking_states state;
-+ packet_require_state_t req_state;
-+ kmdhgGPsha1kex_state_t exchange_state;
-+ _libssh2_bn *p; /* SSH2 defined value (p_value) */
-+ _libssh2_bn *g; /* SSH2 defined value (2) */
-+ unsigned char request[13];
-+ unsigned char *data;
-+ unsigned long request_len;
-+ unsigned long data_len;
-+} key_exchange_state_low_t;
-+
-+typedef struct key_exchange_state_t
-+{
-+ libssh2_nonblocking_states state;
-+ packet_require_state_t req_state;
-+ key_exchange_state_low_t key_state_low;
-+ unsigned char *data;
-+ unsigned long data_len;
-+ unsigned char *oldlocal;
-+ unsigned long oldlocal_len;
-+} key_exchange_state_t;
-+
-+#define FwdNotReq "Forward not requested"
-+
-+typedef struct packet_queue_listener_state_t
-+{
-+ libssh2_nonblocking_states state;
-+ unsigned char packet[17 + (sizeof(FwdNotReq) - 1)];
-+ unsigned char *host;
-+ unsigned char *shost;
-+ uint32_t sender_channel;
-+ uint32_t initial_window_size;
-+ uint32_t packet_size;
-+ uint32_t port;
-+ uint32_t sport;
-+ uint32_t host_len;
-+ uint32_t shost_len;
-+} packet_queue_listener_state_t;
-+
-+#define X11FwdUnAvil "X11 Forward Unavailable"
-+
-+typedef struct packet_x11_open_state_t
-+{
-+ libssh2_nonblocking_states state;
-+ unsigned char packet[17 + (sizeof(X11FwdUnAvil) - 1)];
-+ unsigned char *shost;
-+ uint32_t sender_channel;
-+ uint32_t initial_window_size;
-+ uint32_t packet_size;
-+ uint32_t sport;
-+ uint32_t shost_len;
-+} packet_x11_open_state_t;
-+
-+struct _LIBSSH2_PACKET
-+{
-+ unsigned char type;
-+
-+ /* Unencrypted Payload (no type byte, no padding, just the facts ma'am) */
-+ unsigned char *data;
-+ unsigned long data_len;
-+
-+ /* Where to start reading data from,
-+ * used for channel data that's been partially consumed */
-+ unsigned long data_head;
-+
-+ /* Can the message be confirmed? */
-+ int mac;
-+
-+ LIBSSH2_PACKET_BRIGADE *brigade;
-+
-+ LIBSSH2_PACKET *next, *prev;
-+};
-+
-+struct _LIBSSH2_PACKET_BRIGADE
-+{
-+ LIBSSH2_PACKET *head, *tail;
-+};
-+
-+typedef struct _libssh2_channel_data
-+{
-+ /* Identifier */
-+ unsigned long id;
-+
-+ /* Limits and restrictions */
-+ 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;
-+} libssh2_channel_data;
-+
-+struct _LIBSSH2_CHANNEL
-+{
-+ unsigned char *channel_type;
-+ unsigned channel_type_len;
-+
-+ /* channel's program exit status */
-+ int exit_status;
-+
-+ libssh2_channel_data local, remote;
-+ /* Amount of bytes to be refunded to receive window (but not yet sent) */
-+ unsigned long adjust_queue;
-+
-+ LIBSSH2_SESSION *session;
-+
-+ LIBSSH2_CHANNEL *next, *prev;
-+
-+ void *abstract;
-+ LIBSSH2_CHANNEL_CLOSE_FUNC((*close_cb));
-+
-+ /* State variables used in libssh2_channel_setenv_ex() */
-+ libssh2_nonblocking_states setenv_state;
-+ unsigned char *setenv_packet;
-+ unsigned long setenv_packet_len;
-+ unsigned char setenv_local_channel[4];
-+ packet_requirev_state_t setenv_packet_requirev_state;
-+
-+ /* State variables used in libssh2_channel_request_pty_ex() */
-+ libssh2_nonblocking_states reqPTY_state;
-+ unsigned char *reqPTY_packet;
-+ unsigned long reqPTY_packet_len;
-+ unsigned char reqPTY_local_channel[4];
-+ packet_requirev_state_t reqPTY_packet_requirev_state;
-+
-+ /* State variables used in libssh2_channel_x11_req_ex() */
-+ libssh2_nonblocking_states reqX11_state;
-+ unsigned char *reqX11_packet;
-+ unsigned long reqX11_packet_len;
-+ unsigned char reqX11_local_channel[4];
-+ packet_requirev_state_t reqX11_packet_requirev_state;
-+
-+ /* State variables used in libssh2_channel_process_startup() */
-+ libssh2_nonblocking_states process_state;
-+ unsigned char *process_packet;
-+ unsigned long process_packet_len;
-+ unsigned char process_local_channel[4];
-+ packet_requirev_state_t process_packet_requirev_state;
-+
-+ /* State variables used in libssh2_channel_flush_ex() */
-+ libssh2_nonblocking_states flush_state;
-+ unsigned long flush_refund_bytes;
-+ unsigned long flush_flush_bytes;
-+
-+ /* State variables used in libssh2_channel_receive_window_adjust() */
-+ libssh2_nonblocking_states adjust_state;
-+ unsigned char adjust_adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
-+
-+ /* State variables used in libssh2_channel_read_ex() */
-+ libssh2_nonblocking_states read_state;
-+ LIBSSH2_PACKET *read_packet;
-+ LIBSSH2_PACKET *read_next;
-+ int read_block;
-+ int read_bytes_read;
-+ uint32_t read_local_id;
-+ int read_want;
-+ int read_unlink_packet;
-+
-+ /* State variables used in libssh2_channel_write_ex() */
-+ libssh2_nonblocking_states write_state;
-+ unsigned char *write_packet;
-+ unsigned char *write_s;
-+ unsigned long write_packet_len;
-+ unsigned long write_bufwrote;
-+ size_t write_bufwrite;
-+
-+ /* State variables used in libssh2_channel_close() */
-+ libssh2_nonblocking_states close_state;
-+ unsigned char close_packet[5];
-+
-+ /* State variables used in libssh2_channel_wait_closedeof() */
-+ libssh2_nonblocking_states wait_eof_state;
-+
-+ /* State variables used in libssh2_channel_wait_closed() */
-+ libssh2_nonblocking_states wait_closed_state;
-+
-+ /* State variables used in libssh2_channel_free() */
-+ libssh2_nonblocking_states free_state;
-+
-+ /* State variables used in libssh2_channel_handle_extended_data2() */
-+ libssh2_nonblocking_states extData2_state;
-+};
-+
-+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;
-+
-+ /* State variables used in libssh2_channel_forward_cancel() */
-+ libssh2_nonblocking_states chanFwdCncl_state;
-+ unsigned char *chanFwdCncl_data;
-+ size_t chanFwdCncl_data_len;
-+};
-+
-+typedef struct _libssh2_endpoint_data
-+{
-+ unsigned char *banner;
-+
-+ unsigned char *kexinit;
-+ unsigned long kexinit_len;
-+
-+ const LIBSSH2_CRYPT_METHOD *crypt;
-+ void *crypt_abstract;
-+
-+ const LIBSSH2_MAC_METHOD *mac;
-+ unsigned long seqno;
-+ void *mac_abstract;
-+
-+ const LIBSSH2_COMP_METHOD *comp;
-+ void *comp_abstract;
-+
-+ /* Method Preferences -- NULL yields "load order" */
-+ char *crypt_prefs;
-+ char *mac_prefs;
-+ char *comp_prefs;
-+ char *lang_prefs;
-+} libssh2_endpoint_data;
-+
-+#define PACKETBUFSIZE 4096
-+
-+struct transportpacket
-+{
-+ /* ------------- for incoming data --------------- */
-+ unsigned char buf[PACKETBUFSIZE];
-+ unsigned char init[5]; /* first 5 bytes of the incoming data stream,
-+ still encrypted */
-+ int writeidx; /* at what array index we do the next write into
-+ the buffer */
-+ int readidx; /* at what array index we do the next read from
-+ the buffer */
-+ int packet_length; /* the most recent packet_length as read from the
-+ network data */
-+ int padding_length; /* the most recent padding_length as read from the
-+ network data */
-+ int data_num; /* How much of the total package that has been read
-+ so far. */
-+ int total_num; /* How much a total package is supposed to be, in
-+ number of bytes. A full package is
-+ packet_length + padding_length + 4 +
-+ mac_length. */
-+ unsigned char *payload; /* this is a pointer to a LIBSSH2_ALLOC()
-+ area to which we write decrypted data */
-+ unsigned char *wptr; /* write pointer into the payload to where we
-+ are currently writing decrypted data */
-+
-+ /* ------------- for outgoing data --------------- */
-+ unsigned char *outbuf; /* pointer to a LIBSSH2_ALLOC() area for the
-+ outgoing data */
-+ int ototal_num; /* size of outbuf in number of bytes */
-+ unsigned char *odata; /* original pointer to the data we stored in
-+ outbuf */
-+ unsigned long olen; /* original size of the data we stored in
-+ outbuf */
-+ unsigned long osent; /* number of bytes already sent */
-+};
-+
-+struct _LIBSSH2_PUBLICKEY
-+{
-+ LIBSSH2_CHANNEL *channel;
-+ unsigned long version;
-+
-+ /* State variables used in libssh2_publickey_packet_receive() */
-+ libssh2_nonblocking_states receive_state;
-+ unsigned char *receive_packet;
-+ unsigned long receive_packet_len;
-+
-+ /* State variables used in libssh2_publickey_add_ex() */
-+ libssh2_nonblocking_states add_state;
-+ unsigned char *add_packet;
-+ unsigned char *add_s;
-+
-+ /* State variables used in libssh2_publickey_remove_ex() */
-+ libssh2_nonblocking_states remove_state;
-+ unsigned char *remove_packet;
-+ unsigned char *remove_s;
-+
-+ /* State variables used in libssh2_publickey_list_fetch() */
-+ libssh2_nonblocking_states listFetch_state;
-+ unsigned char *listFetch_s;
-+ unsigned char listFetch_buffer[12];
-+ unsigned char *listFetch_data;
-+ unsigned long listFetch_data_len;
-+};
-+
-+#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */
-+
-+struct _LIBSSH2_SFTP_HANDLE
-+{
-+ LIBSSH2_SFTP *sftp;
-+ LIBSSH2_SFTP_HANDLE *prev, *next;
-+
-+ /* This is a pre-allocated buffer used for sending SFTP requests as the
-+ whole thing might not get sent in one go. This buffer is used for read,
-+ write, close and MUST thus be big enough to suit all these. */
-+ unsigned char request_packet[SFTP_HANDLE_MAXLEN + 25];
-+
-+ char handle[SFTP_HANDLE_MAXLEN];
-+ int handle_len;
-+
-+ char handle_type;
-+
-+ union _libssh2_sftp_handle_data
-+ {
-+ struct _libssh2_sftp_handle_file_data
-+ {
-+ libssh2_uint64_t offset;
-+ } file;
-+ struct _libssh2_sftp_handle_dir_data
-+ {
-+ unsigned long names_left;
-+ void *names_packet;
-+ char *next_name;
-+ } dir;
-+ } u;
-+
-+ /* State variables used in libssh2_sftp_close_handle() */
-+ libssh2_nonblocking_states close_state;
-+ unsigned long close_request_id;
-+ unsigned char *close_packet;
-+};
-+
-+struct _LIBSSH2_SFTP
-+{
-+ LIBSSH2_CHANNEL *channel;
-+
-+ unsigned long request_id, version;
-+
-+ LIBSSH2_PACKET_BRIGADE packets;
-+
-+ LIBSSH2_SFTP_HANDLE *handles;
-+
-+ unsigned long last_errno;
-+
-+ /* Holder for partial packet, use in libssh2_sftp_packet_read() */
-+ unsigned char *partial_packet; /* The data */
-+ unsigned long partial_len; /* Desired number of bytes */
-+ unsigned long partial_received; /* Bytes received so far */
-+
-+ /* Time that libssh2_sftp_packet_requirev() started reading */
-+ time_t requirev_start;
-+
-+ /* State variables used in libssh2_sftp_open_ex() */
-+ libssh2_nonblocking_states open_state;
-+ unsigned char *open_packet;
-+ ssize_t open_packet_len;
-+ unsigned long open_request_id;
-+
-+ /* State variables used in libssh2_sftp_read() */
-+ libssh2_nonblocking_states read_state;
-+ unsigned char *read_packet;
-+ unsigned long read_request_id;
-+ size_t read_total_read;
-+
-+ /* State variables used in libssh2_sftp_readdir() */
-+ libssh2_nonblocking_states readdir_state;
-+ unsigned char *readdir_packet;
-+ unsigned long readdir_request_id;
-+
-+ /* State variables used in libssh2_sftp_write() */
-+ libssh2_nonblocking_states write_state;
-+ unsigned char *write_packet;
-+ unsigned long write_request_id;
-+
-+ /* State variables used in libssh2_sftp_fstat_ex() */
-+ libssh2_nonblocking_states fstat_state;
-+ unsigned char *fstat_packet;
-+ unsigned long fstat_request_id;
-+
-+ /* State variables used in libssh2_sftp_unlink_ex() */
-+ libssh2_nonblocking_states unlink_state;
-+ unsigned char *unlink_packet;
-+ unsigned long unlink_request_id;
-+
-+ /* State variables used in libssh2_sftp_rename_ex() */
-+ libssh2_nonblocking_states rename_state;
-+ unsigned char *rename_packet;
-+ unsigned char *rename_s;
-+ unsigned long rename_request_id;
-+
-+ /* State variables used in libssh2_sftp_mkdir() */
-+ libssh2_nonblocking_states mkdir_state;
-+ unsigned char *mkdir_packet;
-+ unsigned long mkdir_request_id;
-+
-+ /* State variables used in libssh2_sftp_rmdir() */
-+ libssh2_nonblocking_states rmdir_state;
-+ unsigned char *rmdir_packet;
-+ unsigned long rmdir_request_id;
-+
-+ /* State variables used in libssh2_sftp_stat() */
-+ libssh2_nonblocking_states stat_state;
-+ unsigned char *stat_packet;
-+ unsigned long stat_request_id;
-+
-+ /* State variables used in libssh2_sftp_symlink() */
-+ libssh2_nonblocking_states symlink_state;
-+ unsigned char *symlink_packet;
-+ unsigned long symlink_request_id;
-+};
-+
-+#define LIBSSH2_SCP_RESPONSE_BUFLEN 256
-+
-+struct _LIBSSH2_SESSION
-+{
-+ /* Memory management callbacks */
-+ void *abstract;
-+ LIBSSH2_ALLOC_FUNC((*alloc));
-+ LIBSSH2_REALLOC_FUNC((*realloc));
-+ LIBSSH2_FREE_FUNC((*free));
-+
-+ /* Other callbacks */
-+ LIBSSH2_IGNORE_FUNC((*ssh_msg_ignore));
-+ 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;
-+
-+ int state;
-+ int flags;
-+
-+ /* Agreed Key Exchange Method */
-+ const LIBSSH2_KEX_METHOD *kex;
-+ int burn_optimistic_kexinit:1;
-+
-+ unsigned char *session_id;
-+ unsigned long session_id_len;
-+
-+ /* Server's public key */
-+ const LIBSSH2_HOSTKEY_METHOD *hostkey;
-+ void *server_hostkey_abstract;
-+
-+ /* Either set with libssh2_session_hostkey() (for server mode)
-+ * Or read from server in (eg) KEXDH_INIT (for client mode)
-+ */
-+ unsigned char *server_hostkey;
-+ unsigned long server_hostkey_len;
-+#if LIBSSH2_MD5
-+ unsigned char server_hostkey_md5[MD5_DIGEST_LENGTH];
-+#endif /* ! LIBSSH2_MD5 */
-+ unsigned char server_hostkey_sha1[SHA_DIGEST_LENGTH];
-+
-+ /* (remote as source of data -- packet_read ) */
-+ libssh2_endpoint_data remote;
-+
-+ /* (local as source of data -- packet_write ) */
-+ libssh2_endpoint_data local;
-+
-+ /* Inbound Data buffer -- Sometimes the packet that comes in isn't the packet we're ready for */
-+ LIBSSH2_PACKET_BRIGADE packets;
-+
-+ /* Active connection channels */
-+ LIBSSH2_CHANNEL_BRIGADE channels;
-+ unsigned long next_channel;
-+
-+ LIBSSH2_LISTENER *listeners;
-+
-+ /* Actual I/O socket */
-+ int socket_fd;
-+ int socket_block;
-+ int socket_state;
-+ int socket_block_directions;
-+
-+ /* Error tracking */
-+ char *err_msg;
-+ unsigned long err_msglen;
-+ int err_should_free;
-+ int err_code;
-+
-+ /* struct members for packet-level reading */
-+ struct transportpacket packet;
-+#ifdef LIBSSH2DEBUG
-+ int showmask; /* what debug/trace messages to display */
-+#endif
-+
-+ /* State variables used in libssh2_banner_send() */
-+ libssh2_nonblocking_states banner_TxRx_state;
-+ char banner_TxRx_banner[256];
-+ ssize_t banner_TxRx_total_send;
-+
-+ /* State variables used in libssh2_kexinit() */
-+ libssh2_nonblocking_states kexinit_state;
-+ unsigned char *kexinit_data;
-+ size_t kexinit_data_len;
-+
-+ /* State variables used in libssh2_session_startup() */
-+ libssh2_nonblocking_states startup_state;
-+ unsigned char *startup_data;
-+ unsigned long startup_data_len;
-+ unsigned char startup_service[sizeof("ssh-userauth") + 5 - 1];
-+ unsigned long startup_service_length;
-+ packet_require_state_t startup_req_state;
-+ key_exchange_state_t startup_key_state;
-+
-+ /* State variables used in libssh2_session_free() */
-+ libssh2_nonblocking_states free_state;
-+
-+ /* State variables used in libssh2_session_disconnect_ex() */
-+ libssh2_nonblocking_states disconnect_state;
-+ unsigned char *disconnect_data;
-+ unsigned long disconnect_data_len;
-+
-+ /* State variables used in libssh2_packet_read() */
-+ libssh2_nonblocking_states readPack_state;
-+ int readPack_encrypted;
-+
-+ /* State variables used in libssh2_userauth_list() */
-+ libssh2_nonblocking_states userauth_list_state;
-+ unsigned char *userauth_list_data;
-+ unsigned long userauth_list_data_len;
-+ packet_requirev_state_t userauth_list_packet_requirev_state;
-+
-+ /* State variables used in libssh2_userauth_password_ex() */
-+ libssh2_nonblocking_states userauth_pswd_state;
-+ unsigned char *userauth_pswd_data;
-+ unsigned char userauth_pswd_data0;
-+ unsigned long userauth_pswd_data_len;
-+ char *userauth_pswd_newpw;
-+ int userauth_pswd_newpw_len;
-+ packet_requirev_state_t userauth_pswd_packet_requirev_state;
-+
-+ /* State variables used in libssh2_userauth_hostbased_fromfile_ex() */
-+ libssh2_nonblocking_states userauth_host_state;
-+ unsigned char *userauth_host_data;
-+ unsigned long userauth_host_data_len;
-+ unsigned char *userauth_host_packet;
-+ unsigned long userauth_host_packet_len;
-+ unsigned char *userauth_host_method;
-+ unsigned long userauth_host_method_len;
-+ unsigned char *userauth_host_s;
-+ packet_requirev_state_t userauth_host_packet_requirev_state;
-+
-+ /* State variables used in libssh2_userauth_publickey_fromfile_ex() */
-+ libssh2_nonblocking_states userauth_pblc_state;
-+ unsigned char *userauth_pblc_data;
-+ unsigned long userauth_pblc_data_len;
-+ unsigned char *userauth_pblc_packet;
-+ unsigned long userauth_pblc_packet_len;
-+ unsigned char *userauth_pblc_method;
-+ unsigned long userauth_pblc_method_len;
-+ unsigned char *userauth_pblc_s;
-+ unsigned char *userauth_pblc_b;
-+ packet_requirev_state_t userauth_pblc_packet_requirev_state;
-+
-+ /* State variables used in llibssh2_userauth_keyboard_interactive_ex() */
-+ libssh2_nonblocking_states userauth_kybd_state;
-+ unsigned char *userauth_kybd_data;
-+ unsigned long userauth_kybd_data_len;
-+ unsigned char *userauth_kybd_packet;
-+ unsigned long userauth_kybd_packet_len;
-+ unsigned int userauth_kybd_auth_name_len;
-+ char *userauth_kybd_auth_name;
-+ unsigned userauth_kybd_auth_instruction_len;
-+ char *userauth_kybd_auth_instruction;
-+ unsigned int userauth_kybd_num_prompts;
-+ int userauth_kybd_auth_failure;
-+ LIBSSH2_USERAUTH_KBDINT_PROMPT *userauth_kybd_prompts;
-+ LIBSSH2_USERAUTH_KBDINT_RESPONSE *userauth_kybd_responses;
-+ packet_requirev_state_t userauth_kybd_packet_requirev_state;
-+
-+ /* State variables used in libssh2_channel_open_ex() */
-+ libssh2_nonblocking_states open_state;
-+ packet_requirev_state_t open_packet_requirev_state;
-+ LIBSSH2_CHANNEL *open_channel;
-+ unsigned char *open_packet;
-+ unsigned long open_packet_len;
-+ unsigned char *open_data;
-+ unsigned long open_data_len;
-+ unsigned long open_local_channel;
-+
-+ /* State variables used in libssh2_channel_direct_tcpip_ex() */
-+ libssh2_nonblocking_states direct_state;
-+ unsigned char *direct_message;
-+ unsigned long direct_host_len;
-+ unsigned long direct_shost_len;
-+ unsigned long direct_message_len;
-+
-+ /* State variables used in libssh2_channel_forward_listen_ex() */
-+ libssh2_nonblocking_states fwdLstn_state;
-+ unsigned char *fwdLstn_packet;
-+ unsigned long fwdLstn_host_len;
-+ unsigned long fwdLstn_packet_len;
-+ packet_requirev_state_t fwdLstn_packet_requirev_state;
-+
-+ /* State variables used in libssh2_publickey_init() */
-+ libssh2_nonblocking_states pkeyInit_state;
-+ LIBSSH2_PUBLICKEY *pkeyInit_pkey;
-+ LIBSSH2_CHANNEL *pkeyInit_channel;
-+ unsigned char *pkeyInit_data;
-+ unsigned long pkeyInit_data_len;
-+
-+ /* State variables used in libssh2_packet_add() */
-+ libssh2_nonblocking_states packAdd_state;
-+ LIBSSH2_PACKET *packAdd_packet;
-+ LIBSSH2_CHANNEL *packAdd_channel;
-+ unsigned long packAdd_data_head;
-+ key_exchange_state_t packAdd_key_state;
-+ packet_queue_listener_state_t packAdd_Qlstn_state;
-+ packet_x11_open_state_t packAdd_x11open_state;
-+
-+ /* State variables used in fullpacket() */
-+ libssh2_nonblocking_states fullpacket_state;
-+ int fullpacket_macstate;
-+ int fullpacket_payload_len;
-+ libssh2pack_t fullpacket_packet_type;
-+
-+ /* State variables used in libssh2_sftp_init() */
-+ libssh2_nonblocking_states sftpInit_state;
-+ LIBSSH2_SFTP *sftpInit_sftp;
-+ LIBSSH2_CHANNEL *sftpInit_channel;
-+ unsigned char sftpInit_buffer[9]; /* sftp_header(5){excludes request_id} + version_id(4) */
-+
-+ /* State variables used in libssh2_scp_recv() */
-+ libssh2_nonblocking_states scpRecv_state;
-+ unsigned char *scpRecv_command;
-+ unsigned long scpRecv_command_len;
-+ unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
-+ unsigned long scpRecv_response_len;
-+ long scpRecv_mode;
-+#if defined(HAVE_LONGLONG) && defined(strtoll)
-+ /* we have the type and we can parse such numbers */
-+ long long scpRecv_size;
-+#define scpsize_strtol strtoll
-+#else
-+ long scpRecv_size;
-+#define scpsize_strtol strtol
-+#endif
-+ long scpRecv_mtime;
-+ long scpRecv_atime;
-+ char *scpRecv_err_msg;
-+ long scpRecv_err_len;
-+ LIBSSH2_CHANNEL *scpRecv_channel;
-+
-+ /* State variables used in libssh2_scp_send_ex() */
-+ libssh2_nonblocking_states scpSend_state;
-+ unsigned char *scpSend_command;
-+ unsigned long scpSend_command_len;
-+ unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
-+ unsigned long scpSend_response_len;
-+ char *scpSend_err_msg;
-+ long scpSend_err_len;
-+ LIBSSH2_CHANNEL *scpSend_channel;
-+};
-+
-+/* session.state bits */
-+#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
-+#define LIBSSH2_STATE_NEWKEYS 0x00000002
-+#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
-+#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
-+
-+/* session.flag helpers */
-+#ifdef MSG_NOSIGNAL
-+#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
-+#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL)
-+#else
-+/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */
-+#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0
-+#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0
-+#endif
-+
-+/* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */
-+
-+struct _LIBSSH2_KEX_METHOD
-+{
-+ const char *name;
-+
-+ /* Key exchange, populates session->* and returns 0 on success, non-0 on error */
-+ int (*exchange_keys) (LIBSSH2_SESSION * session,
-+ key_exchange_state_low_t * key_state);
-+
-+ long flags;
-+};
-+
-+struct _LIBSSH2_HOSTKEY_METHOD
-+{
-+ const char *name;
-+ unsigned long hash_len;
-+
-+ int (*init) (LIBSSH2_SESSION * session, const unsigned char *hostkey_data,
-+ unsigned long hostkey_data_len, void **abstract);
-+ int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
-+ unsigned const char *passphrase, void **abstract);
-+ int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
-+ unsigned long sig_len, const unsigned char *m,
-+ unsigned long m_len, void **abstract);
-+ int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature,
-+ unsigned long *signature_len, unsigned long veccount,
-+ const struct iovec datavec[], void **abstract);
-+ int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst,
-+ unsigned long *dst_len, const unsigned char *src,
-+ unsigned long src_len, void **abstract);
-+ int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
-+};
-+
-+struct _LIBSSH2_CRYPT_METHOD
-+{
-+ const char *name;
-+
-+ int blocksize;
-+
-+ /* iv and key sizes (-1 for variable length) */
-+ int iv_len;
-+ int secret_len;
-+
-+ long flags;
-+
-+ int (*init) (LIBSSH2_SESSION * session,
-+ const LIBSSH2_CRYPT_METHOD * method, unsigned char *iv,
-+ int *free_iv, unsigned char *secret, int *free_secret,
-+ int encrypt, void **abstract);
-+ int (*crypt) (LIBSSH2_SESSION * session, unsigned char *block,
-+ void **abstract);
-+ int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
-+
-+ _libssh2_cipher_type(algo);
-+};
-+
-+struct _LIBSSH2_COMP_METHOD
-+{
-+ const char *name;
-+
-+ int (*init) (LIBSSH2_SESSION * session, int compress, void **abstract);
-+ int (*comp) (LIBSSH2_SESSION * session, int compress, unsigned char **dest,
-+ unsigned long *dest_len, unsigned long payload_limit,
-+ int *free_dest, const unsigned char *src,
-+ unsigned long src_len, void **abstract);
-+ int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
-+};
-+
-+struct _LIBSSH2_MAC_METHOD
-+{
-+ const char *name;
-+
-+ /* 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);
-+ int (*dtor) (LIBSSH2_SESSION * session, void **abstract);
-+};
-+
-+#define LIBSSH2_DBG_TRANS 1
-+#define LIBSSH2_DBG_KEX 2
-+#define LIBSSH2_DBG_AUTH 3
-+#define LIBSSH2_DBG_CONN 4
-+#define LIBSSH2_DBG_SCP 5
-+#define LIBSSH2_DBG_SFTP 6
-+#define LIBSSH2_DBG_ERROR 7
-+#define LIBSSH2_DBG_PUBLICKEY 8
-+#ifdef LIBSSH2DEBUG
-+void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format,
-+ ...);
-+#else
-+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-+/* C99 style */
-+#define _libssh2_debug(x,y,z, __VA_ARGS__) do {} while (0)
-+#elif defined(__GNUC__)
-+/* GNU style */
-+#define _libssh2_debug(x,y,z,...) do {} while (0)
-+#else
-+/* no gcc and not C99, do static and hopefully inline */
-+static inline void
-+_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
-+{
-+}
-+#endif
-+#endif
-+
-+#ifdef LIBSSH2DEBUG
-+#define libssh2_error(session, errcode, errmsg, should_free) \
-+{ \
-+ if (session->err_msg && session->err_should_free) { \
-+ LIBSSH2_FREE(session, session->err_msg); \
-+ } \
-+ session->err_msg = (char *)errmsg; \
-+ session->err_msglen = strlen(errmsg); \
-+ session->err_should_free = should_free; \
-+ session->err_code = errcode; \
-+ _libssh2_debug(session, LIBSSH2_DBG_ERROR, "%d - %s", session->err_code, session->err_msg); \
-+}
-+
-+#else /* ! LIBSSH2DEBUG */
-+
-+#define libssh2_error(session, errcode, errmsg, should_free) \
-+{ \
-+ if (session->err_msg && session->err_should_free) { \
-+ LIBSSH2_FREE(session, session->err_msg); \
-+ } \
-+ session->err_msg = (char *)errmsg; \
-+ session->err_msglen = strlen(errmsg); \
-+ session->err_should_free = should_free; \
-+ session->err_code = errcode; \
-+}
-+
-+#endif /* ! LIBSSH2DEBUG */
-+
-+
-+#define LIBSSH2_SOCKET_UNKNOWN 1
-+#define LIBSSH2_SOCKET_CONNECTED 0
-+#define LIBSSH2_SOCKET_DISCONNECTED -1
-+
-+/* Initial packet state, prior to MAC check */
-+#define LIBSSH2_MAC_UNCONFIRMED 1
-+/* When MAC type is "none" (proto initiation phase) all packets are deemed "confirmed" */
-+#define LIBSSH2_MAC_CONFIRMED 0
-+/* Something very bad is going on */
-+#define LIBSSH2_MAC_INVALID -1
-+
-+/* SSH Packet Types -- Defined by internet draft */
-+/* Transport Layer */
-+#define SSH_MSG_DISCONNECT 1
-+#define SSH_MSG_IGNORE 2
-+#define SSH_MSG_UNIMPLEMENTED 3
-+#define SSH_MSG_DEBUG 4
-+#define SSH_MSG_SERVICE_REQUEST 5
-+#define SSH_MSG_SERVICE_ACCEPT 6
-+
-+#define SSH_MSG_KEXINIT 20
-+#define SSH_MSG_NEWKEYS 21
-+
-+/* diffie-hellman-group1-sha1 */
-+#define SSH_MSG_KEXDH_INIT 30
-+#define SSH_MSG_KEXDH_REPLY 31
-+
-+/* diffie-hellman-group-exchange-sha1 */
-+#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
-+#define SSH_MSG_KEX_DH_GEX_REQUEST 34
-+#define SSH_MSG_KEX_DH_GEX_GROUP 31
-+#define SSH_MSG_KEX_DH_GEX_INIT 32
-+#define SSH_MSG_KEX_DH_GEX_REPLY 33
-+
-+/* User Authentication */
-+#define SSH_MSG_USERAUTH_REQUEST 50
-+#define SSH_MSG_USERAUTH_FAILURE 51
-+#define SSH_MSG_USERAUTH_SUCCESS 52
-+#define SSH_MSG_USERAUTH_BANNER 53
-+
-+/* "public key" method */
-+#define SSH_MSG_USERAUTH_PK_OK 60
-+/* "password" method */
-+#define SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 60
-+/* "keyboard-interactive" method */
-+#define SSH_MSG_USERAUTH_INFO_REQUEST 60
-+#define SSH_MSG_USERAUTH_INFO_RESPONSE 61
-+
-+/* Channels */
-+#define SSH_MSG_GLOBAL_REQUEST 80
-+#define SSH_MSG_REQUEST_SUCCESS 81
-+#define SSH_MSG_REQUEST_FAILURE 82
-+
-+#define SSH_MSG_CHANNEL_OPEN 90
-+#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
-+#define SSH_MSG_CHANNEL_OPEN_FAILURE 92
-+#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
-+#define SSH_MSG_CHANNEL_DATA 94
-+#define SSH_MSG_CHANNEL_EXTENDED_DATA 95
-+#define SSH_MSG_CHANNEL_EOF 96
-+#define SSH_MSG_CHANNEL_CLOSE 97
-+#define SSH_MSG_CHANNEL_REQUEST 98
-+#define SSH_MSG_CHANNEL_SUCCESS 99
-+#define SSH_MSG_CHANNEL_FAILURE 100
-+
-+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);
-+
-+#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when
-+ waiting for more data to arrive */
-+int libssh2_waitsocket(LIBSSH2_SESSION * session, long seconds);
-+
-+
-+/* CAUTION: some of these error codes are returned in the public API and is
-+ there known with other #defined names from the public header file. They
-+ should not be changed. */
-+
-+#define PACKET_TIMEOUT -7
-+#define PACKET_BADUSE -6
-+#define PACKET_COMPRESS -5
-+#define PACKET_TOOBIG -4
-+#define PACKET_ENOMEM -3
-+#define PACKET_EAGAIN LIBSSH2_ERROR_EAGAIN
-+#define PACKET_FAIL -1
-+#define PACKET_NONE 0
-+
-+libssh2pack_t libssh2_packet_read(LIBSSH2_SESSION * session);
-+
-+int libssh2_packet_ask_ex(LIBSSH2_SESSION * session, unsigned char packet_type,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len, int poll_socket);
-+
-+int libssh2_packet_askv_ex(LIBSSH2_SESSION * session,
-+ const unsigned char *packet_types,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len, int poll_socket);
-+int libssh2_packet_require_ex(LIBSSH2_SESSION * session,
-+ unsigned char packet_type, unsigned char **data,
-+ unsigned long *data_len, unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len,
-+ packet_require_state_t * state);
-+int libssh2_packet_requirev_ex(LIBSSH2_SESSION * session,
-+ const unsigned char *packet_types,
-+ unsigned char **data, unsigned long *data_len,
-+ unsigned long match_ofs,
-+ const unsigned char *match_buf,
-+ unsigned long match_len,
-+ packet_requirev_state_t * state);
-+int libssh2_packet_burn(LIBSSH2_SESSION * session,
-+ libssh2_nonblocking_states * state);
-+int libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned long data_len);
-+int libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
-+ size_t datalen, int macstate);
-+int libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
-+ key_exchange_state_t * state);
-+unsigned long libssh2_channel_nextid(LIBSSH2_SESSION * session);
-+LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION * session,
-+ unsigned long channel_id);
-+unsigned long libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,
-+ int stream_id);
-+
-+/* this is the lib-internal set blocking function */
-+int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
-+
-+/* Let crypt.c/hostkey.c/comp.c/mac.c expose their method structs */
-+const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
-+const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
-+const LIBSSH2_COMP_METHOD **libssh2_comp_methods(void);
-+const LIBSSH2_MAC_METHOD **libssh2_mac_methods(void);
-+
-+/* Language API doesn't exist yet. Just act like we've agreed on a language */
-+#define libssh2_kex_agree_lang(session, endpoint, str, str_len) 0
-+
-+/* pem.c */
-+int _libssh2_pem_parse(LIBSSH2_SESSION * session,
-+ const char *headerbegin,
-+ const char *headerend,
-+ FILE * fp, unsigned char **data, unsigned int *datalen);
-+int _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen);
-+int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
-+ unsigned char **i, unsigned int *ilen);
-+
-+#endif /* LIBSSH2_H */
-
-Property changes on: libssh2/src/libssh2_priv.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/sftp.c
-===================================================================
---- libssh2/src/sftp.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/sftp.c (.../trunk)
-@@ -0,0 +1,2358 @@
-+/* Copyright (c) 2004-2008, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include "libssh2_sftp.h"
-+
-+/* Note: Version 6 was documented at the time of writing
-+ * However it was marked as "DO NOT IMPLEMENT" due to pending changes
-+ *
-+ * This release of libssh2 implements Version 5 with automatic downgrade
-+ * based on server's declaration
-+ */
-+
-+/* SFTP packet types */
-+#define SSH_FXP_INIT 1
-+#define SSH_FXP_VERSION 2
-+#define SSH_FXP_OPEN 3
-+#define SSH_FXP_CLOSE 4
-+#define SSH_FXP_READ 5
-+#define SSH_FXP_WRITE 6
-+#define SSH_FXP_LSTAT 7
-+#define SSH_FXP_FSTAT 8
-+#define SSH_FXP_SETSTAT 9
-+#define SSH_FXP_FSETSTAT 10
-+#define SSH_FXP_OPENDIR 11
-+#define SSH_FXP_READDIR 12
-+#define SSH_FXP_REMOVE 13
-+#define SSH_FXP_MKDIR 14
-+#define SSH_FXP_RMDIR 15
-+#define SSH_FXP_REALPATH 16
-+#define SSH_FXP_STAT 17
-+#define SSH_FXP_RENAME 18
-+#define SSH_FXP_READLINK 19
-+#define SSH_FXP_SYMLINK 20
-+#define SSH_FXP_STATUS 101
-+#define SSH_FXP_HANDLE 102
-+#define SSH_FXP_DATA 103
-+#define SSH_FXP_NAME 104
-+#define SSH_FXP_ATTRS 105
-+#define SSH_FXP_EXTENDED 200
-+#define SSH_FXP_EXTENDED_REPLY 201
-+
-+#define LIBSSH2_SFTP_HANDLE_FILE 0
-+#define LIBSSH2_SFTP_HANDLE_DIR 1
-+
-+/* S_IFREG */
-+#define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE 0100000
-+/* S_IFDIR */
-+#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
-+
-+/* {{{ sftp_packet_add
-+ * Add a packet to the SFTP packet brigade
-+ */
-+static int
-+sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
-+ unsigned long data_len)
-+{
-+ LIBSSH2_SESSION *session = sftp->channel->session;
-+ LIBSSH2_PACKET *packet;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
-+ (int) data[0], data_len);
-+ packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
-+ if (!packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate datablock for SFTP packet", 0);
-+ return -1;
-+ }
-+ memset(packet, 0, sizeof(LIBSSH2_PACKET));
-+
-+ packet->data = data;
-+ packet->data_len = data_len;
-+ packet->data_head = 5;
-+ packet->brigade = &sftp->packets;
-+ packet->next = NULL;
-+ packet->prev = sftp->packets.tail;
-+ if (packet->prev) {
-+ packet->prev->next = packet;
-+ } else {
-+ sftp->packets.head = packet;
-+ }
-+ sftp->packets.tail = packet;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ sftp_packet_read
-+ * Frame an SFTP packet off the channel
-+ */
-+static int
-+sftp_packet_read(LIBSSH2_SFTP * sftp)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char buffer[4]; /* To store the packet length */
-+ unsigned char *packet;
-+ unsigned long packet_len, packet_received;
-+ ssize_t bytes_received;
-+ int rc;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Waiting for packet");
-+
-+
-+ /* If there was a previous partial, start using it */
-+ if (sftp->partial_packet) {
-+
-+ packet = sftp->partial_packet;
-+ packet_len = sftp->partial_len;
-+ packet_received = sftp->partial_received;
-+ sftp->partial_packet = NULL;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "partial read cont, len: %lu", packet_len);
-+ }
-+ else {
-+ rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ else if (4 != rc) {
-+ /* TODO: this is stupid since we can in fact get 1-3 bytes in a
-+ legitimate working case as well if the connection happens to be
-+ super slow or something */
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for FXP packet", 0);
-+ return -1;
-+ }
-+
-+ packet_len = libssh2_ntohu32(buffer);
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Data begin - Packet Length: %lu", packet_len);
-+ if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
-+ "SFTP packet too large", 0);
-+ return -1;
-+ }
-+
-+ packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate SFTP packet", 0);
-+ return -1;
-+ }
-+
-+ packet_received = 0;
-+ }
-+
-+ /* Read as much of the packet as we can */
-+ while (packet_len > packet_received) {
-+ bytes_received =
-+ libssh2_channel_read_ex(channel, 0,
-+ (char *) packet + packet_received,
-+ packet_len - packet_received);
-+
-+ if (bytes_received == PACKET_EAGAIN) {
-+ /*
-+ * We received EAGAIN, save what we have and
-+ * return to EAGAIN to the caller
-+ */
-+ sftp->partial_packet = packet;
-+ sftp->partial_len = packet_len;
-+ sftp->partial_received = packet_received;
-+ packet = NULL;
-+
-+ return PACKET_EAGAIN;
-+ }
-+ else if (bytes_received < 0) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Receive error waiting for SFTP packet", 0);
-+ LIBSSH2_FREE(session, packet);
-+ return -1;
-+ }
-+ packet_received += bytes_received;
-+ }
-+
-+ if (sftp_packet_add(sftp, packet, packet_len)) {
-+ LIBSSH2_FREE(session, packet);
-+ return -1;
-+ }
-+
-+ return packet[0];
-+}
-+
-+/* }}} */
-+
-+/* {{{ sftp_packet_ask
-+ * A la libssh2_packet_ask()
-+ */
-+static int
-+sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
-+ unsigned long request_id, unsigned char **data,
-+ unsigned long *data_len, int poll_channel)
-+{
-+ LIBSSH2_SESSION *session = sftp->channel->session;
-+ LIBSSH2_PACKET *packet = sftp->packets.head;
-+ unsigned char match_buf[5];
-+ int match_len = 5;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet",
-+ (int) packet_type);
-+ if (poll_channel) {
-+ int ret = sftp_packet_read(sftp);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (ret < 0) {
-+ return -1;
-+ }
-+ }
-+
-+ match_buf[0] = packet_type;
-+ if (packet_type == SSH_FXP_VERSION) {
-+ /* Special consideration when matching VERSION packet */
-+ match_len = 1;
-+ } else {
-+ libssh2_htonu32(match_buf + 1, request_id);
-+ }
-+
-+ while (packet) {
-+ if (strncmp((char *) packet->data, (char *) match_buf, match_len) == 0) {
-+ *data = packet->data;
-+ *data_len = packet->data_len;
-+
-+ if (packet->prev) {
-+ packet->prev->next = packet->next;
-+ } else {
-+ sftp->packets.head = packet->next;
-+ }
-+
-+ if (packet->next) {
-+ packet->next->prev = packet->prev;
-+ } else {
-+ sftp->packets.tail = packet->prev;
-+ }
-+
-+ LIBSSH2_FREE(session, packet);
-+
-+ return 0;
-+ }
-+ packet = packet->next;
-+ }
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ sftp_packet_require
-+ * A la libssh2_packet_require
-+ */
-+static int
-+sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
-+ unsigned long request_id, unsigned char **data,
-+ unsigned long *data_len)
-+{
-+ LIBSSH2_SESSION *session = sftp->channel->session;
-+ int ret;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet",
-+ (int) packet_type);
-+
-+ if (sftp_packet_ask(sftp, packet_type, request_id, data,
-+ data_len, 0) == 0) {
-+ /* The right packet was available in the packet brigade */
-+ return 0;
-+ }
-+
-+ while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
-+ ret = sftp_packet_read(sftp);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (ret <= 0) {
-+ return -1;
-+ }
-+
-+ if (packet_type == ret) {
-+ /* Be lazy, let packet_ask pull it out of the brigade */
-+ return sftp_packet_ask(sftp, packet_type, request_id, data,
-+ data_len, 0);
-+ }
-+ }
-+
-+ /* Only reached if the socket died */
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ sftp_packet_requirev
-+ * Require one of N possible reponses
-+ */
-+static int
-+sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
-+ const unsigned char *valid_responses,
-+ unsigned long request_id, unsigned char **data,
-+ unsigned long *data_len)
-+{
-+ int i;
-+ int ret;
-+
-+ /* If no timeout is active, start a new one */
-+ if (sftp->requirev_start == 0) {
-+ sftp->requirev_start = time(NULL);
-+ }
-+
-+ while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
-+ for(i = 0; i < num_valid_responses; i++) {
-+ if (sftp_packet_ask(sftp, valid_responses[i], request_id,
-+ data, data_len, 0) == 0) {
-+ /*
-+ * Set to zero before all returns to say
-+ * the timeout is not active
-+ */
-+ sftp->requirev_start = 0;
-+ return 0;
-+ }
-+ }
-+
-+ ret = sftp_packet_read(sftp);
-+ if ((ret < 0) && (ret != PACKET_EAGAIN)) {
-+ sftp->requirev_start = 0;
-+ return -1;
-+ } else if (ret <= 0) {
-+ /* prevent busy-looping */
-+ long left =
-+ LIBSSH2_READ_TIMEOUT - (time(NULL) - sftp->requirev_start);
-+
-+ if (left <= 0) {
-+ sftp->requirev_start = 0;
-+ return PACKET_TIMEOUT;
-+ } else if (sftp->channel->session->socket_block
-+ && (libssh2_waitsocket(sftp->channel->session, left) <=
-+ 0)) {
-+ sftp->requirev_start = 0;
-+ return PACKET_TIMEOUT;
-+ } else if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+ }
-+
-+ sftp->requirev_start = 0;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_attrsize
-+ * Size that attr will occupy when turned into a bin struct
-+ */
-+static int
-+libssh2_sftp_attrsize(const LIBSSH2_SFTP_ATTRIBUTES * attrs)
-+{
-+ int attrsize = 4; /* flags(4) */
-+
-+ if (!attrs) {
-+ return attrsize;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE)
-+ attrsize += 8;
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID)
-+ attrsize += 8;
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS)
-+ attrsize += 4;
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME)
-+ attrsize += 8; /* atime + mtime as u32 */
-+
-+ return attrsize;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_attr2bin
-+ * Populate attributes into an SFTP block
-+ */
-+static int
-+libssh2_sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
-+{
-+ unsigned char *s = p;
-+ unsigned long flag_mask =
-+ LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID |
-+ LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
-+
-+ /* TODO: When we add SFTP4+ functionality flag_mask can get additional bits */
-+
-+ if (!attrs) {
-+ libssh2_htonu32(s, 0);
-+ return 4;
-+ }
-+
-+ libssh2_htonu32(s, attrs->flags & flag_mask);
-+ s += 4;
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
-+ libssh2_htonu64(s, attrs->filesize);
-+ s += 8;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
-+ libssh2_htonu32(s, attrs->uid);
-+ s += 4;
-+ libssh2_htonu32(s, attrs->gid);
-+ s += 4;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
-+ libssh2_htonu32(s, attrs->permissions);
-+ s += 4;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
-+ libssh2_htonu32(s, attrs->atime);
-+ s += 4;
-+ libssh2_htonu32(s, attrs->mtime);
-+ s += 4;
-+ }
-+
-+ return (s - p);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_bin2attr
-+ */
-+static int
-+libssh2_sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p)
-+{
-+ const unsigned char *s = p;
-+
-+ memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-+ attrs->flags = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
-+ attrs->filesize = libssh2_ntohu64(s);
-+ s += 8;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
-+ attrs->uid = libssh2_ntohu32(s);
-+ s += 4;
-+ attrs->gid = libssh2_ntohu32(s);
-+ s += 4;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
-+ attrs->permissions = libssh2_ntohu32(s);
-+ s += 4;
-+ }
-+
-+ if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
-+ attrs->atime = libssh2_ntohu32(s);
-+ s += 4;
-+ attrs->mtime = libssh2_ntohu32(s);
-+ s += 4;
-+ }
-+
-+ return (s - p);
-+}
-+
-+/* }}} */
-+
-+/* ************
-+ * SFTP API *
-+ ************ */
-+
-+LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor);
-+
-+/* {{{ libssh2_sftp_dtor
-+ * Shutdown an SFTP stream when the channel closes
-+ */
-+LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
-+{
-+ LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract);
-+
-+ (void) session_abstract;
-+ (void) channel;
-+
-+ /* Loop through handles closing them */
-+ while (sftp->handles) {
-+ libssh2_sftp_close_handle(sftp->handles);
-+ }
-+
-+ /* Free the partial packet storage for sftp_packet_read */
-+ if (sftp->partial_packet) {
-+ LIBSSH2_FREE(session, sftp->partial_packet);
-+ }
-+
-+ /* Free the packet storage for _libssh2_sftp_packet_readdir */
-+ if (sftp->readdir_packet) {
-+ LIBSSH2_FREE(session, sftp->readdir_packet);
-+ }
-+
-+ LIBSSH2_FREE(session, sftp);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_init
-+ * Startup an SFTP session
-+ *
-+ * NOTE: Will block in a busy loop on error. This has to be done,
-+ * otherwise the blocking error code would erase the true
-+ * cause of the error.
-+ */
-+LIBSSH2_API LIBSSH2_SFTP *
-+libssh2_sftp_init(LIBSSH2_SESSION * session)
-+{
-+ unsigned char *data, *s;
-+ unsigned long data_len;
-+ int rc;
-+
-+ if (session->sftpInit_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Initializing SFTP subsystem");
-+
-+ session->sftpInit_sftp = NULL;
-+
-+ session->sftpInit_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->sftpInit_state == libssh2_NB_state_created) {
-+ session->sftpInit_channel =
-+ libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
-+ LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-+ LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
-+ if (!session->sftpInit_channel) {
-+ if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block starting up channel", 0);
-+ return NULL;
-+ } else if (libssh2_session_last_errno(session) !=
-+ LIBSSH2_ERROR_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
-+ "Unable to startup channel", 0);
-+ session->sftpInit_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ }
-+
-+ session->sftpInit_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->sftpInit_state == libssh2_NB_state_sent) {
-+ rc = libssh2_channel_process_startup(session->sftpInit_channel,
-+ "subsystem",
-+ sizeof("subsystem") - 1, "sftp",
-+ strlen("sftp"));
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block to request SFTP subsystem", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
-+ "Unable to request SFTP subsystem", 0);
-+ goto sftp_init_error;
-+ }
-+
-+ session->sftpInit_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->sftpInit_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_channel_handle_extended_data2(session->sftpInit_channel,
-+ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block requesting handle extended data", 0);
-+ return NULL;
-+ }
-+
-+ session->sftpInit_sftp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
-+ if (!session->sftpInit_sftp) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate a new SFTP structure", 0);
-+ goto sftp_init_error;
-+ }
-+ memset(session->sftpInit_sftp, 0, sizeof(LIBSSH2_SFTP));
-+ session->sftpInit_sftp->channel = session->sftpInit_channel;
-+ session->sftpInit_sftp->request_id = 0;
-+
-+ libssh2_htonu32(session->sftpInit_buffer, 5);
-+ session->sftpInit_buffer[4] = SSH_FXP_INIT;
-+ libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Sending FXP_INIT packet advertising version %d support",
-+ (int) LIBSSH2_SFTP_VERSION);
-+
-+ session->sftpInit_state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (session->sftpInit_state == libssh2_NB_state_sent2) {
-+ rc = libssh2_channel_write_ex(session->sftpInit_channel, 0,
-+ (char *) session->sftpInit_buffer, 9);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending SSH_FXP_INIT", 0);
-+ return NULL;
-+ } else if (9 != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send SSH_FXP_INIT", 0);
-+ goto sftp_init_error;
-+ }
-+
-+ session->sftpInit_state = libssh2_NB_state_sent3;
-+ }
-+
-+ /* For initiallization we are requiring blocking, probably reasonable */
-+ rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
-+ 0, &data, &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for response from SFTP subsystem",
-+ 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for response from SFTP subsystem", 0);
-+ goto sftp_init_error;
-+ }
-+ if (data_len < 5) {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Invalid SSH_FXP_VERSION response", 0);
-+ goto sftp_init_error;
-+ }
-+
-+ s = data + 1;
-+ session->sftpInit_sftp->version = libssh2_ntohu32(s);
-+ s += 4;
-+ if (session->sftpInit_sftp->version > LIBSSH2_SFTP_VERSION) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Truncating remote SFTP version from %lu",
-+ session->sftpInit_sftp->version);
-+ session->sftpInit_sftp->version = LIBSSH2_SFTP_VERSION;
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Enabling SFTP version %lu compatability",
-+ session->sftpInit_sftp->version);
-+ while (s < (data + data_len)) {
-+ unsigned char *extension_name, *extension_data;
-+ unsigned long extname_len, extdata_len;
-+
-+ extname_len = libssh2_ntohu32(s);
-+ s += 4;
-+ extension_name = s;
-+ s += extname_len;
-+
-+ extdata_len = libssh2_ntohu32(s);
-+ s += 4;
-+ extension_data = s;
-+ s += extdata_len;
-+
-+ /* TODO: Actually process extensions */
-+ }
-+ LIBSSH2_FREE(session, data);
-+
-+ /* Make sure that when the channel gets closed, the SFTP service is shut down too */
-+ session->sftpInit_sftp->channel->abstract = session->sftpInit_sftp;
-+ session->sftpInit_sftp->channel->close_cb = libssh2_sftp_dtor;
-+
-+ session->sftpInit_state = libssh2_NB_state_idle;
-+ return session->sftpInit_sftp;
-+
-+ sftp_init_error:
-+ while (libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
-+ session->sftpInit_channel = NULL;
-+ if (session->sftpInit_sftp) {
-+ LIBSSH2_FREE(session, session->sftpInit_sftp);
-+ session->sftpInit_sftp = NULL;
-+ }
-+ session->sftpInit_state = libssh2_NB_state_idle;
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_shutdown
-+ * Shutsdown the SFTP subsystem
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
-+{
-+ /*
-+ * Make sure all memory used in the state variables are free
-+ */
-+ if (sftp->partial_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->partial_packet);
-+ sftp->partial_packet = NULL;
-+ }
-+ if (sftp->open_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->open_packet);
-+ sftp->open_packet = NULL;
-+ }
-+ if (sftp->readdir_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->readdir_packet);
-+ sftp->readdir_packet = NULL;
-+ }
-+ if (sftp->write_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->write_packet);
-+ sftp->write_packet = NULL;
-+ }
-+ if (sftp->fstat_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->fstat_packet);
-+ sftp->fstat_packet = NULL;
-+ }
-+ if (sftp->unlink_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->unlink_packet);
-+ sftp->unlink_packet = NULL;
-+ }
-+ if (sftp->rename_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->rename_packet);
-+ sftp->rename_packet = NULL;
-+ }
-+ if (sftp->mkdir_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->mkdir_packet);
-+ sftp->mkdir_packet = NULL;
-+ }
-+ if (sftp->rmdir_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->rmdir_packet);
-+ sftp->rmdir_packet = NULL;
-+ }
-+ if (sftp->stat_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->stat_packet);
-+ sftp->stat_packet = NULL;
-+ }
-+ if (sftp->symlink_packet) {
-+ LIBSSH2_FREE(sftp->channel->session, sftp->symlink_packet);
-+ sftp->symlink_packet = NULL;
-+ }
-+
-+ return libssh2_channel_free(sftp->channel);
-+}
-+
-+/* }}} */
-+
-+/* *******************************
-+ * SFTP File and Directory Ops *
-+ ******************************* */
-+
-+/* {{{ libssh2_sftp_open_ex
-+ */
-+LIBSSH2_API LIBSSH2_SFTP_HANDLE *
-+libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
-+ unsigned int filename_len, unsigned long flags, long mode,
-+ int open_type)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_SFTP_HANDLE *fp;
-+ LIBSSH2_SFTP_ATTRIBUTES attrs = {
-+ LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
-+ };
-+ unsigned long data_len;
-+ unsigned char *data, *s;
-+ static const unsigned char fopen_responses[2] =
-+ { SSH_FXP_HANDLE, SSH_FXP_STATUS };
-+ int rc;
-+
-+ if (sftp->open_state == libssh2_NB_state_idle) {
-+ /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
-+ flags(4) */
-+ sftp->open_packet_len = filename_len + 13 +
-+ ((open_type ==
-+ LIBSSH2_SFTP_OPENFILE) ? (4 +
-+ libssh2_sftp_attrsize(&attrs)) : 0);
-+
-+ s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
-+ if (!sftp->open_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_OPEN or "
-+ "FXP_OPENDIR packet",
-+ 0);
-+ return NULL;
-+ }
-+ /* Filetype in SFTP 3 and earlier */
-+ attrs.permissions = mode |
-+ ((open_type ==
-+ LIBSSH2_SFTP_OPENFILE) ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE :
-+ LIBSSH2_SFTP_ATTR_PFILETYPE_DIR);
-+
-+ libssh2_htonu32(s, sftp->open_packet_len - 4);
-+ s += 4;
-+ *(s++) =
-+ (open_type ==
-+ LIBSSH2_SFTP_OPENFILE) ? SSH_FXP_OPEN : SSH_FXP_OPENDIR;
-+ sftp->open_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->open_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, filename_len);
-+ s += 4;
-+ memcpy(s, filename, filename_len);
-+ s += filename_len;
-+ if (open_type == LIBSSH2_SFTP_OPENFILE) {
-+ libssh2_htonu32(s, flags);
-+ s += 4;
-+ s += libssh2_sftp_attr2bin(s, &attrs);
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Sending %s open request",
-+ (open_type ==
-+ LIBSSH2_SFTP_OPENFILE) ? "file" : "directory");
-+
-+ sftp->open_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->open_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->open_packet,
-+ sftp->open_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending FXP_OPEN or FXP_OPENDIR command",
-+ 0);
-+ return NULL;
-+ }
-+ else if (sftp->open_packet_len != rc) {
-+ /* TODO: partial writes should be fine too and is not a sign of
-+ an error when in non-blocking mode! */
-+
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_OPEN or FXP_OPENDIR command", 0);
-+ LIBSSH2_FREE(session, sftp->open_packet);
-+ sftp->open_packet = NULL;
-+ sftp->open_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ LIBSSH2_FREE(session, sftp->open_packet);
-+ sftp->open_packet = NULL;
-+
-+ sftp->open_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (sftp->open_state == libssh2_NB_state_sent) {
-+ rc = sftp_packet_requirev(sftp, 2, fopen_responses,
-+ sftp->open_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for status message", 0);
-+ return NULL;
-+ }
-+ else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->open_state = libssh2_NB_state_idle;
-+ return NULL;
-+ }
-+ }
-+
-+ sftp->open_state = libssh2_NB_state_idle;
-+
-+ /* OPEN can basically get STATUS or HANDLE back, where HANDLE implies a
-+ fine response while STATUS means error. It seems though that at times
-+ we get an SSH_FX_OK back in a STATUS, followed the "real" HANDLE so
-+ we need to properly deal with that. */
-+ if (data[0] == SSH_FXP_STATUS) {
-+ int badness = 1;
-+ sftp->last_errno = libssh2_ntohu32(data + 5);
-+
-+ if(LIBSSH2_FX_OK == sftp->last_errno) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "got HANDLE FXOK!");
-+
-+ /* silly situation, but check for a HANDLE */
-+ rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
-+ sftp->open_request_id, &data, &data_len);
-+ if(rc == PACKET_EAGAIN) {
-+ /* go back to sent state and wait for something else */
-+ sftp->open_state = libssh2_NB_state_sent;
-+ return NULL;
-+ }
-+ else if(!rc)
-+ /* we got the handle so this is not a bad situation */
-+ badness = 0;
-+ }
-+
-+ if(badness) {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Failed opening remote file", 0);
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
-+ sftp->last_errno);
-+ LIBSSH2_FREE(session, data);
-+ return NULL;
-+ }
-+ }
-+
-+ fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
-+ if (!fp) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate new SFTP handle structure", 0);
-+ LIBSSH2_FREE(session, data);
-+ return NULL;
-+ }
-+ memset(fp, 0, sizeof(LIBSSH2_SFTP_HANDLE));
-+ fp->handle_type =
-+ (open_type ==
-+ LIBSSH2_SFTP_OPENFILE) ? LIBSSH2_SFTP_HANDLE_FILE :
-+ LIBSSH2_SFTP_HANDLE_DIR;
-+
-+ fp->handle_len = libssh2_ntohu32(data + 5);
-+ if (fp->handle_len > SFTP_HANDLE_MAXLEN) {
-+ /* SFTP doesn't allow handles longer than 256 characters */
-+ fp->handle_len = SFTP_HANDLE_MAXLEN;
-+ }
-+
-+ memcpy(fp->handle, data + 9, fp->handle_len);
-+ LIBSSH2_FREE(session, data);
-+
-+ /* Link the file and the sftp session together */
-+ fp->next = sftp->handles;
-+ if (fp->next) {
-+ fp->next->prev = fp;
-+ }
-+ fp->sftp = sftp;
-+
-+ fp->u.file.offset = 0;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Open command successful");
-+ return fp;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_read
-+ * Read from an SFTP file handle
-+ */
-+LIBSSH2_API ssize_t
-+libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
-+ size_t buffer_maxlen)
-+{
-+ LIBSSH2_SFTP *sftp = handle->sftp;
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, request_id = 0;
-+ /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
-+ offset(8) + length(4) */
-+ ssize_t packet_len = handle->handle_len + 25;
-+ unsigned char *packet, *s, *data;
-+ static const unsigned char read_responses[2] =
-+ { SSH_FXP_DATA, SSH_FXP_STATUS };
-+ size_t bytes_read = 0;
-+ size_t bytes_requested = 0;
-+ size_t total_read = 0;
-+ int retcode;
-+
-+ if (sftp->read_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Reading %lu bytes from SFTP handle",
-+ (unsigned long) buffer_maxlen);
-+ packet = handle->request_packet;
-+ sftp->read_state = libssh2_NB_state_allocated;
-+ } else {
-+ packet = sftp->read_packet;
-+ request_id = sftp->read_request_id;
-+ total_read = sftp->read_total_read;
-+ }
-+
-+ while (total_read < buffer_maxlen) {
-+ s = packet;
-+ /*
-+ * If buffer_maxlen bytes will be requested, server may return all
-+ * with one packet. But libssh2 have packet length limit.
-+ * So we request data by pieces.
-+ */
-+ bytes_requested = buffer_maxlen - total_read;
-+ /* 10 = packet_type(1) + request_id(4) + data_length(4) +
-+ end_of_line_flag(1)
-+
-+ 10 is changed to 13 below simple because it seems there's a
-+ "GlobalScape" SFTP server that responds with a slightly too big
-+ buffer at times and we can apparently compensate for that by doing
-+ this trick.
-+
-+ Further details on this issue:
-+
-+ https://sourceforge.net/mailarchive/forum.php?thread_name=9c3275a90811261517v6c0b1da2u918cc1b8370abf83%40mail.gmail.com&forum_name=libssh2-devel
-+
-+ http://forums.globalscape.com/tm.aspx?m=15249
-+
-+ */
-+ if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 13) {
-+ bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 13;
-+ }
-+#ifdef LIBSSH2_DEBUG_SFTP
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Requesting %lu bytes from SFTP handle",
-+ (unsigned long) bytes_requested);
-+#endif
-+
-+ if (sftp->read_state == libssh2_NB_state_allocated) {
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_READ;
-+ request_id = sftp->request_id++;
-+ libssh2_htonu32(s, request_id);
-+ s += 4;
-+ libssh2_htonu32(s, handle->handle_len);
-+ s += 4;
-+
-+ memcpy(s, handle->handle, handle->handle_len);
-+ s += handle->handle_len;
-+
-+ libssh2_htonu64(s, handle->u.file.offset);
-+ s += 8;
-+
-+ libssh2_htonu32(s, bytes_requested);
-+ s += 4;
-+
-+ sftp->read_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->read_state == libssh2_NB_state_created) {
-+ retcode =
-+ libssh2_channel_write_ex(channel, 0, (char *) packet,
-+ packet_len);
-+ if (retcode == PACKET_EAGAIN) {
-+ sftp->read_packet = packet;
-+ sftp->read_request_id = request_id;
-+ sftp->read_total_read = total_read;
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != retcode) {
-+ /* TODO: a partial write is not a critical error when in
-+ non-blocking mode! */
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_READ command", 0);
-+ sftp->read_packet = NULL;
-+ sftp->read_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ sftp->read_packet = packet;
-+ sftp->read_request_id = request_id;
-+ sftp->read_total_read = total_read;
-+ sftp->read_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (sftp->read_state == libssh2_NB_state_sent) {
-+ retcode =
-+ sftp_packet_requirev(sftp, 2, read_responses,
-+ request_id, &data, &data_len);
-+ if (retcode == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->read_packet = NULL;
-+ sftp->read_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->read_state = libssh2_NB_state_sent1;
-+ }
-+
-+ switch (data[0]) {
-+ case SSH_FXP_STATUS:
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+ sftp->read_packet = NULL;
-+ sftp->read_state = libssh2_NB_state_idle;
-+
-+ if (retcode == LIBSSH2_FX_EOF) {
-+ return total_read;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+
-+ case SSH_FXP_DATA:
-+ bytes_read = libssh2_ntohu32(data + 5);
-+ if (bytes_read > (data_len - 9)) {
-+ sftp->read_packet = NULL;
-+ sftp->read_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+#ifdef LIBSSH2_DEBUG_SFTP
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu bytes returned",
-+ (unsigned long) bytes_read);
-+#endif
-+ memcpy(buffer + total_read, data + 9, bytes_read);
-+ handle->u.file.offset += bytes_read;
-+ total_read += bytes_read;
-+ LIBSSH2_FREE(session, data);
-+ /*
-+ * Set the state back to allocated, so a new one will be
-+ * created to either request more data or get EOF
-+ */
-+ sftp->read_state = libssh2_NB_state_allocated;
-+ }
-+ }
-+
-+ sftp->read_packet = NULL;
-+ sftp->read_state = libssh2_NB_state_idle;
-+ return total_read;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_readdir
-+ * Read from an SFTP directory handle
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
-+ size_t buffer_maxlen, char *longentry,
-+ size_t longentry_maxlen,
-+ LIBSSH2_SFTP_ATTRIBUTES * attrs)
-+{
-+ LIBSSH2_SFTP *sftp = handle->sftp;
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
-+ unsigned long data_len, filename_len, longentry_len, num_names;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
-+ ssize_t packet_len = handle->handle_len + 13;
-+ unsigned char *s, *data;
-+ unsigned char read_responses[2] = { SSH_FXP_NAME, SSH_FXP_STATUS };
-+ int retcode;
-+
-+ if (sftp->readdir_state == libssh2_NB_state_idle) {
-+ if (handle->u.dir.names_left) {
-+ /*
-+ * A prior request returned more than one directory entry,
-+ * feed it back from the buffer
-+ */
-+ unsigned char *s = (unsigned char *) handle->u.dir.next_name;
-+ unsigned long real_filename_len = libssh2_ntohu32(s);
-+
-+ filename_len = real_filename_len;
-+ s += 4;
-+ if (filename_len > buffer_maxlen) {
-+ filename_len = buffer_maxlen;
-+ }
-+ memcpy(buffer, s, filename_len);
-+ s += real_filename_len;
-+
-+ /* The filename is not null terminated, make it so if possible */
-+ if (filename_len < buffer_maxlen) {
-+ buffer[filename_len] = '\0';
-+ }
-+
-+ if ((longentry == NULL) || (longentry_maxlen == 0)) {
-+ /* Skip longname */
-+ s += 4 + libssh2_ntohu32(s);
-+ } else {
-+ unsigned long real_longentry_len = libssh2_ntohu32(s);
-+
-+ longentry_len = real_longentry_len;
-+ s += 4;
-+ if (longentry_len > longentry_maxlen) {
-+ longentry_len = longentry_maxlen;
-+ }
-+ memcpy(longentry, s, longentry_len);
-+ s += real_longentry_len;
-+
-+ /* The longentry is not null terminated, make it so if possible */
-+ if (longentry_len < longentry_maxlen) {
-+ longentry[longentry_len] = '\0';
-+ }
-+ }
-+
-+ if (attrs) {
-+ memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-+ }
-+ s += libssh2_sftp_bin2attr(attrs ? attrs : &attrs_dummy, s);
-+
-+ handle->u.dir.next_name = (char *) s;
-+ if ((--handle->u.dir.names_left) == 0) {
-+ LIBSSH2_FREE(session, handle->u.dir.names_packet);
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "libssh2_sftp_readdir_ex() return %d",
-+ filename_len);
-+ return filename_len;
-+ }
-+
-+ /* Request another entry(entries?) */
-+
-+ s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->readdir_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_READDIR packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_READDIR;
-+ sftp->readdir_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->readdir_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, handle->handle_len);
-+ s += 4;
-+ memcpy(s, handle->handle, handle->handle_len);
-+ s += handle->handle_len;
-+
-+ sftp->readdir_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->readdir_state == libssh2_NB_state_created) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Reading entries from directory handle");
-+ if ((retcode =
-+ libssh2_channel_write_ex(channel, 0,
-+ (char *) sftp->readdir_packet,
-+ packet_len)) == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != retcode) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_READ command", 0);
-+ LIBSSH2_FREE(session, sftp->readdir_packet);
-+ sftp->readdir_packet = NULL;
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ LIBSSH2_FREE(session, sftp->readdir_packet);
-+ sftp->readdir_packet = NULL;
-+
-+ sftp->readdir_state = libssh2_NB_state_sent;
-+ }
-+
-+ retcode =
-+ sftp_packet_requirev(sftp, 2, read_responses,
-+ sftp->readdir_request_id, &data,
-+ &data_len);
-+ if (retcode == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (data[0] == SSH_FXP_STATUS) {
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+ if (retcode == LIBSSH2_FX_EOF) {
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ }
-+
-+ num_names = libssh2_ntohu32(data + 5);
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned",
-+ num_names);
-+ if (num_names <= 0) {
-+ LIBSSH2_FREE(session, data);
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return (num_names == 0) ? 0 : -1;
-+ }
-+
-+ if (num_names == 1) {
-+ unsigned long real_filename_len = libssh2_ntohu32(data + 9);
-+
-+ filename_len = real_filename_len;
-+ if (filename_len > buffer_maxlen) {
-+ filename_len = buffer_maxlen;
-+ }
-+ memcpy(buffer, data + 13, filename_len);
-+
-+ /* The filename is not null terminated, make it so if possible */
-+ if (filename_len < buffer_maxlen) {
-+ buffer[filename_len] = '\0';
-+ }
-+
-+ if (attrs) {
-+ memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-+ libssh2_sftp_bin2attr(attrs, data + 13 + real_filename_len +
-+ (4 +
-+ libssh2_ntohu32(data + 13 +
-+ real_filename_len)));
-+ }
-+ LIBSSH2_FREE(session, data);
-+
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+ return filename_len;
-+ }
-+
-+ handle->u.dir.names_left = num_names;
-+ handle->u.dir.names_packet = data;
-+ handle->u.dir.next_name = (char *) data + 9;
-+
-+ sftp->readdir_state = libssh2_NB_state_idle;
-+
-+ /* Be lazy, just use the name popping mechanism from the start of the function */
-+ return libssh2_sftp_readdir_ex(handle, buffer, buffer_maxlen, longentry,
-+ longentry_maxlen, attrs);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_write
-+ * Write data to a file handle
-+ */
-+LIBSSH2_API ssize_t
-+libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
-+ size_t count)
-+{
-+ LIBSSH2_SFTP *sftp = handle->sftp;
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, retcode;
-+ /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
-+ offset(8) + count(4) */
-+ ssize_t packet_len = handle->handle_len + count + 25;
-+ unsigned char *s, *data;
-+ int rc;
-+
-+ if (sftp->write_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
-+ (unsigned long) count);
-+ s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->write_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_WRITE packet", 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_WRITE;
-+ sftp->write_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->write_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, handle->handle_len);
-+ s += 4;
-+ memcpy(s, handle->handle, handle->handle_len);
-+ s += handle->handle_len;
-+ libssh2_htonu64(s, handle->u.file.offset);
-+ s += 8;
-+ libssh2_htonu32(s, count);
-+ s += 4;
-+ memcpy(s, buffer, count);
-+ s += count;
-+
-+ sftp->write_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->write_state == libssh2_NB_state_created) {
-+ if ((rc =
-+ libssh2_channel_write_ex(channel, 0, (char *) sftp->write_packet,
-+ packet_len)) == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_READ command", 0);
-+ LIBSSH2_FREE(session, sftp->write_packet);
-+ sftp->write_packet = NULL;
-+ sftp->write_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->write_packet);
-+ sftp->write_packet = NULL;
-+ sftp->write_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
-+ sftp->write_request_id, &data, &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->write_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->write_state = libssh2_NB_state_idle;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ if (retcode == LIBSSH2_FX_OK) {
-+ handle->u.file.offset += count;
-+ return count;
-+ }
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error",
-+ 0);
-+ sftp->last_errno = retcode;
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_fstat_ex
-+ * Get or Set stat on a file
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
-+ LIBSSH2_SFTP_ATTRIBUTES * attrs, int setstat)
-+{
-+ LIBSSH2_SFTP *sftp = handle->sftp;
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
-+ ssize_t packet_len =
-+ handle->handle_len + 13 + (setstat ? libssh2_sftp_attrsize(attrs) : 0);
-+ unsigned char *s, *data;
-+ static const unsigned char fstat_responses[2] =
-+ { SSH_FXP_ATTRS, SSH_FXP_STATUS };
-+ int rc;
-+
-+ if (sftp->fstat_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Issuing %s command",
-+ setstat ? "set-stat" : "stat");
-+ s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->fstat_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FSTAT/FSETSTAT packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT;
-+ sftp->fstat_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->fstat_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, handle->handle_len);
-+ s += 4;
-+ memcpy(s, handle->handle, handle->handle_len);
-+ s += handle->handle_len;
-+ if (setstat) {
-+ s += libssh2_sftp_attr2bin(s, attrs);
-+ }
-+
-+ sftp->fstat_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->fstat_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->fstat_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ (setstat ? "Unable to send FXP_FSETSTAT"
-+ : "Unable to send FXP_FSTAT command"), 0);
-+ LIBSSH2_FREE(session, sftp->fstat_packet);
-+ sftp->fstat_packet = NULL;
-+ sftp->fstat_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->fstat_packet);
-+ sftp->fstat_packet = NULL;
-+
-+ sftp->fstat_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_requirev(sftp, 2, fstat_responses,
-+ sftp->fstat_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->fstat_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->fstat_state = libssh2_NB_state_idle;
-+
-+ if (data[0] == SSH_FXP_STATUS) {
-+ int retcode;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+ }
-+
-+ libssh2_sftp_bin2attr(attrs, data + 5);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_seek
-+ * Set the read/write pointer to an arbitrary position within the file
-+ */
-+LIBSSH2_API void
-+libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle, size_t offset)
-+{
-+ handle->u.file.offset = offset;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_seek64
-+ * Set the read/write pointer to an arbitrary position within the file
-+ */
-+LIBSSH2_API void
-+libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle, libssh2_uint64_t offset)
-+{
-+ handle->u.file.offset = offset;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_tell
-+ * Return the current read/write pointer's offset
-+ */
-+LIBSSH2_API size_t
-+libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
-+{
-+ return handle->u.file.offset;
-+}
-+
-+/* {{{ libssh2_sftp_tell64
-+ * Return the current read/write pointer's offset
-+ */
-+LIBSSH2_API libssh2_uint64_t
-+libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle)
-+{
-+ return handle->u.file.offset;
-+}
-+
-+/* }}} */
-+
-+
-+/* {{{ libssh2_sftp_close_handle
-+ * Close a file or directory handle
-+ * Also frees handle resource and unlinks it from the SFTP structure
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
-+{
-+ LIBSSH2_SFTP *sftp = handle->sftp;
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, retcode;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
-+ ssize_t packet_len = handle->handle_len + 13;
-+ unsigned char *s, *data;
-+ int rc;
-+
-+ if (handle->close_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Closing handle");
-+ s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!handle->close_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_CLOSE packet", 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_CLOSE;
-+ handle->close_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, handle->close_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, handle->handle_len);
-+ s += 4;
-+ memcpy(s, handle->handle, handle->handle_len);
-+ s += handle->handle_len;
-+
-+ handle->close_state = libssh2_NB_state_created;
-+ }
-+
-+ if (handle->close_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0,
-+ (char *) handle->close_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_CLOSE command", 0);
-+ LIBSSH2_FREE(session, handle->close_packet);
-+ handle->close_packet = NULL;
-+ handle->close_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, handle->close_packet);
-+ handle->close_packet = NULL;
-+
-+ handle->close_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (handle->close_state == libssh2_NB_state_sent) {
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
-+ handle->close_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ handle->close_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ handle->close_state = libssh2_NB_state_sent1;
-+ }
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ if (retcode != LIBSSH2_FX_OK) {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ handle->close_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (handle == sftp->handles) {
-+ sftp->handles = handle->next;
-+ }
-+ if (handle->next) {
-+ handle->next->prev = NULL;
-+ }
-+
-+ if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
-+ && handle->u.dir.names_left) {
-+ LIBSSH2_FREE(session, handle->u.dir.names_packet);
-+ }
-+
-+ handle->close_state = libssh2_NB_state_idle;
-+
-+ LIBSSH2_FREE(session, handle);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* **********************
-+ * SFTP Miscellaneous *
-+ ********************** */
-+
-+/* {{{ libssh2_sftp_unlink_ex
-+ * Delete a file from the remote server
-+ */
-+/* libssh2_sftp_unlink_ex - NB-UNSAFE?? */
-+LIBSSH2_API int
-+libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
-+ unsigned int filename_len)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, retcode;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
-+ ssize_t packet_len = filename_len + 13;
-+ unsigned char *s, *data;
-+ int rc;
-+
-+ if (sftp->unlink_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Unlinking %s", filename);
-+ s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->unlink_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_REMOVE packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_REMOVE;
-+ sftp->unlink_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->unlink_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, filename_len);
-+ s += 4;
-+ memcpy(s, filename, filename_len);
-+ s += filename_len;
-+
-+ sftp->unlink_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->unlink_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->unlink_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_REMOVE command", 0);
-+ LIBSSH2_FREE(session, sftp->unlink_packet);
-+ sftp->unlink_packet = NULL;
-+ sftp->unlink_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->unlink_packet);
-+ sftp->unlink_packet = NULL;
-+
-+ sftp->unlink_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
-+ sftp->unlink_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->unlink_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->unlink_state = libssh2_NB_state_idle;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_rename_ex
-+ * Rename a file on the remote server
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
-+ unsigned int source_filename_len,
-+ const char *dest_filename,
-+ unsigned int dest_filename_len, long flags)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, retcode;
-+ ssize_t packet_len =
-+ source_filename_len + dest_filename_len + 17 + (sftp->version >=
-+ 5 ? 4 : 0);
-+ /* packet_len(4) + packet_type(1) + request_id(4) +
-+ source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
-+ unsigned char *data;
-+ int rc;
-+
-+ if (sftp->version < 2) {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Server does not support RENAME", 0);
-+ return -1;
-+ }
-+
-+ if (sftp->rename_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Renaming %s to %s",
-+ source_filename, dest_filename);
-+ sftp->rename_s = sftp->rename_packet =
-+ LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->rename_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_RENAME packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(sftp->rename_s, packet_len - 4);
-+ sftp->rename_s += 4;
-+ *(sftp->rename_s++) = SSH_FXP_RENAME;
-+ sftp->rename_request_id = sftp->request_id++;
-+ libssh2_htonu32(sftp->rename_s, sftp->rename_request_id);
-+ sftp->rename_s += 4;
-+ libssh2_htonu32(sftp->rename_s, source_filename_len);
-+ sftp->rename_s += 4;
-+ memcpy(sftp->rename_s, source_filename, source_filename_len);
-+ sftp->rename_s += source_filename_len;
-+ libssh2_htonu32(sftp->rename_s, dest_filename_len);
-+ sftp->rename_s += 4;
-+ memcpy(sftp->rename_s, dest_filename, dest_filename_len);
-+ sftp->rename_s += dest_filename_len;
-+
-+ if (sftp->version >= 5) {
-+ libssh2_htonu32(sftp->rename_s, flags);
-+ sftp->rename_s += 4;
-+ }
-+
-+ sftp->rename_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->rename_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->rename_packet,
-+ sftp->rename_s - sftp->rename_packet);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_RENAME command", 0);
-+ LIBSSH2_FREE(session, sftp->rename_packet);
-+ sftp->rename_packet = NULL;
-+ sftp->rename_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->rename_packet);
-+ sftp->rename_packet = NULL;
-+
-+ sftp->rename_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
-+ sftp->rename_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->rename_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->rename_state = libssh2_NB_state_idle;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ switch (retcode) {
-+ case LIBSSH2_FX_OK:
-+ retcode = 0;
-+ break;
-+
-+ case LIBSSH2_FX_FILE_ALREADY_EXISTS:
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "File already exists and SSH_FXP_RENAME_OVERWRITE not specified",
-+ 0);
-+ sftp->last_errno = retcode;
-+ retcode = -1;
-+ break;
-+
-+ case LIBSSH2_FX_OP_UNSUPPORTED:
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Operation Not Supported", 0);
-+ sftp->last_errno = retcode;
-+ retcode = -1;
-+ break;
-+
-+ default:
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ sftp->last_errno = retcode;
-+ retcode = -1;
-+ }
-+
-+ return retcode;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_mkdir_ex
-+ * Create an SFTP directory
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
-+ unsigned int path_len, long mode)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_SFTP_ATTRIBUTES attrs = {
-+ LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
-+ };
-+ unsigned long data_len, retcode, request_id;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
-+ ssize_t packet_len = path_len + 13 + libssh2_sftp_attrsize(&attrs);
-+ unsigned char *packet, *s, *data;
-+ int rc;
-+
-+ if (sftp->mkdir_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP,
-+ "Creating directory %s with mode 0%lo", path, mode);
-+ s = packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_MKDIR packet", 0);
-+ return -1;
-+ }
-+ /* Filetype in SFTP 3 and earlier */
-+ attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_MKDIR;
-+ request_id = sftp->request_id++;
-+ libssh2_htonu32(s, request_id);
-+ s += 4;
-+ libssh2_htonu32(s, path_len);
-+ s += 4;
-+ memcpy(s, path, path_len);
-+ s += path_len;
-+ s += libssh2_sftp_attr2bin(s, &attrs);
-+
-+ sftp->mkdir_state = libssh2_NB_state_created;
-+ } else {
-+ packet = sftp->mkdir_packet;
-+ request_id = sftp->mkdir_request_id;
-+ }
-+
-+ if (sftp->mkdir_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) packet, packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ sftp->mkdir_packet = packet;
-+ sftp->mkdir_request_id = request_id;
-+ return PACKET_EAGAIN;
-+ }
-+ if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_READ command", 0);
-+ LIBSSH2_FREE(session, packet);
-+ sftp->mkdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, packet);
-+ sftp->mkdir_state = libssh2_NB_state_sent;
-+ sftp->mkdir_packet = NULL;
-+ }
-+
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->mkdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->mkdir_state = libssh2_NB_state_idle;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ sftp->last_errno = retcode;
-+ return -1;
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_rmdir_ex
-+ * Remove a directory
-+ */
-+/* libssh2_sftp_rmdir_ex - NB-UNSAFE?? */
-+LIBSSH2_API int
-+libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
-+ unsigned int path_len)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, retcode;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
-+ ssize_t packet_len = path_len + 13;
-+ unsigned char *s, *data;
-+ int rc;
-+
-+ if (sftp->rmdir_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Removing directory: %s",
-+ path);
-+ s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->rmdir_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_MKDIR packet", 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ *(s++) = SSH_FXP_RMDIR;
-+ sftp->rmdir_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->rmdir_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, path_len);
-+ s += 4;
-+ memcpy(s, path, path_len);
-+ s += path_len;
-+
-+ sftp->rmdir_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->rmdir_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->rmdir_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send FXP_MKDIR command", 0);
-+ LIBSSH2_FREE(session, sftp->rmdir_packet);
-+ sftp->rmdir_packet = NULL;
-+ sftp->rmdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->rmdir_packet);
-+ sftp->rmdir_packet = NULL;
-+
-+ sftp->rmdir_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
-+ sftp->rmdir_request_id, &data, &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->rmdir_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->rmdir_state = libssh2_NB_state_idle;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_stat_ex
-+ * Stat a file or symbolic link
-+ */
-+/* libssh2_sftp_stat_ex - NB-UNSAFE?? */
-+LIBSSH2_API int
-+libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
-+ unsigned int path_len, int stat_type,
-+ LIBSSH2_SFTP_ATTRIBUTES * attrs)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
-+ ssize_t packet_len =
-+ path_len + 13 +
-+ ((stat_type ==
-+ LIBSSH2_SFTP_SETSTAT) ? libssh2_sftp_attrsize(attrs) : 0);
-+ unsigned char *s, *data;
-+ static const unsigned char stat_responses[2] =
-+ { SSH_FXP_ATTRS, SSH_FXP_STATUS };
-+ int rc;
-+
-+ if (sftp->stat_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s",
-+ (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
-+ (stat_type ==
-+ LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
-+ s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->stat_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for FXP_MKDIR packet", 0);
-+ return -1;
-+ }
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ switch (stat_type) {
-+ case LIBSSH2_SFTP_SETSTAT:
-+ *(s++) = SSH_FXP_SETSTAT;
-+ break;
-+
-+ case LIBSSH2_SFTP_LSTAT:
-+ *(s++) = SSH_FXP_LSTAT;
-+ break;
-+
-+ case LIBSSH2_SFTP_STAT:
-+ default:
-+ *(s++) = SSH_FXP_STAT;
-+ }
-+ sftp->stat_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->stat_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, path_len);
-+ s += 4;
-+ memcpy(s, path, path_len);
-+ s += path_len;
-+ if (stat_type == LIBSSH2_SFTP_SETSTAT) {
-+ s += libssh2_sftp_attr2bin(s, attrs);
-+ }
-+
-+ sftp->stat_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->stat_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->stat_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send STAT/LSTAT/SETSTAT command", 0);
-+ LIBSSH2_FREE(session, sftp->stat_packet);
-+ sftp->stat_packet = NULL;
-+ sftp->stat_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->stat_packet);
-+ sftp->stat_packet = NULL;
-+
-+ sftp->stat_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_requirev(sftp, 2, stat_responses,
-+ sftp->stat_request_id, &data, &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->stat_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->stat_state = libssh2_NB_state_idle;
-+
-+ if (data[0] == SSH_FXP_STATUS) {
-+ int retcode;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+ }
-+
-+ memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
-+ libssh2_sftp_bin2attr(attrs, data + 5);
-+ LIBSSH2_FREE(session, data);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_symlink_ex
-+ * Read or set a symlink
-+ */
-+LIBSSH2_API int
-+libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
-+ unsigned int path_len, char *target,
-+ unsigned int target_len, int link_type)
-+{
-+ LIBSSH2_CHANNEL *channel = sftp->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned long data_len, link_len;
-+ /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
-+ ssize_t packet_len =
-+ path_len + 13 +
-+ ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
-+ unsigned char *s, *data;
-+ static const unsigned char link_responses[2] =
-+ { SSH_FXP_NAME, SSH_FXP_STATUS };
-+ int rc;
-+
-+ if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Server does not support SYMLINK or READLINK", 0);
-+ return -1;
-+ }
-+
-+ if (sftp->symlink_state == libssh2_NB_state_idle) {
-+ s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!sftp->symlink_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for SYMLINK/READLINK"
-+ "/REALPATH packet", 0);
-+ return -1;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s on %s",
-+ (link_type ==
-+ LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
-+ (link_type ==
-+ LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path);
-+
-+ libssh2_htonu32(s, packet_len - 4);
-+ s += 4;
-+ switch (link_type) {
-+ case LIBSSH2_SFTP_REALPATH:
-+ *(s++) = SSH_FXP_REALPATH;
-+ break;
-+
-+ case LIBSSH2_SFTP_SYMLINK:
-+ *(s++) = SSH_FXP_SYMLINK;
-+ break;
-+
-+ case LIBSSH2_SFTP_READLINK:
-+ default:
-+ *(s++) = SSH_FXP_READLINK;
-+ }
-+ sftp->symlink_request_id = sftp->request_id++;
-+ libssh2_htonu32(s, sftp->symlink_request_id);
-+ s += 4;
-+ libssh2_htonu32(s, path_len);
-+ s += 4;
-+ memcpy(s, path, path_len);
-+ s += path_len;
-+ if (link_type == LIBSSH2_SFTP_SYMLINK) {
-+ libssh2_htonu32(s, target_len);
-+ s += 4;
-+ memcpy(s, target, target_len);
-+ s += target_len;
-+ }
-+
-+ sftp->symlink_state = libssh2_NB_state_created;
-+ }
-+
-+ if (sftp->symlink_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0,
-+ (char *) sftp->symlink_packet,
-+ packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (packet_len != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send SYMLINK/READLINK command", 0);
-+ LIBSSH2_FREE(session, sftp->symlink_packet);
-+ sftp->symlink_packet = NULL;
-+ sftp->symlink_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, sftp->symlink_packet);
-+ sftp->symlink_packet = NULL;
-+
-+ sftp->symlink_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = sftp_packet_requirev(sftp, 2, link_responses,
-+ sftp->symlink_request_id, &data,
-+ &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for status message", 0);
-+ sftp->symlink_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ sftp->symlink_state = libssh2_NB_state_idle;
-+
-+ if (data[0] == SSH_FXP_STATUS) {
-+ int retcode;
-+
-+ retcode = libssh2_ntohu32(data + 5);
-+ LIBSSH2_FREE(session, data);
-+ if (retcode == LIBSSH2_FX_OK) {
-+ return 0;
-+ } else {
-+ sftp->last_errno = retcode;
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "SFTP Protocol Error", 0);
-+ return -1;
-+ }
-+ }
-+
-+ if (libssh2_ntohu32(data + 5) < 1) {
-+ libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
-+ "Invalid READLINK/REALPATH response, no name entries",
-+ 0);
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+
-+ link_len = libssh2_ntohu32(data + 9);
-+ if (link_len >= target_len) {
-+ link_len = target_len - 1;
-+ }
-+ memcpy(target, data + 13, link_len);
-+ target[link_len] = 0;
-+ LIBSSH2_FREE(session, data);
-+
-+ return link_len;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_sftp_last_error
-+ * Returns the last error code reported by SFTP
-+ */
-+LIBSSH2_API unsigned long
-+libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)
-+{
-+ return sftp->last_errno;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/sftp.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/libssh2_config.h.in.w32
-===================================================================
---- libssh2/src/libssh2_config.h.in.w32 (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/libssh2_config.h.in.w32 (.../trunk)
-@@ -0,0 +1,44 @@
-+#ifndef LIBSSH2_CONFIG_H
-+#define LIBSSH2_CONFIG_H
-+
-+#ifndef WIN32
-+#define WIN32
-+#endif
-+#include <winsock2.h>
-+#include <mswsock.h>
-+#include <ws2tcpip.h>
-+
-+#ifdef __MINGW32__
-+#define HAVE_UNISTD_H
-+#define HAVE_INTTYPES_H
-+#define HAVE_SYS_TIME_H
-+#endif
-+
-+#define HAVE_WINSOCK2_H
-+#define HAVE_IOCTLSOCKET
-+#define HAVE_SELECT
-+
-+#ifdef _MSC_VER
-+#define snprintf _snprintf
-+#if _MSC_VER < 1500
-+#define vsnprintf _vsnprintf
-+#else
-+#define ssize_t SSIZE_T
-+#define uint32_t UINT32
-+#endif
-+#define strncasecmp _strnicmp
-+#define strcasecmp _stricmp
-+#else
-+#define strncasecmp strnicmp
-+#define strcasecmp stricmp
-+#endif /* _MSC_VER */
-+
-+/* Compile in zlib support */
-+#define LIBSSH2_HAVE_ZLIB 1
-+
-+/* Enable newer diffie-hellman-group-exchange-sha1 syntax */
-+#define LIBSSH2_DH_GEX_NEW 1
-+
-+#endif /* LIBSSH2_CONFIG_H */
-+
-+
-
-Property changes on: libssh2/src/libssh2_config.h.in.w32
-___________________________________________________________________
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/pem.c
-===================================================================
---- libssh2/src/pem.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/pem.c (.../trunk)
-@@ -0,0 +1,209 @@
-+/* Copyright (C) 2007 The Written Word, Inc.
-+ * Copyright (C) 2008, Simon Josefsson
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms,
-+ * with or without modification, are permitted provided
-+ * 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+static int
-+readline(char *line, int line_size, FILE * fp)
-+{
-+ if (!fgets(line, line_size, fp)) {
-+ return -1;
-+ }
-+ if (*line && line[strlen(line) - 1] == '\n') {
-+ line[strlen(line) - 1] = '\0';
-+ }
-+ if (*line && line[strlen(line) - 1] == '\r') {
-+ line[strlen(line) - 1] = '\0';
-+ }
-+ return 0;
-+}
-+
-+#define LINE_SIZE 128
-+
-+int
-+_libssh2_pem_parse(LIBSSH2_SESSION * session,
-+ const char *headerbegin,
-+ const char *headerend,
-+ FILE * fp, unsigned char **data, unsigned int *datalen)
-+{
-+ char line[LINE_SIZE];
-+ char *b64data = NULL;
-+ unsigned int b64datalen = 0;
-+ int ret;
-+
-+ do {
-+ if (readline(line, LINE_SIZE, fp)) {
-+ return -1;
-+ }
-+ }
-+ while (strcmp(line, headerbegin) != 0);
-+
-+ *line = '\0';
-+
-+ do {
-+ if (*line) {
-+ char *tmp;
-+ size_t linelen;
-+
-+ linelen = strlen(line);
-+ tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
-+ if (!tmp) {
-+ ret = -1;
-+ goto out;
-+ }
-+ memcpy(tmp + b64datalen, line, linelen);
-+ b64data = tmp;
-+ b64datalen += linelen;
-+ }
-+
-+ if (readline(line, LINE_SIZE, fp)) {
-+ ret = -1;
-+ goto out;
-+ }
-+ } while (strcmp(line, headerend) != 0);
-+
-+ if (libssh2_base64_decode(session, (char**) data, datalen,
-+ b64data, b64datalen)) {
-+ ret = -1;
-+ goto out;
-+ }
-+
-+ ret = 0;
-+ out:
-+ if (b64data) {
-+ LIBSSH2_FREE(session, b64data);
-+ }
-+ return ret;
-+}
-+
-+static int
-+read_asn1_length(const unsigned char *data,
-+ unsigned int datalen, unsigned int *len)
-+{
-+ unsigned int lenlen;
-+ int nextpos;
-+
-+ if (datalen < 1) {
-+ return -1;
-+ }
-+ *len = data[0];
-+
-+ if (*len >= 0x80) {
-+ lenlen = *len & 0x7F;
-+ *len = data[1];
-+ if (1 + lenlen > datalen) {
-+ return -1;
-+ }
-+ if (lenlen > 1) {
-+ *len <<= 8;
-+ *len |= data[2];
-+ }
-+ } else {
-+ lenlen = 0;
-+ }
-+
-+ nextpos = 1 + lenlen;
-+ if (lenlen > 2 || 1 + lenlen + *len > datalen) {
-+ return -1;
-+ }
-+
-+ return nextpos;
-+}
-+
-+int
-+_libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
-+{
-+ unsigned int len;
-+ int lenlen;
-+
-+ if (*datalen < 1) {
-+ return -1;
-+ }
-+
-+ if ((*data)[0] != '\x30') {
-+ return -1;
-+ }
-+
-+ (*data)++;
-+ (*datalen)--;
-+
-+ lenlen = read_asn1_length(*data, *datalen, &len);
-+ if (lenlen < 0 || lenlen + len != *datalen) {
-+ return -1;
-+ }
-+
-+ *data += lenlen;
-+ *datalen -= lenlen;
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
-+ unsigned char **i, unsigned int *ilen)
-+{
-+ unsigned int len;
-+ int lenlen;
-+
-+ if (*datalen < 1) {
-+ return -1;
-+ }
-+
-+ if ((*data)[0] != '\x02') {
-+ return -1;
-+ }
-+
-+ (*data)++;
-+ (*datalen)--;
-+
-+ lenlen = read_asn1_length(*data, *datalen, &len);
-+ if (lenlen < 0 || lenlen + len > *datalen) {
-+ return -1;
-+ }
-+
-+ *data += lenlen;
-+ *datalen -= lenlen;
-+
-+ *i = *data;
-+ *ilen = len;
-+
-+ *data += len;
-+ *datalen -= len;
-+
-+ return 0;
-+}
-
-Property changes on: libssh2/src/pem.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/session.c
-===================================================================
---- libssh2/src/session.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/session.c (.../trunk)
-@@ -0,0 +1,1554 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <errno.h>
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+#include <stdlib.h>
-+#include <fcntl.h>
-+
-+#ifdef HAVE_GETTIMEOFDAY
-+#include <sys/time.h>
-+#endif
-+#ifdef HAVE_ALLOCA_H
-+#include <alloca.h>
-+#endif
-+
-+/* {{{ libssh2_default_alloc
-+ */
-+static
-+LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
-+{
-+ (void) abstract;
-+ return malloc(count);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_default_free
-+ */
-+static
-+LIBSSH2_FREE_FUNC(libssh2_default_free)
-+{
-+ (void) abstract;
-+ free(ptr);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_default_realloc
-+ */
-+static
-+LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
-+{
-+ (void) abstract;
-+ return realloc(ptr, count);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_banner_receive
-+ * Wait for a hello from the remote host
-+ * Allocate a buffer and store the banner in session->remote.banner
-+ * Returns: 0 on success, PACKET_EAGAIN if read would block, 1 on failure
-+ */
-+static int
-+libssh2_banner_receive(LIBSSH2_SESSION * session)
-+{
-+ int ret;
-+ int banner_len;
-+
-+ if (session->banner_TxRx_state == libssh2_NB_state_idle) {
-+ banner_len = 0;
-+
-+ session->banner_TxRx_state = libssh2_NB_state_created;
-+ } else {
-+ banner_len = session->banner_TxRx_total_send;
-+ }
-+
-+ while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) &&
-+ ((banner_len == 0)
-+ || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
-+ char c = '\0';
-+
-+ ret =
-+ recv(session->socket_fd, &c, 1,
-+ LIBSSH2_SOCKET_RECV_FLAGS(session));
-+
-+ if (ret < 0) {
-+#ifdef WIN32
-+ switch (WSAGetLastError()) {
-+ case WSAEWOULDBLOCK:
-+ errno = EAGAIN;
-+ break;
-+
-+ case WSAENOTSOCK:
-+ errno = EBADF;
-+ break;
-+
-+ case WSAENOTCONN:
-+ case WSAECONNABORTED:
-+ errno = WSAENOTCONN;
-+ break;
-+
-+ case WSAEINTR:
-+ errno = EINTR;
-+ break;
-+ }
-+#endif /* WIN32 */
-+ if (errno == EAGAIN) {
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_INBOUND;
-+ session->banner_TxRx_total_send = banner_len;
-+ return PACKET_EAGAIN;
-+ }
-+
-+ /* Some kinda error */
-+ session->banner_TxRx_state = libssh2_NB_state_idle;
-+ session->banner_TxRx_total_send = 0;
-+ return 1;
-+ }
-+
-+ if (ret == 0) {
-+ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
-+ return PACKET_FAIL;
-+ }
-+
-+ if (c == '\0') {
-+ /* NULLs are not allowed in SSH banners */
-+ session->banner_TxRx_state = libssh2_NB_state_idle;
-+ session->banner_TxRx_total_send = 0;
-+ return 1;
-+ }
-+
-+ session->banner_TxRx_banner[banner_len++] = c;
-+ }
-+
-+ while (banner_len &&
-+ ((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
-+ (session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
-+ banner_len--;
-+ }
-+
-+ /* From this point on, we are done here */
-+ session->banner_TxRx_state = libssh2_NB_state_idle;
-+ session->banner_TxRx_total_send = 0;
-+
-+ if (!banner_len)
-+ return 1;
-+
-+ session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
-+ if (!session->remote.banner) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Error allocating space for remote banner", 0);
-+ return 1;
-+ }
-+ memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
-+ session->remote.banner[banner_len] = '\0';
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Received Banner: %s",
-+ session->remote.banner);
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_banner_send
-+ * Send the default banner, or the one set via libssh2_setopt_string
-+ *
-+ * Returns PACKET_EAGAIN if it would block - and if it does so, you should
-+ * call this function again as soon as it is likely that more data can be
-+ * sent, and this function should then be called with the same argument set
-+ * (same data pointer and same data_len) until zero or failure is returned.
-+ */
-+static int
-+libssh2_banner_send(LIBSSH2_SESSION * session)
-+{
-+ char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
-+ int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
-+ ssize_t ret;
-+#ifdef LIBSSH2DEBUG
-+ char banner_dup[256];
-+#endif
-+
-+ if (session->banner_TxRx_state == libssh2_NB_state_idle) {
-+ if (session->local.banner) {
-+ /* setopt_string will have given us our \r\n characters */
-+ banner_len = strlen((char *) session->local.banner);
-+ banner = (char *) session->local.banner;
-+ }
-+#ifdef LIBSSH2DEBUG
-+ /* Hack and slash to avoid sending CRLF in debug output */
-+ if (banner_len < 256) {
-+ memcpy(banner_dup, banner, banner_len - 2);
-+ banner_dup[banner_len - 2] = '\0';
-+ } else {
-+ memcpy(banner_dup, banner, 255);
-+ banner[255] = '\0';
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Sending Banner: %s",
-+ banner_dup);
-+#endif
-+
-+ session->banner_TxRx_state = libssh2_NB_state_created;
-+ }
-+
-+ ret =
-+ send(session->socket_fd, banner + session->banner_TxRx_total_send,
-+ banner_len - session->banner_TxRx_total_send,
-+ LIBSSH2_SOCKET_SEND_FLAGS(session));
-+
-+ if (ret != (banner_len - session->banner_TxRx_total_send)) {
-+ if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
-+ /* the whole packet could not be sent, save the what was */
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ session->banner_TxRx_total_send += ret;
-+ return PACKET_EAGAIN;
-+ }
-+ session->banner_TxRx_state = libssh2_NB_state_idle;
-+ session->banner_TxRx_total_send = 0;
-+ return PACKET_FAIL;
-+ }
-+
-+ /* Set the state back to idle */
-+ session->banner_TxRx_state = libssh2_NB_state_idle;
-+ session->banner_TxRx_total_send = 0;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/*
-+ * _libssh2_nonblock() sets the given socket to either blocking or
-+ * non-blocking mode based on the 'nonblock' boolean argument. This function
-+ * is copied from the libcurl sources with permission.
-+ */
-+static int
-+_libssh2_nonblock(int sockfd, /* operate on this */
-+ int nonblock /* TRUE or FALSE */ )
-+{
-+#undef SETBLOCK
-+#define SETBLOCK 0
-+#ifdef HAVE_O_NONBLOCK
-+ /* most recent unix versions */
-+ int flags;
-+
-+ flags = fcntl(sockfd, F_GETFL, 0);
-+ if (nonblock)
-+ return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
-+ else
-+ return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
-+#undef SETBLOCK
-+#define SETBLOCK 1
-+#endif
-+
-+#if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
-+ /* older unix versions */
-+ int flags;
-+
-+ flags = nonblock;
-+ return ioctl(sockfd, FIONBIO, &flags);
-+#undef SETBLOCK
-+#define SETBLOCK 2
-+#endif
-+
-+#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
-+ /* Windows? */
-+ unsigned long flags;
-+ flags = nonblock;
-+
-+ return ioctlsocket(sockfd, FIONBIO, &flags);
-+#undef SETBLOCK
-+#define SETBLOCK 3
-+#endif
-+
-+#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
-+ /* presumably for Amiga */
-+ return IoctlSocket(sockfd, FIONBIO, (long) nonblock);
-+#undef SETBLOCK
-+#define SETBLOCK 4
-+#endif
-+
-+#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
-+ /* BeOS */
-+ long b = nonblock ? 1 : 0;
-+ return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
-+#undef SETBLOCK
-+#define SETBLOCK 5
-+#endif
-+
-+#ifdef HAVE_DISABLED_NONBLOCKING
-+ return 0; /* returns success */
-+#undef SETBLOCK
-+#define SETBLOCK 6
-+#endif
-+
-+#if (SETBLOCK == 0)
-+#error "no non-blocking method was found/used/set"
-+#endif
-+}
-+
-+/*
-+ * _libssh2_get_socket_nonblocking() gets the given blocking or non-blocking
-+ * state of the socket.
-+ */
-+static int
-+_libssh2_get_socket_nonblocking(int sockfd)
-+{ /* operate on this */
-+#undef GETBLOCK
-+#define GETBLOCK 0
-+#ifdef HAVE_O_NONBLOCK
-+ /* most recent unix versions */
-+ int flags;
-+
-+ if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) {
-+ /* Assume blocking on error */
-+ return 1;
-+ }
-+ return (flags & O_NONBLOCK);
-+#undef GETBLOCK
-+#define GETBLOCK 1
-+#endif
-+
-+#if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0)
-+ /* Windows? */
-+ unsigned int option_value;
-+ socklen_t option_len = sizeof(option_value);
-+
-+ if (getsockopt
-+ (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) {
-+ /* Assume blocking on error */
-+ return 1;
-+ }
-+ return (int) option_value;
-+#undef GETBLOCK
-+#define GETBLOCK 2
-+#endif
-+
-+#if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0)
-+ /* BeOS */
-+ long b;
-+ if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
-+ /* Assume blocking on error */
-+ return 1;
-+ }
-+ return (int) b;
-+#undef GETBLOCK
-+#define GETBLOCK 5
-+#endif
-+
-+#ifdef HAVE_DISABLED_NONBLOCKING
-+ return 1; /* returns blocking */
-+#undef GETBLOCK
-+#define GETBLOCK 6
-+#endif
-+
-+#if (GETBLOCK == 0)
-+#error "no non-blocking method was found/used/get"
-+#endif
-+}
-+
-+/* {{{ libssh2_banner_set
-+ * Set the local banner
-+ */
-+LIBSSH2_API int
-+libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
-+{
-+ int banner_len = banner ? strlen(banner) : 0;
-+
-+ if (session->local.banner) {
-+ LIBSSH2_FREE(session, session->local.banner);
-+ session->local.banner = NULL;
-+ }
-+
-+ if (!banner_len) {
-+ return 0;
-+ }
-+
-+ session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
-+ if (!session->local.banner) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for local banner", 0);
-+ return -1;
-+ }
-+
-+ memcpy(session->local.banner, banner, banner_len);
-+ session->local.banner[banner_len] = '\0';
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting local Banner: %s",
-+ session->local.banner);
-+ session->local.banner[banner_len++] = '\r';
-+ session->local.banner[banner_len++] = '\n';
-+ session->local.banner[banner_len++] = '\0';
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ proto libssh2_session_init
-+ * Allocate and initialize a libssh2 session structure
-+ * Allows for malloc callbacks in case the calling program has its own memory manager
-+ * It's allowable (but unadvisable) to define some but not all of the malloc callbacks
-+ * An additional pointer value may be optionally passed to be sent to the callbacks (so they know who's asking)
-+ */
-+LIBSSH2_API LIBSSH2_SESSION *
-+libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
-+ LIBSSH2_FREE_FUNC((*my_free)),
-+ LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
-+{
-+ LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
-+ LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
-+ LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
-+ LIBSSH2_SESSION *session;
-+
-+ if (my_alloc) {
-+ local_alloc = my_alloc;
-+ }
-+ if (my_free) {
-+ local_free = my_free;
-+ }
-+ if (my_realloc) {
-+ local_realloc = my_realloc;
-+ }
-+
-+ session = local_alloc(sizeof(LIBSSH2_SESSION), abstract);
-+ if (session) {
-+ memset(session, 0, sizeof(LIBSSH2_SESSION));
-+ session->alloc = local_alloc;
-+ session->free = local_free;
-+ session->realloc = local_realloc;
-+ session->abstract = abstract;
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "New session resource allocated");
-+ libssh2_crypto_init();
-+ }
-+ return session;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_callback_set
-+ * Set (or reset) a callback function
-+ * Returns the prior address
-+ *
-+ * FIXME: this function relies on that we can typecast function pointers
-+ * to void pointers, which isn't allowed in ISO C!
-+ */
-+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;
-+
-+ case LIBSSH2_CALLBACK_DEBUG:
-+ oldcb = session->ssh_msg_debug;
-+ session->ssh_msg_debug = callback;
-+ return oldcb;
-+
-+ case LIBSSH2_CALLBACK_DISCONNECT:
-+ oldcb = session->ssh_msg_disconnect;
-+ session->ssh_msg_disconnect = callback;
-+ return oldcb;
-+
-+ case LIBSSH2_CALLBACK_MACERROR:
-+ oldcb = session->macerror;
-+ session->macerror = callback;
-+ return oldcb;
-+
-+ case LIBSSH2_CALLBACK_X11:
-+ oldcb = session->x11;
-+ session->x11 = callback;
-+ return oldcb;
-+
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Setting Callback %d", cbtype);
-+
-+ 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
-+ * Any memory allocated by libssh2 will use alloc/realloc/free
-+ * callbacks in session
-+ * socket *must* be populated with an opened and connected socket.
-+ */
-+LIBSSH2_API int
-+libssh2_session_startup(LIBSSH2_SESSION * session, int sock)
-+{
-+ int rc;
-+
-+ if (session->startup_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "session_startup for socket %d", sock);
-+ /* FIXME: on some platforms (like win32) sockets are unsigned */
-+ if (sock < 0) {
-+ /* Did we forget something? */
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_NONE,
-+ "Bad socket provided", 0);
-+ return LIBSSH2_ERROR_SOCKET_NONE;
-+ }
-+ session->socket_fd = sock;
-+
-+ session->socket_block =
-+ !_libssh2_get_socket_nonblocking(session->socket_fd);
-+ if (session->socket_block) {
-+ /*
-+ * Since we can't be sure that we are in blocking or there
-+ * was an error detecting the state, so set to blocking to
-+ * be sure
-+ */
-+ _libssh2_nonblock(session->socket_fd, 0);
-+ }
-+
-+ session->startup_state = libssh2_NB_state_created;
-+ }
-+
-+ /* TODO: Liveness check */
-+
-+ if (session->startup_state == libssh2_NB_state_created) {
-+ rc = libssh2_banner_send(session);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending banner to remote host", 0);
-+ return LIBSSH2_ERROR_EAGAIN;
-+ } else if (rc) {
-+ /* Unable to send banner? */
-+ libssh2_error(session, LIBSSH2_ERROR_BANNER_SEND,
-+ "Error sending banner to remote host", 0);
-+ return LIBSSH2_ERROR_BANNER_SEND;
-+ }
-+
-+ session->startup_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->startup_state == libssh2_NB_state_sent) {
-+ rc = libssh2_banner_receive(session);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for banner", 0);
-+ return LIBSSH2_ERROR_EAGAIN;
-+ } else if (rc) {
-+ /* Unable to receive banner from remote */
-+ libssh2_error(session, LIBSSH2_ERROR_BANNER_NONE,
-+ "Timeout waiting for banner", 0);
-+ return LIBSSH2_ERROR_BANNER_NONE;
-+ }
-+
-+ session->startup_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->startup_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_kex_exchange(session, 0, &session->startup_key_state);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block exchanging encryption keys", 0);
-+ return LIBSSH2_ERROR_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
-+ "Unable to exchange encryption keys", 0);
-+ return LIBSSH2_ERROR_KEX_FAILURE;
-+ }
-+
-+ session->startup_state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (session->startup_state == libssh2_NB_state_sent2) {
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Requesting userauth service");
-+
-+ /* Request the userauth service */
-+ session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
-+ libssh2_htonu32(session->startup_service + 1,
-+ sizeof("ssh-userauth") - 1);
-+ memcpy(session->startup_service + 5, "ssh-userauth",
-+ sizeof("ssh-userauth") - 1);
-+
-+ session->startup_state = libssh2_NB_state_sent3;
-+ }
-+
-+ if (session->startup_state == libssh2_NB_state_sent3) {
-+ rc = libssh2_packet_write(session, session->startup_service,
-+ sizeof("ssh-userauth") + 5 - 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block asking for ssh-userauth service", 0);
-+ return LIBSSH2_ERROR_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to ask for ssh-userauth service", 0);
-+ return LIBSSH2_ERROR_SOCKET_SEND;
-+ }
-+
-+ session->startup_state = libssh2_NB_state_sent4;
-+ }
-+
-+ if (session->startup_state == libssh2_NB_state_sent4) {
-+ rc = libssh2_packet_require_ex(session, SSH_MSG_SERVICE_ACCEPT,
-+ &session->startup_data,
-+ &session->startup_data_len, 0, NULL, 0,
-+ &session->startup_req_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return LIBSSH2_ERROR_EAGAIN;
-+ } else if (rc) {
-+ return LIBSSH2_ERROR_SOCKET_DISCONNECT;
-+ }
-+ session->startup_service_length =
-+ libssh2_ntohu32(session->startup_data + 1);
-+
-+ if ((session->startup_service_length != (sizeof("ssh-userauth") - 1))
-+ || strncmp("ssh-userauth", (char *) session->startup_data + 5,
-+ session->startup_service_length)) {
-+ LIBSSH2_FREE(session, session->startup_data);
-+ session->startup_data = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_PROTO,
-+ "Invalid response received from server", 0);
-+ return LIBSSH2_ERROR_PROTO;
-+ }
-+ LIBSSH2_FREE(session, session->startup_data);
-+ session->startup_data = NULL;
-+
-+ session->startup_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+ }
-+
-+ /* just for safety return some error */
-+ return LIBSSH2_ERROR_INVAL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ proto libssh2_session_free
-+ * Frees the memory allocated to the session
-+ * Also closes and frees any channels attached to this session
-+ */
-+LIBSSH2_API int
-+libssh2_session_free(LIBSSH2_SESSION * session)
-+{
-+ int rc;
-+
-+ if (session->free_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Freeing session resource",
-+ session->remote.banner);
-+
-+ session->state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->free_state == libssh2_NB_state_created) {
-+ while (session->channels.head) {
-+ LIBSSH2_CHANNEL *tmp = session->channels.head;
-+
-+ rc = libssh2_channel_free(session->channels.head);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (tmp == session->channels.head) {
-+ /* channel_free couldn't do it's job, perform a messy cleanup */
-+ tmp = session->channels.head;
-+
-+ /* unlink */
-+ session->channels.head = tmp->next;
-+
-+ /* free */
-+ LIBSSH2_FREE(session, tmp);
-+
-+ /* reverse linking isn't important here, we're killing the structure */
-+ }
-+ }
-+
-+ session->state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->state == libssh2_NB_state_sent) {
-+ while (session->listeners) {
-+ rc = libssh2_channel_forward_cancel(session->listeners);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ }
-+
-+ session->state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->state & LIBSSH2_STATE_NEWKEYS) {
-+ /* hostkey */
-+ if (session->hostkey && session->hostkey->dtor) {
-+ session->hostkey->dtor(session, &session->server_hostkey_abstract);
-+ }
-+
-+ /* Client to Server */
-+ /* crypt */
-+ if (session->local.crypt && session->local.crypt->dtor) {
-+ session->local.crypt->dtor(session,
-+ &session->local.crypt_abstract);
-+ }
-+ /* comp */
-+ if (session->local.comp && session->local.comp->dtor) {
-+ session->local.comp->dtor(session, 1,
-+ &session->local.comp_abstract);
-+ }
-+ /* mac */
-+ if (session->local.mac && session->local.mac->dtor) {
-+ session->local.mac->dtor(session, &session->local.mac_abstract);
-+ }
-+
-+ /* Server to Client */
-+ /* crypt */
-+ if (session->remote.crypt && session->remote.crypt->dtor) {
-+ session->remote.crypt->dtor(session,
-+ &session->remote.crypt_abstract);
-+ }
-+ /* comp */
-+ if (session->remote.comp && session->remote.comp->dtor) {
-+ session->remote.comp->dtor(session, 0,
-+ &session->remote.comp_abstract);
-+ }
-+ /* mac */
-+ if (session->remote.mac && session->remote.mac->dtor) {
-+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
-+ }
-+
-+ /* session_id */
-+ if (session->session_id) {
-+ LIBSSH2_FREE(session, session->session_id);
-+ }
-+ }
-+
-+ /* Free banner(s) */
-+ if (session->remote.banner) {
-+ LIBSSH2_FREE(session, session->remote.banner);
-+ }
-+ if (session->local.banner) {
-+ LIBSSH2_FREE(session, session->local.banner);
-+ }
-+
-+ /* Free preference(s) */
-+ if (session->kex_prefs) {
-+ LIBSSH2_FREE(session, session->kex_prefs);
-+ }
-+ if (session->hostkey_prefs) {
-+ LIBSSH2_FREE(session, session->hostkey_prefs);
-+ }
-+
-+ if (session->local.crypt_prefs) {
-+ LIBSSH2_FREE(session, session->local.crypt_prefs);
-+ }
-+ if (session->local.mac_prefs) {
-+ LIBSSH2_FREE(session, session->local.mac_prefs);
-+ }
-+ if (session->local.comp_prefs) {
-+ LIBSSH2_FREE(session, session->local.comp_prefs);
-+ }
-+ if (session->local.lang_prefs) {
-+ LIBSSH2_FREE(session, session->local.lang_prefs);
-+ }
-+
-+ if (session->remote.crypt_prefs) {
-+ LIBSSH2_FREE(session, session->remote.crypt_prefs);
-+ }
-+ if (session->remote.mac_prefs) {
-+ LIBSSH2_FREE(session, session->remote.mac_prefs);
-+ }
-+ if (session->remote.comp_prefs) {
-+ LIBSSH2_FREE(session, session->remote.comp_prefs);
-+ }
-+ if (session->remote.lang_prefs) {
-+ LIBSSH2_FREE(session, session->remote.lang_prefs);
-+ }
-+
-+ /*
-+ * Make sure all memory used in the state variables are free
-+ */
-+ if (session->startup_data) {
-+ LIBSSH2_FREE(session, session->startup_data);
-+ }
-+ if (session->disconnect_data) {
-+ LIBSSH2_FREE(session, session->disconnect_data);
-+ }
-+ if (session->userauth_list_data) {
-+ LIBSSH2_FREE(session, session->userauth_list_data);
-+ }
-+ if (session->userauth_pswd_data) {
-+ LIBSSH2_FREE(session, session->userauth_pswd_data);
-+ }
-+ if (session->userauth_pswd_newpw) {
-+ LIBSSH2_FREE(session, session->userauth_pswd_newpw);
-+ }
-+ if (session->userauth_host_packet) {
-+ LIBSSH2_FREE(session, session->userauth_host_packet);
-+ }
-+ if (session->userauth_host_method) {
-+ LIBSSH2_FREE(session, session->userauth_host_method);
-+ }
-+ if (session->userauth_host_data) {
-+ LIBSSH2_FREE(session, session->userauth_host_data);
-+ }
-+ if (session->userauth_pblc_data) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_data);
-+ }
-+ if (session->userauth_pblc_packet) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
-+ }
-+ if (session->userauth_pblc_method) {
-+ LIBSSH2_FREE(session, session->userauth_pblc_method);
-+ }
-+ if (session->userauth_kybd_data) {
-+ LIBSSH2_FREE(session, session->userauth_kybd_data);
-+ }
-+ if (session->userauth_kybd_packet) {
-+ LIBSSH2_FREE(session, session->userauth_kybd_packet);
-+ }
-+ if (session->userauth_kybd_auth_instruction) {
-+ LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
-+ }
-+ if (session->open_packet) {
-+ LIBSSH2_FREE(session, session->open_packet);
-+ }
-+ if (session->open_data) {
-+ LIBSSH2_FREE(session, session->open_data);
-+ }
-+ if (session->direct_message) {
-+ LIBSSH2_FREE(session, session->direct_message);
-+ }
-+ if (session->fwdLstn_packet) {
-+ LIBSSH2_FREE(session, session->fwdLstn_packet);
-+ }
-+ if (session->pkeyInit_data) {
-+ LIBSSH2_FREE(session, session->pkeyInit_data);
-+ }
-+ if (session->scpRecv_command) {
-+ LIBSSH2_FREE(session, session->scpRecv_command);
-+ }
-+ if (session->scpSend_command) {
-+ LIBSSH2_FREE(session, session->scpSend_command);
-+ }
-+ if (session->scpRecv_err_msg) {
-+ LIBSSH2_FREE(session, session->scpRecv_err_msg);
-+ }
-+ if (session->scpSend_err_msg) {
-+ LIBSSH2_FREE(session, session->scpSend_err_msg);
-+ }
-+
-+ /* Free the error message, if we ar supposed to */
-+ if (session->err_msg && session->err_should_free) {
-+ LIBSSH2_FREE(session, session->err_msg);
-+ }
-+
-+ /* Cleanup any remaining packets */
-+ while (session->packets.head) {
-+ LIBSSH2_PACKET *tmp = session->packets.head;
-+
-+ /* unlink */
-+ session->packets.head = tmp->next;
-+
-+ /* free */
-+ LIBSSH2_FREE(session, tmp->data);
-+ LIBSSH2_FREE(session, tmp);
-+ }
-+
-+ LIBSSH2_FREE(session, session);
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_disconnect_ex
-+ */
-+LIBSSH2_API int
-+libssh2_session_disconnect_ex(LIBSSH2_SESSION * session, int reason,
-+ const char *description, const char *lang)
-+{
-+ unsigned char *s;
-+ unsigned long descr_len = 0, lang_len = 0;
-+ int rc;
-+
-+ if (session->disconnect_state == libssh2_NB_state_idle) {
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS,
-+ "Disconnecting: reason=%d, desc=%s, lang=%s", reason,
-+ description, lang);
-+ if (description) {
-+ descr_len = strlen(description);
-+ }
-+ if (lang) {
-+ lang_len = strlen(lang);
-+ }
-+ /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
-+ session->disconnect_data_len = descr_len + lang_len + 13;
-+
-+ s = session->disconnect_data =
-+ LIBSSH2_ALLOC(session, session->disconnect_data_len);
-+ if (!session->disconnect_data) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for disconnect packet",
-+ 0);
-+ session->disconnect_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_DISCONNECT;
-+ libssh2_htonu32(s, reason);
-+ s += 4;
-+
-+ libssh2_htonu32(s, descr_len);
-+ s += 4;
-+ if (description) {
-+ memcpy(s, description, descr_len);
-+ s += descr_len;
-+ }
-+
-+ libssh2_htonu32(s, lang_len);
-+ s += 4;
-+ if (lang) {
-+ memcpy(s, lang, lang_len);
-+ s += lang_len;
-+ }
-+
-+ session->disconnect_state = libssh2_NB_state_created;
-+ }
-+
-+ rc = libssh2_packet_write(session, session->disconnect_data,
-+ session->disconnect_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ LIBSSH2_FREE(session, session->disconnect_data);
-+ session->disconnect_data = NULL;
-+ session->disconnect_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_methods
-+ * Return the currently active methods for method_type
-+ * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
-+ * Strings should NOT be freed
-+ */
-+LIBSSH2_API const char *
-+libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
-+{
-+ /* All methods have char *name as their first element */
-+ const LIBSSH2_KEX_METHOD *method = NULL;
-+
-+ switch (method_type) {
-+ case LIBSSH2_METHOD_KEX:
-+ method = session->kex;
-+ break;
-+
-+ case LIBSSH2_METHOD_HOSTKEY:
-+ method = (LIBSSH2_KEX_METHOD *) session->hostkey;
-+ break;
-+
-+ case LIBSSH2_METHOD_CRYPT_CS:
-+ method = (LIBSSH2_KEX_METHOD *) session->local.crypt;
-+ break;
-+
-+ case LIBSSH2_METHOD_CRYPT_SC:
-+ method = (LIBSSH2_KEX_METHOD *) session->remote.crypt;
-+ break;
-+
-+ case LIBSSH2_METHOD_MAC_CS:
-+ method = (LIBSSH2_KEX_METHOD *) session->local.mac;
-+ break;
-+
-+ case LIBSSH2_METHOD_MAC_SC:
-+ method = (LIBSSH2_KEX_METHOD *) session->remote.mac;
-+ break;
-+
-+ case LIBSSH2_METHOD_COMP_CS:
-+ method = (LIBSSH2_KEX_METHOD *) session->local.comp;
-+ break;
-+
-+ case LIBSSH2_METHOD_COMP_SC:
-+ method = (LIBSSH2_KEX_METHOD *) session->remote.comp;
-+ break;
-+
-+ case LIBSSH2_METHOD_LANG_CS:
-+ return "";
-+ break;
-+
-+ case LIBSSH2_METHOD_LANG_SC:
-+ return "";
-+ break;
-+
-+ default:
-+ libssh2_error(session, LIBSSH2_ERROR_INVAL,
-+ "Invalid parameter specified for method_type", 0);
-+ return NULL;
-+ break;
-+ }
-+
-+ if (!method) {
-+ libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
-+ "No method negotiated", 0);
-+ return NULL;
-+ }
-+
-+ return method->name;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_abstract
-+ * Retrieve a pointer to the abstract property
-+ */
-+LIBSSH2_API void **
-+libssh2_session_abstract(LIBSSH2_SESSION * session)
-+{
-+ return &session->abstract;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_last_error
-+ * Returns error code and populates an error string into errmsg
-+ * If want_buf is non-zero then the string placed into errmsg must be freed by the calling program
-+ * Otherwise it is assumed to be owned by libssh2
-+ */
-+LIBSSH2_API int
-+libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
-+ int *errmsg_len, int want_buf)
-+{
-+ /* No error to report */
-+ if (!session->err_code) {
-+ if (errmsg) {
-+ if (want_buf) {
-+ *errmsg = LIBSSH2_ALLOC(session, 1);
-+ if (*errmsg) {
-+ **errmsg = 0;
-+ }
-+ } else {
-+ *errmsg = (char *) "";
-+ }
-+ }
-+ if (errmsg_len) {
-+ *errmsg_len = 0;
-+ }
-+ return 0;
-+ }
-+
-+ if (errmsg) {
-+ char *serrmsg = session->err_msg ? session->err_msg : (char *) "";
-+ int ownbuf = session->err_msg ? session->err_should_free : 0;
-+
-+ if (want_buf) {
-+ if (ownbuf) {
-+ /* Just give the calling program the buffer */
-+ *errmsg = serrmsg;
-+ session->err_should_free = 0;
-+ } else {
-+ /* Make a copy so the calling program can own it */
-+ *errmsg = LIBSSH2_ALLOC(session, session->err_msglen + 1);
-+ if (*errmsg) {
-+ memcpy(*errmsg, session->err_msg, session->err_msglen);
-+ (*errmsg)[session->err_msglen] = 0;
-+ }
-+ }
-+ } else {
-+ *errmsg = serrmsg;
-+ }
-+ }
-+
-+ if (errmsg_len) {
-+ *errmsg_len = session->err_msglen;
-+ }
-+
-+ return session->err_code;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_last_error
-+* Returns error code
-+*/
-+LIBSSH2_API int
-+libssh2_session_last_errno(LIBSSH2_SESSION * session)
-+{
-+ return session->err_code;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_flag
-+ * Set/Get session flags
-+ * Passing flag==0 will avoid changing session->flags while still returning its current value
-+ */
-+LIBSSH2_API int
-+libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
-+{
-+ if (value) {
-+ session->flags |= flag;
-+ } else {
-+ session->flags &= ~flag;
-+ }
-+
-+ return session->flags;
-+}
-+
-+/* }}} */
-+
-+/* {{{ _libssh2_session_set_blocking
-+ * Set a session's blocking mode on or off, return the previous status
-+ * when this function is called.
-+ */
-+int
-+_libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
-+{
-+ int bl = session->socket_block;
-+ _libssh2_debug(session, LIBSSH2_DBG_CONN,
-+ "Setting blocking mode on session %d", blocking);
-+ if (blocking == session->socket_block) {
-+ /* avoid if already correct */
-+ return bl;
-+ }
-+ session->socket_block = blocking;
-+
-+ _libssh2_nonblock(session->socket_fd, !blocking);
-+
-+ return bl;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_set_blocking
-+ * Set a channel's blocking mode on or off, similar to a socket's
-+ * fcntl(fd, F_SETFL, O_NONBLOCK); type command
-+ */
-+LIBSSH2_API void
-+libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
-+{
-+ (void) _libssh2_session_set_blocking(session, blocking);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_get_blocking
-+* Returns a session's blocking mode on or off
-+*/
-+LIBSSH2_API int
-+libssh2_session_get_blocking(LIBSSH2_SESSION * session)
-+{
-+ return session->socket_block;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_poll_channel_read
-+ * Returns 0 if no data is waiting on channel,
-+ * non-0 if data is available
-+ */
-+LIBSSH2_API int
-+libssh2_poll_channel_read(LIBSSH2_CHANNEL * channel, int extended)
-+{
-+ LIBSSH2_SESSION *session = channel->session;
-+ LIBSSH2_PACKET *packet = session->packets.head;
-+
-+ while (packet)
-+ {
-+ if ( channel->local.id == libssh2_ntohu32(packet->data + 1)) {
-+ if ( extended == 1 &&
-+ (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
-+ || packet->data[0] == SSH_MSG_CHANNEL_DATA )) {
-+ return 1;
-+ } else if ( extended == 0 &&
-+ packet->data[0] == SSH_MSG_CHANNEL_DATA) {
-+ return 1;
-+ }
-+ /* else - no data of any type is ready to be read */
-+ }
-+ packet = packet->next;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_poll_channel_write
-+ * Returns 0 if writing to channel would block,
-+ * non-0 if data can be written without blocking
-+ */
-+static inline int
-+libssh2_poll_channel_write(LIBSSH2_CHANNEL * channel)
-+{
-+ return channel->local.window_size ? 1 : 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_poll_listener_queued
-+ * Returns 0 if no connections are waiting to be accepted
-+ * non-0 if one or more connections are available
-+ */
-+static inline int
-+libssh2_poll_listener_queued(LIBSSH2_LISTENER * listener)
-+{
-+ return listener->queue ? 1 : 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_poll
-+ * Poll sockets, channels, and listeners for activity
-+ */
-+LIBSSH2_API int
-+libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
-+{
-+ long timeout_remaining;
-+ unsigned int i, active_fds;
-+#ifdef HAVE_POLL
-+ LIBSSH2_SESSION *session = NULL;
-+#ifdef HAVE_ALLOCA
-+ struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds);
-+#else
-+ struct pollfd sockets[256];
-+
-+ if (nfds > 256)
-+ /* systems without alloca use a fixed-size array, this can be fixed
-+ if we really want to, at least if the compiler is a C99 capable one */
-+ return -1;
-+#endif
-+ /* Setup sockets for polling */
-+ for(i = 0; i < nfds; i++) {
-+ fds[i].revents = 0;
-+ switch (fds[i].type) {
-+ case LIBSSH2_POLLFD_SOCKET:
-+ sockets[i].fd = fds[i].fd.socket;
-+ sockets[i].events = fds[i].events;
-+ sockets[i].revents = 0;
-+ break;
-+
-+ case LIBSSH2_POLLFD_CHANNEL:
-+ sockets[i].fd = fds[i].fd.channel->session->socket_fd;
-+ sockets[i].events = POLLIN;
-+ sockets[i].revents = 0;
-+ if (!session)
-+ session = fds[i].fd.channel->session;
-+ break;
-+
-+ case LIBSSH2_POLLFD_LISTENER:
-+ sockets[i].fd = fds[i].fd.listener->session->socket_fd;
-+ sockets[i].events = POLLIN;
-+ sockets[i].revents = 0;
-+ if (!session)
-+ session = fds[i].fd.listener->session;
-+ break;
-+
-+ default:
-+ if (session)
-+ libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
-+ "Invalid descriptor passed to libssh2_poll()",
-+ 0);
-+ return -1;
-+ }
-+ }
-+#elif defined(HAVE_SELECT)
-+ LIBSSH2_SESSION *session = NULL;
-+ int maxfd = 0;
-+ fd_set rfds, wfds;
-+ struct timeval tv;
-+
-+ FD_ZERO(&rfds);
-+ FD_ZERO(&wfds);
-+ for(i = 0; i < nfds; i++) {
-+ fds[i].revents = 0;
-+ switch (fds[i].type) {
-+ case LIBSSH2_POLLFD_SOCKET:
-+ if (fds[i].events & LIBSSH2_POLLFD_POLLIN) {
-+ FD_SET(fds[i].fd.socket, &rfds);
-+ if (fds[i].fd.socket > maxfd)
-+ maxfd = fds[i].fd.socket;
-+ }
-+ if (fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
-+ FD_SET(fds[i].fd.socket, &wfds);
-+ if (fds[i].fd.socket > maxfd)
-+ maxfd = fds[i].fd.socket;
-+ }
-+ break;
-+
-+ case LIBSSH2_POLLFD_CHANNEL:
-+ FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
-+ if (fds[i].fd.channel->session->socket_fd > maxfd)
-+ maxfd = fds[i].fd.channel->session->socket_fd;
-+ if (!session)
-+ session = fds[i].fd.channel->session;
-+ break;
-+
-+ case LIBSSH2_POLLFD_LISTENER:
-+ FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
-+ if (fds[i].fd.listener->session->socket_fd > maxfd)
-+ maxfd = fds[i].fd.listener->session->socket_fd;
-+ if (!session)
-+ session = fds[i].fd.listener->session;
-+ break;
-+
-+ default:
-+ if (session)
-+ libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
-+ "Invalid descriptor passed to libssh2_poll()",
-+ 0);
-+ return -1;
-+ }
-+ }
-+#else
-+ /* No select() or poll()
-+ * no sockets sturcture to setup
-+ */
-+
-+ timeout = 0;
-+#endif /* HAVE_POLL or HAVE_SELECT */
-+
-+ timeout_remaining = timeout;
-+ do {
-+#if defined(HAVE_POLL) || defined(HAVE_SELECT)
-+ int sysret;
-+#endif
-+
-+ active_fds = 0;
-+
-+ for(i = 0; i < nfds; i++) {
-+ if (fds[i].events != fds[i].revents) {
-+ switch (fds[i].type) {
-+ case LIBSSH2_POLLFD_CHANNEL:
-+ if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want to be ready for read */
-+ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* Not yet known to be ready for read */
-+ fds[i].revents |=
-+ libssh2_poll_channel_read(fds[i].fd.channel,
-+ 0) ?
-+ LIBSSH2_POLLFD_POLLIN : 0;
-+ }
-+ if ((fds[i].events & LIBSSH2_POLLFD_POLLEXT) && /* Want to be ready for extended read */
-+ ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) { /* Not yet known to be ready for extended read */
-+ fds[i].revents |=
-+ libssh2_poll_channel_read(fds[i].fd.channel,
-+ 1) ?
-+ LIBSSH2_POLLFD_POLLEXT : 0;
-+ }
-+ if ((fds[i].events & LIBSSH2_POLLFD_POLLOUT) && /* Want to be ready for write */
-+ ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) { /* Not yet known to be ready for write */
-+ fds[i].revents |=
-+ libssh2_poll_channel_write(fds[i].fd.
-+ channel) ?
-+ LIBSSH2_POLLFD_POLLOUT : 0;
-+ }
-+ if (fds[i].fd.channel->remote.close
-+ || fds[i].fd.channel->local.close) {
-+ fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
-+ }
-+ if (fds[i].fd.channel->session->socket_state ==
-+ LIBSSH2_SOCKET_DISCONNECTED) {
-+ fds[i].revents |=
-+ LIBSSH2_POLLFD_CHANNEL_CLOSED |
-+ LIBSSH2_POLLFD_SESSION_CLOSED;
-+ }
-+ break;
-+
-+ case LIBSSH2_POLLFD_LISTENER:
-+ if ((fds[i].events & LIBSSH2_POLLFD_POLLIN) && /* Want a connection */
-+ ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) { /* No connections known of yet */
-+ fds[i].revents |=
-+ libssh2_poll_listener_queued(fds[i].fd.
-+ listener) ?
-+ LIBSSH2_POLLFD_POLLIN : 0;
-+ }
-+ if (fds[i].fd.listener->session->socket_state ==
-+ LIBSSH2_SOCKET_DISCONNECTED) {
-+ fds[i].revents |=
-+ LIBSSH2_POLLFD_LISTENER_CLOSED |
-+ LIBSSH2_POLLFD_SESSION_CLOSED;
-+ }
-+ break;
-+ }
-+ }
-+ if (fds[i].revents) {
-+ active_fds++;
-+ }
-+ }
-+
-+ if (active_fds) {
-+ /* Don't block on the sockets if we have channels/listeners which are ready */
-+ timeout_remaining = 0;
-+ }
-+#ifdef HAVE_POLL
-+
-+#ifdef HAVE_GETTIMEOFDAY
-+ {
-+ struct timeval tv_begin, tv_end;
-+
-+ gettimeofday((struct timeval *) &tv_begin, NULL);
-+ sysret = poll(sockets, nfds, timeout_remaining);
-+ gettimeofday((struct timeval *) &tv_end, NULL);
-+ timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
-+ timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
-+ }
-+#else
-+ /* If the platform doesn't support gettimeofday,
-+ * then just make the call non-blocking and walk away
-+ */
-+ sysret = poll(sockets, nfds, timeout_remaining);
-+ timeout_remaining = 0;
-+#endif /* HAVE_GETTIMEOFDAY */
-+
-+ if (sysret > 0) {
-+ for(i = 0; i < nfds; i++) {
-+ switch (fds[i].type) {
-+ case LIBSSH2_POLLFD_SOCKET:
-+ fds[i].revents = sockets[i].revents;
-+ sockets[i].revents = 0; /* In case we loop again, be nice */
-+ if (fds[i].revents) {
-+ active_fds++;
-+ }
-+ break;
-+ case LIBSSH2_POLLFD_CHANNEL:
-+ if (sockets[i].events & POLLIN) {
-+ /* Spin session until no data available */
-+ while (libssh2_packet_read(fds[i].fd.channel->session)
-+ > 0);
-+ }
-+ if (sockets[i].revents & POLLHUP) {
-+ fds[i].revents |=
-+ LIBSSH2_POLLFD_CHANNEL_CLOSED |
-+ LIBSSH2_POLLFD_SESSION_CLOSED;
-+ }
-+ sockets[i].revents = 0;
-+ break;
-+ case LIBSSH2_POLLFD_LISTENER:
-+ if (sockets[i].events & POLLIN) {
-+ /* Spin session until no data available */
-+ while (libssh2_packet_read(fds[i].fd.listener->session)
-+ > 0);
-+ }
-+ if (sockets[i].revents & POLLHUP) {
-+ fds[i].revents |=
-+ LIBSSH2_POLLFD_LISTENER_CLOSED |
-+ LIBSSH2_POLLFD_SESSION_CLOSED;
-+ }
-+ sockets[i].revents = 0;
-+ break;
-+ }
-+ }
-+ }
-+#elif defined(HAVE_SELECT)
-+ tv.tv_sec = timeout_remaining / 1000;
-+ tv.tv_usec = (timeout_remaining % 1000) * 1000;
-+#ifdef HAVE_GETTIMEOFDAY
-+ {
-+ struct timeval tv_begin, tv_end;
-+
-+ gettimeofday((struct timeval *) &tv_begin, NULL);
-+ sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
-+ gettimeofday((struct timeval *) &tv_end, NULL);
-+
-+ timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
-+ timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
-+ }
-+#else
-+ /* If the platform doesn't support gettimeofday,
-+ * then just make the call non-blocking and walk away
-+ */
-+ sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
-+ timeout_remaining = 0;
-+#endif
-+
-+ if (sysret > 0) {
-+ for(i = 0; i < nfds; i++) {
-+ switch (fds[i].type) {
-+ case LIBSSH2_POLLFD_SOCKET:
-+ if (FD_ISSET(fds[i].fd.socket, &rfds)) {
-+ fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
-+ }
-+ if (FD_ISSET(fds[i].fd.socket, &wfds)) {
-+ fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
-+ }
-+ if (fds[i].revents) {
-+ active_fds++;
-+ }
-+ break;
-+
-+ case LIBSSH2_POLLFD_CHANNEL:
-+ if (FD_ISSET(fds[i].fd.channel->session->socket_fd, &rfds)) {
-+ /* Spin session until no data available */
-+ while (libssh2_packet_read(fds[i].fd.channel->session)
-+ > 0);
-+ }
-+ break;
-+
-+ case LIBSSH2_POLLFD_LISTENER:
-+ if (FD_ISSET
-+ (fds[i].fd.listener->session->socket_fd, &rfds)) {
-+ /* Spin session until no data available */
-+ while (libssh2_packet_read(fds[i].fd.listener->session)
-+ > 0);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+#endif /* else no select() or poll() -- timeout (and by extension timeout_remaining) will be equal to 0 */
-+ } while ((timeout_remaining > 0) && !active_fds);
-+
-+ return active_fds;
-+}
-+
-+/* {{{ libssh2_session_block_direction
-+ * Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
-+ * Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
-+ * or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked
-+ */
-+LIBSSH2_API int
-+libssh2_session_block_directions(LIBSSH2_SESSION *session)
-+{
-+ return session->socket_block_directions;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/session.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.3
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/openssl.c
-===================================================================
---- libssh2/src/openssl.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/openssl.c (.../trunk)
-@@ -0,0 +1,316 @@
-+/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
-+ * Author: Simon Josefsson
-+ * Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
-+ *
-+ * 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <string.h>
-+
-+#ifndef EVP_MAX_BLOCK_LENGTH
-+#define EVP_MAX_BLOCK_LENGTH 32
-+#endif
-+
-+int
-+_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
-+ const unsigned char *edata,
-+ unsigned long elen,
-+ const unsigned char *ndata,
-+ unsigned long nlen,
-+ const unsigned char *ddata,
-+ unsigned long dlen,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *e1data,
-+ unsigned long e1len,
-+ const unsigned char *e2data,
-+ unsigned long e2len,
-+ const unsigned char *coeffdata, unsigned long coefflen)
-+{
-+ *rsa = RSA_new();
-+
-+ (*rsa)->e = BN_new();
-+ BN_bin2bn(edata, elen, (*rsa)->e);
-+
-+ (*rsa)->n = BN_new();
-+ BN_bin2bn(ndata, nlen, (*rsa)->n);
-+
-+ if (ddata) {
-+ (*rsa)->d = BN_new();
-+ BN_bin2bn(ddata, dlen, (*rsa)->d);
-+
-+ (*rsa)->p = BN_new();
-+ BN_bin2bn(pdata, plen, (*rsa)->p);
-+
-+ (*rsa)->q = BN_new();
-+ BN_bin2bn(qdata, qlen, (*rsa)->q);
-+
-+ (*rsa)->dmp1 = BN_new();
-+ BN_bin2bn(e1data, e1len, (*rsa)->dmp1);
-+
-+ (*rsa)->dmq1 = BN_new();
-+ BN_bin2bn(e2data, e2len, (*rsa)->dmq1);
-+
-+ (*rsa)->iqmp = BN_new();
-+ BN_bin2bn(coeffdata, coefflen, (*rsa)->iqmp);
-+ }
-+ return 0;
-+}
-+
-+int
-+_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m, unsigned long m_len)
-+{
-+ unsigned char hash[SHA_DIGEST_LENGTH];
-+ int ret;
-+
-+ SHA1(m, m_len, hash);
-+ ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
-+ (unsigned char *) sig, sig_len, rsactx);
-+ return (ret == 1) ? 0 : -1;
-+}
-+
-+int
-+_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
-+ const unsigned char *p,
-+ unsigned long p_len,
-+ const unsigned char *q,
-+ unsigned long q_len,
-+ const unsigned char *g,
-+ unsigned long g_len,
-+ const unsigned char *y,
-+ unsigned long y_len,
-+ const unsigned char *x, unsigned long x_len)
-+{
-+ *dsactx = DSA_new();
-+
-+ (*dsactx)->p = BN_new();
-+ BN_bin2bn(p, p_len, (*dsactx)->p);
-+
-+ (*dsactx)->q = BN_new();
-+ BN_bin2bn(q, q_len, (*dsactx)->q);
-+
-+ (*dsactx)->g = BN_new();
-+ BN_bin2bn(g, g_len, (*dsactx)->g);
-+
-+ (*dsactx)->pub_key = BN_new();
-+ BN_bin2bn(y, y_len, (*dsactx)->pub_key);
-+
-+ if (x_len) {
-+ (*dsactx)->priv_key = BN_new();
-+ BN_bin2bn(x, x_len, (*dsactx)->priv_key);
-+ }
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *sig,
-+ const unsigned char *m, unsigned long m_len)
-+{
-+ unsigned char hash[SHA_DIGEST_LENGTH];
-+ DSA_SIG dsasig;
-+ int ret;
-+
-+ dsasig.r = BN_new();
-+ BN_bin2bn(sig, 20, dsasig.r);
-+ dsasig.s = BN_new();
-+ BN_bin2bn(sig + 20, 20, dsasig.s);
-+
-+ libssh2_sha1(m, m_len, hash);
-+ ret = DSA_do_verify(hash, SHA_DIGEST_LENGTH, &dsasig, dsactx);
-+ BN_clear_free(dsasig.s);
-+ BN_clear_free(dsasig.r);
-+
-+ return (ret == 1) ? 0 : -1;
-+}
-+
-+int
-+_libssh2_cipher_init(_libssh2_cipher_ctx * h,
-+ _libssh2_cipher_type(algo),
-+ unsigned char *iv, unsigned char *secret, int encrypt)
-+{
-+ EVP_CIPHER_CTX_init(h);
-+ EVP_CipherInit(h, algo(), secret, iv, encrypt);
-+ return 0;
-+}
-+
-+int
-+_libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
-+ _libssh2_cipher_type(algo),
-+ int encrypt, unsigned char *block)
-+{
-+ int blocksize = ctx->cipher->block_size;
-+ unsigned char buf[EVP_MAX_BLOCK_LENGTH];
-+ int ret;
-+ (void) algo;
-+ (void) encrypt;
-+
-+ if (blocksize == 1) {
-+/* Hack for arcfour. */
-+ blocksize = 8;
-+ }
-+ ret = EVP_Cipher(ctx, buf, block, blocksize);
-+ if (ret == 1) {
-+ memcpy(block, buf, blocksize);
-+ }
-+ return ret == 1 ? 0 : 1;
-+}
-+
-+/* TODO: Optionally call a passphrase callback specified by the
-+ * calling program
-+ */
-+static int
-+passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
-+{
-+ int passphrase_len = strlen(passphrase);
-+ (void) rwflag;
-+
-+ if (passphrase_len > (size - 1)) {
-+ passphrase_len = size - 1;
-+ }
-+ memcpy(buf, passphrase, passphrase_len);
-+ buf[passphrase_len] = '\0';
-+
-+ return passphrase_len;
-+}
-+
-+int
-+_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase)
-+{
-+ (void) session;
-+ if (!EVP_get_cipherbyname("des")) {
-+/* If this cipher isn't loaded it's a pretty good indication that none are.
-+ * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
-+ * Someone buy me an OpenSSL manual and I'll read up on it.
-+ */
-+ OpenSSL_add_all_ciphers();
-+ }
-+ *rsa = PEM_read_RSAPrivateKey(fp, NULL, (void *) passphrase_cb,
-+ (void *) passphrase);
-+ if (!*rsa) {
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+int
-+_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase)
-+{
-+ (void) session;
-+ if (!EVP_get_cipherbyname("des")) {
-+/* If this cipher isn't loaded it's a pretty good indication that none are.
-+ * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
-+ * Someone buy me an OpenSSL manual and I'll read up on it.
-+ */
-+ OpenSSL_add_all_ciphers();
-+ }
-+ *dsa = PEM_read_DSAPrivateKey(fp, NULL, (void *) passphrase_cb,
-+ (void *) passphrase);
-+ if (!*dsa) {
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+int
-+_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
-+ libssh2_rsa_ctx * rsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len,
-+ unsigned char **signature, unsigned long *signature_len)
-+{
-+ int ret;
-+ unsigned char *sig;
-+ unsigned int sig_len;
-+
-+ sig_len = RSA_size(rsactx);
-+ sig = LIBSSH2_ALLOC(session, sig_len);
-+
-+ if (!sig) {
-+ return -1;
-+ }
-+
-+ ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx);
-+
-+ if (!ret) {
-+ LIBSSH2_FREE(session, sig);
-+ return -1;
-+ }
-+
-+ *signature = sig;
-+ *signature_len = sig_len;
-+
-+ return 0;
-+}
-+
-+int
-+_libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len, unsigned char *signature)
-+{
-+ DSA_SIG *sig;
-+ int r_len, s_len, rs_pad;
-+ (void) hash_len;
-+
-+ sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx);
-+ if (!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);
-+ return -1;
-+ }
-+
-+ BN_bn2bin(sig->r, signature + rs_pad);
-+ BN_bn2bin(sig->s, signature + rs_pad + r_len);
-+
-+ DSA_SIG_free(sig);
-+
-+ return 0;
-+}
-
-Property changes on: libssh2/src/openssl.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/scp.c
-===================================================================
---- libssh2/src/scp.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/scp.c (.../trunk)
-@@ -0,0 +1,811 @@
-+/* Copyright (c) 2004-2008, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <errno.h>
-+#include <stdlib.h>
-+
-+/* {{{ libssh2_scp_recv
-+ * Open a channel and request a remote file via SCP
-+ *
-+ * NOTE: Will block in a busy loop on error. This has to be done,
-+ * otherwise the blocking error code would erase the true
-+ * cause of the error.
-+ */
-+LIBSSH2_API LIBSSH2_CHANNEL *
-+libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
-+{
-+ int path_len = strlen(path);
-+ int rc;
-+
-+ if (session->scpRecv_state == libssh2_NB_state_idle) {
-+ session->scpRecv_mode = 0;
-+ session->scpRecv_size = 0;
-+ session->scpRecv_mtime = 0;
-+ session->scpRecv_atime = 0;
-+
-+ session->scpRecv_command_len = path_len + sizeof("scp -f ");
-+
-+ if (sb) {
-+ session->scpRecv_command_len++;
-+ }
-+
-+ session->scpRecv_command =
-+ LIBSSH2_ALLOC(session, session->scpRecv_command_len);
-+ if (!session->scpRecv_command) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate a command buffer for SCP session",
-+ 0);
-+ return NULL;
-+ }
-+ if (sb) {
-+ memcpy(session->scpRecv_command, "scp -pf ",
-+ sizeof("scp -pf ") - 1);
-+ memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path,
-+ path_len);
-+ } else {
-+ memcpy(session->scpRecv_command, "scp -f ", sizeof("scp -f ") - 1);
-+ memcpy(session->scpRecv_command + sizeof("scp -f ") - 1, path,
-+ path_len);
-+ }
-+ session->scpRecv_command[session->scpRecv_command_len - 1] = '\0';
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP,
-+ "Opening channel for SCP receive");
-+
-+ session->scpRecv_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_created) {
-+ /* Allocate a channel */
-+ do {
-+ session->scpRecv_channel =
-+ libssh2_channel_open_ex(session, "session",
-+ sizeof("session") - 1,
-+ LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-+ LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
-+ 0);
-+ if (!session->scpRecv_channel) {
-+ if (libssh2_session_last_errno(session) !=
-+ LIBSSH2_ERROR_EAGAIN) {
-+ LIBSSH2_FREE(session, session->scpRecv_command);
-+ session->scpRecv_command = NULL;
-+ session->scpRecv_state = libssh2_NB_state_idle;
-+ return NULL;
-+ } else if (libssh2_session_last_errno(session) ==
-+ LIBSSH2_ERROR_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block starting up channel", 0);
-+ return NULL;
-+ }
-+ }
-+ } while (!session->scpRecv_channel);
-+
-+ session->scpRecv_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent) {
-+ /* Request SCP for the desired file */
-+ rc = libssh2_channel_process_startup(session->scpRecv_channel, "exec",
-+ sizeof("exec") - 1,
-+ (char *) session->scpRecv_command,
-+ session->scpRecv_command_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block requesting SCP startup", 0);
-+ return NULL;
-+ } else if (rc) {
-+ LIBSSH2_FREE(session, session->scpRecv_command);
-+ session->scpRecv_command = NULL;
-+ goto scp_recv_error;
-+ }
-+ LIBSSH2_FREE(session, session->scpRecv_command);
-+ session->scpRecv_command = NULL;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sending initial wakeup");
-+ /* SCP ACK */
-+ session->scpRecv_response[0] = '\0';
-+
-+ session->scpRecv_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
-+ (char *) session->scpRecv_response, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending initial wakeup", 0);
-+ return NULL;
-+ } else if (rc != 1) {
-+ goto scp_recv_error;
-+ }
-+
-+ /* Parse SCP response */
-+ session->scpRecv_response_len = 0;
-+
-+ session->scpRecv_state = libssh2_NB_state_sent2;
-+ }
-+
-+ if ((session->scpRecv_state == libssh2_NB_state_sent2)
-+ || (session->scpRecv_state == libssh2_NB_state_sent3)) {
-+ while (sb
-+ && (session->scpRecv_response_len <
-+ LIBSSH2_SCP_RESPONSE_BUFLEN)) {
-+ unsigned char *s, *p;
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent2) {
-+ rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
-+ (char *) session->
-+ scpRecv_response +
-+ session->scpRecv_response_len, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for SCP response", 0);
-+ return NULL;
-+ } else if (rc <= 0) {
-+ /* Timeout, give up */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Timed out waiting for SCP response", 0);
-+ goto scp_recv_error;
-+ }
-+ session->scpRecv_response_len++;
-+
-+ if (session->scpRecv_response[0] != 'T') {
-+ /*
-+ * Set this as the default error for here, if
-+ * we are successful it will be replaced
-+ */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid data in SCP response, missing Time data",
-+ 0);
-+
-+ session->scpRecv_err_len =
-+ libssh2_channel_packet_data_len(session->
-+ scpRecv_channel, 0);
-+ session->scpRecv_err_msg =
-+ LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
-+ if (!session->scpRecv_err_msg) {
-+ goto scp_recv_error;
-+ }
-+ memset(session->scpRecv_err_msg, 0,
-+ session->scpRecv_err_len + 1);
-+
-+ /* Read the remote error message */
-+ rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
-+ session->scpRecv_err_msg,
-+ session->scpRecv_err_len);
-+ if (rc <= 0) {
-+ /*
-+ * Since we have alread started reading this packet, it is
-+ * already in the systems so it can't return PACKET_EAGAIN
-+ */
-+ LIBSSH2_FREE(session, session->scpRecv_err_msg);
-+ session->scpRecv_err_msg = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Unknown error while getting error string",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ session->scpRecv_err_msg, 1);
-+ session->scpRecv_err_msg = NULL;
-+ goto scp_recv_error;
-+ }
-+
-+ if ((session->scpRecv_response_len > 1) &&
-+ ((session->
-+ scpRecv_response[session->scpRecv_response_len - 1] <
-+ '0')
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] >
-+ '9'))
-+ && (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ ' ')
-+ && (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\r')
-+ && (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\n')) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid data in SCP response", 0);
-+ goto scp_recv_error;
-+ }
-+
-+ if ((session->scpRecv_response_len < 9)
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\n')) {
-+ if (session->scpRecv_response_len ==
-+ LIBSSH2_SCP_RESPONSE_BUFLEN) {
-+ /* You had your chance */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Unterminated response from SCP server",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+ /* Way too short to be an SCP response, or not done yet, short circuit */
-+ continue;
-+ }
-+
-+ /* We're guaranteed not to go under response_len == 0 by the logic above */
-+ while ((session->
-+ scpRecv_response[session->scpRecv_response_len - 1] ==
-+ '\r')
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len -
-+ 1] == '\n'))
-+ session->scpRecv_response_len--;
-+ session->scpRecv_response[session->scpRecv_response_len] =
-+ '\0';
-+
-+ if (session->scpRecv_response_len < 8) {
-+ /* EOL came too soon */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, too short",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ s = session->scpRecv_response + 1;
-+
-+ p = (unsigned char *) strchr((char *) s, ' ');
-+ if (!p || ((p - s) <= 0)) {
-+ /* No spaces or space in the wrong spot */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, malformed mtime",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ *(p++) = '\0';
-+ /* Make sure we don't get fooled by leftover values */
-+ errno = 0;
-+ session->scpRecv_mtime = strtol((char *) s, NULL, 10);
-+ if (errno) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, invalid mtime",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+ s = (unsigned char *) strchr((char *) p, ' ');
-+ if (!s || ((s - p) <= 0)) {
-+ /* No spaces or space in the wrong spot */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, malformed mtime.usec",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ /* Ignore mtime.usec */
-+ s++;
-+ p = (unsigned char *) strchr((char *) s, ' ');
-+ if (!p || ((p - s) <= 0)) {
-+ /* No spaces or space in the wrong spot */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, too short or malformed",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ *(p++) = '\0';
-+ /* Make sure we don't get fooled by leftover values */
-+ errno = 0;
-+ session->scpRecv_atime = strtol((char *) s, NULL, 10);
-+ if (errno) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, invalid atime",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ /* SCP ACK */
-+ session->scpRecv_response[0] = '\0';
-+
-+ session->scpRecv_state = libssh2_NB_state_sent3;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent3) {
-+ rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
-+ (char *) session->
-+ scpRecv_response, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting to send SCP ACK", 0);
-+ return NULL;
-+ } else if (rc != 1) {
-+ goto scp_recv_error;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP,
-+ "mtime = %ld, atime = %ld",
-+ session->scpRecv_mtime, session->scpRecv_atime);
-+
-+ /* We *should* check that atime.usec is valid, but why let that stop use? */
-+ break;
-+ }
-+ }
-+
-+ session->scpRecv_state = libssh2_NB_state_sent4;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent4) {
-+ session->scpRecv_response_len = 0;
-+
-+ session->scpRecv_state = libssh2_NB_state_sent5;
-+ }
-+
-+ if ((session->scpRecv_state == libssh2_NB_state_sent5)
-+ || (session->scpRecv_state == libssh2_NB_state_sent6)) {
-+ while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
-+ char *s, *p, *e = NULL;
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent5) {
-+ rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
-+ (char *) session->
-+ scpRecv_response +
-+ session->scpRecv_response_len, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for SCP response", 0);
-+ return NULL;
-+ } else if (rc <= 0) {
-+ /* Timeout, give up */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Timed out waiting for SCP response", 0);
-+ goto scp_recv_error;
-+ }
-+ session->scpRecv_response_len++;
-+
-+ if (session->scpRecv_response[0] != 'C') {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server", 0);
-+ goto scp_recv_error;
-+ }
-+
-+ if ((session->scpRecv_response_len > 1) &&
-+ (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\r')
-+ && (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\n')
-+ &&
-+ ((session->
-+ scpRecv_response[session->scpRecv_response_len - 1] < 32)
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] >
-+ 126))) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid data in SCP response", 0);
-+ goto scp_recv_error;
-+ }
-+
-+ if ((session->scpRecv_response_len < 7)
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len - 1] !=
-+ '\n')) {
-+ if (session->scpRecv_response_len ==
-+ LIBSSH2_SCP_RESPONSE_BUFLEN) {
-+ /* You had your chance */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Unterminated response from SCP server",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+ /* Way too short to be an SCP response, or not done yet, short circuit */
-+ continue;
-+ }
-+
-+ /* We're guaranteed not to go under response_len == 0 by the logic above */
-+ while ((session->
-+ scpRecv_response[session->scpRecv_response_len - 1] ==
-+ '\r')
-+ || (session->
-+ scpRecv_response[session->scpRecv_response_len -
-+ 1] == '\n')) {
-+ session->scpRecv_response_len--;
-+ }
-+ session->scpRecv_response[session->scpRecv_response_len] =
-+ '\0';
-+
-+ if (session->scpRecv_response_len < 6) {
-+ /* EOL came too soon */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, too short",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ s = (char *) session->scpRecv_response + 1;
-+
-+ p = strchr(s, ' ');
-+ if (!p || ((p - s) <= 0)) {
-+ /* No spaces or space in the wrong spot */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, malformed mode",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ *(p++) = '\0';
-+ /* Make sure we don't get fooled by leftover values */
-+ errno = 0;
-+ session->scpRecv_mode = strtol(s, &e, 8);
-+ if ((e && *e) || errno) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, invalid mode",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ s = strchr(p, ' ');
-+ if (!s || ((s - p) <= 0)) {
-+ /* No spaces or space in the wrong spot */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, too short or malformed",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ *(s++) = '\0';
-+ /* Make sure we don't get fooled by leftover values */
-+ errno = 0;
-+ session->scpRecv_size = scpsize_strtol(p, &e, 10);
-+ if ((e && *e) || errno) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid response from SCP server, invalid size",
-+ 0);
-+ goto scp_recv_error;
-+ }
-+
-+ /* SCP ACK */
-+ session->scpRecv_response[0] = '\0';
-+
-+ session->scpRecv_state = libssh2_NB_state_sent6;
-+ }
-+
-+ if (session->scpRecv_state == libssh2_NB_state_sent6) {
-+ rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
-+ (char *) session->
-+ scpRecv_response, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending SCP ACK", 0);
-+ return NULL;
-+ } else if (rc != 1) {
-+ goto scp_recv_error;
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP,
-+ "mode = 0%lo size = %ld", session->scpRecv_mode,
-+ session->scpRecv_size);
-+
-+ /* We *should* check that basename is valid, but why let that stop us? */
-+ break;
-+ }
-+ }
-+
-+ session->scpRecv_state = libssh2_NB_state_sent7;
-+ }
-+
-+ if (sb) {
-+ memset(sb, 0, sizeof(struct stat));
-+
-+ sb->st_mtime = session->scpRecv_mtime;
-+ sb->st_atime = session->scpRecv_atime;
-+ sb->st_size = session->scpRecv_size;
-+ sb->st_mode = session->scpRecv_mode;
-+ }
-+
-+ session->scpRecv_state = libssh2_NB_state_idle;
-+ return session->scpRecv_channel;
-+
-+ scp_recv_error:
-+ while (libssh2_channel_free(session->scpRecv_channel) == PACKET_EAGAIN);
-+ session->scpRecv_channel = NULL;
-+ session->scpRecv_state = libssh2_NB_state_idle;
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_scp_send_ex
-+ * Send a file using SCP
-+ *
-+ * NOTE: Will block in a busy loop on error. This has to be done,
-+ * otherwise the blocking error code would erase the true
-+ * cause of the error.
-+ */
-+LIBSSH2_API LIBSSH2_CHANNEL *
-+libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
-+ size_t size, long mtime, long atime)
-+{
-+ int path_len = strlen(path);
-+ unsigned const char *base;
-+ int rc;
-+
-+ if (session->scpSend_state == libssh2_NB_state_idle) {
-+ session->scpSend_command_len = path_len + sizeof("scp -t ");
-+
-+ if (mtime || atime) {
-+ session->scpSend_command_len++;
-+ }
-+
-+ session->scpSend_command =
-+ LIBSSH2_ALLOC(session, session->scpSend_command_len);
-+ if (!session->scpSend_command) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate a command buffer for scp session",
-+ 0);
-+ return NULL;
-+ }
-+
-+ if (mtime || atime) {
-+ memcpy(session->scpSend_command, "scp -pt ",
-+ sizeof("scp -pt ") - 1);
-+ memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path,
-+ path_len);
-+ } else {
-+ memcpy(session->scpSend_command, "scp -t ", sizeof("scp -t ") - 1);
-+ memcpy(session->scpSend_command + sizeof("scp -t ") - 1, path,
-+ path_len);
-+ }
-+ session->scpSend_command[session->scpSend_command_len - 1] = '\0';
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP,
-+ "Opening channel for SCP send");
-+ /* Allocate a channel */
-+
-+ session->scpSend_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_created) {
-+ session->scpSend_channel =
-+ libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
-+ LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-+ LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
-+ if (!session->scpSend_channel) {
-+ if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
-+ /* previous call set libssh2_session_last_error(), pass it through */
-+ LIBSSH2_FREE(session, session->scpSend_command);
-+ session->scpSend_command = NULL;
-+ session->scpSend_state = libssh2_NB_state_idle;
-+ return NULL;
-+ } else if (libssh2_session_last_errno(session) ==
-+ LIBSSH2_ERROR_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block starting up channel", 0);
-+ return NULL;
-+ }
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent) {
-+ /* Request SCP for the desired file */
-+ rc = libssh2_channel_process_startup(session->scpSend_channel, "exec",
-+ sizeof("exec") - 1,
-+ (char *) session->scpSend_command,
-+ session->scpSend_command_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block requesting SCP startup", 0);
-+ return NULL;
-+ } else if (rc) {
-+ /* previous call set libssh2_session_last_error(), pass it through */
-+ LIBSSH2_FREE(session, session->scpSend_command);
-+ session->scpSend_command = NULL;
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Unknown error while getting error string", 0);
-+ goto scp_send_error;
-+ }
-+ LIBSSH2_FREE(session, session->scpSend_command);
-+ session->scpSend_command = NULL;
-+
-+ session->scpSend_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent1) {
-+ /* Wait for ACK */
-+ rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
-+ (char *) session->scpSend_response, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for response from remote", 0);
-+ return NULL;
-+ } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid ACK response from remote", 0);
-+ goto scp_send_error;
-+ }
-+
-+ if (mtime || atime) {
-+ /* Send mtime and atime to be used for file */
-+ session->scpSend_response_len =
-+ snprintf((char *) session->scpSend_response,
-+ LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime,
-+ atime);
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
-+ session->scpSend_response);
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_sent2;
-+ }
-+
-+ /* Send mtime and atime to be used for file */
-+ if (mtime || atime) {
-+ if (session->scpSend_state == libssh2_NB_state_sent2) {
-+ rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
-+ (char *) session->scpSend_response,
-+ session->scpSend_response_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending time data for SCP file", 0);
-+ return NULL;
-+ } else if (rc != session->scpSend_response_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send time data for SCP file", 0);
-+ goto scp_send_error;
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_sent3;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent3) {
-+ /* Wait for ACK */
-+ rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
-+ (char *) session->scpSend_response,
-+ 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for response", 0);
-+ return NULL;
-+ } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid ACK response from remote", 0);
-+ goto scp_send_error;
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_sent4;
-+ }
-+ } else {
-+ if (session->scpSend_state == libssh2_NB_state_sent2) {
-+ session->scpSend_state = libssh2_NB_state_sent4;
-+ }
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent4) {
-+ /* Send mode, size, and basename */
-+ base = (unsigned char *) strrchr(path, '/');
-+ if (base) {
-+ base++;
-+ } else {
-+ base = (unsigned char *) path;
-+ }
-+
-+ session->scpSend_response_len =
-+ snprintf((char *) session->scpSend_response,
-+ LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode,
-+ (unsigned long) size, base);
-+ _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
-+ session->scpSend_response);
-+
-+ session->scpSend_state = libssh2_NB_state_sent5;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent5) {
-+ rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
-+ (char *) session->scpSend_response,
-+ session->scpSend_response_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block send core file data for SCP file", 0);
-+ return NULL;
-+ } else if (rc != session->scpSend_response_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send core file data for SCP file", 0);
-+ goto scp_send_error;
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_sent6;
-+ }
-+
-+ if (session->scpSend_state == libssh2_NB_state_sent6) {
-+ /* Wait for ACK */
-+ rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
-+ (char *) session->scpSend_response, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for response", 0);
-+ return NULL;
-+ } else if (rc <= 0) {
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid ACK response from remote", 0);
-+ goto scp_send_error;
-+ } else if (session->scpSend_response[0] != 0) {
-+ /*
-+ * Set this as the default error for here, if
-+ * we are successful it will be replaced
-+ */
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ "Invalid ACK response from remote", 0);
-+
-+ session->scpSend_err_len =
-+ libssh2_channel_packet_data_len(session->scpSend_channel, 0);
-+ session->scpSend_err_msg =
-+ LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
-+ if (!session->scpSend_err_msg) {
-+ goto scp_send_error;
-+ }
-+ memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
-+
-+ /* Read the remote error message */
-+ rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
-+ session->scpSend_err_msg,
-+ session->scpSend_err_len);
-+ if (rc <= 0) {
-+ /*
-+ * Since we have alread started reading this packet, it is
-+ * already in the systems so it can't return PACKET_EAGAIN
-+ */
-+ LIBSSH2_FREE(session, session->scpSend_err_msg);
-+ session->scpSend_err_msg = NULL;
-+ goto scp_send_error;
-+ }
-+
-+ libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
-+ session->scpSend_err_msg, 1);
-+ session->scpSend_err_msg = NULL;
-+ goto scp_send_error;
-+ }
-+ }
-+
-+ session->scpSend_state = libssh2_NB_state_idle;
-+
-+ return session->scpSend_channel;
-+
-+ scp_send_error:
-+ while (libssh2_channel_free(session->scpSend_channel) == PACKET_EAGAIN);
-+ session->scpSend_channel = NULL;
-+ session->scpSend_state = libssh2_NB_state_idle;
-+ return NULL;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/scp.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/hostkey.c
-===================================================================
---- libssh2/src/hostkey.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/hostkey.c (.../trunk)
-@@ -0,0 +1,455 @@
-+/* Copyright (c) 2004-2006, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+/* Needed for struct iovec on some platforms */
-+#ifdef HAVE_SYS_UIO_H
-+#include <sys/uio.h>
-+#endif
-+
-+#if LIBSSH2_RSA
-+/* ***********
-+ * ssh-rsa *
-+ *********** */
-+
-+static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session,
-+ void **abstract);
-+
-+/* {{{ libssh2_hostkey_method_ssh_rsa_init
-+ * Initialize the server hostkey working area with e/n pair
-+ */
-+static int
-+libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session,
-+ const unsigned char *hostkey_data,
-+ unsigned long hostkey_data_len,
-+ void **abstract)
-+{
-+ libssh2_rsa_ctx *rsactx;
-+ const unsigned char *s, *e, *n;
-+ unsigned long len, e_len, n_len;
-+
-+ (void) hostkey_data_len;
-+
-+ if (*abstract) {
-+ libssh2_hostkey_method_ssh_rsa_dtor(session, abstract);
-+ *abstract = NULL;
-+ }
-+
-+ s = hostkey_data;
-+ len = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ if (len != 7 || strncmp((char *) s, "ssh-rsa", 7) != 0) {
-+ return -1;
-+ }
-+ s += 7;
-+
-+ e_len = libssh2_ntohu32(s);
-+ s += 4;
-+
-+ e = s;
-+ s += e_len;
-+ n_len = libssh2_ntohu32(s);
-+ s += 4;
-+ n = s;
-+ s += n_len;
-+
-+ if (_libssh2_rsa_new(&rsactx, e, e_len, n, n_len, NULL, 0,
-+ NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0))
-+ return -1;
-+
-+ *abstract = rsactx;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_rsa_initPEM
-+ * Load a Private Key from a PEM file
-+ */
-+static int
-+libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
-+ const char *privkeyfile,
-+ unsigned const char *passphrase,
-+ void **abstract)
-+{
-+ libssh2_rsa_ctx *rsactx;
-+ FILE *fp;
-+ int ret;
-+
-+ if (*abstract) {
-+ libssh2_hostkey_method_ssh_rsa_dtor(session, abstract);
-+ *abstract = NULL;
-+ }
-+
-+ fp = fopen(privkeyfile, "r");
-+ if (!fp) {
-+ return -1;
-+ }
-+
-+ ret = _libssh2_rsa_new_private(&rsactx, session, fp, passphrase);
-+ fclose(fp);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ *abstract = rsactx;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_rsa_sign
-+ * Verify signature created by remote
-+ */
-+static int
-+libssh2_hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m,
-+ unsigned long m_len, void **abstract)
-+{
-+ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
-+ (void) session;
-+
-+ /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
-+ sig += 15;
-+ sig_len -= 15;
-+ return _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_rsa_signv
-+ * Construct a signature from an array of vectors
-+ */
-+static int
-+libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
-+ unsigned char **signature,
-+ unsigned long *signature_len,
-+ unsigned long veccount,
-+ const struct iovec datavec[],
-+ void **abstract)
-+{
-+ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
-+ int ret;
-+ unsigned int i;
-+ unsigned char hash[SHA_DIGEST_LENGTH];
-+ libssh2_sha1_ctx ctx;
-+
-+ libssh2_sha1_init(&ctx);
-+ for(i = 0; i < veccount; i++) {
-+ libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
-+ }
-+ libssh2_sha1_final(ctx, hash);
-+
-+ ret = _libssh2_rsa_sha1_sign(session, rsactx, hash, SHA_DIGEST_LENGTH,
-+ signature, signature_len);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_rsa_dtor
-+ * Shutdown the hostkey
-+ */
-+static int
-+libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, void **abstract)
-+{
-+ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract);
-+ (void) session;
-+
-+ _libssh2_rsa_free(rsactx);
-+
-+ *abstract = NULL;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_rsa = {
-+ "ssh-rsa",
-+ MD5_DIGEST_LENGTH,
-+ libssh2_hostkey_method_ssh_rsa_init,
-+ libssh2_hostkey_method_ssh_rsa_initPEM,
-+ libssh2_hostkey_method_ssh_rsa_sig_verify,
-+ libssh2_hostkey_method_ssh_rsa_signv,
-+ NULL, /* encrypt */
-+ libssh2_hostkey_method_ssh_rsa_dtor,
-+};
-+#endif /* LIBSSH2_RSA */
-+
-+#if LIBSSH2_DSA
-+/* ***********
-+ * ssh-dss *
-+ *********** */
-+
-+static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session,
-+ void **abstract);
-+
-+/* {{{ libssh2_hostkey_method_ssh_dss_init
-+ * Initialize the server hostkey working area with p/q/g/y set
-+ */
-+static int
-+libssh2_hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session,
-+ const unsigned char *hostkey_data,
-+ unsigned long hostkey_data_len,
-+ void **abstract)
-+{
-+ libssh2_dsa_ctx *dsactx;
-+ const unsigned char *p, *q, *g, *y, *s;
-+ unsigned long p_len, q_len, g_len, y_len, len;
-+ (void) hostkey_data_len;
-+
-+ if (*abstract) {
-+ libssh2_hostkey_method_ssh_dss_dtor(session, abstract);
-+ *abstract = NULL;
-+ }
-+
-+ s = hostkey_data;
-+ len = libssh2_ntohu32(s);
-+ s += 4;
-+ if (len != 7 || strncmp((char *) s, "ssh-dss", 7) != 0) {
-+ return -1;
-+ }
-+ s += 7;
-+
-+ p_len = libssh2_ntohu32(s);
-+ s += 4;
-+ p = s;
-+ s += p_len;
-+ q_len = libssh2_ntohu32(s);
-+ s += 4;
-+ q = s;
-+ s += q_len;
-+ g_len = libssh2_ntohu32(s);
-+ s += 4;
-+ g = s;
-+ s += g_len;
-+ y_len = libssh2_ntohu32(s);
-+ s += 4;
-+ y = s;
-+ s += y_len;
-+
-+ _libssh2_dsa_new(&dsactx, p, p_len, q, q_len, g, g_len, y, y_len, NULL, 0);
-+
-+ *abstract = dsactx;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_dss_initPEM
-+ * Load a Private Key from a PEM file
-+ */
-+static int
-+libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
-+ const char *privkeyfile,
-+ unsigned const char *passphrase,
-+ void **abstract)
-+{
-+ libssh2_dsa_ctx *dsactx;
-+ FILE *fp;
-+ int ret;
-+
-+ if (*abstract) {
-+ libssh2_hostkey_method_ssh_dss_dtor(session, abstract);
-+ *abstract = NULL;
-+ }
-+
-+ fp = fopen(privkeyfile, "r");
-+ if (!fp) {
-+ return -1;
-+ }
-+
-+ ret = _libssh2_dsa_new_private(&dsactx, session, fp, passphrase);
-+ fclose(fp);
-+ if (ret) {
-+ return -1;
-+ }
-+
-+ *abstract = dsactx;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_dss_sign
-+ * Verify signature created by remote
-+ */
-+static int
-+libssh2_hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m,
-+ unsigned long m_len, void **abstract)
-+{
-+ libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
-+
-+ /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */
-+ sig += 15;
-+ sig_len -= 15;
-+ if (sig_len != 40) {
-+ libssh2_error(session, LIBSSH2_ERROR_PROTO,
-+ "Invalid DSS signature length", 0);
-+ return -1;
-+ }
-+ return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_dss_signv
-+ * Construct a signature from an array of vectors
-+ */
-+static int
-+libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
-+ unsigned char **signature,
-+ unsigned long *signature_len,
-+ unsigned long veccount,
-+ const struct iovec datavec[],
-+ void **abstract)
-+{
-+ libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
-+ unsigned char hash[SHA_DIGEST_LENGTH];
-+ libssh2_sha1_ctx ctx;
-+ unsigned int i;
-+
-+ *signature = LIBSSH2_ALLOC(session, 2 * SHA_DIGEST_LENGTH);
-+ if (!*signature) {
-+ return -1;
-+ }
-+
-+ *signature_len = 2 * SHA_DIGEST_LENGTH;
-+ memset(*signature, 0, 2 * SHA_DIGEST_LENGTH);
-+
-+ libssh2_sha1_init(&ctx);
-+ for(i = 0; i < veccount; i++) {
-+ libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
-+ }
-+ libssh2_sha1_final(ctx, hash);
-+
-+ if (_libssh2_dsa_sha1_sign(dsactx, hash, SHA_DIGEST_LENGTH, *signature)) {
-+ LIBSSH2_FREE(session, *signature);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_hostkey_method_ssh_dss_dtor
-+ * Shutdown the hostkey method
-+ */
-+static int
-+libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, void **abstract)
-+{
-+ libssh2_dsa_ctx *dsactx = (libssh2_dsa_ctx *) (*abstract);
-+ (void) session;
-+
-+ _libssh2_dsa_free(dsactx);
-+
-+ *abstract = NULL;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_dss = {
-+ "ssh-dss",
-+ MD5_DIGEST_LENGTH,
-+ libssh2_hostkey_method_ssh_dss_init,
-+ libssh2_hostkey_method_ssh_dss_initPEM,
-+ libssh2_hostkey_method_ssh_dss_sig_verify,
-+ libssh2_hostkey_method_ssh_dss_signv,
-+ NULL, /* encrypt */
-+ libssh2_hostkey_method_ssh_dss_dtor,
-+};
-+#endif /* LIBSSH2_DSA */
-+
-+static const LIBSSH2_HOSTKEY_METHOD *_libssh2_hostkey_methods[] = {
-+#if LIBSSH2_RSA
-+ &libssh2_hostkey_method_ssh_rsa,
-+#endif /* LIBSSH2_RSA */
-+#if LIBSSH2_DSA
-+ &libssh2_hostkey_method_ssh_dss,
-+#endif /* LIBSSH2_DSA */
-+ NULL
-+};
-+
-+const LIBSSH2_HOSTKEY_METHOD **
-+libssh2_hostkey_methods(void)
-+{
-+ return _libssh2_hostkey_methods;
-+}
-+
-+/* {{{ 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
-+ */
-+LIBSSH2_API const char *
-+libssh2_hostkey_hash(LIBSSH2_SESSION * session, int hash_type)
-+{
-+ switch (hash_type) {
-+#if LIBSSH2_MD5
-+ case LIBSSH2_HOSTKEY_HASH_MD5:
-+ return (char *) session->server_hostkey_md5;
-+ break;
-+#endif /* LIBSSH2_MD5 */
-+ case LIBSSH2_HOSTKEY_HASH_SHA1:
-+ return (char *) session->server_hostkey_sha1;
-+ break;
-+ default:
-+ return NULL;
-+ }
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/hostkey.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.2
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/publickey.c
-===================================================================
---- libssh2/src/publickey.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/publickey.c (.../trunk)
-@@ -0,0 +1,1094 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include "libssh2_publickey.h"
-+
-+#define LIBSSH2_PUBLICKEY_VERSION 2
-+
-+/* Numericised response codes -- Not IETF standard, just a local representation */
-+#define LIBSSH2_PUBLICKEY_RESPONSE_STATUS 0
-+#define LIBSSH2_PUBLICKEY_RESPONSE_VERSION 1
-+#define LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY 2
-+
-+typedef struct _LIBSSH2_PUBLICKEY_CODE_LIST
-+{
-+ int code;
-+ const char *name;
-+ int name_len;
-+} LIBSSH2_PUBLICKEY_CODE_LIST;
-+
-+static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_response_codes[] = {
-+ {LIBSSH2_PUBLICKEY_RESPONSE_STATUS, "status", sizeof("status") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_RESPONSE_VERSION, "version", sizeof("version") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY, "publickey", sizeof("publickey") - 1}
-+ ,
-+ {0, NULL, 0}
-+};
-+
-+/* PUBLICKEY status codes -- IETF defined */
-+#define LIBSSH2_PUBLICKEY_SUCCESS 0
-+#define LIBSSH2_PUBLICKEY_ACCESS_DENIED 1
-+#define LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED 2
-+#define LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED 3
-+#define LIBSSH2_PUBLICKEY_KEY_NOT_FOUND 4
-+#define LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED 5
-+#define LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT 6
-+#define LIBSSH2_PUBLICKEY_GENERAL_FAILURE 7
-+#define LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED 8
-+
-+#define LIBSSH2_PUBLICKEY_STATUS_CODE_MAX 8
-+
-+static const LIBSSH2_PUBLICKEY_CODE_LIST libssh2_publickey_status_codes[] = {
-+ {LIBSSH2_PUBLICKEY_SUCCESS, "success", sizeof("success") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_ACCESS_DENIED, "access denied",
-+ sizeof("access denied") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_STORAGE_EXCEEDED, "storage exceeded",
-+ sizeof("storage exceeded") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_VERSION_NOT_SUPPORTED, "version not supported",
-+ sizeof("version not supported") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_KEY_NOT_FOUND, "key not found",
-+ sizeof("key not found") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_KEY_NOT_SUPPORTED, "key not supported",
-+ sizeof("key not supported") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_KEY_ALREADY_PRESENT, "key already present",
-+ sizeof("key already present") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_GENERAL_FAILURE, "general failure",
-+ sizeof("general failure") - 1}
-+ ,
-+ {LIBSSH2_PUBLICKEY_REQUEST_NOT_SUPPORTED, "request not supported",
-+ sizeof("request not supported") - 1}
-+ ,
-+ {0, NULL, 0}
-+};
-+
-+/* {{{ libssh2_publickey_status_error
-+ * Format an error message from a status code
-+ */
-+#define LIBSSH2_PUBLICKEY_STATUS_TEXT_START "Publickey Subsystem Error: \""
-+#define LIBSSH2_PUBLICKEY_STATUS_TEXT_MID "\" Server Reports: \""
-+#define LIBSSH2_PUBLICKEY_STATUS_TEXT_END "\""
-+static void
-+libssh2_publickey_status_error(const LIBSSH2_PUBLICKEY * pkey,
-+ LIBSSH2_SESSION * session, int status,
-+ const unsigned char *message, int message_len)
-+{
-+ const char *status_text;
-+ int status_text_len;
-+ char *m, *s;
-+ int m_len;
-+
-+ /* GENERAL_FAILURE got remapped between version 1 and 2 */
-+ if (status == 6 && pkey && pkey->version == 1) {
-+ status = 7;
-+ }
-+
-+ if (status < 0 || status > LIBSSH2_PUBLICKEY_STATUS_CODE_MAX) {
-+ status_text = "unknown";
-+ status_text_len = sizeof("unknown") - 1;
-+ } else {
-+ status_text = libssh2_publickey_status_codes[status].name;
-+ status_text_len = libssh2_publickey_status_codes[status].name_len;
-+ }
-+
-+ m_len =
-+ (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1) + status_text_len +
-+ (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1) + message_len +
-+ (sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
-+ m = LIBSSH2_ALLOC(session, m_len + 1);
-+ if (!m) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for status message", 0);
-+ return;
-+ }
-+ s = m;
-+ memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_START,
-+ sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1);
-+ s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_START) - 1;
-+ memcpy(s, status_text, status_text_len);
-+ s += status_text_len;
-+ memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_MID,
-+ sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1);
-+ s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_MID) - 1;
-+ memcpy(s, message, message_len);
-+ s += message_len;
-+ memcpy(s, LIBSSH2_PUBLICKEY_STATUS_TEXT_END,
-+ sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END) - 1);
-+ s += sizeof(LIBSSH2_PUBLICKEY_STATUS_TEXT_END);
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, m, 1);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_packet_receive
-+ * Read a packet from the subsystem
-+ */
-+static int
-+libssh2_publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey,
-+ unsigned char **data, unsigned long *data_len)
-+{
-+ LIBSSH2_CHANNEL *channel = pkey->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ unsigned char buffer[4];
-+ int rc;
-+
-+ if (pkey->receive_state == libssh2_NB_state_idle) {
-+ rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc != 4) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Invalid response from publickey subsystem", 0);
-+ return -1;
-+ }
-+
-+ pkey->receive_packet_len = libssh2_ntohu32(buffer);
-+ pkey->receive_packet =
-+ LIBSSH2_ALLOC(session, pkey->receive_packet_len);
-+ if (!pkey->receive_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate publickey response buffer", 0);
-+ return -1;
-+ }
-+
-+ pkey->receive_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (pkey->receive_state == libssh2_NB_state_sent) {
-+ rc = libssh2_channel_read_ex(channel, 0, (char *) pkey->receive_packet,
-+ pkey->receive_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc != (int)pkey->receive_packet_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for publickey subsystem response packet",
-+ 0);
-+ LIBSSH2_FREE(session, pkey->receive_packet);
-+ pkey->receive_packet = NULL;
-+ pkey->receive_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ *data = pkey->receive_packet;
-+ *data_len = pkey->receive_packet_len;
-+ }
-+
-+ pkey->receive_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_response_id
-+ * Translate a string response name to a numeric code
-+ * Data will be incremented by 4 + response_len on success only
-+ */
-+static int
-+libssh2_publickey_response_id(unsigned char **pdata, int data_len)
-+{
-+ unsigned long response_len;
-+ unsigned char *data = *pdata;
-+ const LIBSSH2_PUBLICKEY_CODE_LIST *codes =
-+ libssh2_publickey_response_codes;
-+
-+ if (data_len < 4) {
-+ /* Malformed response */
-+ return -1;
-+ }
-+ response_len = libssh2_ntohu32(data);
-+ data += 4;
-+ data_len -= 4;
-+ if (data_len < (int)response_len) {
-+ /* Malformed response */
-+ return -1;
-+ }
-+
-+ while (codes->name) {
-+ if ((unsigned long)codes->name_len == response_len &&
-+ strncmp(codes->name, (char *) data, response_len) == 0) {
-+ *pdata = data + response_len;
-+ return codes->code;
-+ }
-+ codes++;
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_response_success
-+ * Generic helper routine to wait for success response and nothing else
-+ */
-+static int
-+libssh2_publickey_response_success(LIBSSH2_PUBLICKEY * pkey)
-+{
-+ LIBSSH2_SESSION *session = pkey->channel->session;
-+ unsigned char *data, *s;
-+ unsigned long data_len;
-+ int response;
-+ int rc;
-+
-+ while (1) {
-+ rc = libssh2_publickey_packet_receive(pkey, &data, &data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for response from publickey subsystem",
-+ 0);
-+ return -1;
-+ }
-+
-+ s = data;
-+ if ((response = libssh2_publickey_response_id(&s, data_len)) < 0) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Invalid publickey subsystem response code", 0);
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+
-+ switch (response) {
-+ case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
-+ /* Error, or processing complete */
-+ {
-+ unsigned long status, descr_len, lang_len;
-+ unsigned char *descr, *lang;
-+
-+ status = libssh2_ntohu32(s);
-+ s += 4;
-+ descr_len = libssh2_ntohu32(s);
-+ s += 4;
-+ descr = s;
-+ s += descr_len;
-+ lang_len = libssh2_ntohu32(s);
-+ s += 4;
-+ lang = s;
-+ s += lang_len;
-+
-+ if (s > data + data_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Malformed publickey subsystem packet", 0);
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+
-+ if (status == LIBSSH2_PUBLICKEY_SUCCESS) {
-+ LIBSSH2_FREE(session, data);
-+ return 0;
-+ }
-+
-+ libssh2_publickey_status_error(pkey, session, status, descr,
-+ descr_len);
-+ LIBSSH2_FREE(session, data);
-+ return -1;
-+ }
-+ default:
-+ /* Unknown/Unexpected */
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Unexpected publickey subsystem response, ignoring",
-+ 0);
-+ LIBSSH2_FREE(session, data);
-+ data = NULL;
-+ }
-+ }
-+ /* never reached, but include `return` to silence compiler warnings */
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+
-+/* *****************
-+ * Publickey API *
-+ ***************** */
-+
-+/* {{{ libssh2_publickey_init
-+ * Startup the publickey subsystem
-+ */
-+LIBSSH2_API LIBSSH2_PUBLICKEY *
-+libssh2_publickey_init(LIBSSH2_SESSION * session)
-+{
-+ /* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */
-+ unsigned char buffer[19];
-+ unsigned char *s;
-+ int response;
-+ int rc;
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_idle) {
-+ session->pkeyInit_data = NULL;
-+ session->pkeyInit_pkey = NULL;
-+ session->pkeyInit_channel = NULL;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Initializing publickey subsystem");
-+
-+ session->pkeyInit_state = libssh2_NB_state_allocated;
-+ }
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_allocated) {
-+ do {
-+ session->pkeyInit_channel =
-+ libssh2_channel_open_ex(session, "session",
-+ sizeof("session") - 1,
-+ LIBSSH2_CHANNEL_WINDOW_DEFAULT,
-+ LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
-+ 0);
-+ if (!session->pkeyInit_channel
-+ && (libssh2_session_last_errno(session) ==
-+ LIBSSH2_ERROR_EAGAIN)) {
-+ /* The error state is already set, so leave it */
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block to startup channel", 0);
-+ return NULL;
-+ } else if (!session->pkeyInit_channel
-+ && (libssh2_session_last_errno(session) !=
-+ LIBSSH2_ERROR_EAGAIN)) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
-+ "Unable to startup channel", 0);
-+ goto err_exit;
-+ }
-+ } while (!session->pkeyInit_channel);
-+
-+ session->pkeyInit_state = libssh2_NB_state_sent;
-+ }
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_sent) {
-+ rc = libssh2_channel_process_startup(session->pkeyInit_channel,
-+ "subsystem",
-+ sizeof("subsystem") - 1,
-+ "publickey", strlen("publickey"));
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block starting publickey subsystem", 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
-+ "Unable to request publickey subsystem", 0);
-+ goto err_exit;
-+ }
-+
-+ session->pkeyInit_state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_sent1) {
-+ rc = libssh2_channel_handle_extended_data2(session->pkeyInit_channel,
-+ LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block starting publickey subsystem", 0);
-+ return NULL;
-+ }
-+
-+ session->pkeyInit_pkey =
-+ LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PUBLICKEY));
-+ if (!session->pkeyInit_pkey) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate a new publickey structure", 0);
-+ goto err_exit;
-+ }
-+ memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY));
-+ session->pkeyInit_pkey->channel = session->pkeyInit_channel;
-+ session->pkeyInit_pkey->version = 0;
-+
-+ s = buffer;
-+ libssh2_htonu32(s, 4 + (sizeof("version") - 1) + 4);
-+ s += 4;
-+ libssh2_htonu32(s, sizeof("version") - 1);
-+ s += 4;
-+ memcpy(s, "version", sizeof("version") - 1);
-+ s += sizeof("version") - 1;
-+ libssh2_htonu32(s, LIBSSH2_PUBLICKEY_VERSION);
-+ s += 4;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Sending publickey version packet advertising version %d support",
-+ (int) LIBSSH2_PUBLICKEY_VERSION);
-+
-+ session->pkeyInit_state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_sent2) {
-+ rc = libssh2_channel_write_ex(session->pkeyInit_channel, 0,
-+ (char *) buffer, (s - buffer));
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block sending publickey version packet", 0);
-+ return NULL;
-+ } else if ((s - buffer) != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send publickey version packet", 0);
-+ goto err_exit;
-+ }
-+
-+ session->pkeyInit_state = libssh2_NB_state_sent3;
-+ }
-+
-+ if (session->pkeyInit_state == libssh2_NB_state_sent3) {
-+ while (1) {
-+ rc = libssh2_publickey_packet_receive(session->pkeyInit_pkey,
-+ &session->pkeyInit_data,
-+ &session->pkeyInit_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block waiting for response from publickey subsystem",
-+ 0);
-+ return NULL;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for response from publickey subsystem",
-+ 0);
-+ goto err_exit;
-+ }
-+
-+ s = session->pkeyInit_data;
-+ if ((response =
-+ libssh2_publickey_response_id(&s,
-+ session->pkeyInit_data_len)) <
-+ 0) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Invalid publickey subsystem response code", 0);
-+ goto err_exit;
-+ }
-+
-+ switch (response) {
-+ case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
-+ /* Error */
-+ {
-+ unsigned long status, descr_len, lang_len;
-+ unsigned char *descr, *lang;
-+
-+ status = libssh2_ntohu32(s);
-+ s += 4;
-+ descr_len = libssh2_ntohu32(s);
-+ s += 4;
-+ descr = s;
-+ s += descr_len;
-+ lang_len = libssh2_ntohu32(s);
-+ s += 4;
-+ lang = s;
-+ s += lang_len;
-+
-+ if (s >
-+ session->pkeyInit_data + session->pkeyInit_data_len) {
-+ libssh2_error(session,
-+ LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Malformed publickey subsystem packet",
-+ 0);
-+ goto err_exit;
-+ }
-+
-+ libssh2_publickey_status_error(NULL, session, status,
-+ descr, descr_len);
-+ goto err_exit;
-+ }
-+
-+ case LIBSSH2_PUBLICKEY_RESPONSE_VERSION:
-+ /* What we want */
-+ session->pkeyInit_pkey->version = libssh2_ntohu32(s);
-+ if (session->pkeyInit_pkey->version >
-+ LIBSSH2_PUBLICKEY_VERSION) {
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Truncating remote publickey version from %lu",
-+ session->pkeyInit_pkey->version);
-+ session->pkeyInit_pkey->version =
-+ LIBSSH2_PUBLICKEY_VERSION;
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Enabling publickey subsystem version %lu",
-+ session->pkeyInit_pkey->version);
-+ LIBSSH2_FREE(session, session->pkeyInit_data);
-+ session->pkeyInit_data = NULL;
-+ session->pkeyInit_state = libssh2_NB_state_idle;
-+ return session->pkeyInit_pkey;
-+
-+ default:
-+ /* Unknown/Unexpected */
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Unexpected publickey subsystem response, ignoring",
-+ 0);
-+ LIBSSH2_FREE(session, session->pkeyInit_data);
-+ session->pkeyInit_data = NULL;
-+ }
-+ }
-+ }
-+
-+ /* Never reached except by direct goto */
-+ err_exit:
-+ session->pkeyInit_state = libssh2_NB_state_sent4;
-+ if (session->pkeyInit_channel) {
-+ rc = libssh2_channel_close(session->pkeyInit_channel);
-+ if (rc == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block closing channel", 0);
-+ return NULL;
-+ }
-+ }
-+ if (session->pkeyInit_pkey) {
-+ LIBSSH2_FREE(session, session->pkeyInit_pkey);
-+ session->pkeyInit_pkey = NULL;
-+ }
-+ if (session->pkeyInit_data) {
-+ LIBSSH2_FREE(session, session->pkeyInit_data);
-+ session->pkeyInit_data = NULL;
-+ }
-+ session->pkeyInit_state = libssh2_NB_state_idle;
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_add_ex
-+ * Add a new public key entry
-+ */
-+LIBSSH2_API int
-+libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY * pkey, const unsigned char *name,
-+ unsigned long name_len, const unsigned char *blob,
-+ unsigned long blob_len, char overwrite,
-+ unsigned long num_attrs,
-+ const libssh2_publickey_attribute attrs[])
-+{
-+ LIBSSH2_CHANNEL *channel = pkey->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ /* 19 = packet_len(4) + add_len(4) + "add"(3) + name_len(4) + {name} blob_len(4) + {blob} */
-+ unsigned long i, packet_len = 19 + name_len + blob_len;
-+ unsigned char *comment = NULL;
-+ unsigned long comment_len = 0;
-+ int rc;
-+
-+ if (pkey->add_state == libssh2_NB_state_idle) {
-+ pkey->add_packet = NULL;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY, "Adding %s publickey",
-+ name);
-+
-+ if (pkey->version == 1) {
-+ for(i = 0; i < num_attrs; i++) {
-+ /* Search for a comment attribute */
-+ if (attrs[i].name_len == (sizeof("comment") - 1) &&
-+ strncmp(attrs[i].name, "comment",
-+ sizeof("comment") - 1) == 0) {
-+ comment = (unsigned char *) attrs[i].value;
-+ comment_len = attrs[i].value_len;
-+ break;
-+ }
-+ }
-+ packet_len += 4 + comment_len;
-+ } else {
-+ packet_len += 5; /* overwrite(1) + attribute_count(4) */
-+ for(i = 0; i < num_attrs; i++) {
-+ packet_len += 9 + attrs[i].name_len + attrs[i].value_len;
-+ /* name_len(4) + value_len(4) + mandatory(1) */
-+ }
-+ }
-+
-+ pkey->add_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!pkey->add_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for publickey \"add\" packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ pkey->add_s = pkey->add_packet;
-+ libssh2_htonu32(pkey->add_s, packet_len - 4);
-+ pkey->add_s += 4;
-+ libssh2_htonu32(pkey->add_s, sizeof("add") - 1);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, "add", sizeof("add") - 1);
-+ pkey->add_s += sizeof("add") - 1;
-+ if (pkey->version == 1) {
-+ libssh2_htonu32(pkey->add_s, comment_len);
-+ pkey->add_s += 4;
-+ if (comment) {
-+ memcpy(pkey->add_s, comment, comment_len);
-+ pkey->add_s += comment_len;
-+ }
-+
-+ libssh2_htonu32(pkey->add_s, name_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, name, name_len);
-+ pkey->add_s += name_len;
-+ libssh2_htonu32(pkey->add_s, blob_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, blob, blob_len);
-+ pkey->add_s += blob_len;
-+ } else {
-+ /* Version == 2 */
-+
-+ libssh2_htonu32(pkey->add_s, name_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, name, name_len);
-+ pkey->add_s += name_len;
-+ libssh2_htonu32(pkey->add_s, blob_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, blob, blob_len);
-+ pkey->add_s += blob_len;
-+ *(pkey->add_s++) = overwrite ? 0x01 : 0;
-+ libssh2_htonu32(pkey->add_s, num_attrs);
-+ pkey->add_s += 4;
-+ for(i = 0; i < num_attrs; i++) {
-+ libssh2_htonu32(pkey->add_s, attrs[i].name_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, attrs[i].name, attrs[i].name_len);
-+ pkey->add_s += attrs[i].name_len;
-+ libssh2_htonu32(pkey->add_s, attrs[i].value_len);
-+ pkey->add_s += 4;
-+ memcpy(pkey->add_s, attrs[i].value, attrs[i].value_len);
-+ pkey->add_s += attrs[i].value_len;
-+ *(pkey->add_s++) = attrs[i].mandatory ? 0x01 : 0;
-+ }
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Sending publickey \"add\" packet: type=%s blob_len=%ld num_attrs=%ld",
-+ name, blob_len, num_attrs);
-+
-+ pkey->add_state = libssh2_NB_state_created;
-+ }
-+
-+ if (pkey->add_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->add_packet,
-+ (pkey->add_s - pkey->add_packet));
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if ((pkey->add_s - pkey->add_packet) != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send publickey add packet", 0);
-+ LIBSSH2_FREE(session, pkey->add_packet);
-+ pkey->add_packet = NULL;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, pkey->add_packet);
-+ pkey->add_packet = NULL;
-+
-+ pkey->add_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = libssh2_publickey_response_success(pkey);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ pkey->add_state = libssh2_NB_state_idle;
-+
-+ return rc;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_remove_ex
-+ * Remove an existing publickey so that authentication can no longer be performed using it
-+ */
-+LIBSSH2_API int
-+libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey,
-+ const unsigned char *name, unsigned long name_len,
-+ const unsigned char *blob, unsigned long blob_len)
-+{
-+ LIBSSH2_CHANNEL *channel = pkey->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ /* 22 = packet_len(4) + remove_len(4) + "remove"(6) + name_len(4) + {name} + blob_len(4) + {blob} */
-+ unsigned long packet_len = 22 + name_len + blob_len;
-+ int rc;
-+
-+ if (pkey->remove_state == libssh2_NB_state_idle) {
-+ pkey->remove_packet = NULL;
-+
-+ pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len);
-+ if (!pkey->remove_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for publickey \"remove\" packet",
-+ 0);
-+ return -1;
-+ }
-+
-+ pkey->remove_s = pkey->remove_packet;
-+ libssh2_htonu32(pkey->remove_s, packet_len - 4);
-+ pkey->remove_s += 4;
-+ libssh2_htonu32(pkey->remove_s, sizeof("remove") - 1);
-+ pkey->remove_s += 4;
-+ memcpy(pkey->remove_s, "remove", sizeof("remove") - 1);
-+ pkey->remove_s += sizeof("remove") - 1;
-+ libssh2_htonu32(pkey->remove_s, name_len);
-+ pkey->remove_s += 4;
-+ memcpy(pkey->remove_s, name, name_len);
-+ pkey->remove_s += name_len;
-+ libssh2_htonu32(pkey->remove_s, blob_len);
-+ pkey->remove_s += 4;
-+ memcpy(pkey->remove_s, blob, blob_len);
-+ pkey->remove_s += blob_len;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Sending publickey \"remove\" packet: type=%s blob_len=%ld",
-+ name, blob_len);
-+
-+ pkey->remove_state = libssh2_NB_state_created;
-+ }
-+
-+ if (pkey->remove_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0, (char *) pkey->remove_packet,
-+ (pkey->remove_s - pkey->remove_packet));
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if ((pkey->remove_s - pkey->remove_packet) != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send publickey remove packet", 0);
-+ LIBSSH2_FREE(session, pkey->remove_packet);
-+ pkey->remove_packet = NULL;
-+ pkey->remove_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+ LIBSSH2_FREE(session, pkey->remove_packet);
-+ pkey->remove_packet = NULL;
-+
-+ pkey->remove_state = libssh2_NB_state_sent;
-+ }
-+
-+ rc = libssh2_publickey_response_success(pkey);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ pkey->remove_state = libssh2_NB_state_idle;
-+
-+ return rc;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_list_fetch
-+ * Fetch a list of supported public key from a server
-+ */
-+LIBSSH2_API int
-+libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys,
-+ libssh2_publickey_list ** pkey_list)
-+{
-+ LIBSSH2_CHANNEL *channel = pkey->channel;
-+ LIBSSH2_SESSION *session = channel->session;
-+ libssh2_publickey_list *list = NULL;
-+ unsigned long buffer_len = 12, keys = 0, max_keys = 0, i;
-+ /* 12 = packet_len(4) + list_len(4) + "list"(4) */
-+ int response;
-+ int rc;
-+
-+ if (pkey->listFetch_state == libssh2_NB_state_idle) {
-+ pkey->listFetch_data = NULL;
-+
-+ pkey->listFetch_s = pkey->listFetch_buffer;
-+ libssh2_htonu32(pkey->listFetch_s, buffer_len - 4);
-+ pkey->listFetch_s += 4;
-+ libssh2_htonu32(pkey->listFetch_s, sizeof("list") - 1);
-+ pkey->listFetch_s += 4;
-+ memcpy(pkey->listFetch_s, "list", sizeof("list") - 1);
-+ pkey->listFetch_s += sizeof("list") - 1;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_PUBLICKEY,
-+ "Sending publickey \"list\" packet");
-+
-+ pkey->listFetch_state = libssh2_NB_state_created;
-+ }
-+
-+ if (pkey->listFetch_state == libssh2_NB_state_created) {
-+ rc = libssh2_channel_write_ex(channel, 0,
-+ (char *) pkey->listFetch_buffer,
-+ (pkey->listFetch_s -
-+ pkey->listFetch_buffer));
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send publickey list packet", 0);
-+ pkey->listFetch_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ pkey->listFetch_state = libssh2_NB_state_sent;
-+ }
-+
-+ while (1) {
-+ rc = libssh2_publickey_packet_receive(pkey, &pkey->listFetch_data,
-+ &pkey->listFetch_data_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
-+ "Timeout waiting for response from publickey subsystem",
-+ 0);
-+ goto err_exit;
-+ }
-+
-+ pkey->listFetch_s = pkey->listFetch_data;
-+ if ((response =
-+ libssh2_publickey_response_id(&pkey->listFetch_s,
-+ pkey->listFetch_data_len)) < 0) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Invalid publickey subsystem response code", 0);
-+ goto err_exit;
-+ }
-+
-+ switch (response) {
-+ case LIBSSH2_PUBLICKEY_RESPONSE_STATUS:
-+ /* Error, or processing complete */
-+ {
-+ unsigned long status, descr_len, lang_len;
-+ unsigned char *descr, *lang;
-+
-+ status = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ descr_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ descr = pkey->listFetch_s;
-+ pkey->listFetch_s += descr_len;
-+ lang_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ lang = pkey->listFetch_s;
-+ pkey->listFetch_s += lang_len;
-+
-+ if (pkey->listFetch_s >
-+ pkey->listFetch_data + pkey->listFetch_data_len) {
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Malformed publickey subsystem packet", 0);
-+ goto err_exit;
-+ }
-+
-+ if (status == LIBSSH2_PUBLICKEY_SUCCESS) {
-+ LIBSSH2_FREE(session, pkey->listFetch_data);
-+ pkey->listFetch_data = NULL;
-+ *pkey_list = list;
-+ *num_keys = keys;
-+ pkey->listFetch_state = libssh2_NB_state_idle;
-+ return 0;
-+ }
-+
-+ libssh2_publickey_status_error(pkey, session, status, descr,
-+ descr_len);
-+ goto err_exit;
-+ }
-+ case LIBSSH2_PUBLICKEY_RESPONSE_PUBLICKEY:
-+ /* What we want */
-+ if (keys >= max_keys) {
-+ libssh2_publickey_list *newlist;
-+ /* Grow the key list if necessary */
-+ max_keys += 8;
-+ newlist =
-+ LIBSSH2_REALLOC(session, list,
-+ (max_keys +
-+ 1) * sizeof(libssh2_publickey_list));
-+ if (!newlist) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for publickey list",
-+ 0);
-+ goto err_exit;
-+ }
-+ list = newlist;
-+ }
-+ if (pkey->version == 1) {
-+ unsigned long comment_len;
-+
-+ comment_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ if (comment_len) {
-+ list[keys].num_attrs = 1;
-+ list[keys].attrs =
-+ LIBSSH2_ALLOC(session,
-+ sizeof(libssh2_publickey_attribute));
-+ if (!list[keys].attrs) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for publickey attributes",
-+ 0);
-+ goto err_exit;
-+ }
-+ list[keys].attrs[0].name = "comment";
-+ list[keys].attrs[0].name_len = sizeof("comment") - 1;
-+ list[keys].attrs[0].value = (char *) pkey->listFetch_s;
-+ list[keys].attrs[0].value_len = comment_len;
-+ list[keys].attrs[0].mandatory = 0;
-+
-+ pkey->listFetch_s += comment_len;
-+ } else {
-+ list[keys].num_attrs = 0;
-+ list[keys].attrs = NULL;
-+ }
-+ list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].name = pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].name_len;
-+ list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].blob = pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].blob_len;
-+ } else {
-+ /* Version == 2 */
-+ list[keys].name_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].name = pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].name_len;
-+ list[keys].blob_len = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].blob = pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].blob_len;
-+ list[keys].num_attrs = libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ if (list[keys].num_attrs) {
-+ list[keys].attrs =
-+ LIBSSH2_ALLOC(session,
-+ list[keys].num_attrs *
-+ sizeof(libssh2_publickey_attribute));
-+ if (!list[keys].attrs) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for publickey attributes",
-+ 0);
-+ goto err_exit;
-+ }
-+ for(i = 0; i < list[keys].num_attrs; i++) {
-+ list[keys].attrs[i].name_len =
-+ libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].attrs[i].name = (char *) pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].attrs[i].name_len;
-+ list[keys].attrs[i].value_len =
-+ libssh2_ntohu32(pkey->listFetch_s);
-+ pkey->listFetch_s += 4;
-+ list[keys].attrs[i].value = (char *) pkey->listFetch_s;
-+ pkey->listFetch_s += list[keys].attrs[i].value_len;
-+ list[keys].attrs[i].mandatory = 0; /* actually an ignored value */
-+ }
-+ } else {
-+ list[keys].attrs = NULL;
-+ }
-+ }
-+ list[keys].packet = pkey->listFetch_data; /* To be FREEd in libssh2_publickey_list_free() */
-+ keys++;
-+
-+ list[keys].packet = NULL; /* Terminate the list */
-+ pkey->listFetch_data = NULL;
-+ break;
-+ default:
-+ /* Unknown/Unexpected */
-+ libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL,
-+ "Unexpected publickey subsystem response, ignoring",
-+ 0);
-+ LIBSSH2_FREE(session, pkey->listFetch_data);
-+ pkey->listFetch_data = NULL;
-+ }
-+ }
-+
-+ /* Only reached via explicit goto */
-+ err_exit:
-+ if (pkey->listFetch_data) {
-+ LIBSSH2_FREE(session, pkey->listFetch_data);
-+ pkey->listFetch_data = NULL;
-+ }
-+ if (list) {
-+ libssh2_publickey_list_free(pkey, list);
-+ }
-+ pkey->listFetch_state = libssh2_NB_state_idle;
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_list_free
-+ * Free a previously fetched list of public keys
-+ */
-+LIBSSH2_API void
-+libssh2_publickey_list_free(LIBSSH2_PUBLICKEY * pkey,
-+ libssh2_publickey_list * pkey_list)
-+{
-+ LIBSSH2_SESSION *session = pkey->channel->session;
-+ libssh2_publickey_list *p = pkey_list;
-+
-+ while (p->packet) {
-+ if (p->attrs) {
-+ LIBSSH2_FREE(session, p->attrs);
-+ }
-+ LIBSSH2_FREE(session, p->packet);
-+ p++;
-+ }
-+
-+ LIBSSH2_FREE(session, pkey_list);
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_publickey_shutdown
-+ * Shutdown the publickey subsystem
-+ */
-+LIBSSH2_API int
-+libssh2_publickey_shutdown(LIBSSH2_PUBLICKEY * pkey)
-+{
-+ LIBSSH2_SESSION *session = pkey->channel->session;
-+
-+ /*
-+ * Make sure all memory used in the state variables are free
-+ */
-+ if (pkey->receive_packet) {
-+ LIBSSH2_FREE(session, pkey->receive_packet);
-+ pkey->receive_packet = NULL;
-+ }
-+ if (pkey->add_packet) {
-+ LIBSSH2_FREE(session, pkey->add_packet);
-+ pkey->add_packet = NULL;
-+ }
-+ if (pkey->remove_packet) {
-+ LIBSSH2_FREE(session, pkey->remove_packet);
-+ pkey->remove_packet = NULL;
-+ }
-+ if (pkey->listFetch_data) {
-+ LIBSSH2_FREE(session, pkey->listFetch_data);
-+ pkey->listFetch_data = NULL;
-+ }
-+
-+ if (libssh2_channel_free(pkey->channel) == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ LIBSSH2_FREE(session, pkey);
-+ return 0;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/publickey.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.4
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/kex.c
-===================================================================
---- libssh2/src/kex.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/kex.c (.../trunk)
-@@ -0,0 +1,1916 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+
-+/* TODO: Switch this to an inline and handle alloc() failures */
-+/* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */
-+#define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
-+{ \
-+ libssh2_sha1_ctx hash; \
-+ unsigned long len = 0; \
-+ if (!(value)) { \
-+ value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
-+ } \
-+ if (value) \
-+ while (len < (unsigned long)reqlen) { \
-+ libssh2_sha1_init(&hash); \
-+ libssh2_sha1_update(hash, exchange_state->k_value, \
-+ exchange_state->k_value_len); \
-+ libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
-+ SHA_DIGEST_LENGTH); \
-+ if (len > 0) { \
-+ libssh2_sha1_update(hash, value, len); \
-+ } else { \
-+ libssh2_sha1_update(hash, (version), 1); \
-+ libssh2_sha1_update(hash, session->session_id, \
-+ session->session_id_len); \
-+ } \
-+ libssh2_sha1_final(hash, (value) + len); \
-+ len += SHA_DIGEST_LENGTH; \
-+ } \
-+}
-+
-+/* {{{ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
-+ * Diffie Hellman Key Exchange, Group Agnostic
-+ */
-+static int
-+libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *
-+ session,
-+ _libssh2_bn * g,
-+ _libssh2_bn * p,
-+ int group_order,
-+ unsigned char
-+ packet_type_init,
-+ unsigned char
-+ packet_type_reply,
-+ unsigned char
-+ *midhash,
-+ unsigned long
-+ midhash_len,
-+ kmdhgGPsha1kex_state_t
-+ * exchange_state)
-+{
-+ int ret = 0;
-+ int rc;
-+
-+ if (exchange_state->state == libssh2_NB_state_idle) {
-+ /* Setup initial values */
-+ exchange_state->e_packet = NULL;
-+ exchange_state->s_packet = NULL;
-+ exchange_state->k_value = NULL;
-+ exchange_state->ctx = _libssh2_bn_ctx_new();
-+ exchange_state->x = _libssh2_bn_init(); /* Random from client */
-+ exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
-+ exchange_state->f = _libssh2_bn_init(); /* g^(Random from server) mod p */
-+ exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
-+
-+ /* Zero the whole thing out */
-+ memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
-+
-+ /* Generate x and e */
-+ _libssh2_bn_rand(exchange_state->x, group_order, 0, -1);
-+ _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
-+ exchange_state->ctx);
-+
-+ /* Send KEX init */
-+ /* packet_type(1) + String Length(4) + leading 0(1) */
-+ exchange_state->e_packet_len =
-+ _libssh2_bn_bytes(exchange_state->e) + 6;
-+ if (_libssh2_bn_bits(exchange_state->e) % 8) {
-+ /* Leading 00 not needed */
-+ exchange_state->e_packet_len--;
-+ }
-+
-+ exchange_state->e_packet =
-+ LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
-+ if (!exchange_state->e_packet) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error",
-+ 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ exchange_state->e_packet[0] = packet_type_init;
-+ libssh2_htonu32(exchange_state->e_packet + 1,
-+ exchange_state->e_packet_len - 5);
-+ if (_libssh2_bn_bits(exchange_state->e) % 8) {
-+ _libssh2_bn_to_bin(exchange_state->e,
-+ exchange_state->e_packet + 5);
-+ } else {
-+ exchange_state->e_packet[5] = 0;
-+ _libssh2_bn_to_bin(exchange_state->e,
-+ exchange_state->e_packet + 6);
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending KEX packet %d",
-+ (int) packet_type_init);
-+ exchange_state->state = libssh2_NB_state_created;
-+ }
-+
-+ if (exchange_state->state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, exchange_state->e_packet,
-+ exchange_state->e_packet_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send KEX init message", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ exchange_state->state = libssh2_NB_state_sent;
-+ }
-+
-+ if (exchange_state->state == libssh2_NB_state_sent) {
-+ if (session->burn_optimistic_kexinit) {
-+ /* The first KEX packet to come along will be the guess initially
-+ * sent by the server. That guess turned out to be wrong so we
-+ * need to silently ignore it */
-+ int burn_type;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Waiting for badly guessed KEX packet (to be ignored)");
-+ burn_type =
-+ libssh2_packet_burn(session, &exchange_state->burn_state);
-+ if (burn_type == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (burn_type <= 0) {
-+ /* Failed to receive a packet */
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ session->burn_optimistic_kexinit = 0;
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Burnt packet of type: %02x",
-+ (unsigned int) burn_type);
-+ }
-+
-+ exchange_state->state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (exchange_state->state == libssh2_NB_state_sent1) {
-+ /* Wait for KEX reply */
-+ rc = libssh2_packet_require_ex(session, packet_type_reply,
-+ &exchange_state->s_packet,
-+ &exchange_state->s_packet_len, 0, NULL,
-+ 0, &exchange_state->req_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+ if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
-+ "Timed out waiting for KEX reply", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ /* Parse KEXDH_REPLY */
-+ exchange_state->s = exchange_state->s_packet + 1;
-+
-+ session->server_hostkey_len = libssh2_ntohu32(exchange_state->s);
-+ exchange_state->s += 4;
-+ session->server_hostkey =
-+ LIBSSH2_ALLOC(session, session->server_hostkey_len);
-+ if (!session->server_hostkey) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory for a copy of the host key",
-+ 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ memcpy(session->server_hostkey, exchange_state->s,
-+ session->server_hostkey_len);
-+ exchange_state->s += session->server_hostkey_len;
-+
-+#if LIBSSH2_MD5
-+ {
-+ libssh2_md5_ctx fingerprint_ctx;
-+
-+ libssh2_md5_init(&fingerprint_ctx);
-+ libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
-+ session->server_hostkey_len);
-+ libssh2_md5_final(fingerprint_ctx, session->server_hostkey_md5);
-+ }
-+#ifdef LIBSSH2DEBUG
-+ {
-+ char fingerprint[50], *fprint = fingerprint;
-+ int i;
-+ for(i = 0; i < 16; i++, fprint += 3) {
-+ snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
-+ }
-+ *(--fprint) = '\0';
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Server's MD5 Fingerprint: %s", fingerprint);
-+ }
-+#endif /* LIBSSH2DEBUG */
-+#endif /* ! LIBSSH2_MD5 */
-+
-+ {
-+ libssh2_sha1_ctx fingerprint_ctx;
-+
-+ libssh2_sha1_init(&fingerprint_ctx);
-+ libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
-+ session->server_hostkey_len);
-+ libssh2_sha1_final(fingerprint_ctx, session->server_hostkey_sha1);
-+ }
-+#ifdef LIBSSH2DEBUG
-+ {
-+ char fingerprint[64], *fprint = fingerprint;
-+ int i;
-+
-+ for(i = 0; i < 20; i++, fprint += 3) {
-+ snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
-+ }
-+ *(--fprint) = '\0';
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Server's SHA1 Fingerprint: %s", fingerprint);
-+ }
-+#endif /* LIBSSH2DEBUG */
-+
-+ if (session->hostkey->
-+ init(session, session->server_hostkey, session->server_hostkey_len,
-+ &session->server_hostkey_abstract)) {
-+ libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
-+ "Unable to initialize hostkey importer", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ exchange_state->f_value_len = libssh2_ntohu32(exchange_state->s);
-+ exchange_state->s += 4;
-+ exchange_state->f_value = exchange_state->s;
-+ exchange_state->s += exchange_state->f_value_len;
-+ _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
-+ exchange_state->f_value);
-+
-+ exchange_state->h_sig_len = libssh2_ntohu32(exchange_state->s);
-+ exchange_state->s += 4;
-+ exchange_state->h_sig = exchange_state->s;
-+
-+ /* Compute the shared secret */
-+ _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
-+ exchange_state->x, p, exchange_state->ctx);
-+ exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
-+ if (_libssh2_bn_bits(exchange_state->k) % 8) {
-+ /* don't need leading 00 */
-+ exchange_state->k_value_len--;
-+ }
-+ exchange_state->k_value =
-+ LIBSSH2_ALLOC(session, exchange_state->k_value_len);
-+ if (!exchange_state->k_value) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate buffer for K", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ libssh2_htonu32(exchange_state->k_value,
-+ exchange_state->k_value_len - 4);
-+ if (_libssh2_bn_bits(exchange_state->k) % 8) {
-+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
-+ } else {
-+ exchange_state->k_value[4] = 0;
-+ _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
-+ }
-+
-+ libssh2_sha1_init(&exchange_state->exchange_hash);
-+ if (session->local.banner) {
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ strlen((char *) session->local.banner) - 2);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ (char *) session->local.banner,
-+ strlen((char *) session->local.banner) - 2);
-+ } else {
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ LIBSSH2_SSH_DEFAULT_BANNER,
-+ sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
-+ }
-+
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ strlen((char *) session->remote.banner));
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ session->remote.banner,
-+ strlen((char *) session->remote.banner));
-+
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ session->local.kexinit_len);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ session->local.kexinit,
-+ session->local.kexinit_len);
-+
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ session->remote.kexinit_len);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ session->remote.kexinit,
-+ session->remote.kexinit_len);
-+
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ session->server_hostkey_len);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ session->server_hostkey,
-+ session->server_hostkey_len);
-+
-+ if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
-+ /* diffie-hellman-group-exchange hashes additional fields */
-+#ifdef LIBSSH2_DH_GEX_NEW
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ LIBSSH2_DH_GEX_MINGROUP);
-+ libssh2_htonu32(exchange_state->h_sig_comp + 4,
-+ LIBSSH2_DH_GEX_OPTGROUP);
-+ libssh2_htonu32(exchange_state->h_sig_comp + 8,
-+ LIBSSH2_DH_GEX_MAXGROUP);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 12);
-+#else
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ LIBSSH2_DH_GEX_OPTGROUP);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+#endif
-+ }
-+
-+ if (midhash) {
-+ libssh2_sha1_update(exchange_state->exchange_hash, midhash,
-+ midhash_len);
-+ }
-+
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->e_packet + 1,
-+ exchange_state->e_packet_len - 1);
-+
-+ libssh2_htonu32(exchange_state->h_sig_comp,
-+ exchange_state->f_value_len);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp, 4);
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->f_value,
-+ exchange_state->f_value_len);
-+
-+ libssh2_sha1_update(exchange_state->exchange_hash,
-+ exchange_state->k_value,
-+ exchange_state->k_value_len);
-+
-+ libssh2_sha1_final(exchange_state->exchange_hash,
-+ exchange_state->h_sig_comp);
-+
-+ if (session->hostkey->
-+ sig_verify(session, exchange_state->h_sig,
-+ exchange_state->h_sig_len, exchange_state->h_sig_comp,
-+ 20, &session->server_hostkey_abstract)) {
-+ libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
-+ "Unable to verify hostkey signature", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending NEWKEYS message");
-+ exchange_state->c = SSH_MSG_NEWKEYS;
-+
-+ exchange_state->state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (exchange_state->state == libssh2_NB_state_sent2) {
-+ rc = libssh2_packet_write(session, &exchange_state->c, 1);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send NEWKEYS message", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ exchange_state->state = libssh2_NB_state_sent3;
-+ }
-+
-+ if (exchange_state->state == libssh2_NB_state_sent3) {
-+ rc = libssh2_packet_require_ex(session, SSH_MSG_NEWKEYS,
-+ &exchange_state->tmp,
-+ &exchange_state->tmp_len, 0, NULL, 0,
-+ &exchange_state->req_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
-+ "Timed out waiting for NEWKEYS", 0);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ /* The first key exchange has been performed,
-+ switch to active crypt/comp/mac mode */
-+ session->state |= LIBSSH2_STATE_NEWKEYS;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
-+
-+ /* This will actually end up being just packet_type(1)
-+ for this packet type anyway */
-+ LIBSSH2_FREE(session, exchange_state->tmp);
-+
-+ if (!session->session_id) {
-+ session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
-+ if (!session->session_id) {
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ memcpy(session->session_id, exchange_state->h_sig_comp,
-+ SHA_DIGEST_LENGTH);
-+ session->session_id_len = SHA_DIGEST_LENGTH;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "session_id calculated");
-+ }
-+
-+ /* Cleanup any existing cipher */
-+ if (session->local.crypt->dtor) {
-+ session->local.crypt->dtor(session,
-+ &session->local.crypt_abstract);
-+ }
-+
-+ /* Calculate IV/Secret/Key for each direction */
-+ if (session->local.crypt->init) {
-+ unsigned char *iv = NULL, *secret = NULL;
-+ int free_iv = 0, free_secret = 0;
-+
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
-+ session->local.crypt->
-+ iv_len, "A");
-+ if (!iv) {
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
-+ session->local.crypt->
-+ secret_len, "C");
-+ if (!secret) {
-+ LIBSSH2_FREE(session, iv);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ if (session->local.crypt->
-+ init(session, session->local.crypt, iv, &free_iv, secret,
-+ &free_secret, 1, &session->local.crypt_abstract)) {
-+ LIBSSH2_FREE(session, iv);
-+ LIBSSH2_FREE(session, secret);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ if (free_iv) {
-+ memset(iv, 0, session->local.crypt->iv_len);
-+ LIBSSH2_FREE(session, iv);
-+ }
-+
-+ if (free_secret) {
-+ memset(secret, 0, session->local.crypt->secret_len);
-+ LIBSSH2_FREE(session, secret);
-+ }
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Client to Server IV and Key calculated");
-+
-+ if (session->remote.crypt->dtor) {
-+ /* Cleanup any existing cipher */
-+ session->remote.crypt->dtor(session,
-+ &session->remote.crypt_abstract);
-+ }
-+
-+ if (session->remote.crypt->init) {
-+ unsigned char *iv = NULL, *secret = NULL;
-+ int free_iv = 0, free_secret = 0;
-+
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
-+ session->remote.crypt->
-+ iv_len, "B");
-+ if (!iv) {
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
-+ session->remote.crypt->
-+ secret_len, "D");
-+ if (!secret) {
-+ LIBSSH2_FREE(session, iv);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ if (session->remote.crypt->
-+ init(session, session->remote.crypt, iv, &free_iv, secret,
-+ &free_secret, 0, &session->remote.crypt_abstract)) {
-+ LIBSSH2_FREE(session, iv);
-+ LIBSSH2_FREE(session, secret);
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+
-+ if (free_iv) {
-+ memset(iv, 0, session->remote.crypt->iv_len);
-+ LIBSSH2_FREE(session, iv);
-+ }
-+
-+ if (free_secret) {
-+ memset(secret, 0, session->remote.crypt->secret_len);
-+ LIBSSH2_FREE(session, secret);
-+ }
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Server to Client IV and Key calculated");
-+
-+ if (session->local.mac->dtor) {
-+ session->local.mac->dtor(session, &session->local.mac_abstract);
-+ }
-+
-+ if (session->local.mac->init) {
-+ unsigned char *key = NULL;
-+ int free_key = 0;
-+
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
-+ session->local.mac->
-+ key_len, "E");
-+ if (!key) {
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ session->local.mac->init(session, key, &free_key,
-+ &session->local.mac_abstract);
-+
-+ if (free_key) {
-+ memset(key, 0, session->local.mac->key_len);
-+ LIBSSH2_FREE(session, key);
-+ }
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Client to Server HMAC Key calculated");
-+
-+ if (session->remote.mac->dtor) {
-+ session->remote.mac->dtor(session, &session->remote.mac_abstract);
-+ }
-+
-+ if (session->remote.mac->init) {
-+ unsigned char *key = NULL;
-+ int free_key = 0;
-+
-+ LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
-+ session->remote.mac->
-+ key_len, "F");
-+ if (!key) {
-+ ret = -1;
-+ goto clean_exit;
-+ }
-+ session->remote.mac->init(session, key, &free_key,
-+ &session->remote.mac_abstract);
-+
-+ if (free_key) {
-+ memset(key, 0, session->remote.mac->key_len);
-+ LIBSSH2_FREE(session, key);
-+ }
-+ }
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Server to Client HMAC Key calculated");
-+ }
-+
-+ clean_exit:
-+ _libssh2_bn_free(exchange_state->x);
-+ exchange_state->x = NULL;
-+ _libssh2_bn_free(exchange_state->e);
-+ exchange_state->e = NULL;
-+ _libssh2_bn_free(exchange_state->f);
-+ exchange_state->f = NULL;
-+ _libssh2_bn_free(exchange_state->k);
-+ exchange_state->k = NULL;
-+ _libssh2_bn_ctx_free(exchange_state->ctx);
-+ exchange_state->ctx = NULL;
-+
-+ if (exchange_state->e_packet) {
-+ LIBSSH2_FREE(session, exchange_state->e_packet);
-+ exchange_state->e_packet = NULL;
-+ }
-+
-+ if (exchange_state->s_packet) {
-+ LIBSSH2_FREE(session, exchange_state->s_packet);
-+ exchange_state->s_packet = NULL;
-+ }
-+
-+ if (exchange_state->k_value) {
-+ LIBSSH2_FREE(session, exchange_state->k_value);
-+ exchange_state->k_value = NULL;
-+ }
-+
-+ if (session->server_hostkey) {
-+ LIBSSH2_FREE(session, session->server_hostkey);
-+ session->server_hostkey = NULL;
-+ }
-+
-+ exchange_state->state = libssh2_NB_state_idle;
-+
-+ return ret;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange
-+ * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1
-+ */
-+static int
-+libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *
-+ session,
-+ key_exchange_state_low_t
-+ * key_state)
-+{
-+ static const unsigned char p_value[128] = {
-+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
-+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
-+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
-+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
-+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
-+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
-+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
-+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
-+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
-+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
-+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
-+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
-+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
-+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
-+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-+ };
-+
-+ int ret;
-+
-+ if (key_state->state == libssh2_NB_state_idle) {
-+ /* g == 2 */
-+ key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */
-+ key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
-+
-+ /* Initialize P and G */
-+ _libssh2_bn_set_word(key_state->g, 2);
-+ _libssh2_bn_from_bin(key_state->p, 128, p_value);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Initiating Diffie-Hellman Group1 Key Exchange");
-+
-+ key_state->state = libssh2_NB_state_created;
-+ }
-+
-+ ret =
-+ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
-+ key_state->
-+ g,
-+ key_state->
-+ p, 128,
-+ SSH_MSG_KEXDH_INIT,
-+ SSH_MSG_KEXDH_REPLY,
-+ NULL, 0,
-+ &key_state->
-+ exchange_state);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ _libssh2_bn_free(key_state->p);
-+ key_state->p = NULL;
-+ _libssh2_bn_free(key_state->g);
-+ key_state->g = NULL;
-+ key_state->state = libssh2_NB_state_idle;
-+
-+ return ret;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange
-+ * Diffie-Hellman Group14 Key Exchange using SHA1
-+ */
-+static int
-+libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *
-+ session,
-+ key_exchange_state_low_t
-+ * key_state)
-+{
-+ static const unsigned char p_value[256] = {
-+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
-+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
-+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
-+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
-+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
-+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
-+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
-+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
-+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
-+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
-+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
-+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
-+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
-+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
-+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
-+ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
-+ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
-+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
-+ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
-+ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
-+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
-+ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
-+ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
-+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
-+ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
-+ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
-+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
-+ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
-+ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
-+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
-+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-+ };
-+ int ret;
-+
-+ if (key_state->state == libssh2_NB_state_idle) {
-+ key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */
-+ key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
-+
-+ /* g == 2 */
-+ /* Initialize P and G */
-+ _libssh2_bn_set_word(key_state->g, 2);
-+ _libssh2_bn_from_bin(key_state->p, 256, p_value);
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Initiating Diffie-Hellman Group14 Key Exchange");
-+
-+ key_state->state = libssh2_NB_state_created;
-+ }
-+ ret =
-+ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
-+ key_state->
-+ g,
-+ key_state->
-+ p, 256,
-+ SSH_MSG_KEXDH_INIT,
-+ SSH_MSG_KEXDH_REPLY,
-+ NULL, 0,
-+ &key_state->
-+ exchange_state);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ key_state->state = libssh2_NB_state_idle;
-+ _libssh2_bn_free(key_state->p);
-+ key_state->p = NULL;
-+ _libssh2_bn_free(key_state->g);
-+ key_state->g = NULL;
-+
-+ return ret;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange
-+ * Diffie-Hellman Group Exchange Key Exchange using SHA1
-+ * Negotiates random(ish) group for secret derivation
-+ */
-+static int
-+ libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange
-+ (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
-+{
-+ unsigned char *s;
-+ unsigned long p_len, g_len;
-+ int ret = 0;
-+ int rc;
-+
-+ if (key_state->state == libssh2_NB_state_idle) {
-+ key_state->p = _libssh2_bn_init();
-+ key_state->g = _libssh2_bn_init();
-+ /* Ask for a P and G pair */
-+#ifdef LIBSSH2_DH_GEX_NEW
-+ key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
-+ libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
-+ libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
-+ libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
-+ key_state->request_len = 13;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Initiating Diffie-Hellman Group-Exchange (New Method)");
-+#else
-+ key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
-+ libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
-+ key_state->request_len = 5;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX,
-+ "Initiating Diffie-Hellman Group-Exchange (Old Method)");
-+#endif
-+
-+ key_state->state = libssh2_NB_state_created;
-+ }
-+
-+ if (key_state->state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_write(session, key_state->request,
-+ key_state->request_len);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send Group Exchange Request", 0);
-+ ret = -1;
-+ goto dh_gex_clean_exit;
-+ }
-+
-+ key_state->state = libssh2_NB_state_sent;
-+ }
-+
-+ if (key_state->state == libssh2_NB_state_sent) {
-+ rc = libssh2_packet_require_ex(session, SSH_MSG_KEX_DH_GEX_GROUP,
-+ &key_state->data, &key_state->data_len,
-+ 0, NULL, 0, &key_state->req_state);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
-+ "Timeout waiting for GEX_GROUP reply", 0);
-+ ret = -1;
-+ goto dh_gex_clean_exit;
-+ }
-+
-+ key_state->state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (key_state->state == libssh2_NB_state_sent1) {
-+ s = key_state->data + 1;
-+ p_len = libssh2_ntohu32(s);
-+ s += 4;
-+ _libssh2_bn_from_bin(key_state->p, p_len, s);
-+ s += p_len;
-+
-+ g_len = libssh2_ntohu32(s);
-+ s += 4;
-+ _libssh2_bn_from_bin(key_state->g, g_len, s);
-+ s += g_len;
-+
-+ ret =
-+ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
-+ (session, key_state->g, key_state->p, p_len,
-+ SSH_MSG_KEX_DH_GEX_INIT, SSH_MSG_KEX_DH_GEX_REPLY,
-+ key_state->data + 1, key_state->data_len - 1,
-+ &key_state->exchange_state);
-+ if (ret == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ }
-+
-+ LIBSSH2_FREE(session, key_state->data);
-+ }
-+
-+ dh_gex_clean_exit:
-+ key_state->state = libssh2_NB_state_idle;
-+ _libssh2_bn_free(key_state->g);
-+ key_state->g = NULL;
-+ _libssh2_bn_free(key_state->p);
-+ key_state->p = NULL;
-+
-+ return ret;
-+}
-+
-+/* }}} */
-+
-+#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001
-+#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002
-+
-+static const LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group1_sha1 = {
-+ "diffie-hellman-group1-sha1",
-+ libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange,
-+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
-+};
-+
-+static const LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group14_sha1 = {
-+ "diffie-hellman-group14-sha1",
-+ libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange,
-+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
-+};
-+
-+static const LIBSSH2_KEX_METHOD
-+ libssh2_kex_method_diffie_helman_group_exchange_sha1 = {
-+ "diffie-hellman-group-exchange-sha1",
-+ libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
-+ LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
-+};
-+
-+static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
-+ &libssh2_kex_method_diffie_helman_group14_sha1,
-+ &libssh2_kex_method_diffie_helman_group_exchange_sha1,
-+ &libssh2_kex_method_diffie_helman_group1_sha1,
-+ NULL
-+};
-+
-+typedef struct _LIBSSH2_COMMON_METHOD
-+{
-+ const char *name;
-+} LIBSSH2_COMMON_METHOD;
-+
-+/* {{{ libssh2_kex_method_strlen
-+ * Calculate the length of a particular method list's resulting string
-+ * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used)
-+ * Another sign of bad coding practices gone mad. Pretend you don't see this.
-+ */
-+static size_t
-+libssh2_kex_method_strlen(LIBSSH2_COMMON_METHOD ** method)
-+{
-+ size_t len = 0;
-+
-+ if (!method || !*method) {
-+ return 0;
-+ }
-+
-+ while (*method && (*method)->name) {
-+ len += strlen((*method)->name) + 1;
-+ method++;
-+ }
-+
-+ return len - 1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_method_list
-+ * Generate formatted preference list in buf
-+ */
-+static size_t
-+libssh2_kex_method_list(unsigned char *buf, size_t list_strlen,
-+ LIBSSH2_COMMON_METHOD ** method)
-+{
-+ libssh2_htonu32(buf, list_strlen);
-+ buf += 4;
-+
-+ if (!method || !*method) {
-+ return 4;
-+ }
-+
-+ while (*method && (*method)->name) {
-+ int mlen = strlen((*method)->name);
-+ memcpy(buf, (*method)->name, mlen);
-+ buf += mlen;
-+ *(buf++) = ',';
-+ method++;
-+ }
-+
-+ return list_strlen + 4;
-+}
-+
-+/* }}} */
-+
-+#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)); \
-+ }
-+
-+/* {{{ libssh2_kexinit
-+ * Send SSH_MSG_KEXINIT packet
-+ */
-+static int
-+libssh2_kexinit(LIBSSH2_SESSION * session)
-+{
-+ /* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
-+ reserved(4) + length longs(40) */
-+ size_t data_len = 62;
-+ size_t kex_len, hostkey_len = 0;
-+ size_t crypt_cs_len, crypt_sc_len;
-+ size_t comp_cs_len, comp_sc_len;
-+ size_t mac_cs_len, mac_sc_len;
-+ size_t lang_cs_len, lang_sc_len;
-+ unsigned char *data, *s;
-+ int rc;
-+
-+ if (session->kexinit_state == libssh2_NB_state_idle) {
-+ 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);
-+
-+ data_len += kex_len + hostkey_len + crypt_cs_len + crypt_sc_len +
-+ comp_cs_len + comp_sc_len + mac_cs_len + mac_sc_len +
-+ lang_cs_len + lang_sc_len;
-+
-+ s = data = LIBSSH2_ALLOC(session, data_len);
-+ if (!data) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC,
-+ "Unable to allocate memory", 0);
-+ return -1;
-+ }
-+
-+ *(s++) = SSH_MSG_KEXINIT;
-+
-+ libssh2_random(s, 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);
-+
-+ /* No optimistic KEX packet follows */
-+ /* Deal with optimistic packets
-+ * session->flags |= KEXINIT_OPTIMISTIC
-+ * session->flags |= KEXINIT_METHODSMATCH
-+ */
-+ *(s++) = 0;
-+
-+ /* Reserved == 0 */
-+ *(s++) = 0;
-+ *(s++) = 0;
-+ *(s++) = 0;
-+ *(s++) = 0;
-+
-+#ifdef LIBSSH2DEBUG
-+ {
-+ /* Funnily enough, they'll all "appear" to be '\0' terminated */
-+ unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent KEX: %s", p);
-+ p += kex_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent HOSTKEY: %s", p);
-+ p += hostkey_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_CS: %s", p);
-+ p += crypt_cs_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_SC: %s", p);
-+ p += crypt_sc_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_CS: %s", p);
-+ p += mac_cs_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_SC: %s", p);
-+ p += mac_sc_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_CS: %s", p);
-+ p += comp_cs_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_SC: %s", p);
-+ p += comp_sc_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_CS: %s", p);
-+ p += lang_cs_len + 4;
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_SC: %s", p);
-+ p += lang_sc_len + 4;
-+ }
-+#endif /* LIBSSH2DEBUG */
-+
-+ session->kexinit_state = libssh2_NB_state_created;
-+ } else {
-+ data = session->kexinit_data;
-+ data_len = session->kexinit_data_len;
-+ }
-+
-+ if ((rc = libssh2_packet_write(session, data, data_len)) == PACKET_EAGAIN) {
-+ session->kexinit_data = data;
-+ session->kexinit_data_len = data_len;
-+ return PACKET_EAGAIN;
-+ } else if (rc) {
-+ LIBSSH2_FREE(session, data);
-+ libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
-+ "Unable to send KEXINIT packet to remote host", 0);
-+ session->kexinit_state = libssh2_NB_state_idle;
-+ return -1;
-+ }
-+
-+ if (session->local.kexinit) {
-+ LIBSSH2_FREE(session, session->local.kexinit);
-+ }
-+
-+ session->local.kexinit = data;
-+ session->local.kexinit_len = data_len;
-+
-+ session->kexinit_state = libssh2_NB_state_idle;
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_agree_instr
-+ * Kex specific variant of strstr()
-+ * Needle must be preceed by BOL or ',', and followed by ',' or EOL
-+ */
-+static unsigned char *
-+libssh2_kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
-+ const unsigned char *needle, unsigned long needle_len)
-+{
-+ unsigned char *s;
-+
-+ /* Haystack too short to bother trying */
-+ if (haystack_len < needle_len) {
-+ return NULL;
-+ }
-+
-+ /* Needle at start of haystack */
-+ if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
-+ (needle_len == haystack_len || haystack[needle_len] == ',')) {
-+ return haystack;
-+ }
-+
-+ s = haystack;
-+ /* Search until we run out of comas or we run out of haystack,
-+ whichever comes first */
-+ while ((s = (unsigned char *) strchr((char *) s, ','))
-+ && ((haystack_len - (s - haystack)) > needle_len)) {
-+ s++;
-+ /* Needle at X position */
-+ if ((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
-+ (((s - haystack) + needle_len) == haystack_len
-+ || s[needle_len] == ',')) {
-+ return s;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_get_method_by_name
-+ */
-+static const LIBSSH2_COMMON_METHOD *
-+libssh2_get_method_by_name(const char *name, int name_len,
-+ const 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)
-+{
-+ const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
-+ unsigned char *s;
-+
-+ if (session->hostkey_prefs) {
-+ s = (unsigned char *) session->hostkey_prefs;
-+
-+ while (s && *s) {
-+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
-+ int method_len = (p ? (p - s) : strlen((char *) s));
-+ if (libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
-+ const LIBSSH2_HOSTKEY_METHOD *method =
-+ (const LIBSSH2_HOSTKEY_METHOD *)
-+ libssh2_get_method_by_name((char *) s, method_len,
-+ (const LIBSSH2_COMMON_METHOD **)
-+ hostkeyp);
-+
-+ if (!method) {
-+ /* Invalid method -- Should never be reached */
-+ return -1;
-+ }
-+
-+ /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
-+ if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
-+ 0) || (method->encrypt)) {
-+ /* Either this hostkey can do encryption or this kex just doesn't require it */
-+ if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
-+ == 0) || (method->sig_verify)) {
-+ /* Either this hostkey can do signing or this kex just doesn't require it */
-+ session->hostkey = method;
-+ return 0;
-+ }
-+ }
-+ }
-+
-+ s = p ? p + 1 : NULL;
-+ }
-+ return -1;
-+ }
-+
-+ while (hostkeyp && (*hostkeyp)->name) {
-+ s = libssh2_kex_agree_instr(hostkey, hostkey_len,
-+ (unsigned char *) (*hostkeyp)->name,
-+ strlen((*hostkeyp)->name));
-+ if (s) {
-+ /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
-+ if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
-+ ((*hostkeyp)->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) || ((*hostkeyp)->sig_verify)) {
-+ /* Either this hostkey can do signing or this kex just doesn't require it */
-+ session->hostkey = *hostkeyp;
-+ return 0;
-+ }
-+ }
-+ }
-+ hostkeyp++;
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_agree_kex_hostkey
-+ * Agree on a Key Exchange method and a hostkey encoding type
-+ */
-+static int
-+libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
-+ unsigned long kex_len, unsigned char *hostkey,
-+ unsigned long hostkey_len)
-+{
-+ const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
-+ unsigned char *s;
-+
-+ if (session->kex_prefs) {
-+ s = (unsigned char *) session->kex_prefs;
-+
-+ while (s && *s) {
-+ unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
-+ int method_len = (p ? (p - s) : strlen((char *) s));
-+ if ((q = libssh2_kex_agree_instr(kex, kex_len, s, method_len))) {
-+ const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
-+ libssh2_get_method_by_name((char *) s, method_len,
-+ (const 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;
-+ if (session->burn_optimistic_kexinit && (kex == q)) {
-+ /* Server sent an optimistic packet,
-+ * and client agrees with preference
-+ * cancel burning the first KEX_INIT packet that comes in */
-+ session->burn_optimistic_kexinit = 0;
-+ }
-+ return 0;
-+ }
-+ }
-+
-+ s = p ? p + 1 : NULL;
-+ }
-+ return -1;
-+ }
-+
-+ while (*kexp && (*kexp)->name) {
-+ s = libssh2_kex_agree_instr(kex, kex_len,
-+ (unsigned char *) (*kexp)->name,
-+ strlen((*kexp)->name));
-+ if (s) {
-+ /* 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, (*kexp)->flags, hostkey, hostkey_len) == 0) {
-+ session->kex = *kexp;
-+ if (session->burn_optimistic_kexinit && (kex == s)) {
-+ /* Server sent an optimistic packet,
-+ * and client agrees with preference
-+ * cancel burning the first KEX_INIT packet that comes in */
-+ session->burn_optimistic_kexinit = 0;
-+ }
-+ return 0;
-+ }
-+ }
-+ kexp++;
-+ }
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_agree_crypt
-+ * Agree on a cipher algo
-+ */
-+static int
-+libssh2_kex_agree_crypt(LIBSSH2_SESSION * session,
-+ libssh2_endpoint_data * endpoint, unsigned char *crypt,
-+ unsigned long crypt_len)
-+{
-+ const LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
-+ unsigned char *s;
-+
-+ (void) session;
-+
-+ if (endpoint->crypt_prefs) {
-+ s = (unsigned char *) endpoint->crypt_prefs;
-+
-+ while (s && *s) {
-+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
-+ int method_len = (p ? (p - s) : strlen((char *) s));
-+
-+ if (libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
-+ const LIBSSH2_CRYPT_METHOD *method =
-+ (const LIBSSH2_CRYPT_METHOD *)
-+ libssh2_get_method_by_name((char *) s, method_len,
-+ (const LIBSSH2_COMMON_METHOD **)
-+ cryptp);
-+
-+ if (!method) {
-+ /* Invalid method -- Should never be reached */
-+ return -1;
-+ }
-+
-+ endpoint->crypt = method;
-+ return 0;
-+ }
-+
-+ s = p ? p + 1 : NULL;
-+ }
-+ return -1;
-+ }
-+
-+ while (*cryptp && (*cryptp)->name) {
-+ s = libssh2_kex_agree_instr(crypt, crypt_len,
-+ (unsigned char *) (*cryptp)->name,
-+ strlen((*cryptp)->name));
-+ if (s) {
-+ endpoint->crypt = *cryptp;
-+ return 0;
-+ }
-+ cryptp++;
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_agree_mac
-+ * Agree on a message authentication hash
-+ */
-+static int
-+libssh2_kex_agree_mac(LIBSSH2_SESSION * session,
-+ libssh2_endpoint_data * endpoint, unsigned char *mac,
-+ unsigned long mac_len)
-+{
-+ const LIBSSH2_MAC_METHOD **macp = libssh2_mac_methods();
-+ unsigned char *s;
-+ (void) session;
-+
-+ if (endpoint->mac_prefs) {
-+ s = (unsigned char *) endpoint->mac_prefs;
-+
-+ while (s && *s) {
-+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
-+ int method_len = (p ? (p - s) : strlen((char *) s));
-+
-+ if (libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
-+ const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
-+ libssh2_get_method_by_name((char *) s, method_len,
-+ (const LIBSSH2_COMMON_METHOD **)
-+ macp);
-+
-+ if (!method) {
-+ /* Invalid method -- Should never be reached */
-+ return -1;
-+ }
-+
-+ endpoint->mac = method;
-+ return 0;
-+ }
-+
-+ s = p ? p + 1 : NULL;
-+ }
-+ return -1;
-+ }
-+
-+ while (*macp && (*macp)->name) {
-+ s = libssh2_kex_agree_instr(mac, mac_len,
-+ (unsigned char *) (*macp)->name,
-+ strlen((*macp)->name));
-+ if (s) {
-+ endpoint->mac = *macp;
-+ return 0;
-+ }
-+ macp++;
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_agree_comp
-+ * Agree on a compression scheme
-+ */
-+static int
-+libssh2_kex_agree_comp(LIBSSH2_SESSION * session,
-+ libssh2_endpoint_data * endpoint, unsigned char *comp,
-+ unsigned long comp_len)
-+{
-+ const LIBSSH2_COMP_METHOD **compp = libssh2_comp_methods();
-+ unsigned char *s;
-+ (void) session;
-+
-+ if (endpoint->comp_prefs) {
-+ s = (unsigned char *) endpoint->comp_prefs;
-+
-+ while (s && *s) {
-+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
-+ int method_len = (p ? (p - s) : strlen((char *) s));
-+
-+ if (libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
-+ const LIBSSH2_COMP_METHOD *method =
-+ (const LIBSSH2_COMP_METHOD *)
-+ libssh2_get_method_by_name((char *) s, method_len,
-+ (const LIBSSH2_COMMON_METHOD **)
-+ compp);
-+
-+ if (!method) {
-+ /* Invalid method -- Should never be reached */
-+ return -1;
-+ }
-+
-+ endpoint->comp = method;
-+ return 0;
-+ }
-+
-+ s = p ? p + 1 : NULL;
-+ }
-+ return -1;
-+ }
-+
-+ while (*compp && (*compp)->name) {
-+ s = libssh2_kex_agree_instr(comp, comp_len,
-+ (unsigned char *) (*compp)->name,
-+ strlen((*compp)->name));
-+ if (s) {
-+ endpoint->comp = *compp;
-+ return 0;
-+ }
-+ compp++;
-+ }
-+
-+ return -1;
-+}
-+
-+/* }}} */
-+
-+/* TODO: When in server mode we need to turn this logic on its head
-+ * The Client gets to make the final call on "agreed methods"
-+ */
-+
-+/* {{{ libssh2_kex_agree_methods
-+ * Decide which specific method to use of the methods offered by each party
-+ */
-+static int
-+libssh2_kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned data_len)
-+{
-+ unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc,
-+ *mac_cs, *mac_sc, *lang_cs, *lang_sc;
-+ size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
-+ size_t comp_sc_len, mac_cs_len, mac_sc_len, lang_cs_len, lang_sc_len;
-+ unsigned char *s = data;
-+
-+ /* Skip packet_type, we know it already */
-+ s++;
-+
-+ /* Skip cookie, don't worry, it's preserved in the kexinit field */
-+ s += 16;
-+
-+ /* Locate each string */
-+ kex_len = libssh2_ntohu32(s);
-+ kex = s + 4;
-+ s += 4 + kex_len;
-+ hostkey_len = libssh2_ntohu32(s);
-+ hostkey = s + 4;
-+ s += 4 + hostkey_len;
-+ crypt_cs_len = libssh2_ntohu32(s);
-+ crypt_cs = s + 4;
-+ s += 4 + crypt_cs_len;
-+ crypt_sc_len = libssh2_ntohu32(s);
-+ crypt_sc = s + 4;
-+ s += 4 + crypt_sc_len;
-+ mac_cs_len = libssh2_ntohu32(s);
-+ mac_cs = s + 4;
-+ s += 4 + mac_cs_len;
-+ mac_sc_len = libssh2_ntohu32(s);
-+ mac_sc = s + 4;
-+ s += 4 + mac_sc_len;
-+ comp_cs_len = libssh2_ntohu32(s);
-+ comp_cs = s + 4;
-+ s += 4 + comp_cs_len;
-+ comp_sc_len = libssh2_ntohu32(s);
-+ comp_sc = s + 4;
-+ s += 4 + comp_sc_len;
-+ lang_cs_len = libssh2_ntohu32(s);
-+ lang_cs = s + 4;
-+ s += 4 + lang_cs_len;
-+ lang_sc_len = libssh2_ntohu32(s);
-+ lang_sc = s + 4;
-+ s += 4 + lang_sc_len;
-+
-+ /* If the server sent an optimistic packet, assume that it guessed wrong.
-+ * If the guess is determined to be right (by libssh2_kex_agree_kex_hostkey)
-+ * This flag will be reset to zero so that it's not ignored */
-+ session->burn_optimistic_kexinit = *(s++);
-+ /* Next uint32 in packet is all zeros (reserved) */
-+
-+ if (data_len < (unsigned) (s - data))
-+ return -1; /* short packet */
-+
-+ if (libssh2_kex_agree_kex_hostkey
-+ (session, kex, kex_len, hostkey, hostkey_len)) {
-+ return -1;
-+ }
-+
-+ if (libssh2_kex_agree_crypt
-+ (session, &session->local, crypt_cs, crypt_cs_len)
-+ || libssh2_kex_agree_crypt(session, &session->remote, crypt_sc,
-+ crypt_sc_len)) {
-+ return -1;
-+ }
-+
-+ if (libssh2_kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
-+ libssh2_kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
-+ return -1;
-+ }
-+
-+ if (libssh2_kex_agree_comp(session, &session->local, comp_cs, comp_cs_len)
-+ || libssh2_kex_agree_comp(session, &session->remote, comp_sc,
-+ comp_sc_len)) {
-+ return -1;
-+ }
-+
-+ if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
-+ || libssh2_kex_agree_lang(session, &session->remote, lang_sc,
-+ lang_sc_len)) {
-+ return -1;
-+ }
-+
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on KEX method: %s",
-+ session->kex->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on HOSTKEY method: %s",
-+ session->hostkey->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_CS method: %s",
-+ session->local.crypt->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_SC method: %s",
-+ session->remote.crypt->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_CS method: %s",
-+ session->local.mac->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_SC method: %s",
-+ session->remote.mac->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_CS method: %s",
-+ session->local.comp->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_SC method: %s",
-+ session->remote.comp->name);
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_CS method:"); /* None yet */
-+ _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_SC method:"); /* None yet */
-+
-+ /* Initialize compression layer */
-+ if (session->local.comp && session->local.comp->init &&
-+ session->local.comp->init(session, 1, &session->local.comp_abstract)) {
-+ return -1;
-+ }
-+
-+ if (session->remote.comp && session->remote.comp->init &&
-+ session->remote.comp->init(session, 0,
-+ &session->remote.comp_abstract)) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_kex_exchange
-+ * Exchange keys
-+ * Returns 0 on success, non-zero on failure
-+ */
-+int
-+libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
-+ key_exchange_state_t * key_state)
-+{
-+ int rc = 0;
-+ int retcode;
-+
-+ session->state |= LIBSSH2_STATE_KEX_ACTIVE;
-+
-+ if (key_state->state == libssh2_NB_state_idle) {
-+ /* Prevent loop in packet_add() */
-+ session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
-+
-+ if (reexchange) {
-+ session->kex = NULL;
-+
-+ if (session->hostkey && session->hostkey->dtor) {
-+ session->hostkey->dtor(session,
-+ &session->server_hostkey_abstract);
-+ }
-+ session->hostkey = NULL;
-+ }
-+
-+ key_state->state = libssh2_NB_state_created;
-+ }
-+
-+ if (!session->kex || !session->hostkey) {
-+ if (key_state->state == libssh2_NB_state_created) {
-+ /* Preserve in case of failure */
-+ key_state->oldlocal = session->local.kexinit;
-+ key_state->oldlocal_len = session->local.kexinit_len;
-+
-+ session->local.kexinit = NULL;
-+
-+ key_state->state = libssh2_NB_state_sent;
-+ }
-+
-+ if (key_state->state == libssh2_NB_state_sent) {
-+ retcode = libssh2_kexinit(session);
-+ if (retcode == PACKET_EAGAIN) {
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ session->local.kexinit = key_state->oldlocal;
-+ session->local.kexinit_len = key_state->oldlocal_len;
-+ key_state->state = libssh2_NB_state_idle;
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
-+ return -1;
-+ }
-+
-+ key_state->state = libssh2_NB_state_sent1;
-+ }
-+
-+ if (key_state->state == libssh2_NB_state_sent1) {
-+ retcode =
-+ libssh2_packet_require_ex(session, SSH_MSG_KEXINIT,
-+ &key_state->data,
-+ &key_state->data_len, 0, NULL, 0,
-+ &key_state->req_state);
-+ if (retcode == PACKET_EAGAIN) {
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ if (session->local.kexinit) {
-+ LIBSSH2_FREE(session, session->local.kexinit);
-+ }
-+ session->local.kexinit = key_state->oldlocal;
-+ session->local.kexinit_len = key_state->oldlocal_len;
-+ key_state->state = libssh2_NB_state_idle;
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
-+ return -1;
-+ }
-+
-+ if (session->remote.kexinit) {
-+ LIBSSH2_FREE(session, session->remote.kexinit);
-+ }
-+ session->remote.kexinit = key_state->data;
-+ session->remote.kexinit_len = key_state->data_len;
-+
-+ if (libssh2_kex_agree_methods
-+ (session, key_state->data, key_state->data_len)) {
-+ rc = -1;
-+ }
-+
-+ key_state->state = libssh2_NB_state_sent2;
-+ }
-+ } else {
-+ key_state->state = libssh2_NB_state_sent2;
-+ }
-+
-+ if (rc == 0) {
-+ if (key_state->state == libssh2_NB_state_sent2) {
-+ retcode =
-+ session->kex->exchange_keys(session,
-+ &key_state->key_state_low);
-+ if (retcode == PACKET_EAGAIN) {
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ return PACKET_EAGAIN;
-+ } else if (retcode) {
-+ libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
-+ "Unrecoverable error exchanging keys", 0);
-+ rc = -1;
-+ }
-+ }
-+ }
-+
-+ /* Done with kexinit buffers */
-+ if (session->local.kexinit) {
-+ LIBSSH2_FREE(session, session->local.kexinit);
-+ session->local.kexinit = NULL;
-+ }
-+ if (session->remote.kexinit) {
-+ LIBSSH2_FREE(session, session->remote.kexinit);
-+ session->remote.kexinit = NULL;
-+ }
-+
-+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
-+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
-+
-+ key_state->state = libssh2_NB_state_idle;
-+
-+ return rc;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_session_method_pref
-+ * Set preferred method
-+ */
-+LIBSSH2_API int
-+libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
-+ const char *prefs)
-+{
-+ char **prefvar, *s, *newprefs;
-+ int prefs_len = strlen(prefs);
-+ const LIBSSH2_COMMON_METHOD **mlist;
-+
-+ switch (method_type) {
-+ case LIBSSH2_METHOD_KEX:
-+ prefvar = &session->kex_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
-+ break;
-+
-+ case LIBSSH2_METHOD_HOSTKEY:
-+ prefvar = &session->hostkey_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_CRYPT_CS:
-+ prefvar = &session->local.crypt_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_CRYPT_SC:
-+ prefvar = &session->remote.crypt_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_MAC_CS:
-+ prefvar = &session->local.mac_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_mac_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_MAC_SC:
-+ prefvar = &session->remote.mac_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_mac_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_COMP_CS:
-+ prefvar = &session->local.comp_prefs;
-+ mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_comp_methods();
-+ break;
-+
-+ case LIBSSH2_METHOD_COMP_SC:
-+ prefvar = &session->remote.comp_prefs;
-+ mlist = (const 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) : (int) 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;
-+}
-+
-+/* }}} */
-
-Property changes on: libssh2/src/kex.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.3
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/openssl.h
-===================================================================
---- libssh2/src/openssl.h (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/openssl.h (.../trunk)
-@@ -0,0 +1,224 @@
-+/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
-+ * Author: Simon Josefsson
-+ *
-+ * 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.
-+ */
-+
-+#include <openssl/opensslconf.h>
-+#include <openssl/sha.h>
-+#ifndef OPENSSL_NO_MD5
-+#include <openssl/md5.h>
-+#endif
-+#include <openssl/evp.h>
-+#include <openssl/hmac.h>
-+#include <openssl/bn.h>
-+#include <openssl/pem.h>
-+#include <openssl/rand.h>
-+
-+#ifdef OPENSSL_NO_RSA
-+# define LIBSSH2_RSA 0
-+#else
-+# define LIBSSH2_RSA 1
-+#endif
-+
-+#ifdef OPENSSL_NO_DSA
-+# define LIBSSH2_DSA 0
-+#else
-+# define LIBSSH2_DSA 1
-+#endif
-+
-+#ifdef OPENSSL_NO_MD5
-+# define LIBSSH2_MD5 0
-+#else
-+# define LIBSSH2_MD5 1
-+#endif
-+
-+#ifdef OPENSSL_NO_RIPEMD
-+# define LIBSSH2_HMAC_RIPEMD 0
-+#else
-+# define LIBSSH2_HMAC_RIPEMD 1
-+#endif
-+
-+#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
-+# define LIBSSH2_AES 1
-+#else
-+# define LIBSSH2_AES 0
-+#endif
-+
-+#ifdef OPENSSL_NO_BLOWFISH
-+# define LIBSSH2_BLOWFISH 0
-+#else
-+# define LIBSSH2_BLOWFISH 1
-+#endif
-+
-+#ifdef OPENSSL_NO_RC4
-+# define LIBSSH2_RC4 0
-+#else
-+# define LIBSSH2_RC4 1
-+#endif
-+
-+#ifdef OPENSSL_NO_CAST
-+# define LIBSSH2_CAST 0
-+#else
-+# define LIBSSH2_CAST 1
-+#endif
-+
-+#ifdef OPENSSL_NO_DES
-+# define LIBSSH2_3DES 0
-+#else
-+# define LIBSSH2_3DES 1
-+#endif
-+
-+#define libssh2_random(buf, len) \
-+ RAND_bytes ((buf), (len))
-+
-+#define libssh2_sha1_ctx SHA_CTX
-+#define libssh2_sha1_init(ctx) SHA1_Init(ctx)
-+#define libssh2_sha1_update(ctx, data, len) SHA1_Update(&(ctx), data, len)
-+#define libssh2_sha1_final(ctx, out) SHA1_Final(out, &(ctx))
-+#define libssh2_sha1(message, len, out) SHA1(message, len, out)
-+
-+#define libssh2_md5_ctx MD5_CTX
-+#define libssh2_md5_init(ctx) MD5_Init(ctx)
-+#define libssh2_md5_update(ctx, data, len) MD5_Update(&(ctx), data, len)
-+#define libssh2_md5_final(ctx, out) MD5_Final(out, &(ctx))
-+#define libssh2_md5(message, len, out) MD5(message, len, out)
-+
-+#define libssh2_hmac_ctx HMAC_CTX
-+#define libssh2_hmac_sha1_init(ctx, key, keylen) \
-+ HMAC_Init(ctx, key, keylen, EVP_sha1())
-+#define libssh2_hmac_md5_init(ctx, key, keylen) \
-+ HMAC_Init(ctx, key, keylen, EVP_md5())
-+#define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
-+ HMAC_Init(ctx, key, keylen, EVP_ripemd160())
-+#define libssh2_hmac_update(ctx, data, datalen) \
-+ HMAC_Update(&(ctx), data, datalen)
-+#define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL)
-+#define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx)
-+
-+#define libssh2_crypto_init()
-+
-+#define libssh2_rsa_ctx RSA
-+
-+int _libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
-+ const unsigned char *edata,
-+ unsigned long elen,
-+ const unsigned char *ndata,
-+ unsigned long nlen,
-+ const unsigned char *ddata,
-+ unsigned long dlen,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *e1data,
-+ unsigned long e1len,
-+ const unsigned char *e2data,
-+ unsigned long e2len,
-+ const unsigned char *coeffdata, unsigned long coefflen);
-+int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase);
-+int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
-+ const unsigned char *sig,
-+ unsigned long sig_len,
-+ const unsigned char *m, unsigned long m_len);
-+int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
-+ libssh2_rsa_ctx * rsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len,
-+ unsigned char **signature,
-+ unsigned long *signature_len);
-+
-+#define _libssh2_rsa_free(rsactx) RSA_free(rsactx)
-+
-+#define libssh2_dsa_ctx DSA
-+
-+int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
-+ const unsigned char *pdata,
-+ unsigned long plen,
-+ const unsigned char *qdata,
-+ unsigned long qlen,
-+ const unsigned char *gdata,
-+ unsigned long glen,
-+ const unsigned char *ydata,
-+ unsigned long ylen,
-+ const unsigned char *x, unsigned long x_len);
-+int _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
-+ LIBSSH2_SESSION * session,
-+ FILE * fp, unsigned const char *passphrase);
-+int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *sig,
-+ const unsigned char *m, unsigned long m_len);
-+int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
-+ const unsigned char *hash,
-+ unsigned long hash_len, unsigned char *sig);
-+
-+#define _libssh2_dsa_free(dsactx) DSA_free(dsactx)
-+
-+#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
-+#define _libssh2_cipher_ctx EVP_CIPHER_CTX
-+
-+#define _libssh2_cipher_aes256 EVP_aes_256_cbc
-+#define _libssh2_cipher_aes192 EVP_aes_192_cbc
-+#define _libssh2_cipher_aes128 EVP_aes_128_cbc
-+#define _libssh2_cipher_blowfish EVP_bf_cbc
-+#define _libssh2_cipher_arcfour EVP_rc4
-+#define _libssh2_cipher_cast5 EVP_cast5_cbc
-+#define _libssh2_cipher_3des EVP_des_ede3_cbc
-+
-+int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
-+ _libssh2_cipher_type(algo),
-+ unsigned char *iv,
-+ unsigned char *secret, int encrypt);
-+
-+int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
-+ _libssh2_cipher_type(algo),
-+ int encrypt, unsigned char *block);
-+
-+#define _libssh2_cipher_dtor(ctx) EVP_CIPHER_CTX_cleanup(ctx)
-+
-+#define _libssh2_bn BIGNUM
-+#define _libssh2_bn_ctx BN_CTX
-+#define _libssh2_bn_ctx_new() BN_CTX_new()
-+#define _libssh2_bn_ctx_free(bnctx) BN_CTX_free(bnctx)
-+#define _libssh2_bn_init() BN_new()
-+#define _libssh2_bn_rand(bn, bits, top, bottom) BN_rand(bn, bits, top, bottom)
-+#define _libssh2_bn_mod_exp(r, a, p, m, ctx) BN_mod_exp(r, a, p, m, ctx)
-+#define _libssh2_bn_set_word(bn, val) BN_set_word(bn, val)
-+#define _libssh2_bn_from_bin(bn, len, val) BN_bin2bn(val, len, bn)
-+#define _libssh2_bn_to_bin(bn, val) BN_bn2bin(bn, val)
-+#define _libssh2_bn_bytes(bn) BN_num_bytes(bn)
-+#define _libssh2_bn_bits(bn) BN_num_bits(bn)
-+#define _libssh2_bn_free(bn) BN_clear_free(bn)
-
-Property changes on: libssh2/src/openssl.h
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-Index: libssh2/src/misc.c
-===================================================================
---- libssh2/src/misc.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/misc.c (.../trunk)
-@@ -0,0 +1,240 @@
-+/* Copyright (c) 2004-2007, 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.
-+ */
-+
-+#include "libssh2_priv.h"
-+#ifdef HAVE_UNISTD_H
-+#include <unistd.h>
-+#endif
-+
-+/* {{{ libssh2_ntohu32
-+ */
-+unsigned long
-+libssh2_ntohu32(const unsigned char *buf)
-+{
-+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_ntohu64
-+ *
-+ */
-+libssh2_uint64_t
-+libssh2_ntohu64(const unsigned char *buf)
-+{
-+ unsigned long msl, lsl;
-+
-+ msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-+ lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
-+
-+ return ((libssh2_uint64_t)msl <<32) | lsl;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_htonu32
-+ */
-+void
-+libssh2_htonu32(unsigned char *buf, unsigned long value)
-+{
-+ buf[0] = (value >> 24) & 0xFF;
-+ buf[1] = (value >> 16) & 0xFF;
-+ buf[2] = (value >> 8) & 0xFF;
-+ buf[3] = value & 0xFF;
-+}
-+
-+/* }}} */
-+
-+/* {{{ libssh2_htonu64
-+ */
-+void
-+libssh2_htonu64(unsigned char *buf, libssh2_uint64_t value)
-+{
-+ unsigned long msl = ((libssh2_uint64_t)value >> 32);
-+
-+ 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 */
-+
-+/* {{{ */
-+static const char libssh2_base64_table[] =
-+ { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
-+};
-+
-+static const char libssh2_base64_pad = '=';
-+
-+static const short libssh2_base64_reverse_table[256] = {
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
-+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-+};
-+
-+/* }}} */
-+
-+
-+/* {{{ libssh2_base64_decode
-+ * Decode a base64 chunk and store it into a newly alloc'd buffer
-+ */
-+LIBSSH2_API int
-+libssh2_base64_decode(LIBSSH2_SESSION * session, char **data,
-+ unsigned int *datalen, const char *src,
-+ unsigned int src_len)
-+{
-+ unsigned char *s, *d;
-+ short v;
-+ int i = 0, len = 0;
-+
-+ *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
-+ d = (unsigned char *) *data;
-+ if (!d) {
-+ return -1;
-+ }
-+
-+ for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
-+ if ((v = libssh2_base64_reverse_table[*s]) < 0)
-+ continue;
-+ switch (i % 4) {
-+ case 0:
-+ d[len] = v << 2;
-+ break;
-+ case 1:
-+ d[len++] |= v >> 4;
-+ d[len] = v << 4;
-+ break;
-+ case 2:
-+ d[len++] |= v >> 2;
-+ d[len] = v << 6;
-+ break;
-+ case 3:
-+ d[len++] |= v;
-+ break;
-+ }
-+ i++;
-+ }
-+ if ((i % 4) == 1) {
-+ /* Invalid -- We have a byte which belongs exclusively to a partial octet */
-+ LIBSSH2_FREE(session, *data);
-+ return -1;
-+ }
-+
-+ *datalen = len;
-+ return 0;
-+}
-+
-+/* }}} */
-+
-+#ifdef LIBSSH2DEBUG
-+LIBSSH2_API int
-+libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
-+{
-+ session->showmask = bitmask;
-+ return 0;
-+}
-+
-+void
-+_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
-+{
-+ char buffer[1536];
-+ int len;
-+ va_list vargs;
-+ static const char *const contexts[9] = {
-+ "Unknown",
-+ "Transport",
-+ "Key Exchange",
-+ "Userauth",
-+ "Connection",
-+ "scp",
-+ "SFTP Subsystem",
-+ "Failure Event",
-+ "Publickey Subsystem",
-+ };
-+
-+ if (context < 1 || context > 8) {
-+ context = 0;
-+ }
-+ if (!(session->showmask & (1 << context))) {
-+ /* no such output asked for */
-+ return;
-+ }
-+
-+ len = snprintf(buffer, 1535, "[libssh2] %s: ", contexts[context]);
-+
-+ va_start(vargs, format);
-+ len += vsnprintf(buffer + len, 1535 - len, format, vargs);
-+ buffer[len] = '\n';
-+ va_end(vargs);
-+ write(2, buffer, len + 1);
-+
-+}
-+
-+#else
-+LIBSSH2_API int
-+libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
-+{
-+ (void) session;
-+ (void) bitmask;
-+ return 0;
-+}
-+#endif
-
-Property changes on: libssh2/src/misc.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.3
-Added: svn:eol-style
- + native
-
-Index: libssh2/src/transport.c
-===================================================================
---- libssh2/src/transport.c (.../tags/RELEASE_0_11_0)
-+++ libssh2/src/transport.c (.../trunk)
-@@ -0,0 +1,815 @@
-+/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
-+ * Author: Daniel Stenberg <daniel@haxx.se>
-+ *
-+ * 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.
-+ *
-+ * This file handles reading and writing to the SECSH transport layer. RFC4253.
-+ */
-+
-+#include "libssh2_priv.h"
-+#include <errno.h>
-+#include <fcntl.h>
-+
-+#include <assert.h>
-+
-+#define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
-+#define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
-+
-+#ifdef LIBSSH2DEBUG
-+#define UNPRINTABLE_CHAR '.'
-+static void
-+debugdump(LIBSSH2_SESSION * session,
-+ const char *desc, unsigned char *ptr, unsigned long size)
-+{
-+ size_t i;
-+ size_t c;
-+ FILE *stream = stdout;
-+ unsigned int width = 0x10;
-+
-+ if (!(session->showmask & (1 << LIBSSH2_DBG_TRANS))) {
-+ /* not asked for, bail out */
-+ return;
-+ }
-+
-+ fprintf(stream, "=> %s (%d bytes)\n", desc, (int) size);
-+
-+ for(i = 0; i < size; i += width) {
-+
-+ fprintf(stream, "%04lx: ", (long)i);
-+
-+ /* hex not disabled, show it */
-+ for(c = 0; c < width; c++) {
-+ if (i + c < size)
-+ fprintf(stream, "%02x ", ptr[i + c]);
-+ else
-+ fputs(" ", stream);
-+ }
-+
-+ for(c = 0; (c < width) && (i + c < size); c++) {
-+ fprintf(stream, "%c",
-+ (ptr[i + c] >= 0x20) &&
-+ (ptr[i + c] < 0x80) ? ptr[i + c] : UNPRINTABLE_CHAR);
-+ }
-+ fputc('\n', stream); /* newline */
-+ }
-+ fflush(stream);
-+}
-+#else
-+#define debugdump(a,x,y,z)
-+#endif
-+
-+
-+/* decrypt() decrypts 'len' bytes from 'source' to 'dest'.
-+ *
-+ * returns PACKET_NONE on success and PACKET_FAIL on failure
-+ */
-+
-+static libssh2pack_t
-+decrypt(LIBSSH2_SESSION * session, unsigned char *source,
-+ unsigned char *dest, int len)
-+{
-+ struct transportpacket *p = &session->packet;
-+ int blocksize = session->remote.crypt->blocksize;
-+
-+ /* if we get called with a len that isn't an even number of blocksizes
-+ we risk losing those extra bytes */
-+ assert((len % blocksize) == 0);
-+
-+ while (len >= blocksize) {
-+ if (session->remote.crypt->crypt(session, source,
-+ &session->remote.crypt_abstract)) {
-+ libssh2_error(session, LIBSSH2_ERROR_DECRYPT,
-+ (char *) "Error decrypting packet", 0);
-+ LIBSSH2_FREE(session, p->payload);
-+ return PACKET_FAIL;
-+ }
-+
-+ /* if the crypt() function would write to a given address it
-+ wouldn't have to memcpy() and we could avoid this memcpy()
-+ too */
-+ memcpy(dest, source, blocksize);
-+
-+ len -= blocksize; /* less bytes left */
-+ dest += blocksize; /* advance write pointer */
-+ source += blocksize; /* advance read pointer */
-+ }
-+ return PACKET_NONE; /* all is fine */
-+}
-+
-+/*
-+ * fullpacket() gets called when a full packet has been received and properly
-+ * collected.
-+ */
-+static libssh2pack_t
-+fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
-+{
-+ unsigned char macbuf[MAX_MACSIZE];
-+ struct transportpacket *p = &session->packet;
-+ int rc;
-+
-+ if (session->fullpacket_state == libssh2_NB_state_idle) {
-+ session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
-+ session->fullpacket_payload_len = p->packet_length - 1;
-+
-+ if (encrypted) {
-+
-+ /* Calculate MAC hash */
-+ session->remote.mac->hash(session, macbuf, /* store hash here */
-+ session->remote.seqno,
-+ p->init, 5,
-+ p->payload,
-+ session->fullpacket_payload_len,
-+ &session->remote.mac_abstract);
-+
-+ /* Compare the calculated hash with the MAC we just read from
-+ * the network. The read one is at the very end of the payload
-+ * buffer. Note that 'payload_len' here is the packet_length
-+ * field which includes the padding but not the MAC.
-+ */
-+ if (memcmp(macbuf, p->payload + session->fullpacket_payload_len,
-+ session->remote.mac->mac_len)) {
-+ session->fullpacket_macstate = LIBSSH2_MAC_INVALID;
-+ }
-+ }
-+
-+ session->remote.seqno++;
-+
-+ /* ignore the padding */
-+ session->fullpacket_payload_len -= p->padding_length;
-+
-+ /* Check for and deal with decompression */
-+ if (session->remote.comp && strcmp(session->remote.comp->name, "none")) {
-+ unsigned char *data;
-+ unsigned long data_len;
-+ int free_payload = 1;
-+
-+ if (session->remote.comp->comp(session, 0,
-+ &data, &data_len,
-+ LIBSSH2_PACKET_MAXDECOMP,
-+ &free_payload,
-+ p->payload,
-+ session->fullpacket_payload_len,
-+ &session->remote.comp_abstract)) {
-+ LIBSSH2_FREE(session, p->payload);
-+ return PACKET_FAIL;
-+ }
-+
-+ if (free_payload) {
-+ LIBSSH2_FREE(session, p->payload);
-+ p->payload = data;
-+ session->fullpacket_payload_len = data_len;
-+ } else {
-+ if (data == p->payload) {
-+ /* It's not to be freed, because the
-+ * compression layer reused payload, So let's
-+ * do the same!
-+ */
-+ session->fullpacket_payload_len = data_len;
-+ } else {
-+ /* No comp_method actually lets this happen,
-+ * but let's prepare for the future */
-+
-+ LIBSSH2_FREE(session, p->payload);
-+
-+ /* We need a freeable struct otherwise the
-+ * brigade won't know what to do with it */
-+ p->payload = LIBSSH2_ALLOC(session, data_len);
-+ if (!p->payload) {
-+ libssh2_error(session, LIBSSH2_ERROR_ALLOC, (char *)
-+ "Unable to allocate memory for copy of uncompressed data",
-+ 0);
-+ return PACKET_ENOMEM;
-+ }
-+ memcpy(p->payload, data, data_len);
-+ session->fullpacket_payload_len = data_len;
-+ }
-+ }
-+ }
-+
-+ session->fullpacket_packet_type = p->payload[0];
-+
-+ debugdump(session, "libssh2_packet_read() plain",
-+ p->payload, session->fullpacket_payload_len);
-+
-+ session->fullpacket_state = libssh2_NB_state_created;
-+ }
-+
-+ if (session->fullpacket_state == libssh2_NB_state_created) {
-+ rc = libssh2_packet_add(session, p->payload,
-+ session->fullpacket_payload_len,
-+ session->fullpacket_macstate);
-+ if (rc == PACKET_EAGAIN) {
-+ return PACKET_EAGAIN;
-+ } else if (rc < 0) {
-+ return PACKET_FAIL;
-+ }
-+ }
-+
-+ session->fullpacket_state = libssh2_NB_state_idle;
-+
-+ return session->fullpacket_packet_type;
-+}
-+
-+
-+/* {{{ libssh2_packet_read
-+ * Collect a packet into the input brigade
-+ * block only controls whether or not to wait for a packet to start,
-+ * Once a packet starts, libssh2 will block until it is complete
-+ *
-+ * Returns packet type added to input brigade (PACKET_NONE if nothing added),
-+ * or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full
-+ * packet.
-+ */
-+
-+/*
-+ * This function reads the binary stream as specified in chapter 6 of RFC4253
-+ * "The Secure Shell (SSH) Transport Layer Protocol"
-+ */
-+libssh2pack_t
-+libssh2_packet_read(LIBSSH2_SESSION * session)
-+{
-+ libssh2pack_t rc;
-+ struct transportpacket *p = &session->packet;
-+ int remainbuf;
-+ int remainpack;
-+ int numbytes;
-+ int numdecrypt;
-+ unsigned char block[MAX_BLOCKSIZE];
-+ int blocksize;
-+ int encrypted = 1;
-+
-+ int status;
-+
-+ /*
-+ * All channels, systems, subsystems, etc eventually make it down here
-+ * when looking for more incoming data. If a key exchange is going on
-+ * (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end
-+ * will ONLY send key exchange related traffic. In non-blocking mode,
-+ * there is a chance to break out of the kex_exchange function with an
-+ * EAGAIN status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS
-+ * is active, then we must redirect to the key exchange. However,
-+ * if kex_exchange is active (as in it is the one that calls this execution
-+ * of packet_read, then don't redirect, as that would be an infinite loop!
-+ */
-+
-+ if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&
-+ !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {
-+
-+ /* Whoever wants a packet won't get anything until the key re-exchange
-+ * is done!
-+ */
-+ _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Redirecting into the"
-+ " key re-exchange");
-+ status = libssh2_kex_exchange(session, 1, &session->startup_key_state);
-+ if (status == PACKET_EAGAIN) {
-+ libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
-+ "Would block exchanging encryption keys", 0);
-+ return PACKET_EAGAIN;
-+ } else if (status) {
-+ libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
-+ "Unable to exchange encryption keys",0);
-+ return LIBSSH2_ERROR_KEX_FAILURE;
-+ }
-+ }
-+
-+ /*
-+ * =============================== NOTE ===============================
-+ * I know this is very ugly and not a really good use of "goto", but
-+ * this case statement would be even uglier to do it any other way
-+ */
-+ if (session->readPack_state == libssh2_NB_state_jump1) {
-+ session->readPack_state = libssh2_NB_state_idle;
-+ encrypted = session->readPack_encrypted;
-+ goto libssh2_packet_read_point1;
-+ }
-+
-+ do {
-+ if (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
-+ return PACKET_NONE;
-+ }
-+
-+ if (session->state & LIBSSH2_STATE_NEWKEYS) {
-+ blocksize = session->remote.crypt->blocksize;
-+ } else {
-+ encrypted = 0; /* not encrypted */
-+ blocksize = 5; /* not strictly true, but we can use 5 here to
-+ make the checks below work fine still */
-+ }
-+
-+ /* read/use a whole big chunk into a temporary area stored in
-+ the LIBSSH2_SESSION struct. We will decrypt data from that
-+ buffer into the packet buffer so this temp one doesn't have
-+ to be able to keep a whole SSH packet, just be large enough
-+ so that we can read big chunks from the network layer. */
-+
-+ /* how much data there is remaining in the buffer to deal with
-+ before we should read more from the network */
-+ remainbuf = p->writeidx - p->readidx;
-+
-+ /* if remainbuf turns negative we have a bad internal error */
-+ assert(remainbuf >= 0);
-+
-+ if (remainbuf < blocksize) {
-+ /* If we have less than a blocksize left, it is too
-+ little data to deal with, read more */
-+ ssize_t nread;
-+
-+ /* move any remainder to the start of the buffer so
-+ that we can do a full refill */
-+ if (remainbuf) {
-+ memmove(p->buf, &p->buf[p->readidx], remainbuf);
-+ p->readidx = 0;
-+ p->writeidx = remainbuf;
-+ } else {
-+ /* nothing to move, just zero the indexes */
-+ p->readidx = p->writeidx = 0;
-+ }
-+
-+ /* now read a big chunk from the network into the temp buffer */
-+ nread =
-+ recv(session->socket_fd, &p->buf[remainbuf],
-+ PACKETBUFSIZE - remainbuf,
-+ LIBSSH2_SOCKET_RECV_FLAGS(session));
-+ if (nread <= 0) {
-+ /* check if this is due to EAGAIN and return the special
-+ return code if so, error out normally otherwise */
-+#ifdef WIN32
-+ switch (WSAGetLastError()) {
-+ case WSAEWOULDBLOCK:
-+ errno = EAGAIN;
-+ break;
-+
-+ case WSAENOTSOCK:
-+ errno = EBADF;
-+ break;
-+
-+ case WSAENOTCONN:
-+ case WSAECONNABORTED:
-+ errno = WSAENOTCONN;
-+ break;
-+
-+ case WSAEINTR:
-+ errno = EINTR;
-+ break;
-+ }
-+#endif /* WIN32 */
-+ if ((nread < 0) && (errno == EAGAIN)) {
-+ session->socket_block_directions =
-+ LIBSSH2_SESSION_BLOCK_INBOUND;
-+ return PACKET_EAGAIN;
-+ }
-+ return PACKET_FAIL;
-+ }
-+ debugdump(session, "libssh2_packet_read() raw",
-+ &p->buf[remainbuf], nread);
-+ /* advance write pointer */
-+ p->writeidx += nread;
-+
-+ /* update remainbuf counter */
-+ remainbuf = p->writeidx - p->readidx;
-+ }
-+
-+ /* how much data to deal with from the buffer */
-+ numbytes = remainbuf;
-+
-+ if (!p->total_num) {
-+ /* No payload package area allocated yet. To know the
-+ size of this payload, we need to decrypt the first
-+ blocksize data. */
-+
-+ if (numbytes < blocksize) {
-+ /* we can't act on anything less than blocksize, but this
-+ check is only done for the initial block since once we have
-+ got the start of a block we can in fact deal with fractions
-+ */
-+ return PACKET_EAGAIN;
-+ }
-+
-+ if (encrypted) {
-+ rc = decrypt(session, &p->buf[p->readidx], block, blocksize);
-+ if (rc != PACKET_NONE) {
-+ return rc;
-+ }
-+ /* save the first 5 bytes of the decrypted package, to be
-+ used in the hash calculation later down. */
-+ memcpy(p->init, &p->buf[p->readidx], 5);
-+ } else {
-+ /* the data is plain, just copy it verbatim to
-+ the working block buffer */
-+ memcpy(block, &p->buf[p->readidx], blocksize);
-+ }
-+
-+ /* advance the read pointer */
-+ p->readidx += blocksize;
-+
-+ /* we now have the initial blocksize bytes decrypted,
-+ * and we can extract packet and padding length from it
-+ */
-+ p->packet_length = libssh2_ntohu32(block);
-+ p->padding_length = block[4];
-+
-+ /* total_num is the number of bytes following the initial
-+ (5 bytes) packet length and padding length fields */
-+ p->total_num =
-+ p->packet_length - 1 +
-+ (encrypted ? session->remote.mac->mac_len : 0);
-+
-+ /* RFC4253 section 6.1 Maximum Packet Length says:
-+ *
-+ * "All implementations MUST be able to process
-+ * packets with uncompressed payload length of 32768
-+ * bytes or less and total packet size of 35000 bytes
-+ * or less (including length, padding length, payload,
-+ * padding, and MAC.)."
-+ */
-+ if (p->total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
-+ return PACKET_TOOBIG;
-+ }
-+
-+ /* Get a packet handle put data into. We get one to
-+ hold all data, including padding and MAC. */
-+ p->payload = LIBSSH2_ALLOC(session, p->total_num);
-+ if (!p->payload) {
-+ return PACKET_ENOMEM;
-+ }
-+ /* init write pointer to start of payload buffer */
-+ p->wptr = p->payload;
-+
-+ if (blocksize > 5) {
-+ /* copy the data from index 5 to the end of
-+ the blocksize from the temporary buffer to
-+ the start of the decrypted buffer */
-+ memcpy(p->wptr, &block[5], blocksize - 5);
-+ p->wptr += blocksize - 5; /* advance write pointer */
-+ }
-+
-+ /* init the data_num field to the number of bytes of
-+ the package read so far */
-+ p->data_num = p->wptr - p->payload;
-+
-+ /* we already dealt with a blocksize worth of data */
-+ numbytes -= blocksize;
-+ }
-+
-+ /* how much there is left to add to the current payload
-+ package */
-+ remainpack = p->total_num - p->data_num;
-+
-+ if (numbytes > remainpack) {
-+ /* if we have more data in the buffer than what is going into this
-+ particular packet, we limit this round to this packet only */
-+ numbytes = remainpack;
-+ }
-+
-+ if (encrypted) {
-+ /* At the end of the incoming stream, there is a MAC,
-+ and we don't want to decrypt that since we need it
-+ "raw". We MUST however decrypt the padding data
-+ since it is used for the hash later on. */
-+ int skip = session->remote.mac->mac_len;
-+
-+ /* if what we have plus numbytes is bigger than the
-+ total minus the skip margin, we should lower the
-+ amount to decrypt even more */
-+ if ((p->data_num + numbytes) > (p->total_num - skip)) {
-+ numdecrypt = (p->total_num - skip) - p->data_num;
-+ } else {
-+ int frac;
-+ numdecrypt = numbytes;
-+ frac = numdecrypt % blocksize;
-+ if (frac) {
-+ /* not an aligned amount of blocks,
-+ align it */
-+ numdecrypt -= frac;
-+ /* and make it no unencrypted data
-+ after it */
-+ numbytes = 0;
-+ }
-+ }
-+ } else {
-+ /* unencrypted data should not be decrypted at all */
-+ numdecrypt = 0;
-+ }
-+
-+ /* if there are bytes to decrypt, do that */
-+ if (numdecrypt > 0) {
-+ /* now decrypt the lot */
-+ rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt);
-+ if (rc != PACKET_NONE) {
-+ return rc;
-+ }
-+
-+ /* advance the read pointer */
-+ p->readidx += numdecrypt;
-+ /* advance write pointer */
-+ p->wptr += numdecrypt;
-+ /* increse data_num */
-+ p->data_num += numdecrypt;
-+
-+ /* bytes left to take care of without decryption */
-+ numbytes -= numdecrypt;
-+ }
-+
-+ /* if there are bytes to copy that aren't decrypted, simply
-+ copy them as-is to the target buffer */
-+ if (numbytes > 0) {
-+ memcpy(p->wptr, &p->buf[p->readidx], numbytes);
-+
-+ /* advance the read pointer */
-+ p->readidx += numbytes;
-+ /* advance write pointer */
-+ p->wptr += numbytes;
-+ /* increse data_num */
-+ p->data_num += numbytes;
-+ }
-+
-+ /* now check how much data there's left to read to finish the
-+ current packet */
-+ remainpack = p->total_num - p->data_num;
-+
-+ if (!remainpack) {
-+ /* we have a full packet */
-+ libssh2_packet_read_point1:
-+ rc = fullpacket(session, encrypted);
-+ if (rc == PACKET_EAGAIN) {
-+
-+ if (session->packAdd_state != libssh2_NB_state_idle)
-+ {
-+ /* fullpacket only returns PACKET_EAGAIN if
-+ * libssh2_packet_add returns PACKET_EAGAIN. If that
-+ * returns PACKET_EAGAIN but the packAdd_state is idle,
-+ * then the packet has been added to the brigade, but some
-+ * immediate action that was taken based on the packet
-+ * type (such as key re-exchange) is not yet complete.
-+ * Clear the way for a new packet to be read in.
-+ */
-+ session->readPack_encrypted = encrypted;
-+ session->readPack_state = libssh2_NB_state_jump1;
-+ }
-+
-+ return PACKET_EAGAIN;
-+ }
-+
-+ p->total_num = 0; /* no packet buffer available */
-+
-+ return rc;
-+ }
-+ } while (1); /* loop */
-+
-+ return PACKET_FAIL; /* we never reach this point */
-+}
-+
-+/* }}} */
-+
-+static libssh2pack_t
-+send_existing(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned long data_len, ssize_t * ret)
-+{
-+ ssize_t rc;
-+ ssize_t length;
-+ struct transportpacket *p = &session->packet;
-+
-+ if (!p->outbuf) {
-+ *ret = 0;
-+ return PACKET_NONE;
-+ }
-+
-+ /* send as much as possible of the existing packet */
-+ if ((data != p->odata) || (data_len != p->olen)) {
-+ /* When we are about to complete the sending of a packet, it is vital
-+ that the caller doesn't try to send a new/different packet since
-+ we don't add this one up until the previous one has been sent. To
-+ make the caller really notice his/hers flaw, we return error for
-+ this case */
-+ return PACKET_BADUSE;
-+ }
-+
-+ *ret = 1; /* set to make our parent return */
-+
-+ /* number of bytes left to send */
-+ length = p->ototal_num - p->osent;
-+
-+ rc = send(session->socket_fd, &p->outbuf[p->osent], length,
-+ LIBSSH2_SOCKET_SEND_FLAGS(session));
-+
-+ if (rc == length) {
-+ /* the remainder of the package was sent */
-+ LIBSSH2_FREE(session, p->outbuf);
-+ p->outbuf = NULL;
-+ p->ototal_num = 0;
-+ } else if (rc < 0) {
-+ /* nothing was sent */
-+ if (errno != EAGAIN) {
-+ /* send failure! */
-+ return PACKET_FAIL;
-+ }
-+ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ return PACKET_EAGAIN;
-+ }
-+
-+ debugdump(session, "libssh2_packet_write send()", &p->outbuf[p->osent],
-+ length);
-+ p->osent += length; /* we sent away this much data */
-+
-+ return PACKET_NONE;
-+}
-+
-+/* {{{ libssh2_packet_write
-+ * Send a packet, encrypting it and adding a MAC code if necessary
-+ * Returns 0 on success, non-zero on failure.
-+ *
-+ * Returns PACKET_EAGAIN if it would block - and if it does so, you should
-+ * call this function again as soon as it is likely that more data can be
-+ * sent, and this function should then be called with the same argument set
-+ * (same data pointer and same data_len) until zero or failure is returned.
-+ *
-+ * NOTE: this function does not verify that 'data_len' is less than ~35000
-+ * which is what all implementations should support at least as packet size.
-+ * (RFC4253 section 6.1)
-+ */
-+int
-+libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
-+ unsigned long data_len)
-+{
-+ int blocksize =
-+ (session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt->
-+ blocksize : 8;
-+ int padding_length;
-+ int packet_length;
-+ int total_length;
-+ int free_data = 0;
-+#ifdef RANDOM_PADDING
-+ int rand_max;
-+ int seed = data[0]; /* FIXME: make this random */
-+#endif
-+ struct transportpacket *p = &session->packet;
-+ int encrypted;
-+ int i;
-+ ssize_t ret;
-+ libssh2pack_t rc;
-+ unsigned char *orgdata = data;
-+ unsigned long orgdata_len = data_len;
-+
-+ debugdump(session, "libssh2_packet_write plain", data, data_len);
-+
-+ /* FIRST, check if we have a pending write to complete */
-+ rc = send_existing(session, data, data_len, &ret);
-+ if (rc || ret) {
-+ return rc;
-+ }
-+
-+ encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;
-+
-+ /* check if we should compress */
-+ if (encrypted && strcmp(session->local.comp->name, "none")) {
-+ if (session->local.comp->comp(session, 1, &data, &data_len,
-+ LIBSSH2_PACKET_MAXCOMP,
-+ &free_data, data, data_len,
-+ &session->local.comp_abstract)) {
-+ return PACKET_COMPRESS; /* compression failure */
-+ }
-+ }
-+
-+ /* RFC4253 says: Note that the length of the concatenation of
-+ 'packet_length', 'padding_length', 'payload', and 'random padding'
-+ MUST be a multiple of the cipher block size or 8, whichever is
-+ larger. */
-+
-+ /* Plain math: (4 + 1 + packet_length + padding_length) % blocksize == 0 */
-+
-+ packet_length = data_len + 1 + 4; /* 1 is for padding_length field
-+ 4 for the packet_length field */
-+
-+ /* at this point we have it all except the padding */
-+
-+ /* first figure out our minimum padding amount to make it an even
-+ block size */
-+ padding_length = blocksize - (packet_length % blocksize);
-+
-+ /* if the padding becomes too small we add another blocksize worth
-+ of it (taken from the original libssh2 where it didn't have any
-+ real explanation) */
-+ if (padding_length < 4) {
-+ padding_length += blocksize;
-+ }
-+#ifdef RANDOM_PADDING
-+ /* FIXME: we can add padding here, but that also makes the packets
-+ bigger etc */
-+
-+ /* now we can add 'blocksize' to the padding_length N number of times
-+ (to "help thwart traffic analysis") but it must be less than 255 in
-+ total */
-+ rand_max = (255 - padding_length) / blocksize + 1;
-+ padding_length += blocksize * (seed % rand_max);
-+#endif
-+
-+ packet_length += padding_length;
-+
-+ /* append the MAC length to the total_length size */
-+ total_length =
-+ packet_length + (encrypted ? session->local.mac->mac_len : 0);
-+
-+ /* allocate memory to store the outgoing packet in, in case we can't
-+ send the whole one and thus need to keep it after this function
-+ returns. */
-+ p->outbuf = LIBSSH2_ALLOC(session, total_length);
-+ if (!p->outbuf) {
-+ return PACKET_ENOMEM;
-+ }
-+
-+ /* store packet_length, which is the size of the whole packet except
-+ the MAC and the packet_length field itself */
-+ libssh2_htonu32(p->outbuf, packet_length - 4);
-+ /* store padding_length */
-+ p->outbuf[4] = padding_length;
-+ /* copy the payload data */
-+ memcpy(p->outbuf + 5, data, data_len);
-+ /* fill the padding area with random junk */
-+ libssh2_random(p->outbuf + 5 + data_len, padding_length);
-+ if (free_data) {
-+ LIBSSH2_FREE(session, data);
-+ }
-+
-+ if (encrypted) {
-+ /* Calculate MAC hash. Put the output at index packet_length,
-+ since that size includes the whole packet. The MAC is
-+ calculated on the entire unencrypted packet, including all
-+ fields except the MAC field itself. */
-+ session->local.mac->hash(session, p->outbuf + packet_length,
-+ session->local.seqno, p->outbuf,
-+ packet_length, NULL, 0,
-+ &session->local.mac_abstract);
-+
-+ /* Encrypt the whole packet data, one block size at a time.
-+ The MAC field is not encrypted. */
-+ for(i = 0; i < packet_length; i += session->local.crypt->blocksize) {
-+ unsigned char *ptr = &p->outbuf[i];
-+ if (session->local.crypt->crypt(session, ptr,
-+ &session->local.crypt_abstract))
-+ return PACKET_FAIL; /* encryption failure */
-+ }
-+ }
-+
-+ session->local.seqno++;
-+
-+ ret = send(session->socket_fd, p->outbuf, total_length,
-+ LIBSSH2_SOCKET_SEND_FLAGS(session));
-+
-+ if (ret != -1) {
-+ debugdump(session, "libssh2_packet_write send()", p->outbuf, ret);
-+ }
-+ if (ret != total_length) {
-+ if ((ret > 0) || ((ret == -1) && (errno == EAGAIN))) {
-+ /* the whole packet could not be sent, save the rest */
-+ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND;
-+ p->odata = orgdata;
-+ p->olen = orgdata_len;
-+ p->osent = (ret == -1) ? 0 : ret;
-+ p->ototal_num = total_length;
-+ return PACKET_EAGAIN;
-+ }
-+ return PACKET_FAIL;
-+ }
-+
-+ /* the whole thing got sent away */
-+ p->odata = NULL;
-+ p->olen = 0;
-+ LIBSSH2_FREE(session, p->outbuf);
-+ p->outbuf = NULL;
-+
-+ return PACKET_NONE; /* all is good */
-+}
-+
-+/* }}} */
-+
-
-Property changes on: libssh2/src/transport.c
-___________________________________________________________________
-Added: svn:mime-type
- + text/x-c
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-Added: svn:eol-style
- + native
-Added: svn:executable
- + *
-
-
-Property changes on: libssh2/src
-___________________________________________________________________
-Added: svn:ignore
- + libssh2_config.h
-
-
-Index: package.xml
-===================================================================
-Cannot display: file marked as a binary type.
-svn:mime-type = application/xml
-
-Property changes on: package.xml
-___________________________________________________________________
-Deleted: svn:mime-type
- - application/xml
-
-Index: ssh2_fopen_wrappers.c
-===================================================================
---- ssh2_fopen_wrappers.c (.../tags/RELEASE_0_11_0)
-+++ ssh2_fopen_wrappers.c (.../trunk)
-@@ -46,7 +46,7 @@
- libssh2_channel_set_blocking(abstract->channel, abstract->is_blocking);
-
- readstate = libssh2_channel_read_ex(abstract->channel, abstract->streamid, buf, count);
-- return (readstate == LIBSSH2_ERROR_EAGAIN ? 0 : readstate);
-+ return (readstate < 0 ? 0 : readstate);
- }
-
- static int php_ssh2_channel_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
-
-Property changes on: ssh2_fopen_wrappers.c
-___________________________________________________________________
-Modified: cvs2svn:cvs-rev
- - 1.15
- + 1.16
-
-Index: php_ssh2.h
-===================================================================
---- php_ssh2.h (.../tags/RELEASE_0_11_0)
-+++ php_ssh2.h (.../trunk)
-@@ -101,6 +101,10 @@
- } php_ssh2_pkey_subsys_data;
- #endif
-
-+#ifndef PHP_WIN32
-+#define closesocket(s) close(s)
-+#endif
-+
- #ifdef ZTS
- #define SSH2_TSRMLS_SET(datap) ((php_ssh2_session_data*)(datap))->tsrm_ls = TSRMLS_C
- #define SSH2_TSRMLS_FETCH(datap) TSRMLS_D = ((php_ssh2_session_data*)(datap))->tsrm_ls
-@@ -109,6 +113,12 @@
- #define SSH2_TSRMLS_FETCH(datap)
- #endif
-
-+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
-+#define ZEND_IS_CALLABLE_TSRMLS_CC TSRMLS_CC
-+#else
-+#define ZEND_IS_CALLABLE_TSRMLS_CC
-+#endif
-+
- /* < 5.3 compatibility */
- #ifndef Z_REFCOUNT_P
- #define Z_REFCOUNT_P(pz) (pz)->refcount
-
-Property changes on: php_ssh2.h
-___________________________________________________________________
-Modified: cvs2svn:cvs-rev
- - 1.12
- + 1.14
-
-Index: EXPERIMENTAL
-===================================================================
-
-Property changes on: EXPERIMENTAL
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:keywords
- + Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
-Added: cvs2svn:cvs-rev
- + 1.1
-
-
-Property changes on: .
-___________________________________________________________________
-Added: svn:ignore
- + #*#
-*.dsw
-*.la
-*.lo
-*.ncb
-*.opt
-*.plg
-*.tgz
-*~
-.#*
-.deps
-.libs
-Debug
-Debug_TS
-Makefile
-Makefile.fragments
-Makefile.global
-Makefile.objects
-Release
-Release_TS
-Release_TSDbg
-Release_TS_inline
-Release_inline
-acinclude.m4
-aclocal.m4
-autom4te.cache
-build
-config.cache
-config.guess
-config.h
-config.h.in
-config.log
-config.nice
-config.status
-config.sub
-configure
-configure.in
-conftest
-conftest.c
-include
-install-sh
-libs.mk
-libtool
-ltmain.sh
-missing
-mkinstalldirs
-modules
-scan_makefile_in.awk
-*.gcda
-*.gcno
-run-tests.php
-
-