From 74709a4983fd76106141b1926d8b1dc904a00c4d Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 12 Dec 2012 11:23:38 -0500 Subject: [PATCH 01/14] bug fixes --- include/fc/json_rpc_connection.hpp | 4 +- include/fc/json_rpc_error_object.hpp | 22 +- include/fc/json_rpc_stream_connection.hpp | 2 +- include/fc/reflect.hpp | 6 +- include/fc/value.hpp | 1 + include/fc/value_cast.hpp | 3 +- include/fc/value_io.hpp | 3 +- src/json_rpc_connection.cpp | 9 +- src/json_rpc_error_object.cpp | 11 +- src/json_rpc_stream_connection.cpp | 5 +- src/value.cpp | 6 + .../boost/process/include/boost/process.hpp | 25 - .../process/include/boost/process/all.hpp | 40 - .../process/include/boost/process/child.hpp | 92 - .../process/include/boost/process/config.hpp | 74 - .../process/include/boost/process/context.hpp | 133 - .../boost/process/detail/basic_status.hpp | 69 - .../process/detail/basic_status_service.hpp | 318 -- .../boost/process/detail/posix_helpers.hpp | 106 - .../boost/process/detail/status_impl.hpp | 190 - .../boost/process/detail/systembuf.hpp | 228 -- .../boost/process/detail/windows_helpers.hpp | 138 - .../include/boost/process/environment.hpp | 52 - .../process/include/boost/process/handle.hpp | 231 -- .../include/boost/process/operations.hpp | 433 --- .../include/boost/process/pid_type.hpp | 56 - .../process/include/boost/process/pipe.hpp | 49 - .../include/boost/process/pistream.hpp | 114 - .../include/boost/process/postream.hpp | 115 - .../process/include/boost/process/process.hpp | 212 -- .../process/include/boost/process/self.hpp | 188 - .../process/include/boost/process/status.hpp | 41 - .../include/boost/process/stream_behavior.hpp | 326 -- .../include/boost/process/stream_ends.hpp | 68 - .../include/boost/process/stream_id.hpp | 50 - .../include/boost/process/stream_type.hpp | 45 - vendor/libssh2-1.4.2/CMakeLists.txt | 26 - vendor/libssh2-1.4.2/include/libssh2.h | 1188 ------ .../libssh2-1.4.2/include/libssh2_publickey.h | 118 - vendor/libssh2-1.4.2/include/libssh2_sftp.h | 345 -- vendor/libssh2-1.4.2/src/agent.c | 793 ---- vendor/libssh2-1.4.2/src/channel.c | 2570 ------------- vendor/libssh2-1.4.2/src/channel.h | 141 - vendor/libssh2-1.4.2/src/comp.c | 390 -- vendor/libssh2-1.4.2/src/comp.h | 45 - vendor/libssh2-1.4.2/src/crypt.c | 334 -- vendor/libssh2-1.4.2/src/crypto.h | 118 - vendor/libssh2-1.4.2/src/global.c | 78 - vendor/libssh2-1.4.2/src/hostkey.c | 485 --- vendor/libssh2-1.4.2/src/keepalive.c | 98 - vendor/libssh2-1.4.2/src/kex.c | 2008 ---------- vendor/libssh2-1.4.2/src/knownhost.c | 1146 ------ vendor/libssh2-1.4.2/src/libgcrypt.c | 593 --- vendor/libssh2-1.4.2/src/libgcrypt.h | 150 - vendor/libssh2-1.4.2/src/libssh2_config.h | 5 - vendor/libssh2-1.4.2/src/libssh2_config_osx.h | 224 -- vendor/libssh2-1.4.2/src/libssh2_config_win.h | 41 - vendor/libssh2-1.4.2/src/libssh2_priv.h | 1038 ------ vendor/libssh2-1.4.2/src/mac.c | 314 -- vendor/libssh2-1.4.2/src/mac.h | 67 - vendor/libssh2-1.4.2/src/misc.c | 612 --- vendor/libssh2-1.4.2/src/misc.h | 94 - vendor/libssh2-1.4.2/src/openssl.c | 804 ---- vendor/libssh2-1.4.2/src/openssl.h | 178 - vendor/libssh2-1.4.2/src/packet.c | 1243 ------- vendor/libssh2-1.4.2/src/packet.h | 76 - vendor/libssh2-1.4.2/src/pem.c | 213 -- vendor/libssh2-1.4.2/src/publickey.c | 1058 ------ vendor/libssh2-1.4.2/src/scp.c | 1085 ------ vendor/libssh2-1.4.2/src/session.c | 1751 --------- vendor/libssh2-1.4.2/src/session.h | 93 - vendor/libssh2-1.4.2/src/sftp.c | 3278 ----------------- vendor/libssh2-1.4.2/src/sftp.h | 230 -- vendor/libssh2-1.4.2/src/transport.c | 873 ----- vendor/libssh2-1.4.2/src/transport.h | 87 - vendor/libssh2-1.4.2/src/userauth.c | 1687 --------- vendor/libssh2-1.4.2/src/userauth.h | 50 - vendor/libssh2-1.4.2/src/version.c | 54 - 78 files changed, 52 insertions(+), 29194 deletions(-) delete mode 100644 vendor/boost/process/include/boost/process.hpp delete mode 100644 vendor/boost/process/include/boost/process/all.hpp delete mode 100644 vendor/boost/process/include/boost/process/child.hpp delete mode 100644 vendor/boost/process/include/boost/process/config.hpp delete mode 100644 vendor/boost/process/include/boost/process/context.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/basic_status.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/basic_status_service.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/posix_helpers.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/status_impl.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/systembuf.hpp delete mode 100644 vendor/boost/process/include/boost/process/detail/windows_helpers.hpp delete mode 100644 vendor/boost/process/include/boost/process/environment.hpp delete mode 100644 vendor/boost/process/include/boost/process/handle.hpp delete mode 100644 vendor/boost/process/include/boost/process/operations.hpp delete mode 100644 vendor/boost/process/include/boost/process/pid_type.hpp delete mode 100644 vendor/boost/process/include/boost/process/pipe.hpp delete mode 100644 vendor/boost/process/include/boost/process/pistream.hpp delete mode 100644 vendor/boost/process/include/boost/process/postream.hpp delete mode 100644 vendor/boost/process/include/boost/process/process.hpp delete mode 100644 vendor/boost/process/include/boost/process/self.hpp delete mode 100644 vendor/boost/process/include/boost/process/status.hpp delete mode 100644 vendor/boost/process/include/boost/process/stream_behavior.hpp delete mode 100644 vendor/boost/process/include/boost/process/stream_ends.hpp delete mode 100644 vendor/boost/process/include/boost/process/stream_id.hpp delete mode 100644 vendor/boost/process/include/boost/process/stream_type.hpp delete mode 100644 vendor/libssh2-1.4.2/CMakeLists.txt delete mode 100644 vendor/libssh2-1.4.2/include/libssh2.h delete mode 100644 vendor/libssh2-1.4.2/include/libssh2_publickey.h delete mode 100644 vendor/libssh2-1.4.2/include/libssh2_sftp.h delete mode 100644 vendor/libssh2-1.4.2/src/agent.c delete mode 100644 vendor/libssh2-1.4.2/src/channel.c delete mode 100644 vendor/libssh2-1.4.2/src/channel.h delete mode 100644 vendor/libssh2-1.4.2/src/comp.c delete mode 100644 vendor/libssh2-1.4.2/src/comp.h delete mode 100644 vendor/libssh2-1.4.2/src/crypt.c delete mode 100644 vendor/libssh2-1.4.2/src/crypto.h delete mode 100644 vendor/libssh2-1.4.2/src/global.c delete mode 100644 vendor/libssh2-1.4.2/src/hostkey.c delete mode 100644 vendor/libssh2-1.4.2/src/keepalive.c delete mode 100644 vendor/libssh2-1.4.2/src/kex.c delete mode 100644 vendor/libssh2-1.4.2/src/knownhost.c delete mode 100644 vendor/libssh2-1.4.2/src/libgcrypt.c delete mode 100644 vendor/libssh2-1.4.2/src/libgcrypt.h delete mode 100644 vendor/libssh2-1.4.2/src/libssh2_config.h delete mode 100644 vendor/libssh2-1.4.2/src/libssh2_config_osx.h delete mode 100644 vendor/libssh2-1.4.2/src/libssh2_config_win.h delete mode 100644 vendor/libssh2-1.4.2/src/libssh2_priv.h delete mode 100644 vendor/libssh2-1.4.2/src/mac.c delete mode 100644 vendor/libssh2-1.4.2/src/mac.h delete mode 100644 vendor/libssh2-1.4.2/src/misc.c delete mode 100644 vendor/libssh2-1.4.2/src/misc.h delete mode 100644 vendor/libssh2-1.4.2/src/openssl.c delete mode 100644 vendor/libssh2-1.4.2/src/openssl.h delete mode 100644 vendor/libssh2-1.4.2/src/packet.c delete mode 100644 vendor/libssh2-1.4.2/src/packet.h delete mode 100644 vendor/libssh2-1.4.2/src/pem.c delete mode 100644 vendor/libssh2-1.4.2/src/publickey.c delete mode 100644 vendor/libssh2-1.4.2/src/scp.c delete mode 100644 vendor/libssh2-1.4.2/src/session.c delete mode 100644 vendor/libssh2-1.4.2/src/session.h delete mode 100644 vendor/libssh2-1.4.2/src/sftp.c delete mode 100644 vendor/libssh2-1.4.2/src/sftp.h delete mode 100644 vendor/libssh2-1.4.2/src/transport.c delete mode 100644 vendor/libssh2-1.4.2/src/transport.h delete mode 100644 vendor/libssh2-1.4.2/src/userauth.c delete mode 100644 vendor/libssh2-1.4.2/src/userauth.h delete mode 100644 vendor/libssh2-1.4.2/src/version.c diff --git a/include/fc/json_rpc_connection.hpp b/include/fc/json_rpc_connection.hpp index 5bb920d..c0c4e42 100644 --- a/include/fc/json_rpc_connection.hpp +++ b/include/fc/json_rpc_connection.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -6,6 +7,7 @@ namespace fc { namespace json { class rpc_connection; + class error_object; struct rpc_server_method : public fc::retainable { typedef fc::shared_ptr ptr; @@ -141,7 +143,7 @@ namespace fc { namespace json { void handle_message( const value& m ); virtual void send_notice( const fc::string& m, value&& param ) = 0; virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ) = 0; - virtual void send_error( uint64_t id, int64_t code, const fc::string& msg ) = 0; + virtual void send_error( uint64_t id, const error_object& e ) = 0; virtual void send_result( uint64_t id, value&& r ) = 0; diff --git a/include/fc/json_rpc_error_object.hpp b/include/fc/json_rpc_error_object.hpp index 6c6e999..d898356 100644 --- a/include/fc/json_rpc_error_object.hpp +++ b/include/fc/json_rpc_error_object.hpp @@ -2,18 +2,26 @@ #include #include #include +#include -namespace fc { namespace json { - struct error_object { - error_object( const fc::string& msg = fc::string(), fc::value v = fc::value(), int64_t c = -32000); +namespace fc { + class value; - int64_t code; - fc::string message; - fc::optional data; + namespace json { + + class error_object { + public: + error_object( const fc::string& msg, const fc::value& v , int64_t c = -32000); + error_object( const fc::string& msg=fc::string(), int64_t c = -32000 ); + error_object( const error_object& e ); + ~error_object(); + + int64_t code; + fc::string message; + fc::optional data; }; } } -#include FC_REFLECT( fc::json::error_object, (code)(message)(data) ) diff --git a/include/fc/json_rpc_stream_connection.hpp b/include/fc/json_rpc_stream_connection.hpp index c6ea8ec..acf689b 100644 --- a/include/fc/json_rpc_stream_connection.hpp +++ b/include/fc/json_rpc_stream_connection.hpp @@ -30,7 +30,7 @@ namespace fc { ~rpc_stream_connection(); virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ); virtual void send_notice( const fc::string& m, value&& param ); - virtual void send_error( uint64_t id, int64_t code, const fc::string& msg ); + virtual void send_error( uint64_t id, const error_object& eo ); virtual void send_result( uint64_t id, value&& r ); private: diff --git a/include/fc/reflect.hpp b/include/fc/reflect.hpp index 9bede15..7dd64ed 100644 --- a/include/fc/reflect.hpp +++ b/include/fc/reflect.hpp @@ -17,6 +17,7 @@ #include #include +#include namespace fc { @@ -79,8 +80,7 @@ struct reflector{ #endif //#include #define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \ - -// visitor.TEMPLATE operator()elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) ); + visitor.TEMPLATE operator()elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) ); #define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ @@ -147,6 +147,7 @@ template<> struct reflector { \ */ #define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \ namespace fc { \ + template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ typedef fc::true_type is_defined; \ @@ -172,6 +173,7 @@ template<> struct reflector {\ #define FC_REFLECT_FWD( TYPE ) \ namespace fc { \ + template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ typedef fc::true_type is_defined; \ diff --git a/include/fc/value.hpp b/include/fc/value.hpp index 711f892..7dd9c44 100644 --- a/include/fc/value.hpp +++ b/include/fc/value.hpp @@ -85,6 +85,7 @@ namespace fc { value& operator=( value&& v ); value& operator=( const value& v ); + value& operator=( value& v ); /** diff --git a/include/fc/value_cast.hpp b/include/fc/value_cast.hpp index be4cd4d..7063f2b 100644 --- a/include/fc/value_cast.hpp +++ b/include/fc/value_cast.hpp @@ -7,8 +7,9 @@ #include #include #include +#include -#include +//#include namespace fc { diff --git a/include/fc/value_io.hpp b/include/fc/value_io.hpp index de9c678..b18ce56 100644 --- a/include/fc/value_io.hpp +++ b/include/fc/value_io.hpp @@ -177,11 +177,12 @@ namespace fc { template static inline void pack(fc::value& s, const T& v ) { v.did_not_implement_reflect_macro(); + wlog( "warning, ignoring unknown type" ); } template static inline void unpack( const fc::value& s, T& v ) { v.did_not_implement_reflect_macro(); - //wlog( "warning, ignoring unknown type" ); + wlog( "warning, ignoring unknown type" ); } }; diff --git a/src/json_rpc_connection.cpp b/src/json_rpc_connection.cpp index ebc8684..32ca5ab 100644 --- a/src/json_rpc_connection.cpp +++ b/src/json_rpc_connection.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ namespace fc { namespace json { if( id_itr != end ) { // TODO: send invalid method reply auto id = value_cast(id_itr->val); - send_error( id, -1, "Unknown method '"+mname+"'"); + send_error( id, fc::json::error_object( "Unknown method '"+mname+"'" )); } // nothing to do, unknown method } else { // known method, attempt to call it and send reply; @@ -65,14 +66,16 @@ namespace fc { namespace json { value nul; const value& params = (p_itr != end) ? p_itr->val : nul; - slog( "params '%s'", to_string( params ).c_str() ); + // slog( "params '%s'", to_string( params ).c_str() ); if( id_itr != end ) { // capture reply auto id = value_cast(id_itr->val); try { send_result( id, smeth->second->call(params) ); + } catch ( const fc::json::error_object& eo ) { + send_error( id, eo ); } catch ( ... ) { - send_error( id, -1, fc::except_str() ); + send_error( id, error_object( fc::except_str(), fc::value() ) ); } } else { // ignore exception + result try { smeth->second->call( params ); }catch(...){} diff --git a/src/json_rpc_error_object.cpp b/src/json_rpc_error_object.cpp index 944d5f1..0c6a189 100644 --- a/src/json_rpc_error_object.cpp +++ b/src/json_rpc_error_object.cpp @@ -1,6 +1,13 @@ #include +#include + namespace fc { namespace json { - error_object::error_object( const fc::string& m, fc::value v, int64_t c ) - :code(c),message(m),data(fc::move(v)){} + error_object::error_object( const fc::string& m, const fc::value& v, int64_t c ) + :code(c),message(m),data(v){ } + error_object::error_object(const fc::string& m, int64_t c) + :code(c),message(m){ } + error_object::error_object(const error_object& e) + :code(e.code),message(e.message),data(e.data){} + error_object::~error_object(){} }} diff --git a/src/json_rpc_stream_connection.cpp b/src/json_rpc_stream_connection.cpp index ecf4f27..f173b82 100644 --- a/src/json_rpc_stream_connection.cpp +++ b/src/json_rpc_stream_connection.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -86,9 +87,9 @@ namespace fc { namespace json { fc::string o = ss.str(); my->out.write( o.c_str(), o.size() ); } - void rpc_stream_connection::send_error( uint64_t id, int64_t code, const fc::string& msg ) { + void rpc_stream_connection::send_error( uint64_t id, const json::error_object& eo ) { fc::stringstream ss; - ss<<"{\"id\":"<out.write( o.c_str(), o.size() ); } diff --git a/src/value.cpp b/src/value.cpp index 783dc61..51e177f 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -276,6 +276,12 @@ value& value::operator=( const value& v ){ gh(v.holder)->copy_helper(holder); return *this; } +value& value::operator=( value& v ){ + if( this == &v ) return *this; + gh(holder)->~value_holder(); + gh(v.holder)->copy_helper(holder); + return *this; +} bool value::is_null()const { return strcmp(gh(holder)->type(), "void") == 0; } diff --git a/vendor/boost/process/include/boost/process.hpp b/vendor/boost/process/include/boost/process.hpp deleted file mode 100644 index 98e3c89..0000000 --- a/vendor/boost/process/include/boost/process.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process.hpp - * - * Convenience header that includes all public Boost.Process header files. - */ - -#ifndef BOOST_PROCESS_HPP -#define BOOST_PROCESS_HPP - -#include - -#endif diff --git a/vendor/boost/process/include/boost/process/all.hpp b/vendor/boost/process/include/boost/process/all.hpp deleted file mode 100644 index f30e566..0000000 --- a/vendor/boost/process/include/boost/process/all.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/all.hpp - * - * Convenience header that includes all public Boost.Process header files. - */ - -#ifndef BOOST_PROCESS_ALL_HPP -#define BOOST_PROCESS_ALL_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/vendor/boost/process/include/boost/process/child.hpp b/vendor/boost/process/include/boost/process/child.hpp deleted file mode 100644 index f0a632a..0000000 --- a/vendor/boost/process/include/boost/process/child.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/child.hpp - * - * Includes the declaration of the child class. - */ - -#ifndef BOOST_PROCESS_CHILD_HPP -#define BOOST_PROCESS_CHILD_HPP - -#include - -#if defined(BOOST_POSIX_API) -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * The child class provides access to a child process. - */ -class child : public process -{ -public: - /** - * Creates a new child object that represents the just spawned child - * process \a id. - */ - child(pid_type id, std::map handles) - : process(id), - handles_(handles) - { - } - -#if defined(BOOST_WINDOWS_API) - /** - * Creates a new child object that represents the just spawned child - * process \a id. - * - * This operation is only available on Windows systems. - */ - child(handle hprocess, std::map handles) - : process(hprocess), - handles_(handles) - { - } -#endif - - /** - * Gets a handle to a stream attached to the child. - * - * If the handle doesn't exist an invalid handle is returned. - */ - handle get_handle(stream_id id) const - { - std::map::const_iterator it = handles_.find(id); - return (it != handles_.end()) ? it->second : handle(); - } - -private: - /** - * Handles providing access to streams attached to the child process. - */ - std::map handles_; -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/config.hpp b/vendor/boost/process/include/boost/process/config.hpp deleted file mode 100644 index 7ce15eb..0000000 --- a/vendor/boost/process/include/boost/process/config.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/config.hpp - * - * Defines macros that are used by the library to determine the operating - * system it is running under and the features it supports. - */ - -#ifndef BOOST_PROCESS_CONFIG_HPP -#define BOOST_PROCESS_CONFIG_HPP - -#include -#include -#include -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) || defined(BOOST_PROCESS_DOXYGEN) -/** - * Specifies the system's maximal supported path length. - * - * The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer - * value which specifies the system's maximal supported path length. It is - * only used if neither PATH_MAX nor _PC_PATH_MAX and HAVE_PATHCONF are defined. - * The maximal supported path length is required by - * boost::process::self::get_work_dir(). Please note that this function is - * also called by the constructor of boost::process::context. - */ -# define BOOST_PROCESS_POSIX_PATH_MAX 259 -# endif -#endif - -/** \cond */ -#define BOOST_PROCESS_SOURCE_LOCATION \ - "in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": " - -#if defined(BOOST_POSIX_API) -# define BOOST_PROCESS_LAST_ERROR errno -#elif defined(BOOST_WINDOWS_API) -# define BOOST_PROCESS_LAST_ERROR GetLastError() -#endif - -#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \ - boost::throw_exception(boost::system::system_error( \ - boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \ - boost::system::get_system_category()), \ - BOOST_PROCESS_SOURCE_LOCATION what)) - -#define BOOST_PROCESS_THROW_ERROR(error, what) \ - boost::throw_exception(boost::system::system_error( \ - boost::system::error_code(error, \ - boost::system::get_system_category()), \ - BOOST_PROCESS_SOURCE_LOCATION what)) -/** \endcond */ - -#endif diff --git a/vendor/boost/process/include/boost/process/context.hpp b/vendor/boost/process/include/boost/process/context.hpp deleted file mode 100644 index 6d4a8d0..0000000 --- a/vendor/boost/process/include/boost/process/context.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/context.hpp - * - * Includes the declaration of the context class. - */ - -#ifndef BOOST_PROCESS_CONTEXT_HPP -#define BOOST_PROCESS_CONTEXT_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Context class to define how a child process is created. - * - * The context class is used to configure streams, to set the work directory - * and define environment variables. It is also used to change a process - * name (the variable commonly known as argv[0]). - */ -struct context -{ - typedef std::map > - streams_t; - - /** - * Streams. - * - * Streams of a child process can be configured through factory functions - * which return a pair of handles - one handle to use as a stream end - * in the child process and possibly another handle to use as a stream end - * in the parent process (if a pipe is setup both processes can communicate - * with each other). - */ - streams_t streams; - - /** - * Process name. - * - * The child process can access the process name via a variable - * commonly known as argv[0]. - */ - std::string process_name; - - /** - * Work directory. - */ - std::string work_dir; - - /** - * Environment variables. - */ - environment env; - - /** - * Constructs a process context. - * - * The default behavior of standard streams is to inherit them. The current - * work directory is also the work directory of the child process. The child - * process also inherits all environment variables. - */ - context() - : work_dir(self::get_work_dir()), - env(self::get_environment()) - { -#if 0 // this default behavior will throw in non-console apps -#if defined(BOOST_POSIX_API) - streams[stdin_id] = behavior::inherit(STDIN_FILENO); - streams[stdout_id] = behavior::inherit(STDOUT_FILENO); - streams[stderr_id] = behavior::inherit(STDERR_FILENO); -#elif defined(BOOST_WINDOWS_API) - streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE)); - streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE)); - streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE)); -#endif -#endif - } - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Setups a child process. - * - * This is an extension point to support more configuration options for - * child processes. You can initialize \a setup with a user-defined function - * which is called when a child process is created. - * - * On POSIX platforms setup() is called in the child process. That's why in - * a multithreaded application only async-signal-safe functions must be - * called in the function \a setup is bound to. - * - * On Windows platforms setup() is called in the parent process. A - * reference to a STARTUPINFOA structure is passed as parameter. - */ - boost::function setup; -#elif defined(BOOST_WINDOWS_API) - boost::function setup; -#endif -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/basic_status.hpp b/vendor/boost/process/include/boost/process/detail/basic_status.hpp deleted file mode 100644 index 2da361a..0000000 --- a/vendor/boost/process/include/boost/process/detail/basic_status.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/basic_status.hpp - * - * Includes the declaration of the basic status class. - */ - -#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP -#define BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP - -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * The basic_status class to wait for processes to exit. - * - * The basic_status class is a Boost.Asio I/O object and supports synchronous - * and asynchronous wait operations. It must be instantiated with a Service. - */ -template -class basic_status - : public boost::asio::basic_io_object -{ -public: - explicit basic_status(boost::asio::io_service &io_service) - : boost::asio::basic_io_object(io_service) - { - } - - /** - * Waits synchronously for a process to exit. - */ - int wait(pid_type pid) - { - return this->service.wait(this->implementation, pid); - } - - /** - * Waits asynchronously for a process to exit. - */ - template - void async_wait(pid_type pid, Handler handler) - { - this->service.async_wait(this->implementation, pid, handler); - } -}; - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/basic_status_service.hpp b/vendor/boost/process/include/boost/process/detail/basic_status_service.hpp deleted file mode 100644 index 97c8162..0000000 --- a/vendor/boost/process/include/boost/process/detail/basic_status_service.hpp +++ /dev/null @@ -1,318 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/basic_status_service.hpp - * - * Includes the declaration of the basic status service class. - */ - -#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP -#define BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * The basic_status_service class provides the service to wait for processes - * synchronously and asynchronously. - */ -template -class basic_status_service - : public boost::asio::detail::service_base -{ -public: - explicit basic_status_service(boost::asio::io_service &io_service) - : boost::asio::detail::service_base(io_service), -#if defined(BOOST_POSIX_API) - interrupt_pid_(-1), - pids_(0) -#elif defined(BOOST_WINDOWS_API) - run_(true) -#endif - { -#if defined(BOOST_WINDOWS_API) - handles_.push_back(CreateEvent(NULL, FALSE, FALSE, NULL)); - if (handles_[0] == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed"); - work_thread_ = boost::thread( - &basic_status_service::work_thread, this); -#endif - } - - ~basic_status_service() - { -#if defined(BOOST_POSIX_API) - boost::unique_lock lock(work_thread_mutex_); - bool worker_thread_active = (pids_ != 0); - lock.unlock(); - if (worker_thread_active) - { - stop_work_thread(); - work_thread_.join(); - } -#elif defined(BOOST_WINDOWS_API) - stop_work_thread(); - work_thread_.join(); - CloseHandle(handles_[0]); -#endif - } - - typedef boost::shared_ptr implementation_type; - - void construct(implementation_type &impl) - { - impl = boost::make_shared(); - boost::unique_lock lock(work_thread_mutex_); - impls_.push_back(impl); - } - - void destroy(implementation_type &impl) - { - boost::unique_lock lock(work_thread_mutex_); - typename std::vector::iterator it = - std::find(impls_.begin(), impls_.end(), impl); - if (it != impls_.end()) - impls_.erase(it); -#if defined(BOOST_WINDOWS_API) - interrupt_work_thread(); - work_thread_cond_.wait(work_thread_mutex_); - impl->clear(handles_); - work_thread_cond_.notify_all(); -#endif - impl.reset(); - } - - int wait(implementation_type &impl, pid_type pid) - { - boost::system::error_code ec; - int status = impl->wait(pid, ec); -#if defined(BOOST_POSIX_API) - if (ec.value() == ECHILD) - { - boost::unique_lock lock(work_thread_mutex_); - boost::unordered_map::iterator it = statuses_.find(pid); - if (it == statuses_.end()) - { - work_thread_cond_.wait(work_thread_mutex_); - it = statuses_.find(pid); - } - if (it != statuses_.end()) - { - status = it->second; - statuses_.erase(it); - ec.clear(); - } - } -#endif - boost::asio::detail::throw_error(ec); - return status; - } - - template - void async_wait(implementation_type &impl, pid_type pid, Handler handler) - { -#if defined(BOOST_POSIX_API) - boost::unique_lock lock(work_thread_mutex_); - if (++pids_ == 1) - { - work_.reset(new boost::asio::io_service::work( - this->get_io_service())); - work_thread_ = boost::thread( - &basic_status_service::work_thread, - this); - } - impl->async_wait(pid, this->get_io_service().wrap(handler)); -#elif defined(BOOST_WINDOWS_API) - HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, - FALSE, pid); - if (handle == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - boost::unique_lock lock(work_thread_mutex_); - if (!work_) - work_.reset(new boost::asio::io_service::work( - this->get_io_service())); - interrupt_work_thread(); - work_thread_cond_.wait(work_thread_mutex_); - handles_.push_back(handle); - impl->async_wait(handle, this->get_io_service().wrap(handler)); - work_thread_cond_.notify_all(); -#endif - } - -private: - void shutdown_service() - { -#if defined(BOOST_WINDOWS_API) - boost::unique_lock lock(work_thread_mutex_); - work_.reset(); -#endif - } - - void work_thread() - { -#if defined(BOOST_POSIX_API) - for (;;) - { - int status; - pid_t pid = ::wait(&status); - if (pid == -1) - { - if (errno != EINTR) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("wait(2) failed"); - } - else if (interrupted(pid)) - { - // On POSIX the only reason to interrupt is to break out. - break; - } - else - { - boost::unique_lock lock(work_thread_mutex_); - bool regchild = false; - for (typename std::vector::iterator it = - impls_.begin(); it != impls_.end(); ++it) - regchild |= (*it)->complete(pid, status); - if (regchild && --pids_ == 0) - { - work_.reset(); - break; - } - else if (!regchild) - { - statuses_.insert(boost::unordered_map:: - value_type(pid, status)); - work_thread_cond_.notify_all(); - } - } - } -#elif defined(BOOST_WINDOWS_API) - for (;;) - { - DWORD res = WaitForMultipleObjects(handles_.size(), &handles_[0], - FALSE, INFINITE); - if (res == WAIT_FAILED) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "WaitForMultipleObjects() failed"); - else if (res - WAIT_OBJECT_0 == 0) - { - boost::unique_lock lock(work_thread_mutex_); - if (!run_) - break; - work_thread_cond_.notify_all(); - work_thread_cond_.wait(work_thread_mutex_); - } - else if (res - WAIT_OBJECT_0 > 0) - { - HANDLE handle = handles_[res - WAIT_OBJECT_0]; - DWORD exit_code; - if (!GetExitCodeProcess(handle, &exit_code)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetExitCodeProcess() failed"); - boost::unique_lock lock(work_thread_mutex_); - for (typename std::vector::iterator it = - impls_.begin(); it != impls_.end(); ++it) - (*it)->complete(handle, exit_code); - std::vector::iterator it = handles_.begin(); - std::advance(it, res - WAIT_OBJECT_0); - handles_.erase(it); - if (handles_.size() == 1) - work_.reset(); - } - } -#endif - } - - void interrupt_work_thread() - { -#if defined(BOOST_POSIX_API) - // By creating a child process which immediately exits - // we interrupt wait(). - std::vector args; - args.push_back("-c"); - args.push_back("'exit'"); - interrupt_pid_ = create_child("/bin/sh", args).get_id(); -#elif defined(BOOST_WINDOWS_API) - // By signaling the event in the first slot WaitForMultipleObjects() - // will return. The work thread won't do anything except checking if - // it should continue to run. - if (!SetEvent(handles_[0])) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetEvent() failed"); -#endif - } - -#if defined(BOOST_POSIX_API) - bool interrupted(pid_t pid) - { - boost::mutex::scoped_lock lock(work_thread_mutex_); - return interrupt_pid_ == pid; - } -#endif - - void stop_work_thread() - { - boost::mutex::scoped_lock lock(work_thread_mutex_); -#if defined(BOOST_WINDOWS_API) - // Access to run_ must be sychronized with running(). - run_ = false; -#endif - // Access to interrupt_pid_ must be sychronized with interrupted(). - interrupt_work_thread(); - } - - boost::scoped_ptr work_; - std::vector impls_; - boost::mutex work_thread_mutex_; - boost::thread work_thread_; - boost::condition_variable_any work_thread_cond_; -#if defined(BOOST_POSIX_API) - pid_t interrupt_pid_; - int pids_; - boost::unordered_map statuses_; -#elif defined(BOOST_WINDOWS_API) - bool run_; - std::vector handles_; -#endif -}; - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/posix_helpers.hpp b/vendor/boost/process/include/boost/process/detail/posix_helpers.hpp deleted file mode 100644 index 993e2e0..0000000 --- a/vendor/boost/process/include/boost/process/detail/posix_helpers.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/posix_helpers.hpp - * - * Includes the declaration of helper functions for POSIX systems. - */ - -#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP -#define BOOST_PROCESS_POSIX_HELPERS_HPP - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts an environment to a char** table as used by execve(). - * - * Converts the environment's contents to the format used by the - * execve() system call. The returned char** array is allocated - * in dynamic memory; the caller must free it when not used any - * more. Each entry is also allocated in dynamic memory and is a - * NULL-terminated string of the form var=value; these must also be - * released by the caller. - * - * This operation is only available on POSIX systems. - * - * \return The first argument of the pair is an integer that indicates - * how many strings are stored in the second argument. The - * second argument is a NULL-terminated, dynamically allocated - * array of dynamically allocated strings representing the - * enviroment's content. Each array entry is a NULL-terminated - * string of the form var=value. The caller is responsible for - * freeing them. - */ -inline std::pair environment_to_envp(const environment - &env) -{ - std::size_t nargs = env.size(); - char **envp = new char*[nargs + 1]; - environment::size_type i = 0; - for (environment::const_iterator it = env.begin(); it != env.end(); ++it) - { - std::string s = it->first + "=" + it->second; - envp[i] = new char[s.size() + 1]; - std::strncpy(envp[i], s.c_str(), s.size() + 1); - ++i; - } - envp[i] = 0; - return std::pair(nargs, envp); -} - -/** - * Converts the command line to an array of C strings. - * - * Converts the command line's list of arguments to the format expected - * by the \a argv parameter in the POSIX execve() system call. - * - * This operation is only available on POSIX systems. - * - * \return The first argument of the pair is an integer that indicates - * how many strings are stored in the second argument. The - * second argument is a NULL-terminated, dynamically allocated - * array of dynamically allocated strings holding the arguments - * to the executable. The caller is responsible for freeing them. - */ -template -inline std::pair collection_to_argv(const Arguments &args) -{ - std::size_t nargs = args.size(); - char **argv = new char*[nargs + 1]; - typename Arguments::size_type i = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); - ++it) - { - argv[i] = new char[it->size() + 1]; - std::strncpy(argv[i], it->c_str(), it->size() + 1); - ++i; - } - argv[nargs] = 0; - return std::pair(nargs, argv); -} - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/status_impl.hpp b/vendor/boost/process/include/boost/process/detail/status_impl.hpp deleted file mode 100644 index 618db49..0000000 --- a/vendor/boost/process/include/boost/process/detail/status_impl.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/status_impl.hpp - * - * Includes the declaration of the status implementation class. - */ - -#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP -#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -#if defined(BOOST_POSIX_API) -typedef pid_t phandle; -#elif defined(BOOST_WINDOWS_API) -typedef HANDLE phandle; -#endif - -struct operation -{ - virtual ~operation(){} - virtual void operator()(int exit_code) - { -#if defined(BOOST_MSVC) - exit_code; -#endif - } -}; - -template -class wrapped_handler : public operation -{ -public: - wrapped_handler(Handler handler) - : handler_(handler) - { - } - - void operator()(int exit_code) - { - handler_(boost::system::error_code(), exit_code); - } - -private: - Handler handler_; -}; - -/** - * The status_impl class saves internal data of every status I/O object. - */ -class status_impl -{ -public: -#if defined(BOOST_WINDOWS_API) - template - void clear(Container &handles) - { - for (operations_type::iterator it = ops_.begin(); it != ops_.end(); - ++it) - { - for (typename Container::iterator it2 = handles.begin(); it2 != - handles.end(); ++it2) - { - if (*it2 == it->first) - { - handles.erase(it2); - break; - } - } - CloseHandle(it->first); - } - } -#endif - - int wait(pid_type pid, boost::system::error_code &ec) - { -#if defined(BOOST_POSIX_API) - pid_t p; - int status; - do - { - p = waitpid(pid, &status, 0); - } while (p == -1 && errno == EINTR); - if (p == -1) - { - ec = boost::system::error_code(errno, - boost::system::get_system_category()); - return -1; - } - return status; -#elif defined(BOOST_WINDOWS_API) - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, - pid); - if (h == NULL) - { - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - - if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) - { - CloseHandle(h); - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - - DWORD exit_code; - if (!GetExitCodeProcess(h, &exit_code)) - { - CloseHandle(h); - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - if (!CloseHandle(h)) - { - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - return exit_code; -#endif - } - - template - void async_wait(phandle ph, Handler handler) - { - ops_.insert(ph, new wrapped_handler(handler)); - } - - bool complete(phandle ph, int exit_code) - { - boost::iterator_range r = - ops_.equal_range(ph); - if (r.empty()) - return false; - for (operations_type::iterator it = r.begin(); it != r.end(); ++it) - (*it->second)(exit_code); - ops_.erase(r.begin(), r.end()); -#if defined(BOOST_WINDOWS_API) - if (!CloseHandle(ph)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); -#endif - return true; - } - -private: - typedef boost::ptr_unordered_multimap operations_type; - operations_type ops_; -}; - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/systembuf.hpp b/vendor/boost/process/include/boost/process/detail/systembuf.hpp deleted file mode 100644 index d6dce50..0000000 --- a/vendor/boost/process/include/boost/process/detail/systembuf.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/systembuf.hpp - * - * Includes the declaration of the systembuf class. - */ - -#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP -#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -class postream; - -namespace detail { - -/** - * std::streambuf implementation for handles. - * - * systembuf provides a std::streambuf implementation for handles. - * Contrarywise to the handle class, this class does \b not take - * ownership of the native handle; this should be taken care of - * somewhere else. - * - * This class follows the expected semantics of a std::streambuf object. - * However, it is not copyable to avoid introducing inconsistences with - * the on-disk file and the in-memory buffers. - */ -class systembuf : public std::streambuf, public boost::noncopyable -{ - friend class boost::process::postream; - -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - */ - typedef NativeHandleType handle_type; -#elif defined(BOOST_POSIX_API) - typedef int handle_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE handle_type; -#endif - - /** - * Constructs a new systembuf for the given handle. - * - * This constructor creates a new systembuf object that reads or - * writes data from/to the \a h native handle. This handle - * is \b not owned by the created systembuf object; the code - * should take care of it externally. - * - * This class buffers input and output; the buffer size may be - * tuned through the \a bufsize parameter, which defaults to 8192 - * bytes. - * - * \see pistream and postream - */ - explicit systembuf(handle_type h, std::size_t bufsize = 8192) - : handle_(h), - bufsize_(bufsize), - read_buf_(new char[bufsize]), - write_buf_(new char[bufsize]) - { -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(handle_ >= 0); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE); -#endif - BOOST_ASSERT(bufsize_ > 0); - setp(write_buf_.get(), write_buf_.get() + bufsize_); - } - -protected: - /** - * Reads new data from the native handle. - * - * This operation is called by input methods when there is no more - * data in the input buffer. The function fills the buffer with new - * data, if available. - * - * \pre All input positions are exhausted (gptr() >= egptr()). - * \post The input buffer has new data, if available. - * \returns traits_type::eof() if a read error occurrs or there are - * no more data to be read. Otherwise returns - * traits_type::to_int_type(*gptr()). - */ - virtual int_type underflow() - { - BOOST_ASSERT(gptr() >= egptr()); - - bool ok; -#if defined(BOOST_POSIX_API) - ssize_t cnt = read(handle_, read_buf_.get(), bufsize_); - ok = (cnt != -1 && cnt != 0); -#elif defined(BOOST_WINDOWS_API) - DWORD cnt; - BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL); - ok = (res && cnt > 0); -#endif - - if (!ok) - return traits_type::eof(); - else - { - setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt); - return traits_type::to_int_type(*gptr()); - } - } - - /** - * Makes room in the write buffer for additional data. - * - * This operation is called by output methods when there is no more - * space in the output buffer to hold a new element. The function - * first flushes the buffer's contents to disk and then clears it to - * leave room for more characters. The given \a c character is - * stored at the beginning of the new space. - * - * \pre All output positions are exhausted (pptr() >= epptr()). - * \post The output buffer has more space if no errors occurred - * during the write to disk. - * \post *(pptr() - 1) is \a c. - * \returns traits_type::eof() if a write error occurrs. Otherwise - * returns traits_type::not_eof(c). - */ - virtual int_type overflow(int c) - { - BOOST_ASSERT(pptr() >= epptr()); - - if (sync() == -1) - return traits_type::eof(); - - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - traits_type::assign(*pptr(), static_cast( - c)); - pbump(1); - } - - return traits_type::not_eof(c); - } - - /** - * Flushes the output buffer to disk. - * - * Synchronizes the systembuf buffers with the contents of the file - * associated to this object through the native handle. The output buffer - * is flushed to disk and cleared to leave new room for more data. - * - * \returns 0 on success, -1 if an error occurred. - */ - virtual int sync() - { -#if defined(BOOST_POSIX_API) - ssize_t cnt = pptr() - pbase(); - bool ok = (write(handle_, pbase(), cnt) == cnt); - if (ok) - pbump(-cnt); - return ok ? 0 : -1; -#elif defined(BOOST_WINDOWS_API) - long cnt = pptr() - pbase(); - DWORD rcnt; - BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL); - bool ok = (res && static_cast(rcnt) == cnt); - if (ok) - pbump(-cnt); - return ok ? 0 : -1; -#endif - } - -private: - /** - * Native handle used by the systembuf object. - */ - handle_type handle_; - - /** - * Internal buffer size used during read and write operations. - */ - std::size_t bufsize_; - - /** - * Internal buffer used during read operations. - */ - boost::scoped_array read_buf_; - - /** - * Internal buffer used during write operations. - */ - boost::scoped_array write_buf_; -}; - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/detail/windows_helpers.hpp b/vendor/boost/process/include/boost/process/detail/windows_helpers.hpp deleted file mode 100644 index 5656aaa..0000000 --- a/vendor/boost/process/include/boost/process/detail/windows_helpers.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/windows_helpers.hpp - * - * Includes the declaration of helper functions for Windows systems. - */ - -#ifndef BOOST_PROCESS_WINDOWS_HELPERS_HPP -#define BOOST_PROCESS_WINDOWS_HELPERS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts an environment to a string used by CreateProcess(). - * - * Converts the environment's contents to the format used by the - * CreateProcess() system call. The returned char* string is - * allocated in dynamic memory; the caller must free it when not - * used any more. This is enforced by the use of a shared pointer. - * - * This operation is only available on Windows systems. - * - * \return A dynamically allocated char* string that represents - * the environment's content. This string is of the form - * var1=value1\\0var2=value2\\0\\0. - */ -inline boost::shared_array environment_to_windows_strings(environment - &env) -{ - boost::shared_array envp; - - if (env.empty()) - { - envp.reset(new char[2]); - ZeroMemory(envp.get(), 2); - } - else - { - std::string s; - for (environment::const_iterator it = env.begin(); it != env.end(); - ++it) - { - s += it->first + "=" + it->second; - s.push_back(0); - } - envp.reset(new char[s.size() + 1]); -#if (BOOST_MSVC >= 1400) - memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1); -#else - memcpy(envp.get(), s.c_str(), s.size() + 1); -#endif - } - - return envp; -} - -/** - * Converts the command line to a plain string. - * - * Converts the command line's list of arguments to the format expected by the - * \a lpCommandLine parameter in the CreateProcess() system call. - * - * This operation is only available on Windows systems. - * - * \return A dynamically allocated string holding the command line - * to be passed to the executable. It is returned in a - * shared_array object to ensure its release at some point. - */ -template -inline boost::shared_array collection_to_windows_cmdline(const Arguments - &args) -{ - typedef std::vector arguments_t; - arguments_t args2; - typename Arguments::size_type i = 0; - std::size_t size = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); - ++it) - { - std::string arg = *it; - - std::string::size_type pos = 0; - while ( (pos = arg.find('"', pos)) != std::string::npos) - { - arg.replace(pos, 1, "\\\""); - pos += 2; - } - - if (arg.find(' ') != std::string::npos) - arg = '\"' + arg + '\"'; - - if (i++ != args.size() - 1) - arg += ' '; - - args2.push_back(arg); - size += arg.size() + 1; - } - - boost::shared_array cmdline(new char[size]); - cmdline.get()[0] = '\0'; - for (arguments_t::size_type i = 0; i < args.size(); ++i) -#if (BOOST_MSVC >= 1400) - strcat_s(cmdline.get(), size, args2[i].c_str()); -#else - strncat(cmdline.get(), args2[i].c_str(), args2[i].size()); -#endif - - return cmdline; -} - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/environment.hpp b/vendor/boost/process/include/boost/process/environment.hpp deleted file mode 100644 index daf44e3..0000000 --- a/vendor/boost/process/include/boost/process/environment.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/environment.hpp - * - * Includes the declaration of the environment class. - */ - -#ifndef BOOST_PROCESS_ENVIRONMENT_HPP -#define BOOST_PROCESS_ENVIRONMENT_HPP - -#include -#include - -namespace boost { -namespace process { - -/** - * Representation of a process' environment variables. - * - * The environment is a map that establishes an unidirectional - * association between variable names and their values and is - * represented by a string to string map. - * - * Variables may be defined to the empty string. Be aware that doing so - * is not portable: POSIX systems will treat such variables as being - * defined to the empty value, but Windows systems are not able to - * distinguish them from undefined variables. - * - * Neither POSIX nor Windows systems support a variable with no name. - * - * It is worthy to note that the environment is sorted alphabetically. - * This is provided for-free by the map container used to implement this - * type, and this behavior is required by Windows systems. - */ -typedef std::map environment; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/handle.hpp b/vendor/boost/process/include/boost/process/handle.hpp deleted file mode 100644 index b880a3e..0000000 --- a/vendor/boost/process/include/boost/process/handle.hpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/handle.hpp - * - * Includes the declaration of the handle class. - */ - -#ifndef BOOST_PROCESS_HANDLE_HPP -#define BOOST_PROCESS_HANDLE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include - -namespace boost { -namespace process { - -/** - * RAII model for handles. - * - * The \a handle class is a RAII model for native handles. This class wraps - * one of such handles grabbing its ownership, and automaticaly closes it - * upon destruction. It is used to avoid leaking open handles, shall an - * unexpected execution trace occur. - */ -class handle -{ -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - * - * On POSIX systems \a NativeSystemHandle is an integer type while it is - * a \a HANDLE on Windows systems. - */ - typedef NativeSystemHandle native_type; -#elif defined(BOOST_POSIX_API) - typedef int native_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE native_type; -#endif - - /** - * Constructs an invalid handle. - * - * \see valid() - */ - handle() - { - } - - /** - * RAII settings to specify if handle should be automatically closed. - */ - enum close_type { do_close, dont_close }; - - /** - * Constructs a handle from a native handle. - * - * This constructor creates a new \a handle object that takes - * ownership of the given \a native handle. If \a close is set to - * handle::dont_close the \a native handle is not closed upon destruction. - * The user must not close \a native if it is owned by a \a handle object. - * Ownership can be reclaimed using release(). - * - * \see release() - */ - handle(native_type native, close_type close = handle::do_close) - : impl_(boost::make_shared(native, close)) - { - } - - /** - * Checks whether the handle is valid or not. - * - * \return true if the handle is valid; false otherwise. - */ - bool valid() const - { - return impl_ && impl_->valid(); - } - - /** - * Closes the handle. - * - * \post The handle is invalid. - * \post The native handle is closed. - */ - void close() - { - if (impl_) - impl_->close(); - } - - /** - * Gets the native handle. - * - * The caller can issue any operation on it except closing it. - * If closing is required, release() shall be used. - * - * \return The native handle. - */ - native_type native() const - { - return impl_ ? impl_->native() : invalid_handle(); - } - - /** - * Reclaims ownership of the native handle. - * - * The caller is responsible of closing the native handle. - * - * \post The handle is invalid. - * \return The native handle. - */ - native_type release() - { - return impl_ ? impl_->release() : invalid_handle(); - } - -private: - class impl - { - public: - typedef handle::native_type native_type; - - impl(native_type native, close_type close) - : native_(native), - close_(close) - { - } - - ~impl() - { - if (valid() && close_ == handle::do_close) - { -#if defined(BOOST_POSIX_API) - ::close(native_); -#elif defined(BOOST_WINDOWS_API) - CloseHandle(native_); -#endif - } - } - - bool valid() const - { - return native_ != handle::invalid_handle(); - } - - void close() - { - if (valid()) - { -#if defined(BOOST_POSIX_API) - ::close(native_); -#elif defined(BOOST_WINDOWS_API) - CloseHandle(native_); -#endif - native_ = handle::invalid_handle(); - } - } - - native_type native() const - { - return native_; - } - - native_type release() - { - native_type native = native_; - native_ = handle::invalid_handle(); - return native; - } - - private: - native_type native_; - close_type close_; - }; - - /** - * Implementation of handle to store native handle value. - * - * A shared pointer is used as handles represent system resources. If a - * handle is closed and becomes invalid the state of copies of the handle - * object will be updated as they all share the handle implementation. - */ - boost::shared_ptr impl_; - - /** - * Constant function representing an invalid handle value. - * - * Returns the platform-specific handle value that represents an - * invalid handle. This is a constant function rather than a regular - * constant because, in the latter case, we cannot define it under - * Windows due to the value being of a complex type. - */ - static const native_type invalid_handle() - { -#if defined(BOOST_POSIX_API) - return -1; -#elif defined(BOOST_WINDOWS_API) - return INVALID_HANDLE_VALUE; -#endif - } -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/operations.hpp b/vendor/boost/process/include/boost/process/operations.hpp deleted file mode 100644 index 5fcdd04..0000000 --- a/vendor/boost/process/include/boost/process/operations.hpp +++ /dev/null @@ -1,433 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/operations.hpp - * - * Provides miscellaneous free functions. - */ - -#ifndef BOOST_PROCESS_OPERATIONS_HPP -#define BOOST_PROCESS_OPERATIONS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# include -# include -# if defined(__CYGWIN__) -# include -# include -# endif -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Locates the executable program \a file in all the directory components - * specified in \a path. If \a path is empty, the value of the PATH - * environment variable is used. - * - * The path variable is interpreted following the same conventions used - * to parse the PATH environment variable in the underlying platform. - * - * \throw boost::filesystem::filesystem_error If the file cannot be found - * in the path. - */ -inline std::string find_executable_in_path(const std::string &file, - std::string path = "") -{ -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(file.find('/') == std::string::npos); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos); -#endif - - std::string result; - -#if defined(BOOST_POSIX_API) - if (path.empty()) - { - const char *envpath = getenv("PATH"); - if (!envpath) - boost::throw_exception(boost::filesystem::filesystem_error( - BOOST_PROCESS_SOURCE_LOCATION "file not found", file, - boost::system::errc::make_error_code( - boost::system::errc::no_such_file_or_directory))); - path = envpath; - } - BOOST_ASSERT(!path.empty()); - -#if defined(__CYGWIN__) - if (!cygwin_posix_path_list_p(path.c_str())) - { - int size = cygwin_win32_to_posix_path_list_buf_size(path.c_str()); - boost::scoped_array cygpath(new char[size]); - cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get()); - path = cygpath.get(); - } -#endif - - std::string::size_type pos1 = 0, pos2; - do - { - pos2 = path.find(':', pos1); - std::string dir = (pos2 != std::string::npos) ? - path.substr(pos1, pos2 - pos1) : path.substr(pos1); - std::string f = dir + - (boost::algorithm::ends_with(dir, "/") ? "" : "/") + file; - if (!access(f.c_str(), X_OK)) - result = f; - pos1 = pos2 + 1; - } while (pos2 != std::string::npos && result.empty()); -#elif defined(BOOST_WINDOWS_API) - const char *exts[] = { "", ".exe", ".com", ".bat", NULL }; - const char **ext = exts; - while (*ext) - { - char buf[MAX_PATH]; - char *dummy; - DWORD size = SearchPathA(path.empty() ? NULL : path.c_str(), - file.c_str(), *ext, MAX_PATH, buf, &dummy); - BOOST_ASSERT(size < MAX_PATH); - if (size > 0) - { - result = buf; - break; - } - ++ext; - } -#endif - - if (result.empty()) - boost::throw_exception(boost::filesystem::filesystem_error( - BOOST_PROCESS_SOURCE_LOCATION "file not found", file, - boost::system::errc::make_error_code( - boost::system::errc::no_such_file_or_directory))); - - return result; -} - -/** - * Extracts the program name from a given executable. - * - * \return The program name. On Windows the program name - * is returned without a file extension. - */ -inline std::string executable_to_progname(const std::string &exe) -{ - std::string::size_type begin = 0; - std::string::size_type end = std::string::npos; - -#if defined(BOOST_POSIX_API) - std::string::size_type slash = exe.rfind('/'); -#elif defined(BOOST_WINDOWS_API) - std::string::size_type slash = exe.find_last_of("/\\"); -#endif - if (slash != std::string::npos) - begin = slash + 1; - -#if defined(BOOST_WINDOWS_API) - if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") || - boost::algorithm::iends_with(exe, ".com") || - boost::algorithm::iends_with(exe, ".bat"))) - end = exe.size() - 4; -#endif - - return exe.substr(begin, end - begin); -} - -/** - * Starts a new child process. - * - * Launches a new process based on the binary image specified by the - * executable, the set of arguments passed to it and the execution context. - * - * \remark Blocking remarks: This function may block if the device holding the - * executable blocks when loading the image. This might happen if, e.g., - * the binary is being loaded from a network share. - * - * \return A handle to the new child process. - */ -template -inline child create_child(const std::string &executable, Arguments args, - Context ctx) -{ - typedef std::map handles_t; - handles_t handles; - typename Context::streams_t::iterator it = ctx.streams.begin(); - for (; it != ctx.streams.end(); ++it) - { - if (it->first == stdin_id) - handles[it->first] = it->second(input_stream); - else if (it->first == stdout_id) - handles[it->first] = it->second(output_stream); - else if (it->first == stderr_id) - handles[it->first] = it->second(output_stream); -#if defined(BOOST_POSIX_API) - else - handles[it->first] = it->second(unknown_stream); -#endif - } - - std::string p_name = ctx.process_name.empty() ? - executable_to_progname(executable) : ctx.process_name; - args.insert(args.begin(), p_name); - -#if defined(BOOST_POSIX_API) - // Between fork() and execve() only async-signal-safe functions - // must be called if multithreaded applications should be supported. - // That's why the following code is executed before fork() is called. -#if defined(F_MAXFD) - int maxdescs = fcntl(-1, F_MAXFD, 0); - if (maxdescs == -1) - maxdescs = sysconf(_SC_OPEN_MAX); -#else - int maxdescs = sysconf(_SC_OPEN_MAX); -#endif - if (maxdescs == -1) - maxdescs = 1024; - std::vector closeflags(maxdescs, true); - std::pair argv = detail::collection_to_argv(args); - std::pair envp = - detail::environment_to_envp(ctx.env); - - const char *work_dir = ctx.work_dir.c_str(); - - pid_t pid = fork(); - if (pid == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed"); - else if (pid == 0) - { - if (chdir(work_dir) == -1) - { - write(STDERR_FILENO, "chdir() failed\n", 15); - _exit(127); - } - - for (handles_t::iterator it = handles.begin(); it != handles.end(); - ++it) - { - if (it->second.child.valid()) - { - handles_t::iterator it2 = it; - ++it2; - for (; it2 != handles.end(); ++it2) - { - if (it2->second.child.native() == it->first) - { - int fd = fcntl(it2->second.child.native(), F_DUPFD, - it->first + 1); - if (fd == -1) - { - write(STDERR_FILENO, "fcntl() failed\n", 15); - _exit(127); - } - it2->second.child = fd; - } - } - - if (dup2(it->second.child.native(), it->first) == -1) - { - write(STDERR_FILENO, "dup2() failed\n", 14); - _exit(127); - } - closeflags[it->first] = false; - } - } - - if (ctx.setup) - ctx.setup(); - - for (std::size_t i = 0; i < closeflags.size(); ++i) - { - if (closeflags[i]) - close(i); - } - - execve(executable.c_str(), argv.second, envp.second); - - // Actually we should delete argv and envp data. As we must not - // call any non-async-signal-safe functions though we simply exit. - write(STDERR_FILENO, "execve() failed\n", 16); - _exit(127); - } - else - { - BOOST_ASSERT(pid > 0); - - for (std::size_t i = 0; i < argv.first; ++i) - delete[] argv.second[i]; - delete[] argv.second; - - for (std::size_t i = 0; i < envp.first; ++i) - delete[] envp.second[i]; - delete[] envp.second; - - std::map parent_ends; - for (handles_t::iterator it = handles.begin(); it != handles.end(); - ++it) - parent_ends[it->first] = it->second.parent; - - return child(pid, parent_ends); - } -#elif defined(BOOST_WINDOWS_API) - STARTUPINFOA startup_info; - ZeroMemory(&startup_info, sizeof(startup_info)); - startup_info.cb = sizeof(startup_info); - startup_info.dwFlags |= STARTF_USESTDHANDLES; - startup_info.hStdInput = handles[stdin_id].child.native(); - startup_info.hStdOutput = handles[stdout_id].child.native(); - startup_info.hStdError = handles[stderr_id].child.native(); - - if (ctx.setup) - ctx.setup(startup_info); - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - - boost::shared_array cmdline = - detail::collection_to_windows_cmdline(args); - - boost::scoped_array exe(new char[executable.size() + 1]); -#if (BOOST_MSVC >= 1400) - strcpy_s(exe.get(), executable.size() + 1, executable.c_str()); -#else - strcpy(exe.get(), executable.c_str()); -#endif - - boost::scoped_array workdir(new char[ctx.work_dir.size() + 1]); -#if (BOOST_MSVC >= 1400) - strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str()); -#else - strcpy(workdir.get(), ctx.work_dir.c_str()); -#endif - - boost::shared_array envstrs = - detail::environment_to_windows_strings(ctx.env); - - if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, - envstrs.get(), workdir.get(), &startup_info, &pi) == 0) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed"); - - handle hprocess(pi.hProcess); - - if (!CloseHandle(pi.hThread)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); - - std::map parent_ends; - parent_ends[stdin_id] = handles[stdin_id].parent; - parent_ends[stdout_id] = handles[stdout_id].parent; - parent_ends[stderr_id] = handles[stderr_id].parent; - - return child(hprocess, parent_ends); -#endif -} - -/** - * \overload - */ -inline child create_child(const std::string &executable) -{ - return create_child(executable, std::vector(), context()); -} - -/** - * \overload - */ -template -inline child create_child(const std::string &executable, Arguments args) -{ - return create_child(executable, args, context()); -} - -/** - * Starts a shell-based command. - * - * Executes the given command through the default system shell. The - * command is subject to pattern expansion, redirection and pipelining. - * The shell is launched as described by the parameters in the context. - * - * This function behaves similarly to the system(3) system call. In a - * POSIX system, the command is fed to /bin/sh whereas under a Windows - * system, it is fed to cmd.exe. It is difficult to write portable - * commands, but this function comes in handy in multiple situations. - * - * \remark Blocking remarks: This function may block if the device holding the - * executable blocks when loading the image. This might happen if, e.g., - * the binary is being loaded from a network share. - * - * \return A handle to the new child process. - */ -template -inline child shell(const std::string &command, Context ctx) -{ -#if defined(BOOST_POSIX_API) - std::string executable = "/bin/sh"; - std::vector args; - args.push_back("-c"); - args.push_back(command); -#elif defined(BOOST_WINDOWS_API) - char sysdir[MAX_PATH]; - UINT size = GetSystemDirectoryA(sysdir, sizeof(sysdir)); - if (!size) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed"); - std::string executable = std::string(sysdir) + - (sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe"); - std::vector args; - args.push_back("/c"); - args.push_back(command); -#endif - return create_child(executable, args, ctx); -} - -/** - * \overload - */ -inline child shell(const std::string &command) -{ - return shell(command, context()); -} - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/pid_type.hpp b/vendor/boost/process/include/boost/process/pid_type.hpp deleted file mode 100644 index 49dc51e..0000000 --- a/vendor/boost/process/include/boost/process/pid_type.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pid_type.hpp - * - * Includes the declaration of the pid type. - */ - -#ifndef BOOST_PROCESS_PID_TYPE_HPP -#define BOOST_PROCESS_PID_TYPE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -namespace boost { -namespace process { - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * Opaque name for the process identifier type. - * - * Each operating system identifies processes using a specific type. - * The \a pid_type type is used to transparently refer to a process - * regardless of the operating system. - * - * This type is guaranteed to be an integral type on all supported - * platforms. On POSIX systems it is defined as pid_t, on Windows systems as - * DWORD. - */ -typedef NativeProcessId pid_type; -#elif defined(BOOST_POSIX_API) -typedef pid_t pid_type; -#elif defined(BOOST_WINDOWS_API) -typedef DWORD pid_type; -#endif - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/pipe.hpp b/vendor/boost/process/include/boost/process/pipe.hpp deleted file mode 100644 index 23eb0a8..0000000 --- a/vendor/boost/process/include/boost/process/pipe.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pipe.hpp - * - * Includes the declaration of the pipe class. - */ - -#ifndef BOOST_PROCESS_PIPE_HPP -#define BOOST_PROCESS_PIPE_HPP - -#include -#include - -namespace boost { -namespace process { - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * The pipe class is a type definition for stream-based classes defined by - * Boost.Asio. - * - * The type definition is provided for convenience. You can also use Boost.Asio - * classes directly for asynchronous I/O operations. - */ -typedef BoostAsioPipe pipe; -#elif defined(BOOST_POSIX_API) -typedef boost::asio::posix::stream_descriptor pipe; -#elif defined(BOOST_WINDOWS_API) -typedef boost::asio::windows::stream_handle pipe; -#else -# error "Unsupported platform." -#endif - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/pistream.hpp b/vendor/boost/process/include/boost/process/pistream.hpp deleted file mode 100644 index 9bb252f..0000000 --- a/vendor/boost/process/include/boost/process/pistream.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pistream.hpp - * - * Includes the declaration of the pistream class. - */ - -#ifndef BOOST_PROCESS_PISTREAM_HPP -#define BOOST_PROCESS_PISTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' output stream. - * - * The pistream class represents an output communication channel with the - * child process. The child process writes data to this stream and the - * parent process can read it through the pistream object. In other - * words, from the child's point of view, the communication channel is an - * output one, but from the parent's point of view it is an input one; - * hence the confusing pistream name. - * - * pistream objects cannot be copied because they buffer data - * that flows through the communication channel. - * - * A pistream object behaves as a std::istream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that read data from this - * stream can block if the associated handle blocks during - * the read. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child has no more data to send to - * the pipe's system buffer. When this happens, the buffer - * eventually empties and the system blocks until the writer - * generates some data. - */ -class pistream : public std::istream, public boost::noncopyable -{ -public: - /** - * Creates a new process' output stream. - */ - explicit pistream(boost::process::handle h) - : std::istream(0), - handle_(h), - systembuf_(handle_.native()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the handle managed by this stream. - */ - const boost::process::handle &handle() const - { - return handle_; - } - - /** - * Returns the handle managed by this stream. - */ - boost::process::handle &handle() - { - return handle_; - } - - /** - * Closes the handle managed by this stream. - * - * Explicitly closes the handle managed by this stream. This - * function can be used by the user to tell the child process it's - * not willing to receive more data. - */ - void close() - { - handle_.close(); - } - -private: - /** - * The handle managed by this stream. - */ - boost::process::handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/postream.hpp b/vendor/boost/process/include/boost/process/postream.hpp deleted file mode 100644 index 23c34a9..0000000 --- a/vendor/boost/process/include/boost/process/postream.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/postream.hpp - * - * Includes the declaration of the postream class. - */ - -#ifndef BOOST_PROCESS_POSTREAM_HPP -#define BOOST_PROCESS_POSTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' input stream. - * - * The postream class represents an input communication channel with the - * child process. The child process reads data from this stream and the - * parent process can write to it through the postream object. In other - * words, from the child's point of view, the communication channel is an - * input one, but from the parent's point of view it is an output one; - * hence the confusing postream name. - * - * postream objects cannot be copied because they buffer data that flows - * through the communication channel. - * - * A postream object behaves as a std::ostream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that write data to this - * stream can block if the associated handle blocks during - * the write. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child is not processing the data - * in the pipe's system buffer. When this happens, the buffer - * eventually fills up and the system blocks until the reader - * consumes some data, leaving some new room. - */ -class postream : public std::ostream, public boost::noncopyable -{ -public: - /** - * Creates a new process' input stream. - */ - explicit postream(boost::process::handle h) - : std::ostream(0), - handle_(h), - systembuf_(handle_.native()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the handle managed by this stream. - */ - const boost::process::handle &handle() const - { - return handle_; - } - - /** - * Returns the handle managed by this stream. - */ - boost::process::handle &handle() - { - return handle_; - } - - /** - * Closes the handle managed by this stream. - * - * Explicitly closes the handle managed by this stream. This - * function can be used by the user to tell the child process there - * is no more data to send. - */ - void close() - { - systembuf_.sync(); - handle_.close(); - } - -private: - /** - * The handle managed by this stream. - */ - boost::process::handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/process.hpp b/vendor/boost/process/include/boost/process/process.hpp deleted file mode 100644 index 8858954..0000000 --- a/vendor/boost/process/include/boost/process/process.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/process.hpp - * - * Includes the declaration of the process class. - */ - -#ifndef BOOST_PROCESS_PROCESS_HPP -#define BOOST_PROCESS_PROCESS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include - -namespace boost { -namespace process { - -/** - * Process class to represent any running process. - */ -class process -{ -public: - /** - * Constructs a new process object. - * - * Creates a new process object that represents a running process - * within the system. - * - * On Windows the process is opened and a handle saved. This is required - * to avoid the operating system removing process resources when the - * process exits. The handle is closed when the process instance (and all - * of its copies) is destroyed. - */ - process(pid_type id) - : id_(id) -#if defined(BOOST_WINDOWS_API) - , handle_(open_process(id)) -#endif - { - } - -#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Constructs a new process object. - * - * Creates a new process object that represents a running process - * within the system. - * - * This operation is only available on Windows systems. The handle is - * closed when the process instance (and all of its copies) is destroyed. - */ - process(handle h) - : id_(GetProcessId(h.native())), - handle_(h) - { - } -#endif - - /** - * Returns the process identifier. - */ - pid_type get_id() const - { - return id_; - } - - /** - * Terminates the process execution. - * - * Forces the termination of the process execution. Some platforms - * allow processes to ignore some external termination notifications - * or to capture them for a proper exit cleanup. You can set the - * \a force flag to true to force their termination regardless - * of any exit handler. - * - * After this call, accessing this object can be dangerous because the - * process identifier may have been reused by a different process. It - * might still be valid, though, if the process has refused to die. - * - * \throw boost::system::system_error If system calls used to terminate the - * process fail. - */ - void terminate(bool force = false) const - { -#if defined(BOOST_POSIX_API) - if (kill(id_, force ? SIGKILL : SIGTERM) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed"); -#elif defined(BOOST_WINDOWS_API) -#if defined(BOOST_MSVC) - force; -#endif - HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - if (!TerminateProcess(h, EXIT_FAILURE)) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed"); - } - if (!CloseHandle(h)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); -#endif - } - - /** - * Blocks and waits for the process to terminate. - * - * Returns an exit code. The process object ceases to be valid after this - * call. - * - * \remark Blocking remarks: This call blocks if the process has not - * finalized execution and waits until it terminates. - * - * \throw boost::system::system_error If system calls used to wait for the - * process fail. - */ - int wait() const - { -#if defined(BOOST_POSIX_API) - pid_t p; - int status; - do - { - p = waitpid(id_, &status, 0); - } while (p == -1 && errno == EINTR); - if (p == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed"); - return status; -#elif defined(BOOST_WINDOWS_API) - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, - id_); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "WaitForSingleObject() failed"); - } - DWORD exit_code; - if (!GetExitCodeProcess(h, &exit_code)) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetExitCodeProcess() failed"); - } - if (!CloseHandle(h)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); - return exit_code; -#endif - } - -private: - /** - * The process identifier. - */ - pid_type id_; - -#if defined(BOOST_WINDOWS_API) - /** - * Opens a process and returns a handle. - * - * OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure. - * That's why the return value is manually checked in this helper function - * instead of simply passing it to the constructor of the handle class. - */ - HANDLE open_process(pid_type id) - { - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - return h; - } - - /** - * The process handle. - */ - handle handle_; -#endif -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/self.hpp b/vendor/boost/process/include/boost/process/self.hpp deleted file mode 100644 index 704501c..0000000 --- a/vendor/boost/process/include/boost/process/self.hpp +++ /dev/null @@ -1,188 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/self.hpp - * - * Includes the declaration of the self class. - */ - -#ifndef BOOST_PROCESS_SELF_HPP -#define BOOST_PROCESS_SELF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# if defined(__APPLE__) -# include -# endif -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -#if defined(BOOST_POSIX_API) -extern "C" -{ - extern char **environ; -} -#endif - -namespace boost { -namespace process { - -/** - * The self class provides access to the process itself. - */ -class self : public process, public boost::noncopyable -{ -public: - /** - * Returns the self instance representing the caller's process. - */ - static self &get_instance() - { - static self *instance = 0; - if (!instance) - instance = new self; - return *instance; - } - - /** - * Returns the current environment. - * - * Returns the current process environment variables. Modifying the - * returned object has no effect on the current environment. - */ - static environment get_environment() - { - environment e; - -#if defined(BOOST_POSIX_API) -# if defined(__APPLE__) - char **env = *_NSGetEnviron(); -# else - char **env = environ; -# endif - - while (*env) - { - std::string s = *env; - std::string::size_type pos = s.find('='); - e.insert(environment::value_type(s.substr(0, pos), - s.substr(pos + 1))); - ++env; - } -#elif defined(BOOST_WINDOWS_API) -# ifdef GetEnvironmentStrings -# undef GetEnvironmentStrings -# endif - - char *ms_environ = GetEnvironmentStrings(); - if (!ms_environ) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetEnvironmentStrings() failed"); - try - { - char *env = ms_environ; - while (*env) - { - std::string s = env; - std::string::size_type pos = s.find('='); - e.insert(environment::value_type(s.substr(0, pos), - s.substr(pos + 1))); - env += s.size() + 1; - } - } - catch (...) - { - FreeEnvironmentStringsA(ms_environ); - throw; - } - FreeEnvironmentStringsA(ms_environ); -#endif - - return e; - } - - /** - * Returns the current work directory. - */ - static std::string get_work_dir() - { -#if defined(BOOST_POSIX_API) -#if defined(PATH_MAX) - char buffer[PATH_MAX]; - char *cwd = buffer; - long size = PATH_MAX; -#elif defined(_PC_PATH_MAX) - errno = 0; - long size = pathconf("/", _PC_PATH_MAX); - if (size == -1 && errno) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed"); - else if (size == -1) - size = BOOST_PROCESS_POSIX_PATH_MAX; - BOOST_ASSERT(size > 0); - boost::scoped_array buffer(new char[size]); - char *cwd = buffer.get(); -#else - char buffer[BOOST_PROCESS_POSIX_PATH_MAX]; - char *cwd = buffer; - long size = BOOST_PROCESS_POSIX_PATH_MAX; -#endif - if (!getcwd(cwd, size)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed"); - BOOST_ASSERT(cwd[0] != '\0'); - return cwd; -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(MAX_PATH > 0); - char cwd[MAX_PATH]; - if (!GetCurrentDirectoryA(sizeof(cwd), cwd)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetCurrentDirectory() failed"); - BOOST_ASSERT(cwd[0] != '\0'); - return cwd; -#endif - } - -private: - /** - * Constructs a new self object. - * - * Creates a new self object that represents the current process. - */ - self() : -#if defined(BOOST_POSIX_API) - process(getpid()) -#elif defined(BOOST_WINDOWS_API) - process(GetCurrentProcessId()) -#endif - { - } -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/status.hpp b/vendor/boost/process/include/boost/process/status.hpp deleted file mode 100644 index 55b89f3..0000000 --- a/vendor/boost/process/include/boost/process/status.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/status.hpp - * - * Includes the declaration of the status class. - */ - -#ifndef BOOST_PROCESS_STATUS_HPP -#define BOOST_PROCESS_STATUS_HPP - -#include -#include -#include - -namespace boost { -namespace process { - -/** - * The status class to wait for processes to exit. - * - * The status class is a Boost.Asio I/O object and supports synchronous - * and asynchronous wait operations. - */ -typedef detail::basic_status > status; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/stream_behavior.hpp b/vendor/boost/process/include/boost/process/stream_behavior.hpp deleted file mode 100644 index 2911f56..0000000 --- a/vendor/boost/process/include/boost/process/stream_behavior.hpp +++ /dev/null @@ -1,326 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_behavior.hpp - * - * Includes the declaration of stream behavior classes. - */ - -#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP -#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace behavior { - -/** - * Stream behavior to close streams of a child process. - * - * A child process will not be able to use the stream. - */ -class close -{ -public: - stream_ends operator()(stream_type) const - { - return stream_ends(); - } -}; - -/** - * Stream behavior to make a child process inherit streams. - * - * A child process will use the very same stream of its parent process. - */ -class inherit -{ -public: - inherit(handle::native_type h) - : h_(h, handle::dont_close) - { -#if defined(BOOST_WINDOWS_API) - if (h != INVALID_HANDLE_VALUE) - { - if (!SetHandleInformation(h_.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - { - HANDLE proc = GetCurrentProcess(); - HANDLE dup; - if (!DuplicateHandle(proc, h_.native(), proc, &dup, 0, - TRUE, DUPLICATE_SAME_ACCESS)) - { - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "DuplicateHandle() failed"); - } - h_ = dup; - } - } -#endif - } - - stream_ends operator()(stream_type) const - { - return stream_ends(h_, handle()); - } - -private: - handle h_; -}; - -/** - * Stream behavior to redirect streams with a pipe. - * - * A child process will be able to communicate with its parent process. - */ -class pipe -{ -public: -#if defined(BOOST_POSIX_API) - pipe() - : stype_(unknown_stream) - { - } - - pipe(stream_type stype) - : stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { - handle::native_type ends[2]; -#if defined(BOOST_POSIX_API) - if (::pipe(ends) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed"); - if (stype_ != unknown_stream) - stype = stype_; -#elif defined(BOOST_WINDOWS_API) - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = FALSE; - if (!CreatePipe(&ends[0], &ends[1], &sa, 0)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed"); -#endif - handle child_end = ends[stype == input_stream ? 0 : 1]; - handle parent_end = ends[stype == input_stream ? 1 : 0]; -#if defined(BOOST_WINDOWS_API) - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, parent_end); - } - -#if defined(BOOST_POSIX_API) -private: - stream_type stype_; -#endif -}; - -/** - * Stream behavior to redirect streams with a named pipe. - * - * A child process will be able to communicate with its parent process. - */ -class named_pipe -{ -public: - named_pipe(const std::string &name) - : name_(name) -#if defined(BOOST_POSIX_API) - , stype_(unknown_stream) -#endif - { - } - -#if defined(BOOST_POSIX_API) - named_pipe(const std::string &name, stream_type stype) - : name_(name), - stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { -#if defined(BOOST_POSIX_API) - if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed"); - handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); - int opts = fcntl(child_end.native(), F_GETFL); - if (opts == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed"); - opts ^= O_NONBLOCK; - if (fcntl(child_end.native(), F_SETFL, opts) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed"); - handle parent_end = open(name_.c_str(), O_WRONLY); - if (!parent_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); - if (stype_ != unknown_stream) - stype = stype_; -#elif defined(BOOST_WINDOWS_API) - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND | - FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed"); - handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (!parent_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); -#endif - if (stype == output_stream) - std::swap(child_end, parent_end); -#if defined(BOOST_WINDOWS_API) - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, parent_end); - } - -private: - std::string name_; - -#if defined(BOOST_POSIX_API) - stream_type stype_; -#endif -}; - -/** - * Stream behavior to redirect streams with a pipe which supports asynchronous - * I/O. - * - * As platforms require different types of pipes for asynchronous I/O this - * stream behavior is provided for convenience. It uses the minimum required - * pipe type on a platform in order to be able to use asynchronous I/O. - */ -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -typedef pipe async_pipe; -#elif defined(BOOST_WINDOWS_API) -class async_pipe -{ -public: - stream_ends operator()(stream_type stype) const - { - UUID uuid; - RPC_STATUS s = UuidCreateSequential(&uuid); - if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY) - BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed"); - unsigned char *c; - s = UuidToStringA(&uuid, &c); - if (s != RPC_S_OK) - BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed"); - std::string name; - try - { - name = reinterpret_cast(c); - } - catch (...) - { - RpcStringFreeA(&c); - throw; - } - RpcStringFreeA(&c); - named_pipe p("\\\\.\\pipe\\boost_process_" + name); - return p(stype); - } -}; -#endif - -/** - * Stream behavior to mute streams. - * - * A child process will be able to use streams. But data written to an - * output stream is discarded and data read from an input stream is 0. - */ -class null -{ -public: -#if defined(BOOST_POSIX_API) - null() - : stype_(unknown_stream) - { - } - - null(stream_type stype) - : stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { -#if defined(BOOST_POSIX_API) - if (stype_ != unknown_stream) - stype = stype_; - std::string filename = (stype == input_stream) ? "/dev/zero" : - "/dev/null"; - int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY; - handle child_end = open(filename.c_str(), flag); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); -#elif defined(BOOST_WINDOWS_API) - DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE; - handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, handle()); - } - -#if defined(BOOST_POSIX_API) -private: - stream_type stype_; -#endif -}; - -} -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/stream_ends.hpp b/vendor/boost/process/include/boost/process/stream_ends.hpp deleted file mode 100644 index 2ae87a1..0000000 --- a/vendor/boost/process/include/boost/process/stream_ends.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_ends.hpp - * - * Includes the declaration of the stream_ends class. - */ - -#ifndef BOOST_PROCESS_STREAM_ENDS_HPP -#define BOOST_PROCESS_STREAM_ENDS_HPP - -#include -#include - -namespace boost { -namespace process { - -/** - * A pair of handles to configure streams. - * - * Stream behaviors return a pair of handles to specify how a child's stream - * should be configured and possibly the opposite end of a child's end. This - * is the end remaining in the parent process and which can be used for example - * to communicate with a child process through its standard streams. - */ -struct stream_ends { - /** - * The child's end. - */ - handle child; - - /** - * The parent's end. - */ - handle parent; - - /** - * Standard constructor creating two invalid handles. - */ - stream_ends() - { - } - - /** - * Helper constructor to easily initialize handles. - */ - stream_ends(handle c, handle p) - : child(c), - parent(p) - { - } -}; - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/stream_id.hpp b/vendor/boost/process/include/boost/process/stream_id.hpp deleted file mode 100644 index cb098c7..0000000 --- a/vendor/boost/process/include/boost/process/stream_id.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_id.hpp - * - * Includes the declaration of the stream_id type. - */ - -#ifndef BOOST_PROCESS_STREAM_ID_HPP -#define BOOST_PROCESS_STREAM_ID_HPP - -#include - -namespace boost { -namespace process { - -/** - * Standard stream id to refer to standard streams in a cross-platform manner. - */ -enum std_stream_id { stdin_id, stdout_id, stderr_id }; - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * Stream id type. - * - * Depending on the platform the stream id type is defined to refer to standard - * streams only or to support more streams. - */ -typedef NativeStreamId stream_id; -#elif defined(BOOST_POSIX_API) -typedef int stream_id; -#elif defined(BOOST_WINDOWS_API) -typedef std_stream_id stream_id; -#endif - -} -} - -#endif diff --git a/vendor/boost/process/include/boost/process/stream_type.hpp b/vendor/boost/process/include/boost/process/stream_type.hpp deleted file mode 100644 index d78c1f9..0000000 --- a/vendor/boost/process/include/boost/process/stream_type.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_type.hpp - * - * Includes the declaration of the stream_type enumeration. - */ - -#ifndef BOOST_PROCESS_STREAM_TYPE_HPP -#define BOOST_PROCESS_STREAM_TYPE_HPP - -#include - -namespace boost { -namespace process { - -/** - * Stream type to differentiate between input and output streams. - * - * On POSIX systems another value unknown_stream is defined. It is passed - * to stream behaviors for file descriptors greater than 2. - */ -enum stream_type { - input_stream, - output_stream -#if defined(BOOST_POSIX_API) - , unknown_stream -#endif -}; - -} -} - -#endif diff --git a/vendor/libssh2-1.4.2/CMakeLists.txt b/vendor/libssh2-1.4.2/CMakeLists.txt deleted file mode 100644 index cbd38d7..0000000 --- a/vendor/libssh2-1.4.2/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -include_directories(include) -include_directories( ${OPENSSL_INCLUDE_DIR} ) -SET( sources - src/agent.c - src/channel.c - src/comp.c - src/crypt.c - src/global.c - src/hostkey.c - src/keepalive.c - src/kex.c - src/knownhost.c - src/mac.c - src/misc.c - src/openssl.c - src/packet.c - src/publickey.c - src/scp.c - src/session.c - src/sftp.c - src/transport.c - src/userauth.c - src/version.c -) - -SETUP_LIBRARY( ssh2 SOURCES ${sources} LIBRARIES ${libraries} LIBRARY_TYPE STATIC ) diff --git a/vendor/libssh2-1.4.2/include/libssh2.h b/vendor/libssh2-1.4.2/include/libssh2.h deleted file mode 100644 index 6af0028..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2.h +++ /dev/null @@ -1,1188 +0,0 @@ -/* Copyright (c) 2004-2009, Sara Golemon - * Copyright (c) 2009-2012 Daniel Stenberg - * Copyright (c) 2010 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. - */ - -#ifndef LIBSSH2_H -#define LIBSSH2_H 1 - -#define LIBSSH2_COPYRIGHT "2004-2012 The libssh2 project and its contributors." - -/* We use underscore instead of dash when appending DEV 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 course not - have dashes either. */ -#define LIBSSH2_VERSION "1.4.2" - -/* The numeric version number is also available "in parts" by using these - defines: */ -#define LIBSSH2_VERSION_MAJOR 1 -#define LIBSSH2_VERSION_MINOR 4 -#define LIBSSH2_VERSION_PATCH 2 - -/* 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 0x010402 - -/* - * This is the date and time when the full source package was created. The - * timestamp is not stored in the source code repo, 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 May 18 21:30:56 UTC 2012" - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef _WIN32 -# include -# include -#endif - -#include -#include -#include -#include - -/* 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) -# include -#endif - -#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) -# include -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -#endif - -#ifdef _MSC_VER -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 libssh2_uint64_t; -typedef __int64 libssh2_int64_t; -#ifndef ssize_t -typedef SSIZE_T ssize_t; -#endif -#else -typedef unsigned long long libssh2_uint64_t; -typedef long long libssh2_int64_t; -#endif - -#ifdef WIN32 -typedef SOCKET libssh2_socket_t; -#define LIBSSH2_INVALID_SOCKET INVALID_SOCKET -#else /* !WIN32 */ -typedef int libssh2_socket_t; -#define LIBSSH2_INVALID_SOCKET -1 -#endif /* WIN32 */ - -/* 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; - -/* 'publickey' authentication callback */ -#define LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC(name) \ - int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, \ - const unsigned char *data, size_t data_len, void **abstract) - -/* '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) - -/* I/O callbacks */ -#define LIBSSH2_RECV_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - void *buffer, size_t length, \ - int flags, void **abstract) -#define LIBSSH2_SEND_FUNC(name) ssize_t name(libssh2_socket_t socket, \ - const void *buffer, size_t length,\ - int flags, void **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 -#define LIBSSH2_CALLBACK_SEND 5 -#define LIBSSH2_CALLBACK_RECV 6 - -/* 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 - -/* flags */ -#define LIBSSH2_FLAG_SIGPIPE 1 -#define LIBSSH2_FLAG_COMPRESS 2 - -typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; -typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL; -typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER; -typedef struct _LIBSSH2_KNOWNHOSTS LIBSSH2_KNOWNHOSTS; -typedef struct _LIBSSH2_AGENT LIBSSH2_AGENT; - -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 - -/* Hostkey Types */ -#define LIBSSH2_HOSTKEY_TYPE_UNKNOWN 0 -#define LIBSSH2_HOSTKEY_TYPE_RSA 1 -#define LIBSSH2_HOSTKEY_TYPE_DSS 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 - -/* The library once used -1 as a generic error return value on numerous places - through the code, which subsequently was converted to - LIBSSH2_ERROR_SOCKET_NONE uses over time. As this is a generic error code, - the goal is to never ever return this code but instead make sure that a - more accurate and descriptive error code is used. */ -#define LIBSSH2_ERROR_SOCKET_NONE -1 - -#define LIBSSH2_ERROR_BANNER_RECV -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_AUTHENTICATION_FAILED -18 -#define LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_AUTHENTICATION_FAILED -#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 -#define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38 -#define LIBSSH2_ERROR_BAD_USE -39 -#define LIBSSH2_ERROR_COMPRESS -40 -#define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41 -#define LIBSSH2_ERROR_AGENT_PROTOCOL -42 -#define LIBSSH2_ERROR_SOCKET_RECV -43 -#define LIBSSH2_ERROR_ENCRYPT -44 -#define LIBSSH2_ERROR_BAD_SOCKET -45 - -/* this is a define to provide the old (<= 1.2.7) name */ -#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV - -/* Global API */ -#define LIBSSH2_INIT_NO_CRYPTO 0x0001 - -/* - * libssh2_init() - * - * Initialize the libssh2 functions. This typically initialize the - * crypto library. It uses a global state, and is not thread safe -- - * you must make sure this function is not called concurrently. - * - * Flags can be: - * 0: Normal initialize - * LIBSSH2_INIT_NO_CRYPTO: Do not initialize the crypto library (ie. - * OPENSSL_add_cipher_algoritms() for OpenSSL - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int libssh2_init(int flags); - -/* - * libssh2_exit() - * - * Exit the libssh2 functions and free's all memory used internal. - */ -LIBSSH2_API void libssh2_exit(void); - -/* - * libssh2_free() - * - * Deallocate memory allocated by earlier call to libssh2 functions. - */ -LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr); - -/* - * libssh2_session_supported_algs() - * - * Fills algs with a list of supported acryptographic algorithms. Returns a - * non-negative number (number of supported algorithms) on success or a - * negative number (an eror code) on failure. - * - * NOTE: on success, algs must be deallocated (by calling libssh2_free) when - * not needed anymore - */ -LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, - int method_type, - const char*** algs); - -/* 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_session_banner_set(LIBSSH2_SESSION *session, - const char *banner); -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_handshake(LIBSSH2_SESSION *session, - libssh2_socket_t 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 const char *libssh2_session_hostkey(LIBSSH2_SESSION *session, - size_t *len, int *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); -LIBSSH2_API const char *libssh2_session_banner_get(LIBSSH2_SESSION *session); - -/* 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_publickey(LIBSSH2_SESSION *session, - const char *username, - const unsigned char *pubkeydata, - size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void **abstract); - -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 (256*1024) -#define LIBSSH2_CHANNEL_PACKET_DEFAULT 32768 -#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_channel_receive_window_adjust is DEPRECATED, do not use! */ -LIBSSH2_API unsigned long -libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, - unsigned long adjustment, - unsigned char force); - -LIBSSH2_API int -libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, - unsigned long adjustment, - unsigned char force, - unsigned int *storewindow); - -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_session_set_timeout(LIBSSH2_SESSION* session, - long timeout); -LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION* session); - -/* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */ -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_get_exit_signal(LIBSSH2_CHANNEL* channel, - char **exitsignal, - size_t *exitsignal_len, - char **errmsg, - size_t *errmsg_len, - char **langtag, - size_t *langtag_len); -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); -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t 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); - -LIBSSH2_API -const char *libssh2_version(int req_version_num); - -#define HAVE_LIBSSH2_KNOWNHOST_API 0x010101 /* since 1.1.1 */ -#define HAVE_LIBSSH2_VERSION_API 0x010100 /* libssh2_version since 1.1 */ - -struct libssh2_knownhost { - unsigned int magic; /* magic stored by the library */ - void *node; /* handle to the internal representation of this host */ - char *name; /* this is NULL if no plain text host name exists */ - char *key; /* key in base64/printable format */ - int typemask; -}; - -/* - * libssh2_knownhost_init - * - * Init a collection of known hosts. Returns the pointer to a collection. - * - */ -LIBSSH2_API LIBSSH2_KNOWNHOSTS * -libssh2_knownhost_init(LIBSSH2_SESSION *session); - -/* - * libssh2_knownhost_add - * - * Add a host and its associated key to the collection of known hosts. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -/* host format (2 bits) */ -#define LIBSSH2_KNOWNHOST_TYPE_MASK 0xffff -#define LIBSSH2_KNOWNHOST_TYPE_PLAIN 1 -#define LIBSSH2_KNOWNHOST_TYPE_SHA1 2 /* always base64 encoded */ -#define LIBSSH2_KNOWNHOST_TYPE_CUSTOM 3 - -/* key format (2 bits) */ -#define LIBSSH2_KNOWNHOST_KEYENC_MASK (3<<16) -#define LIBSSH2_KNOWNHOST_KEYENC_RAW (1<<16) -#define LIBSSH2_KNOWNHOST_KEYENC_BASE64 (2<<16) - -/* type of key (2 bits) */ -#define LIBSSH2_KNOWNHOST_KEY_MASK (3<<18) -#define LIBSSH2_KNOWNHOST_KEY_SHIFT 18 -#define LIBSSH2_KNOWNHOST_KEY_RSA1 (1<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHRSA (2<<18) -#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18) - -LIBSSH2_API int -libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, - const char *salt, - const char *key, size_t keylen, int typemask, - struct libssh2_knownhost **store); - -/* - * libssh2_knownhost_addc - * - * Add a host and its associated key to the collection of known hosts. - * - * Takes a comment argument that may be NULL. A NULL comment indicates - * there is no comment and the entry will end directly after the key - * when written out to a file. An empty string "" comment will indicate an - * empty comment which will cause a single space to be written after the key. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, - const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, int typemask, - struct libssh2_knownhost **store); - -/* - * libssh2_knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The type is the type/format of the given host name. - * - * plain - ascii "hostname.domain.tld" - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * - * 'knownhost' may be set to NULL if you don't care about that info. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_* values, see below - * - */ - -#define LIBSSH2_KNOWNHOST_CHECK_MATCH 0 -#define LIBSSH2_KNOWNHOST_CHECK_MISMATCH 1 -#define LIBSSH2_KNOWNHOST_CHECK_NOTFOUND 2 -#define LIBSSH2_KNOWNHOST_CHECK_FAILURE 3 - -LIBSSH2_API int -libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **knownhost); - -/* this function is identital to the above one, but also takes a port - argument that allows libssh2 to do a better check */ -LIBSSH2_API int -libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **knownhost); - -/* - * libssh2_knownhost_del - * - * Remove a host from the collection of known hosts. The 'entry' struct is - * retrieved by a call to libssh2_knownhost_check(). - * - */ -LIBSSH2_API int -libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *entry); - -/* - * libssh2_knownhost_free - * - * Free an entire collection of known hosts. - * - */ -LIBSSH2_API void -libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts); - -/* - * libssh2_knownhost_readline() - * - * Pass in a line of a file of 'type'. It makes libssh2 read this line. - * - * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type. - * - */ -LIBSSH2_API int -libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, - const char *line, size_t len, int type); - -/* - * libssh2_knownhost_readfile - * - * Add hosts+key pairs from a given file. - * - * Returns a negative value for error or number of successfully added hosts. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - */ - -#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1 - -LIBSSH2_API int -libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type); - -/* - * libssh2_knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - * - */ -LIBSSH2_API int -libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *known, - char *buffer, size_t buflen, - size_t *outlen, /* the amount of written data */ - int type); - -/* - * libssh2_knownhost_writefile - * - * Write hosts+key pairs to a given file. - * - * This implementation currently only knows one 'type' (openssh), all others - * are reserved for future use. - */ - -LIBSSH2_API int -libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type); - -/* - * libssh2_knownhost_get() - * - * Traverse the internal list of known hosts. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine host was stored in 'store' - * 1 if end of hosts - * [negative] on errors - */ -LIBSSH2_API int -libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost **store, - struct libssh2_knownhost *prev); - -#define HAVE_LIBSSH2_AGENT_API 0x010202 /* since 1.2.2 */ - -struct libssh2_agent_publickey { - unsigned int magic; /* magic stored by the library */ - void *node; /* handle to the internal representation of key */ - unsigned char *blob; /* public key blob */ - size_t blob_len; /* length of the public key blob */ - char *comment; /* comment in printable format */ -}; - -/* - * libssh2_agent_init - * - * Init an ssh-agent handle. Returns the pointer to the handle. - * - */ -LIBSSH2_API LIBSSH2_AGENT * -libssh2_agent_init(LIBSSH2_SESSION *session); - -/* - * libssh2_agent_connect() - * - * Connect to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_connect(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_list_identities() - * - * Request an ssh-agent to list identities. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_list_identities(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_get_identity() - * - * Traverse the internal list of public keys. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine public key was stored in 'store' - * 1 if end of public keys - * [negative] on errors - */ -LIBSSH2_API int -libssh2_agent_get_identity(LIBSSH2_AGENT *agent, - struct libssh2_agent_publickey **store, - struct libssh2_agent_publickey *prev); - -/* - * libssh2_agent_userauth() - * - * Do publickey user authentication with the help of ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_userauth(LIBSSH2_AGENT *agent, - const char *username, - struct libssh2_agent_publickey *identity); - -/* - * libssh2_agent_disconnect() - * - * Close a connection to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_disconnect(LIBSSH2_AGENT *agent); - -/* - * libssh2_agent_free() - * - * Free an ssh-agent handle. This function also frees the internal - * collection of public keys. - */ -LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent); - - -/* - * libssh2_keepalive_config() - * - * Set how often keepalive messages should be sent. WANT_REPLY - * indicates whether the keepalive messages should request a response - * from the server. INTERVAL is number of seconds that can pass - * without any I/O, use 0 (the default) to disable keepalives. To - * avoid some busy-loop corner-cases, if you specify an interval of 1 - * it will be treated as 2. - * - * Note that non-blocking applications are responsible for sending the - * keepalive messages using libssh2_keepalive_send(). - */ -LIBSSH2_API void libssh2_keepalive_config (LIBSSH2_SESSION *session, - int want_reply, - unsigned interval); - -/* - * libssh2_keepalive_send() - * - * Send a keepalive message if needed. SECONDS_TO_NEXT indicates how - * many seconds you can sleep after this call before you need to call - * it again. Returns 0 on success, or LIBSSH2_ERROR_SOCKET_SEND on - * I/O errors. - */ -LIBSSH2_API int libssh2_keepalive_send (LIBSSH2_SESSION *session, - int *seconds_to_next); - -/* 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) -#define LIBSSH2_TRACE_SOCKET (1<<9) - -typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*, - void*, - const char *, - size_t); -LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session, - void* context, - libssh2_trace_handler_func callback); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* !RC_INVOKED */ - -#endif /* LIBSSH2_H */ diff --git a/vendor/libssh2-1.4.2/include/libssh2_publickey.h b/vendor/libssh2-1.4.2/include/libssh2_publickey.h deleted file mode 100644 index 7350e9f..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2_publickey.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2004-2006, Sara Golemon - * 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 - -#include "libssh2.h" - -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 /* ifndef: LIBSSH2_PUBLICKEY_H */ diff --git a/vendor/libssh2-1.4.2/include/libssh2_sftp.h b/vendor/libssh2-1.4.2/include/libssh2_sftp.h deleted file mode 100644 index 74884fb..0000000 --- a/vendor/libssh2-1.4.2/include/libssh2_sftp.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright (c) 2004-2008, Sara Golemon - * 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 - -#include "libssh2.h" - -#ifndef WIN32 -#include -#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 - -typedef struct _LIBSSH2_SFTP LIBSSH2_SFTP; -typedef struct _LIBSSH2_SFTP_HANDLE LIBSSH2_SFTP_HANDLE; -typedef struct _LIBSSH2_SFTP_ATTRIBUTES LIBSSH2_SFTP_ATTRIBUTES; -typedef struct _LIBSSH2_SFTP_STATVFS LIBSSH2_SFTP_STATVFS; - -/* 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 - -/* SFTP statvfs flag bits */ -#define LIBSSH2_SFTP_ST_RDONLY 0x00000001 -#define LIBSSH2_SFTP_ST_NOSUID 0x00000002 - -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; -}; - -struct _LIBSSH2_SFTP_STATVFS { - libssh2_uint64_t f_bsize; /* file system block size */ - libssh2_uint64_t f_frsize; /* fragment size */ - libssh2_uint64_t f_blocks; /* size of fs in f_frsize units */ - libssh2_uint64_t f_bfree; /* # free blocks */ - libssh2_uint64_t f_bavail; /* # free blocks for non-root */ - libssh2_uint64_t f_files; /* # inodes */ - libssh2_uint64_t f_ffree; /* # free inodes */ - libssh2_uint64_t f_favail; /* # free inodes for non-root */ - libssh2_uint64_t f_fsid; /* file system ID */ - libssh2_uint64_t f_flag; /* mount flags */ - libssh2_uint64_t f_namemax; /* maximum filename length */ -}; - -/* 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 */ - -/* macros to check for specific file types, added in 1.2.5 */ -#define LIBSSH2_SFTP_S_ISLNK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFLNK) -#define LIBSSH2_SFTP_S_ISREG(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFREG) -#define LIBSSH2_SFTP_S_ISDIR(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFDIR) -#define LIBSSH2_SFTP_S_ISCHR(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFCHR) -#define LIBSSH2_SFTP_S_ISBLK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFBLK) -#define LIBSSH2_SFTP_S_ISFIFO(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFIFO) -#define LIBSSH2_SFTP_S_ISSOCK(m) \ - (((m) & LIBSSH2_SFTP_S_IFMT) == LIBSSH2_SFTP_S_IFSOCK) - -/* 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); -LIBSSH2_API LIBSSH2_CHANNEL *libssh2_sftp_get_channel(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_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, - LIBSSH2_SFTP_STATVFS *st); - -LIBSSH2_API int libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, - const char *path, - size_t path_len, - LIBSSH2_SFTP_STATVFS *st); - -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 */ diff --git a/vendor/libssh2-1.4.2/src/agent.c b/vendor/libssh2-1.4.2/src/agent.c deleted file mode 100644 index 1c65149..0000000 --- a/vendor/libssh2-1.4.2/src/agent.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * Copyright (c) 2009 by Daiki Ueno - * Copyright (C) 2010 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" -#include "misc.h" -#include -#ifdef HAVE_SYS_UN_H -#include -#else -/* Use the existence of sys/un.h as a test if Unix domain socket is - supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually - support them. */ -#undef PF_UNIX -#endif -#include "userauth.h" -#include "session.h" - -/* Requests from client to agent for protocol 1 key operations */ -#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 -#define SSH_AGENTC_RSA_CHALLENGE 3 -#define SSH_AGENTC_ADD_RSA_IDENTITY 7 -#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 -#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 -#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 - -/* Requests from client to agent for protocol 2 key operations */ -#define SSH2_AGENTC_REQUEST_IDENTITIES 11 -#define SSH2_AGENTC_SIGN_REQUEST 13 -#define SSH2_AGENTC_ADD_IDENTITY 17 -#define SSH2_AGENTC_REMOVE_IDENTITY 18 -#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 -#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - -/* Key-type independent requests from client to agent */ -#define SSH_AGENTC_ADD_SMARTCARD_KEY 20 -#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 -#define SSH_AGENTC_LOCK 22 -#define SSH_AGENTC_UNLOCK 23 -#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 - -/* Generic replies from agent to client */ -#define SSH_AGENT_FAILURE 5 -#define SSH_AGENT_SUCCESS 6 - -/* Replies from agent to client for protocol 1 key operations */ -#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 -#define SSH_AGENT_RSA_RESPONSE 4 - -/* Replies from agent to client for protocol 2 key operations */ -#define SSH2_AGENT_IDENTITIES_ANSWER 12 -#define SSH2_AGENT_SIGN_RESPONSE 14 - -/* Key constraint identifiers */ -#define SSH_AGENT_CONSTRAIN_LIFETIME 1 -#define SSH_AGENT_CONSTRAIN_CONFIRM 2 - -/* non-blocking mode on agent connection is not yet implemented, but - for future use. */ -typedef enum { - agent_NB_state_init = 0, - agent_NB_state_request_created, - agent_NB_state_request_length_sent, - agent_NB_state_request_sent, - agent_NB_state_response_length_received, - agent_NB_state_response_received -} agent_nonblocking_states; - -typedef struct agent_transaction_ctx { - unsigned char *request; - size_t request_len; - unsigned char *response; - size_t response_len; - agent_nonblocking_states state; -} *agent_transaction_ctx_t; - -typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent); -typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent, - agent_transaction_ctx_t transctx); -typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent); - -struct agent_publickey { - struct list_node node; - - /* this is the struct we expose externally */ - struct libssh2_agent_publickey external; -}; - -struct agent_ops { - agent_connect_func connect; - agent_transact_func transact; - agent_disconnect_func disconnect; -}; - -struct _LIBSSH2_AGENT -{ - LIBSSH2_SESSION *session; /* the session this "belongs to" */ - - libssh2_socket_t fd; - - struct agent_ops *ops; - - struct agent_transaction_ctx transctx; - struct agent_publickey *identity; - struct list_head head; /* list of public keys */ -}; - -#ifdef PF_UNIX -static int -agent_connect_unix(LIBSSH2_AGENT *agent) -{ - const char *path; - struct sockaddr_un s_un; - - path = getenv("SSH_AUTH_SOCK"); - if (!path) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "no auth sock variable"); - - agent->fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (agent->fd < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET, - "failed creating socket"); - - s_un.sun_family = AF_UNIX; - strncpy (s_un.sun_path, path, sizeof s_un.sun_path); - if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { - close (agent->fd); - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed connecting with agent"); - } - - return LIBSSH2_ERROR_NONE; -} - -static int -agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) -{ - unsigned char buf[4]; - int rc; - - /* Send the length of the request */ - if (transctx->state == agent_NB_state_request_created) { - _libssh2_htonu32(buf, transctx->request_len); - rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent send failed"); - transctx->state = agent_NB_state_request_length_sent; - } - - /* Send the request body */ - if (transctx->state == agent_NB_state_request_length_sent) { - rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request, - transctx->request_len, 0); - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent send failed"); - transctx->state = agent_NB_state_request_sent; - } - - /* Receive the length of a response */ - if (transctx->state == agent_NB_state_request_sent) { - rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc < 0) { - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV, - "agent recv failed"); - } - transctx->response_len = _libssh2_ntohu32(buf); - transctx->response = LIBSSH2_ALLOC(agent->session, - transctx->response_len); - if (!transctx->response) - return LIBSSH2_ERROR_ALLOC; - - transctx->state = agent_NB_state_response_length_received; - } - - /* Receive the response body */ - if (transctx->state == agent_NB_state_response_length_received) { - rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response, - transctx->response_len, 0); - if (rc < 0) { - if (rc == -EAGAIN) - return LIBSSH2_ERROR_EAGAIN; - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, - "agent recv failed"); - } - transctx->state = agent_NB_state_response_received; - } - - return 0; -} - -static int -agent_disconnect_unix(LIBSSH2_AGENT *agent) -{ - int ret; - ret = close(agent->fd); - - if(ret == -1) - return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT, - "failed closing the agent socket"); - return LIBSSH2_ERROR_NONE; -} - -struct agent_ops agent_ops_unix = { - agent_connect_unix, - agent_transact_unix, - agent_disconnect_unix -}; -#endif /* PF_UNIX */ - -#ifdef WIN32 -/* Code to talk to Pageant was taken from PuTTY. - * - * Portions copyright Robert de Bath, Joris van Rantwijk, Delian - * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas - * Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, - * Markus Kuhn, Colin Watson, and CORE SDI S.A. - */ -#define PAGEANT_COPYDATA_ID 0x804e50ba /* random goop */ -#define PAGEANT_MAX_MSGLEN 8192 - -static int -agent_connect_pageant(LIBSSH2_AGENT *agent) -{ - HWND hwnd; - hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed connecting agent"); - agent->fd = 0; /* Mark as the connection has been established */ - return LIBSSH2_ERROR_NONE; -} - -static int -agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) -{ - HWND hwnd; - char mapname[23]; - HANDLE filemap; - unsigned char *p; - unsigned char *p2; - int id; - COPYDATASTRUCT cds; - - if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) - return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL, - "illegal input"); - - hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "found no pageant"); - - sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId()); - filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, PAGEANT_MAX_MSGLEN, mapname); - - if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "failed setting up pageant filemap"); - - p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); - _libssh2_store_str(&p2, (const char *)transctx->request, - transctx->request_len); - - cds.dwData = PAGEANT_COPYDATA_ID; - cds.cbData = 1 + strlen(mapname); - cds.lpData = mapname; - - id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); - if (id > 0) { - transctx->response_len = _libssh2_ntohu32(p); - if (transctx->response_len > PAGEANT_MAX_MSGLEN) { - UnmapViewOfFile(p); - CloseHandle(filemap); - return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, - "agent setup fail"); - } - transctx->response = LIBSSH2_ALLOC(agent->session, - transctx->response_len); - if (!transctx->response) { - UnmapViewOfFile(p); - CloseHandle(filemap); - return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC, - "agent malloc"); - } - memcpy(transctx->response, p + 4, transctx->response_len); - } - - UnmapViewOfFile(p); - CloseHandle(filemap); - return 0; -} - -static int -agent_disconnect_pageant(LIBSSH2_AGENT *agent) -{ - agent->fd = LIBSSH2_INVALID_SOCKET; - return 0; -} - -struct agent_ops agent_ops_pageant = { - agent_connect_pageant, - agent_transact_pageant, - agent_disconnect_pageant -}; -#endif /* WIN32 */ - -static struct { - const char *name; - struct agent_ops *ops; -} supported_backends[] = { -#ifdef WIN32 - {"Pageant", &agent_ops_pageant}, -#endif /* WIN32 */ -#ifdef PF_UNIX - {"Unix", &agent_ops_unix}, -#endif /* PF_UNIX */ - {NULL, NULL} -}; - -static int -agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, - const unsigned char *data, size_t data_len, void **abstract) -{ - LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *) (*abstract); - agent_transaction_ctx_t transctx = &agent->transctx; - struct agent_publickey *identity = agent->identity; - ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4; - ssize_t method_len; - unsigned char *s; - int rc; - - /* Create a request to sign the data */ - if (transctx->state == agent_NB_state_init) { - s = transctx->request = LIBSSH2_ALLOC(session, len); - if (!transctx->request) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "out of memory"); - - *s++ = SSH2_AGENTC_SIGN_REQUEST; - /* key blob */ - _libssh2_store_str(&s, (const char *)identity->external.blob, - identity->external.blob_len); - /* data */ - _libssh2_store_str(&s, (const char *)data, data_len); - - /* flags */ - _libssh2_store_u32(&s, 0); - - transctx->request_len = s - transctx->request; - transctx->state = agent_NB_state_request_created; - } - - /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "illegal request"); - - if (!agent->ops) - /* if no agent has been connected, bail out */ - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "agent not connected"); - - rc = agent->ops->transact(agent, transctx); - if (rc) { - goto error; - } - LIBSSH2_FREE(session, transctx->request); - transctx->request = NULL; - - len = transctx->response_len; - s = transctx->response; - len--; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - if (*s != SSH2_AGENT_SIGN_RESPONSE) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s++; - - /* Skip the entire length of the signature */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s += 4; - - /* Skip signing method */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - method_len = _libssh2_ntohu32(s); - s += 4; - len -= method_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s += method_len; - - /* Read the signature */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - *sig_len = _libssh2_ntohu32(s); - s += 4; - len -= *sig_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - - *sig = LIBSSH2_ALLOC(session, *sig_len); - if (!*sig) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - memcpy(*sig, s, *sig_len); - - error: - LIBSSH2_FREE(session, transctx->request); - transctx->request = NULL; - - LIBSSH2_FREE(session, transctx->response); - transctx->response = NULL; - - return _libssh2_error(session, rc, "agent sign failure"); -} - -static int -agent_list_identities(LIBSSH2_AGENT *agent) -{ - agent_transaction_ctx_t transctx = &agent->transctx; - ssize_t len, num_identities; - unsigned char *s; - int rc; - unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES; - - /* Create a request to list identities */ - if (transctx->state == agent_NB_state_init) { - transctx->request = &c; - transctx->request_len = 1; - transctx->state = agent_NB_state_request_created; - } - - /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "illegal agent request"); - - if (!agent->ops) - /* if no agent has been connected, bail out */ - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "agent not connected"); - - rc = agent->ops->transact(agent, transctx); - if (rc) { - goto error; - } - transctx->request = NULL; - - len = transctx->response_len; - s = transctx->response; - len--; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - if (*s != SSH2_AGENT_IDENTITIES_ANSWER) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - s++; - - /* Read the length of identities */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - num_identities = _libssh2_ntohu32(s); - s += 4; - - while (num_identities--) { - struct agent_publickey *identity; - ssize_t comment_len; - - identity = LIBSSH2_ALLOC(agent->session, sizeof *identity); - if (!identity) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - - /* Read the length of the blob */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.blob_len = _libssh2_ntohu32(s); - s += 4; - - /* Read the blob */ - len -= identity->external.blob_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.blob = LIBSSH2_ALLOC(agent->session, - identity->external.blob_len); - if (!identity->external.blob) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - memcpy(identity->external.blob, s, identity->external.blob_len); - s += identity->external.blob_len; - - /* Read the length of the comment */ - len -= 4; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - comment_len = _libssh2_ntohu32(s); - s += 4; - - /* Read the comment */ - len -= comment_len; - if (len < 0) { - rc = LIBSSH2_ERROR_AGENT_PROTOCOL; - goto error; - } - identity->external.comment = LIBSSH2_ALLOC(agent->session, - comment_len + 1); - if (!identity->external.comment) { - rc = LIBSSH2_ERROR_ALLOC; - goto error; - } - identity->external.comment[comment_len] = '\0'; - memcpy(identity->external.comment, s, comment_len); - s += comment_len; - - _libssh2_list_add(&agent->head, &identity->node); - } - error: - LIBSSH2_FREE(agent->session, transctx->response); - transctx->response = NULL; - - return _libssh2_error(agent->session, rc, - "agent list id failed"); -} - -static void -agent_free_identities(LIBSSH2_AGENT *agent) { - struct agent_publickey *node; - struct agent_publickey *next; - - for (node = _libssh2_list_first(&agent->head); node; node = next) { - next = _libssh2_list_next(&node->node); - LIBSSH2_FREE(agent->session, node->external.blob); - LIBSSH2_FREE(agent->session, node->external.comment); - LIBSSH2_FREE(agent->session, node); - } - _libssh2_list_init(&agent->head); -} - -#define AGENT_PUBLICKEY_MAGIC 0x3bdefed2 -/* - * agent_publickey_to_external() - * - * Copies data from the internal to the external representation struct. - * - */ -static struct libssh2_agent_publickey * -agent_publickey_to_external(struct agent_publickey *node) -{ - struct libssh2_agent_publickey *ext = &node->external; - - ext->magic = AGENT_PUBLICKEY_MAGIC; - ext->node = node; - - return ext; -} - -/* - * libssh2_agent_init - * - * Init an ssh-agent handle. Returns the pointer to the handle. - * - */ -LIBSSH2_API LIBSSH2_AGENT * -libssh2_agent_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_AGENT *agent; - - agent = LIBSSH2_ALLOC(session, sizeof *agent); - if (!agent) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate space for agent connection"); - return NULL; - } - memset(agent, 0, sizeof *agent); - agent->session = session; - _libssh2_list_init(&agent->head); - - return agent; -} - -/* - * libssh2_agent_connect() - * - * Connect to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_connect(LIBSSH2_AGENT *agent) -{ - int i, rc = -1; - for (i = 0; supported_backends[i].name; i++) { - agent->ops = supported_backends[i].ops; - rc = agent->ops->connect(agent); - if (!rc) - return 0; - } - return rc; -} - -/* - * libssh2_agent_list_identities() - * - * Request ssh-agent to list identities. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_list_identities(LIBSSH2_AGENT *agent) -{ - memset(&agent->transctx, 0, sizeof agent->transctx); - /* Abondon the last fetched identities */ - agent_free_identities(agent); - return agent_list_identities(agent); -} - -/* - * libssh2_agent_get_identity() - * - * Traverse the internal list of public keys. Pass NULL to 'prev' to get - * the first one. Or pass a poiner to the previously returned one to get the - * next. - * - * Returns: - * 0 if a fine public key was stored in 'store' - * 1 if end of public keys - * [negative] on errors - */ -LIBSSH2_API int -libssh2_agent_get_identity(LIBSSH2_AGENT *agent, - struct libssh2_agent_publickey **ext, - struct libssh2_agent_publickey *oprev) -{ - struct agent_publickey *node; - if (oprev && oprev->node) { - /* we have a starting point */ - struct agent_publickey *prev = oprev->node; - - /* get the next node in the list */ - node = _libssh2_list_next(&prev->node); - } - else - node = _libssh2_list_first(&agent->head); - - if (!node) - /* no (more) node */ - return 1; - - *ext = agent_publickey_to_external(node); - - return 0; -} - -/* - * libssh2_agent_userauth() - * - * Do publickey user authentication with the help of ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_userauth(LIBSSH2_AGENT *agent, - const char *username, - struct libssh2_agent_publickey *identity) -{ - void *abstract = agent; - int rc; - - if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) { - memset(&agent->transctx, 0, sizeof agent->transctx); - agent->identity = identity->node; - } - - BLOCK_ADJUST(rc, agent->session, - _libssh2_userauth_publickey(agent->session, username, - strlen(username), - identity->blob, - identity->blob_len, - agent_sign, - &abstract)); - return rc; -} - -/* - * libssh2_agent_disconnect() - * - * Close a connection to an ssh-agent. - * - * Returns 0 if succeeded, or a negative value for error. - */ -LIBSSH2_API int -libssh2_agent_disconnect(LIBSSH2_AGENT *agent) -{ - if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) - return agent->ops->disconnect(agent); - return 0; -} - -/* - * libssh2_agent_free() - * - * Free an ssh-agent handle. This function also frees the internal - * collection of public keys. - */ -LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent) { - /* Allow connection freeing when the socket has lost its connection */ - if (agent->fd != LIBSSH2_INVALID_SOCKET) { - libssh2_agent_disconnect(agent); - } - agent_free_identities(agent); - LIBSSH2_FREE(agent->session, agent); -} diff --git a/vendor/libssh2-1.4.2/src/channel.c b/vendor/libssh2-1.4.2/src/channel.c deleted file mode 100644 index 63e5d5b..0000000 --- a/vendor/libssh2-1.4.2/src/channel.c +++ /dev/null @@ -1,2570 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2008-2011 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 -#endif -#include -#ifdef HAVE_INTTYPES_H -#include -#endif -#include - -#include "channel.h" -#include "transport.h" -#include "packet.h" -#include "session.h" - -/* - * _libssh2_channel_nextid - * - * Determine the next channel ID we can use at our end - */ -uint32_t -_libssh2_channel_nextid(LIBSSH2_SESSION * session) -{ - uint32_t id = session->next_channel; - LIBSSH2_CHANNEL *channel; - - channel = _libssh2_list_first(&session->channels); - - while (channel) { - if (channel->local.id > id) { - id = channel->local.id; - } - channel = _libssh2_list_next(&channel->node); - } - - /* 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_TRACE_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, uint32_t channel_id) -{ - LIBSSH2_CHANNEL *channel; - LIBSSH2_LISTENER *l; - - for(channel = _libssh2_list_first(&session->channels); - channel; - channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) - return channel; - } - - /* We didn't find the channel in the session, let's then check its - listeners since each listener may have its own set of pending channels - */ - for(l = _libssh2_list_first(&session->listeners); l; - l = _libssh2_list_next(&l->node)) { - for(channel = _libssh2_list_first(&l->queue); - channel; - channel = _libssh2_list_next(&channel->node)) { - if (channel->local.id == channel_id) - return channel; - } - } - - return NULL; -} - -/* - * _libssh2_channel_open - * - * Establish a generic session channel - */ -LIBSSH2_CHANNEL * -_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, - uint32_t channel_type_len, - uint32_t window_size, - uint32_t packet_size, - const unsigned char *message, - size_t 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 + 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_TRACE_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"); - 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"); - 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; - session->open_channel->session = session; - - _libssh2_list_add(&session->channels, - &session->open_channel->node); - - 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"); - goto channel_error; - } - *(s++) = SSH_MSG_CHANNEL_OPEN; - _libssh2_store_str(&s, channel_type, channel_type_len); - _libssh2_store_u32(&s, session->open_local_channel); - _libssh2_store_u32(&s, window_size); - _libssh2_store_u32(&s, packet_size); - - /* Do not copy the message */ - - session->open_state = libssh2_NB_state_created; - } - - if (session->open_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - session->open_packet, - session->open_packet_len, - message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending channel-open request"); - return NULL; - } - else if (rc) { - _libssh2_error(session, rc, - "Unable to send channel-open request"); - goto channel_error; - } - - session->open_state = libssh2_NB_state_sent; - } - - if (session->open_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(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 == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - 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_TRACE_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"); - } - } - - 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); - - _libssh2_list_remove(&session->open_channel->node); - - /* Clear out packets meant for this channel */ - _libssh2_htonu32(channel_id, session->open_channel->local.id); - while ((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, - &session->open_data, - &session->open_data_len, 1, - channel_id, 4) >= 0) - || - (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, - &session->open_data, - &session->open_data_len, 1, - channel_id, 4) >= 0)) { - LIBSSH2_FREE(session, session->open_data); - session->open_data = NULL; - } - - LIBSSH2_FREE(session, session->open_channel); - session->open_channel = NULL; - } - - session->open_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_channel_open_ex - * - * Establish a generic session channel - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type, - unsigned int type_len, - unsigned int window_size, unsigned int packet_size, - const char *msg, unsigned int msg_len) -{ - LIBSSH2_CHANNEL *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - _libssh2_channel_open(session, type, type_len, - window_size, packet_size, - (unsigned char *)msg, - msg_len)); - return ptr; -} - -/* - * libssh2_channel_direct_tcpip_ex - * - * Tunnel TCP/IP connect through the SSH session to direct host/port - */ -static LIBSSH2_CHANNEL * -channel_direct_tcpip(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_TRACE_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"); - return NULL; - } - _libssh2_store_str(&s, host, session->direct_host_len); - _libssh2_store_u32(&s, port); - _libssh2_store_str(&s, shost, session->direct_shost_len); - _libssh2_store_u32(&s, sport); - } - - channel = - _libssh2_channel_open(session, "direct-tcpip", - sizeof("direct-tcpip") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, - session->direct_message, - session->direct_message_len); - - if (!channel && - libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) { - /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state - to created to avoid re-creating the package on next invoke */ - session->direct_state = libssh2_NB_state_created; - return NULL; - } - /* by default we set (keep?) idle state... */ - session->direct_state = libssh2_NB_state_idle; - - LIBSSH2_FREE(session, session->direct_message); - session->direct_message = NULL; - - return channel; -} - -/* - * 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 *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - channel_direct_tcpip(session, host, port, shost, sport)); - return ptr; -} - -/* - * channel_forward_listen - * - * Bind a port on the remote host and listen for connections - */ -static LIBSSH2_LISTENER * -channel_forward_listen(LIBSSH2_SESSION * session, const char *host, - int port, int *bound_port, int queue_maxsize) -{ - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 }; - int rc; - - if(!host) - host = "0.0.0.0"; - - if (session->fwdLstn_state == libssh2_NB_state_idle) { - session->fwdLstn_host_len = strlen(host); - /* 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_TRACE_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"); - return NULL; - } - - *(s++) = SSH_MSG_GLOBAL_REQUEST; - _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1); - *(s++) = 0x01; /* want_reply */ - - _libssh2_store_str(&s, host, session->fwdLstn_host_len); - _libssh2_store_u32(&s, port); - - session->fwdLstn_state = libssh2_NB_state_created; - } - - if (session->fwdLstn_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - session->fwdLstn_packet, - session->fwdLstn_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending global-request packet for " - "forward listen request"); - return NULL; - } - else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send global-request packet for forward " - "listen request"); - 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) { - unsigned char *data; - size_t data_len; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 0, NULL, 0, - &session->fwdLstn_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown"); - 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"); - else { - memset(listener, 0, sizeof(LIBSSH2_LISTENER)); - 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"); - LIBSSH2_FREE(session, listener); - listener = NULL; - } - else { - listener->session = session; - 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_TRACE_CONN, - "Dynamic tcpip-forward port allocated: %d", - listener->port); - } - else - listener->port = port; - - listener->queue_size = 0; - listener->queue_maxsize = queue_maxsize; - - /* append this to the parent's list of listeners */ - _libssh2_list_add(&session->listeners, &listener->node); - - if (bound_port) { - *bound_port = listener->port; - } - } - } - - LIBSSH2_FREE(session, data); - session->fwdLstn_state = libssh2_NB_state_idle; - return listener; - } - else 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"); - session->fwdLstn_state = libssh2_NB_state_idle; - return NULL; - } - } - - session->fwdLstn_state = libssh2_NB_state_idle; - - return NULL; -} - -/* - * 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) -{ - LIBSSH2_LISTENER *ptr; - - if(!session) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, session, - channel_forward_listen(session, host, port, bound_port, - queue_maxsize)); - return ptr; -} - -/* - * _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, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) -{ - LIBSSH2_SESSION *session = listener->session; - LIBSSH2_CHANNEL *queued; - unsigned char *packet, *s; - size_t host_len = strlen(listener->host); - /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + - port(4) */ - size_t packet_len = - host_len + 14 + sizeof("cancel-tcpip-forward") - 1; - int rc; - - if (listener->chanFwdCncl_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_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"); - return LIBSSH2_ERROR_ALLOC; - } - - *(s++) = SSH_MSG_GLOBAL_REQUEST; - _libssh2_store_str(&s, "cancel-tcpip-forward", - sizeof("cancel-tcpip-forward") - 1); - *(s++) = 0x00; /* want_reply */ - - _libssh2_store_str(&s, listener->host, host_len); - _libssh2_store_u32(&s, listener->port); - - listener->chanFwdCncl_state = libssh2_NB_state_created; - } else { - packet = listener->chanFwdCncl_data; - } - - if (listener->chanFwdCncl_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending forward request"); - listener->chanFwdCncl_data = packet; - return rc; - } - else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send global-request packet for forward " - "listen request"); - LIBSSH2_FREE(session, packet); - listener->chanFwdCncl_state = libssh2_NB_state_idle; - return LIBSSH2_ERROR_SOCKET_SEND; - } - LIBSSH2_FREE(session, packet); - - listener->chanFwdCncl_state = libssh2_NB_state_sent; - } - - queued = _libssh2_list_first(&listener->queue); - while (queued) { - LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node); - - rc = _libssh2_channel_free(queued); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - queued = next; - } - LIBSSH2_FREE(session, listener->host); - - /* remove this entry from the parent's list of listeners */ - _libssh2_list_remove(&listener->node); - - LIBSSH2_FREE(session, listener); - - listener->chanFwdCncl_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * 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, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -LIBSSH2_API int -libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) -{ - int rc; - - if(!listener) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, listener->session, - _libssh2_channel_forward_cancel(listener)); - return rc; -} - -/* - * channel_forward_accept - * - * Accept a connection - */ -static LIBSSH2_CHANNEL * -channel_forward_accept(LIBSSH2_LISTENER *listener) -{ - int rc; - - do { - rc = _libssh2_transport_read(listener->session); - } while (rc > 0); - - if (_libssh2_list_first(&listener->queue)) { - LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue); - - /* detach channel from listener's queue */ - _libssh2_list_remove(&channel->node); - - listener->queue_size--; - - /* add channel to session's channel list */ - _libssh2_list_add(&channel->session->channels, &channel->node); - - return channel; - } - - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for packet"); - } - else - _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, - "Channel not found"); - return NULL; -} - -/* - * libssh2_channel_forward_accept - * - * Accept a connection - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener) -{ - LIBSSH2_CHANNEL *ptr; - - if(!listener) - return NULL; - - BLOCK_ADJUST_ERRNO(ptr, listener->session, - channel_forward_accept(listener)); - return ptr; - -} - -/* - * channel_setenv - * - * Set an environment variable prior to requesting a shell/program/subsystem - */ -static int channel_setenv(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 }; - size_t 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_TRACE_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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memeory " - "for setenv packet"); - } - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, "env", sizeof("env") - 1); - *(s++) = 0x01; - _libssh2_store_str(&s, varname, varname_len); - _libssh2_store_str(&s, value, value_len); - - channel->setenv_state = libssh2_NB_state_created; - } - - if (channel->setenv_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - channel->setenv_packet, - channel->setenv_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending setenv request"); - return rc; - } else if (rc) { - LIBSSH2_FREE(session, channel->setenv_packet); - channel->setenv_packet = NULL; - channel->setenv_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send channel-request packet for " - "setenv request"); - } - 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(session, reply_codes, &data, &data_len, - 1, channel->setenv_local_channel, 4, - &channel-> - setenv_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - if (rc) { - channel->setenv_state = libssh2_NB_state_idle; - return rc; - } - - if (data[0] == SSH_MSG_CHANNEL_SUCCESS) { - LIBSSH2_FREE(session, data); - channel->setenv_state = libssh2_NB_state_idle; - return 0; - } - - LIBSSH2_FREE(session, data); - } - - channel->setenv_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel-setenv"); -} - -/* - * 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) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_setenv(channel, varname, varname_len, - value, value_len)); - return rc; -} - -/* - * channel_request_pty - * Duh... Request a PTY - */ -static int channel_request_pty(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; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - 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) */ - if(term_len + modes_len > 256) { - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "term + mode lengths too large"); - } - - 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_TRACE_CONN, - "Allocating tty on channel %lu/%lu", channel->local.id, - channel->remote.id); - - s = channel->reqPTY_packet; - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, (char *)"pty-req", sizeof("pty-req") - 1); - - *(s++) = 0x01; - - _libssh2_store_str(&s, term, term_len); - _libssh2_store_u32(&s, width); - _libssh2_store_u32(&s, height); - _libssh2_store_u32(&s, width_px); - _libssh2_store_u32(&s, height_px); - _libssh2_store_str(&s, modes, modes_len); - - channel->reqPTY_state = libssh2_NB_state_created; - } - - if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqPTY_packet, - channel->reqPTY_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending pty request"); - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send pty-request packet"); - } - _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); - - channel->reqPTY_state = libssh2_NB_state_sent; - } - - if (channel->reqPTY_state == libssh2_NB_state_sent) { - unsigned char *data; - size_t data_len; - unsigned char code; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->reqPTY_local_channel, 4, - &channel->reqPTY_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Failed to require the PTY package"); - } - - code = data[0]; - - LIBSSH2_FREE(session, data); - channel->reqPTY_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel request-pty"); -} - -/* - * 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) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_request_pty(channel, term, term_len, modes, - modes_len, width, height, - width_px, height_px)); - return rc; -} - -static int -channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, - int height, int width_px, int height_px) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - int rc; - int retcode = LIBSSH2_ERROR_PROTO; - - 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_TRACE_CONN, - "changing tty size on channel %lu/%lu", - channel->local.id, - channel->remote.id); - - s = channel->reqPTY_packet; - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, (char *)"window-change", - sizeof("window-change") - 1); - *(s++) = 0x00; /* Don't reply */ - _libssh2_store_u32(&s, width); - _libssh2_store_u32(&s, height); - _libssh2_store_u32(&s, width_px); - _libssh2_store_u32(&s, height_px); - - channel->reqPTY_state = libssh2_NB_state_created; - } - - if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqPTY_packet, - channel->reqPTY_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending window-change request"); - return rc; - } else if (rc) { - channel->reqPTY_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send window-change packet"); - } - _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); - retcode = LIBSSH2_ERROR_NONE; - } - - channel->reqPTY_state = libssh2_NB_state_idle; - return retcode; -} - -LIBSSH2_API int -libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width, - int height, int width_px, int height_px) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_request_pty_size(channel, width, height, width_px, - height_px)); - return rc; -} - -/* Keep this an even number */ -#define LIBSSH2_X11_RANDOM_COOKIE_LEN 32 - -/* - * channel_x11_req - * Request X11 forwarding - */ -static int -channel_x11_req(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; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - size_t proto_len = - auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1); - size_t 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_TRACE_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 : "", screen_number); - - s = channel->reqX11_packet = - LIBSSH2_ALLOC(session, channel->reqX11_packet_len); - if (!channel->reqX11_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for pty-request"); - } - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1); - - *(s++) = 0x01; /* want_reply */ - *(s++) = single_connection ? 0x01 : 0x00; - - _libssh2_store_str(&s, auth_proto?auth_proto:"MIT-MAGIC-COOKIE-1", - proto_len); - - _libssh2_store_u32(&s, cookie_len); - if (auth_cookie) { - memcpy(s, auth_cookie, cookie_len); - } else { - int i; - /* note: the extra +1 below is necessary since the sprintf() - loop will always write 3 bytes so the last one will write - the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2 - border */ - unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) +1]; - - _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); - for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) { - sprintf((char *)&s[i*2], "%02X", buffer[i]); - } - } - s += cookie_len; - - _libssh2_store_u32(&s, screen_number); - channel->reqX11_state = libssh2_NB_state_created; - } - - if (channel->reqX11_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, channel->reqX11_packet, - channel->reqX11_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending X11-req packet"); - return rc; - } - if (rc) { - LIBSSH2_FREE(session, channel->reqX11_packet); - channel->reqX11_packet = NULL; - channel->reqX11_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send x11-req packet"); - } - 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) { - size_t data_len; - unsigned char *data; - unsigned char code; - - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->reqX11_local_channel, 4, - &channel->reqX11_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->reqX11_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "waiting for x11-req response packet"); - } - - code = data[0]; - LIBSSH2_FREE(session, data); - channel->reqX11_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for channel x11-req"); -} - -/* - * 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) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - channel_x11_req(channel, single_connection, auth_proto, - auth_cookie, screen_number)); - return rc; -} - - -/* - * _libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -int -_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *request, size_t request_len, - const char *message, size_t message_len) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char *s; - static const unsigned char reply_codes[3] = - { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }; - int 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 += + 4; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "starting request(%s) on channel %lu/%lu, message=%s", - request, channel->local.id, channel->remote.id, - message?message:""); - s = channel->process_packet = - LIBSSH2_ALLOC(session, channel->process_packet_len); - if (!channel->process_packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory " - "for channel-process request"); - - *(s++) = SSH_MSG_CHANNEL_REQUEST; - _libssh2_store_u32(&s, channel->remote.id); - _libssh2_store_str(&s, request, request_len); - *(s++) = 0x01; - - if (message) - _libssh2_store_u32(&s, message_len); - - channel->process_state = libssh2_NB_state_created; - } - - if (channel->process_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, - channel->process_packet, - channel->process_packet_len, - (unsigned char *)message, message_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending channel request"); - return rc; - } - else if (rc) { - LIBSSH2_FREE(session, channel->process_packet); - channel->process_packet = NULL; - channel->process_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel request"); - } - 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) { - unsigned char *data; - size_t data_len; - unsigned char code; - rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len, - 1, channel->process_local_channel, 4, - &channel->process_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - channel->process_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Failed waiting for channel success"); - } - - code = data[0]; - LIBSSH2_FREE(session, data); - channel->process_state = libssh2_NB_state_idle; - - if (code == SSH_MSG_CHANNEL_SUCCESS) - return 0; - } - - return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, - "Unable to complete request for " - "channel-process-startup"); -} - -/* - * libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -LIBSSH2_API int -libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *req, unsigned int req_len, - const char *msg, unsigned int msg_len) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_process_startup(channel, req, req_len, - msg, msg_len)); - return rc; -} - - -/* - * libssh2_channel_set_blocking - * - * Set a channel's BEHAVIOR blocking on or off. The socket will remain non- - * blocking. - */ -LIBSSH2_API void -libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking) -{ - if(channel) - (void) _libssh2_session_set_blocking(channel->session, blocking); -} - -/* - * _libssh2_channel_flush - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -int -_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid) -{ - if (channel->flush_state == libssh2_NB_state_idle) { - LIBSSH2_PACKET *packet = - _libssh2_list_first(&channel->session->packets); - channel->flush_refund_bytes = 0; - channel->flush_flush_bytes = 0; - - while (packet) { - LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node); - 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_TRACE_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); - - /* remove this packet from the parent's list */ - _libssh2_list_remove(&packet->node); - 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, - 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - channel->flush_state = libssh2_NB_state_idle; - - return channel->flush_flush_bytes; -} - -/* - * libssh2_channel_flush_ex - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -LIBSSH2_API int -libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_flush(channel, stream)); - return rc; -} - -/* - * libssh2_channel_get_exit_status - * - * Return the channel's program exit status. Note that the actual protocol - * provides the full 32bit this function returns. We cannot abuse it to - * return error values in case of errors so we return a zero if channel is - * NULL. - */ -LIBSSH2_API int -libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel) -{ - if(!channel) - return 0; - - return channel->exit_status; -} - -/* - * libssh2_channel_get_exit_signal - * - * Get exit signal (without leading "SIG"), error message, and language - * tag into newly allocated buffers of indicated length. Caller can - * use NULL pointers to indicate that the value should not be set. The - * *_len variables are set if they are non-NULL even if the - * corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE - * on success, or an API error code. - */ -LIBSSH2_API int -libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, - char **exitsignal, - size_t *exitsignal_len, - char **errmsg, - size_t *errmsg_len, - char **langtag, - size_t *langtag_len) -{ - LIBSSH2_SESSION *session = channel->session; - size_t namelen = 0; - - if (channel) { - if (channel->exit_signal) { - namelen = strlen(channel->exit_signal); - if (exitsignal) { - *exitsignal = LIBSSH2_ALLOC(session, namelen + 1); - if (!*exitsignal) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for signal name"); - } - memcpy(*exitsignal, channel->exit_signal, namelen); - (*exitsignal)[namelen] = '\0'; - } - if (exitsignal_len) - *exitsignal_len = namelen; - } else { - if (exitsignal) - *exitsignal = NULL; - if (exitsignal_len) - *exitsignal_len = 0; - } - - /* TODO: set error message and language tag */ - - if (errmsg) - *errmsg = NULL; - - if (errmsg_len) - *errmsg_len = 0; - - if (langtag) - *langtag = NULL; - - if (langtag_len) - *langtag_len = 0; - } - - return LIBSSH2_ERROR_NONE; -} - -/* - * _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. - * - * Calls _libssh2_error() ! - */ -int -_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, - uint32_t adjustment, - unsigned char force, - unsigned int *store) -{ - int rc; - - if (channel->adjust_state == libssh2_NB_state_idle) { - if (!force - && (adjustment + channel->adjust_queue < - LIBSSH2_CHANNEL_MINADJUST)) { - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Queueing %lu bytes for receive window adjustment " - "for channel %lu/%lu", - adjustment, channel->local.id, channel->remote.id); - channel->adjust_queue += adjustment; - if(store) - *store = channel->remote.window_size; - return 0; - } - - if (!adjustment && !channel->adjust_queue) { - if(store) - *store = channel->remote.window_size; - return 0; - } - - 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_TRACE_CONN, - "Adjusting window %lu bytes for data on " - "channel %lu/%lu", - adjustment, channel->local.id, channel->remote.id); - - channel->adjust_state = libssh2_NB_state_created; - } - - rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(channel->session, rc, - "Would block sending window adjust"); - return rc; - } - else if (rc) { - channel->adjust_queue = adjustment; - return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send transfer-window adjustment " - "packet, deferring"); - } - else { - channel->remote.window_size += adjustment; - } - - channel->adjust_state = libssh2_NB_state_idle; - - if(store) - *store = channel->remote.window_size; - return 0; -} - -/* - * libssh2_channel_receive_window_adjust - * - * DEPRECATED - * - * 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). - * Note that it might return EAGAIN too which is highly stupid. - * - */ -LIBSSH2_API unsigned long -libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, - unsigned long adj, - unsigned char force) -{ - unsigned int window; - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, adj, - force, &window)); - - /* stupid - but this is how it was made to work before and this is just - kept for backwards compatibility */ - return rc?(unsigned long)rc:window; -} - -/* - * libssh2_channel_receive_window_adjust2 - * - * 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. - * - * Stores the new size of the receive window in the data 'window' points to. - * - * Returns the "normal" error code: 0 for success, negative for failure. - */ -LIBSSH2_API int -libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel, - unsigned long adj, - unsigned char force, - unsigned int *window) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, adj, force, - window)); - return rc; -} - -int -_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) -{ - if (channel->extData2_state == libssh2_NB_state_idle) { - _libssh2_debug(channel->session, LIBSSH2_TRACE_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) { - int rc = - _libssh2_channel_flush(channel, - LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); - if(LIBSSH2_ERROR_EAGAIN == rc) - return rc; - } - } - - channel->extData2_state = libssh2_NB_state_idle; - return 0; -} - -/* - * libssh2_channel_handle_extended_data2() - * - */ -LIBSSH2_API int -libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, - int mode) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel, - mode)); - return rc; -} - -/* - * libssh2_channel_handle_extended_data - * - * DEPRECATED DO NOTE USE! - * - * 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) -{ - (void)libssh2_channel_handle_extended_data2(channel, ignore_mode); -} - - - -/* - * _libssh2_channel_read - * - * Read data from a channel - * - * 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 LIBSSH2_ERROR_EAGAIN. - * - * The receive window must be maintained (enlarged) by the user of this - * function. - */ -ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, - char *buf, size_t buflen) -{ - LIBSSH2_SESSION *session = channel->session; - int rc; - int bytes_read = 0; - int bytes_want; - int unlink_packet; - LIBSSH2_PACKET *read_packet; - LIBSSH2_PACKET *read_next; - - if (channel->read_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "channel_read() wants %d bytes from channel %lu/%lu " - "stream #%d", - (int) buflen, channel->local.id, channel->remote.id, - stream_id); - channel->read_state = libssh2_NB_state_created; - } - - rc = 1; /* set to >0 to let the while loop start */ - - /* Process all pending incoming packets in all states in order to "even - out" the network readings. Tests prove that this way produces faster - transfers. */ - while (rc > 0) - rc = _libssh2_transport_read(session); - - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) - return _libssh2_error(session, rc, "transport read"); - - read_packet = _libssh2_list_first(&session->packets); - while (read_packet && (bytes_read < (int) buflen)) { - /* previously this loop condition also checked for - !channel->remote.close but we cannot let it do this: - - We may have a series of packets to read that are still pending even - if a close has been received. Acknowledging the close too early - makes us flush buffers prematurely and loose data. - */ - - LIBSSH2_PACKET *readpkt = read_packet; - - /* In case packet gets destroyed during this iteration */ - read_next = _libssh2_list_next(&readpkt->node); - - channel->read_local_id = - _libssh2_ntohu32(readpkt->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 - && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) - && (channel->local.id == channel->read_local_id) - && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5))) - || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA) - && (channel->local.id == channel->read_local_id)) - || (!stream_id - && (readpkt->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))) { - - /* figure out much more data we want to read */ - bytes_want = buflen - bytes_read; - unlink_packet = FALSE; - - if (bytes_want >= (int) (readpkt->data_len - readpkt->data_head)) { - /* we want more than this node keeps, so adjust the number and - delete this node after the copy */ - bytes_want = readpkt->data_len - readpkt->data_head; - unlink_packet = TRUE; - } - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "channel_read() got %d of data from %lu/%lu/%d%s", - bytes_want, channel->local.id, - channel->remote.id, stream_id, - unlink_packet?" [ul]":""); - - /* copy data from this struct to the target buffer */ - memcpy(&buf[bytes_read], - &readpkt->data[readpkt->data_head], bytes_want); - - /* advance pointer and counter */ - readpkt->data_head += bytes_want; - bytes_read += bytes_want; - - /* if drained, remove from list */ - if (unlink_packet) { - /* detach readpkt from session->packets list */ - _libssh2_list_remove(&readpkt->node); - - LIBSSH2_FREE(session, readpkt->data); - LIBSSH2_FREE(session, readpkt); - } - } - - /* check the next struct in the chain */ - read_packet = read_next; - } - - if (!bytes_read) { - channel->read_state = libssh2_NB_state_idle; - - /* If the channel is already at EOF or even closed, we need to signal - that back. We may have gotten that info while draining the incoming - transport layer until EAGAIN so we must not be fooled by that - return code. */ - if(channel->remote.eof || channel->remote.close) - return 0; - else if(rc != LIBSSH2_ERROR_EAGAIN) - return 0; - - /* if the transport layer said EAGAIN then we say so as well */ - return _libssh2_error(session, rc, "would block"); - } - else - /* make sure we remain in the created state to focus on emptying the - data we already have in the packet brigade before we try to read - more off the network again */ - channel->read_state = libssh2_NB_state_created; - - return bytes_read; -} - -/* - * 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 - * LIBSSH2_ERROR_EAGAIN. - * - * This function will first make sure there's a receive window enough to - * receive a full buffer's wort of contents. An application may choose to - * adjust the receive window more to increase transfer performance. - */ -LIBSSH2_API ssize_t -libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, - size_t buflen) -{ - int rc; - unsigned long recv_window; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL); - - if(buflen > recv_window) { - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_receive_window_adjust(channel, buflen, - 1, NULL)); - } - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_read(channel, stream_id, buf, buflen)); - return rc; -} - -/* - * _libssh2_channel_packet_data_len - * - * Return the size of the data block of the current packet, or 0 if there - * isn't a packet. - */ -size_t -_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; - - read_packet = _libssh2_list_first(&session->packets); - if (read_packet == 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 = _libssh2_list_next(&read_packet->node); - } - - return 0; -} - -/* - * _libssh2_channel_write - * - * Send data to a channel. Note that if this returns EAGAIN, the caller must - * call this function again with the SAME input arguments. - * - * Returns: number of bytes sent, or if it returns a negative number, that is - * the error code! - */ -ssize_t -_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const unsigned char *buf, size_t buflen) -{ - int rc = 0; - LIBSSH2_SESSION *session = channel->session; - ssize_t wrote = 0; /* counter for this specific this call */ - - /* In theory we could split larger buffers into several smaller packets - * but it turns out to be really hard and nasty to do while still offering - * the API/prototype. - * - * Instead we only deal with the first 32K in this call and for the parent - * function to call it again with the remainder! 32K is a conservative - * limit based on the text in RFC4253 section 6.1. - */ - if(buflen > 32700) - buflen = 32700; - - if (channel->write_state == libssh2_NB_state_idle) { - unsigned char *s = channel->write_packet; - - _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN, - "Writing %d bytes on channel %lu/%lu, stream #%d", - (int) buflen, channel->local.id, channel->remote.id, - stream_id); - - if (channel->local.close) - return _libssh2_error(channel->session, - LIBSSH2_ERROR_CHANNEL_CLOSED, - "We've already closed this channel"); - else if (channel->local.eof) - return _libssh2_error(channel->session, - LIBSSH2_ERROR_CHANNEL_EOF_SENT, - "EOF has already been received, " - "data might be ignored"); - - /* drain the incoming flow first, mostly to make sure we get all - * pending window adjust packets */ - do - rc = _libssh2_transport_read(session); - while (rc > 0); - - if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) - return rc; - - if(channel->local.window_size <= 0) - /* there's no room for data so we stop */ - return (rc==LIBSSH2_ERROR_EAGAIN?rc:0); - - channel->write_bufwrite = buflen; - - *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA : - SSH_MSG_CHANNEL_DATA; - _libssh2_store_u32(&s, channel->remote.id); - if (stream_id) - _libssh2_store_u32(&s, stream_id); - - /* 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_TRACE_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_TRACE_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; - } - /* store the size here only, the buffer is passed in as-is to - _libssh2_transport_send() */ - _libssh2_store_u32(&s, channel->write_bufwrite); - channel->write_packet_len = s - channel->write_packet; - - _libssh2_debug(session, LIBSSH2_TRACE_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_transport_send(session, channel->write_packet, - channel->write_packet_len, - buf, channel->write_bufwrite); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, rc, - "Unable to send channel data"); - } - else if (rc) { - channel->write_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel data"); - } - /* Shrink local window size */ - channel->local.window_size -= channel->write_bufwrite; - - wrote += channel->write_bufwrite; - - /* Since _libssh2_transport_write() succeeded, we must return - now to allow the caller to provide the next chunk of data. - - We cannot move on to send the next piece of data that may - already have been provided in this same function call, as we - risk getting EAGAIN for that and we can't return information - both about sent data as well as EAGAIN. So, by returning short - now, the caller will call this function again with new data to - send */ - - channel->write_state = libssh2_NB_state_idle; - - return wrote; - } - - return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */ -} - -/* - * 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) -{ - ssize_t rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_write(channel, stream_id, - (unsigned char *)buf, buflen)); - return rc; -} - -/* - * channel_send_eof - * - * Send EOF on channel - */ -static int 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_TRACE_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_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending EOF"); - return rc; - } - else if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send EOF on channel"); - } - channel->local.eof = 1; - - return 0; -} - -/* - * libssh2_channel_send_eof - * - * Send EOF on channel - */ -LIBSSH2_API int -libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel)); - return rc; -} - -/* - * libssh2_channel_eof - * - * Read channel's eof status - */ -LIBSSH2_API int -libssh2_channel_eof(LIBSSH2_CHANNEL * channel) -{ - LIBSSH2_SESSION *session; - LIBSSH2_PACKET *packet; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - session = channel->session; - packet = _libssh2_list_first(&session->packets); - - 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 = _libssh2_list_next(&packet->node); - } - - return channel->remote.eof; -} - -/* - * channel_wait_eof - * - * Awaiting channel EOF - */ -static int 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_TRACE_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_transport_read(session); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if (rc < 0) { - channel->wait_eof_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "_libssh2_transport_read() bailed out!"); - } - } while (1); - - channel->wait_eof_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_channel_wait_eof - * - * Awaiting channel EOF - */ -LIBSSH2_API int -libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel)); - return rc; -} - -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->local.eof) - if ((retcode = channel_send_eof(channel))) - return retcode; - - /* ignore if we have received a remote eof or not, as it is now too - late for us to wait for it. Continue closing! */ - - if (channel->close_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu", - channel->local.id, channel->remote.id); - - 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_transport_send(session, channel->close_packet, 5, - NULL, 0); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, rc, - "Would block sending close-channel"); - return retcode; - } else if (retcode) { - channel->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Unable to send close-channel request"); - } - - 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 */ - - while (!channel->remote.close && !rc && - (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED)) - rc = _libssh2_transport_read(session); - } - - if(rc != LIBSSH2_ERROR_EAGAIN) { - /* set the local close state first when we're perfectly confirmed to not - do any more EAGAINs */ - channel->local.close = 1; - - /* We call the callback last in this function to make it keep the local - data as long as EAGAIN is returned. */ - if (channel->close_cb) { - LIBSSH2_CHANNEL_CLOSE(session, channel); - } - - channel->close_state = libssh2_NB_state_idle; - } - - /* return 0 or an error */ - return rc>=0?0:rc; -} - -/* - * libssh2_channel_close - * - * Close a channel - */ -LIBSSH2_API int -libssh2_channel_close(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) ); - return rc; -} - -/* - * channel_wait_closed - * - * Awaiting channel close after EOF - */ -static int channel_wait_closed(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - int rc; - - if (!libssh2_channel_eof(channel)) { - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "libssh2_channel_wait_closed() invoked when " - "channel is not in EOF state"); - } - - if (channel->wait_closed_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_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. - */ - if (!channel->remote.close) { - do { - rc = _libssh2_transport_read(session); - if (channel->remote.close) - /* it is now closed, move on! */ - break; - } while (rc > 0); - if(rc < 0) - return rc; - } - - channel->wait_closed_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_channel_wait_closed - * - * Awaiting channel close after EOF - */ -LIBSSH2_API int -libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel)); - return rc; -} - -/* - * _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, negative on failure - */ -int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) -{ - LIBSSH2_SESSION *session = channel->session; - unsigned char channel_id[4]; - unsigned char *data; - size_t data_len; - int rc; - - assert(session); - - if (channel->free_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_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)) { - rc = _libssh2_channel_close(channel); - - if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - /* ignore all other errors as they otherwise risk blocking the channel - free from happening */ - } - - channel->free_state = libssh2_NB_state_idle; - - if (channel->exit_signal) { - LIBSSH2_FREE(session, channel->exit_signal); - } - - /* - * 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(session, SSH_MSG_CHANNEL_DATA, &data, - &data_len, 1, channel_id, 4) >= 0) - || - (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data, - &data_len, 1, channel_id, 4) >= 0)) { - LIBSSH2_FREE(session, data); - } - - /* free "channel_type" */ - if (channel->channel_type) { - LIBSSH2_FREE(session, channel->channel_type); - } - - /* Unlink from channel list */ - _libssh2_list_remove(&channel->node); - - /* - * Make sure all memory used in the state variables are free - */ - if (channel->setenv_packet) { - LIBSSH2_FREE(session, channel->setenv_packet); - } - if (channel->reqX11_packet) { - LIBSSH2_FREE(session, channel->reqX11_packet); - } - if (channel->process_packet) { - LIBSSH2_FREE(session, channel->process_packet); - } - - LIBSSH2_FREE(session, channel); - - 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, negative on failure - */ -LIBSSH2_API int -libssh2_channel_free(LIBSSH2_CHANNEL *channel) -{ - int rc; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel)); - return rc; -} -/* - * 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(!channel) - return 0; /* no channel, no window! */ - - if (window_size_initial) { - *window_size_initial = channel->remote.window_size_initial; - } - - if (read_avail) { - size_t bytes_queued = 0; - LIBSSH2_PACKET *packet = - _libssh2_list_first(&channel->session->packets); - - 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 = _libssh2_list_next(&packet->node); - } - - *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(!channel) - return 0; /* no channel, no window! */ - - 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; -} diff --git a/vendor/libssh2-1.4.2/src/channel.h b/vendor/libssh2-1.4.2/src/channel.h deleted file mode 100644 index dc0ee37..0000000 --- a/vendor/libssh2-1.4.2/src/channel.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef __LIBSSH2_CHANNEL_H -#define __LIBSSH2_CHANNEL_H -/* Copyright (c) 2008-2010 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. - */ - -/* - * _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. - * - * Always non-blocking. - */ -int _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, - uint32_t adjustment, - unsigned char force, - unsigned int *store); - -/* - * _libssh2_channel_flush - * - * Flush data from one (or all) stream - * Returns number of bytes flushed, or negative on failure - */ -int _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid); - -/* - * _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, negative on failure - */ -int _libssh2_channel_free(LIBSSH2_CHANNEL *channel); - -int -_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); - -/* - * _libssh2_channel_write - * - * Send data to a channel - */ -ssize_t -_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const unsigned char *buf, size_t buflen); - -/* - * _libssh2_channel_open - * - * Establish a generic session channel - */ -LIBSSH2_CHANNEL * -_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, - uint32_t channel_type_len, - uint32_t window_size, - uint32_t packet_size, - const unsigned char *message, size_t message_len); - - -/* - * _libssh2_channel_process_startup - * - * Primitive for libssh2_channel_(shell|exec|subsystem) - */ -int -_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, - const char *request, size_t request_len, - const char *message, size_t message_len); - -/* - * _libssh2_channel_read - * - * Read data from a channel - * - * 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. - */ -ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, - char *buf, size_t buflen); - -uint32_t _libssh2_channel_nextid(LIBSSH2_SESSION * session); - -LIBSSH2_CHANNEL *_libssh2_channel_locate(LIBSSH2_SESSION * session, - uint32_t channel_id); - -size_t _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, - int stream_id); - -int _libssh2_channel_close(LIBSSH2_CHANNEL * channel); - -/* - * _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, LIBSSH2_ERROR_EAGAIN if would block, -1 on error - */ -int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener); - -#endif /* __LIBSSH2_CHANNEL_H */ - diff --git a/vendor/libssh2-1.4.2/src/comp.c b/vendor/libssh2-1.4.2/src/comp.c deleted file mode 100644 index 0296f62..0000000 --- a/vendor/libssh2-1.4.2/src/comp.c +++ /dev/null @@ -1,390 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010, 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 LIBSSH2_HAVE_ZLIB -# include -#endif - -#include "comp.h" - -/* ******** - * none * - ******** */ - -/* - * comp_method_none_comp - * - * Minimalist compression: Absolutely none - */ -static int -comp_method_none_comp(LIBSSH2_SESSION *session, - unsigned char *dest, - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract) -{ - (void) session; - (void) abstract; - (void) dest; - (void) dest_len; - (void) src; - (void) src_len; - - return 0; -} - -/* - * comp_method_none_decomp - * - * Minimalist decompression: Absolutely none - */ -static int -comp_method_none_decomp(LIBSSH2_SESSION * session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t src_len, void **abstract) -{ - (void) session; - (void) payload_limit; - (void) abstract; - *dest = (unsigned char *) src; - *dest_len = src_len; - return 0; -} - - - -static const LIBSSH2_COMP_METHOD comp_method_none = { - "none", - 0, /* not really compressing */ - NULL, - comp_method_none_comp, - comp_method_none_decomp, - NULL -}; - -#ifdef LIBSSH2_HAVE_ZLIB -/* ******** - * zlib * - ******** */ - -/* Memory management wrappers - * Yes, I realize we're doing a callback to a callback, - * Deal... - */ - -static voidpf -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 -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 -comp_method_zlib_init(LIBSSH2_SESSION * session, int compr, - void **abstract) -{ - z_stream *strm; - int status; - - strm = LIBSSH2_ALLOC(session, sizeof(z_stream)); - if (!strm) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "zlib compression/decompression"); - } - memset(strm, 0, sizeof(z_stream)); - - strm->opaque = (voidpf) session; - strm->zalloc = (alloc_func) comp_method_zlib_alloc; - strm->zfree = (free_func) comp_method_zlib_free; - if (compr) { - /* deflate */ - status = deflateInit(strm, Z_DEFAULT_COMPRESSION); - } else { - /* inflate */ - status = inflateInit(strm); - } - - if (status != Z_OK) { - LIBSSH2_FREE(session, strm); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return LIBSSH2_ERROR_COMPRESS; - } - *abstract = strm; - - return LIBSSH2_ERROR_NONE; -} - -/* - * libssh2_comp_method_zlib_comp - * - * Compresses source to destination. Without allocation. - */ -static int -comp_method_zlib_comp(LIBSSH2_SESSION *session, - unsigned char *dest, - - /* dest_len is a pointer to allow this function to - update it with the final actual size used */ - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract) -{ - z_stream *strm = *abstract; - int out_maxlen = *dest_len; - int status; - - strm->next_in = (unsigned char *) src; - strm->avail_in = src_len; - strm->next_out = dest; - strm->avail_out = out_maxlen; - - status = deflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "compression failure"); - } - - *dest_len = out_maxlen - strm->avail_out; - return 0; -} - -/* - * libssh2_comp_method_zlib_decomp - * - * Decompresses source to destination. Allocates the output memory. - */ -static int -comp_method_zlib_decomp(LIBSSH2_SESSION * session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t 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 = 8 * src_len; - int limiter = 0; - - /* If strm is null, then we have not yet been initialized. */ - if (strm == NULL) - return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS, - "decompression unitilized");; - - /* 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) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate decompression buffer"); - while (strm->avail_in) { - int status; - - status = inflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - LIBSSH2_FREE(session, out); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "decompression failure"); - } - if (strm->avail_in) { - size_t out_ofs = out_maxlen - strm->avail_out; - char *newout; - - out_maxlen += 8 * strm->avail_in; - - if ((out_maxlen > (int) payload_limit) && limiter++) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "Excessive growth in decompression phase"); - } - - newout = LIBSSH2_REALLOC(session, out, out_maxlen); - if (!newout) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to expand decompression buffer"); - } - out = newout; - strm->next_out = (unsigned char *) out + out_ofs; - strm->avail_out += 8 * 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 = 2048; - char *newout; - - if (out_maxlen >= (int) payload_limit) { - LIBSSH2_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "Excessive growth in decompression " - "phase"); - } - - 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_FREE(session, out); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to expand final " - "decompress buffer"); - } - out = newout; - strm->next_out = (unsigned char *) out + out_maxlen - - grow_size; - - status = inflate(strm, Z_PARTIAL_FLUSH); - - if (status != Z_OK) { - LIBSSH2_FREE(session, out); - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "decompression failure"); - } - } - } - - *dest = (unsigned char *) out; - *dest_len = out_maxlen - strm->avail_out; - - return 0; -} - - -/* libssh2_comp_method_zlib_dtor - * All done, no more compression for you - */ -static int -comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract) -{ - z_stream *strm = *abstract; - - if (strm) { - if (compr) - deflateEnd(strm); - else - inflateEnd(strm); - LIBSSH2_FREE(session, strm); - } - - *abstract = NULL; - return 0; -} - -static const LIBSSH2_COMP_METHOD comp_method_zlib = { - "zlib", - 1, /* yes, this compresses */ - comp_method_zlib_init, - comp_method_zlib_comp, - comp_method_zlib_decomp, - comp_method_zlib_dtor, -}; -#endif /* LIBSSH2_HAVE_ZLIB */ - -/* If compression is enabled by the API, then this array is used which then - may allow compression if zlib is available at build time */ -static const LIBSSH2_COMP_METHOD *comp_methods[] = { -#ifdef LIBSSH2_HAVE_ZLIB - &comp_method_zlib, -#endif /* LIBSSH2_HAVE_ZLIB */ - &comp_method_none, - NULL -}; - -/* If compression is disabled by the API, then this array is used */ -static const LIBSSH2_COMP_METHOD *no_comp_methods[] = { - &comp_method_none, - NULL -}; - -const LIBSSH2_COMP_METHOD ** -_libssh2_comp_methods(LIBSSH2_SESSION *session) -{ - if(session->flag.compress) - return comp_methods; - else - return no_comp_methods; -} diff --git a/vendor/libssh2-1.4.2/src/comp.h b/vendor/libssh2-1.4.2/src/comp.h deleted file mode 100644 index 8edc150..0000000 --- a/vendor/libssh2-1.4.2/src/comp.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __LIBSSH2_COMP_H -#define __LIBSSH2_COMP_H - -/* Copyright (C) 2009-2010 by Daniel Stenberg - * - * 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" - -const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session); - -#endif /* __LIBSSH2_COMP_H */ diff --git a/vendor/libssh2-1.4.2/src/crypt.c b/vendor/libssh2-1.4.2/src/crypt.c deleted file mode 100644 index 93d99c4..0000000 --- a/vendor/libssh2-1.4.2/src/crypt.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright (c) 2009, 2010 Simon Josefsson - * Copyright (c) 2004-2007, Sara Golemon - * 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 - -/* crypt_none_crypt - * Minimalist cipher: VERY secure *wink* - */ -static int -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, - crypt_none_crypt, - NULL -}; -#endif /* LIBSSH2_CRYPT_NONE */ - -struct crypt_ctx -{ - int encrypt; - _libssh2_cipher_type(algo); - _libssh2_cipher_ctx h; -}; - -static int -crypt_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 LIBSSH2_ERROR_ALLOC; - - 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 -crypt_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 -crypt_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_CTR -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = { - "aes128-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 16, /* secret length -- 16*8 == 128bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes128ctr -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = { - "aes192-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 24, /* secret length -- 24*8 == 192bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes192ctr -}; - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = { - "aes256-ctr", - 16, /* blocksize */ - 16, /* initial value length */ - 32, /* secret length -- 32*8 == 256bit */ - 0, /* flags */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_aes256ctr -}; -#endif - -#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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_arcfour -}; - -static int -crypt_init_arcfour128(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 rc; - - rc = crypt_init (session, method, iv, free_iv, secret, free_secret, - encrypt, abstract); - if (rc == 0) { - struct crypt_ctx *cctx = *(struct crypt_ctx **) abstract; - unsigned char block[8]; - size_t discard = 1536; - for (; discard; discard -= 8) - _libssh2_cipher_crypt(&cctx->h, cctx->algo, cctx->encrypt, block); - } - - return rc; -} - -static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour128 = { - "arcfour128", - 8, /* blocksize */ - 8, /* initial value length */ - 16, /* secret length */ - 0, /* flags */ - &crypt_init_arcfour128, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_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 */ - &crypt_init, - &crypt_encrypt, - &crypt_dtor, - _libssh2_cipher_3des -}; -#endif - -static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = { -#if LIBSSH2_AES_CTR - &libssh2_crypt_method_aes128_ctr, - &libssh2_crypt_method_aes192_ctr, - &libssh2_crypt_method_aes256_ctr, -#endif /* LIBSSH2_AES */ -#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_arcfour128, - &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; -} diff --git a/vendor/libssh2-1.4.2/src/crypto.h b/vendor/libssh2-1.4.2/src/crypto.h deleted file mode 100644 index 8cf34f5..0000000 --- a/vendor/libssh2-1.4.2/src/crypto.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2010 Daniel Stenberg - * - * 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_CRYPTO_H -#define LIBSSH2_CRYPTO_H - -#ifdef LIBSSH2_LIBGCRYPT -#include "libgcrypt.h" -#else -#include "openssl.h" -#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); -int _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, - 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, - size_t hash_len, - unsigned char **signature, - size_t *signature_len); - -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, - const char *filename, - 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); - -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); - -int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase); - -void _libssh2_init_aes_ctr(void); - -#endif diff --git a/vendor/libssh2-1.4.2/src/global.c b/vendor/libssh2-1.4.2/src/global.c deleted file mode 100644 index dc45e70..0000000 --- a/vendor/libssh2-1.4.2/src/global.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2010 Lars Nordin - * Copyright (C) 2010 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 _libssh2_initialized = 0; -static int _libssh2_init_flags = 0; - -LIBSSH2_API int -libssh2_init(int flags) -{ - if (_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) { - libssh2_crypto_init(); - _libssh2_init_aes_ctr(); - } - - _libssh2_initialized++; - _libssh2_init_flags |= flags; - - return 0; -} - -LIBSSH2_API void -libssh2_exit(void) -{ - if (_libssh2_initialized == 0) - return; - - _libssh2_initialized--; - - if (!(_libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO)) { - libssh2_crypto_exit(); - } - - return; -} - -void -_libssh2_init_if_needed(void) -{ - if (_libssh2_initialized == 0) - (void)libssh2_init (0); -} diff --git a/vendor/libssh2-1.4.2/src/hostkey.c b/vendor/libssh2-1.4.2/src/hostkey.c deleted file mode 100644 index 53f7479..0000000 --- a/vendor/libssh2-1.4.2/src/hostkey.c +++ /dev/null @@ -1,485 +0,0 @@ -/* Copyright (c) 2004-2006, Sara Golemon - * Copyright (c) 2009 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" -#include "misc.h" - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#if LIBSSH2_RSA -/* *********** - * ssh-rsa * - *********** */ - -static int hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION * session, - void **abstract); - -/* - * hostkey_method_ssh_rsa_init - * - * Initialize the server hostkey working area with e/n pair - */ -static int -hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, - const unsigned char *hostkey_data, - size_t 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) { - 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; - - 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; -} - -/* - * hostkey_method_ssh_rsa_initPEM - * - * Load a Private Key from a PEM file - */ -static int -hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session, - const char *privkeyfile, - unsigned const char *passphrase, - void **abstract) -{ - libssh2_rsa_ctx *rsactx; - int ret; - - if (*abstract) { - hostkey_method_ssh_rsa_dtor(session, abstract); - *abstract = NULL; - } - - ret = _libssh2_rsa_new_private(&rsactx, session, privkeyfile, passphrase); - if (ret) { - return -1; - } - - *abstract = rsactx; - - return 0; -} - -/* - * hostkey_method_ssh_rsa_sign - * - * Verify signature created by remote - */ -static int -hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION * session, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, - size_t 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); -} - -/* - * hostkey_method_ssh_rsa_signv - * - * Construct a signature from an array of vectors - */ -static int -hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, - unsigned char **signature, - size_t *signature_len, - int veccount, - const struct iovec datavec[], - void **abstract) -{ - libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); - int ret; - 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; -} - -/* - * hostkey_method_ssh_rsa_dtor - * - * Shutdown the hostkey - */ -static int -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 hostkey_method_ssh_rsa = { - "ssh-rsa", - MD5_DIGEST_LENGTH, - hostkey_method_ssh_rsa_init, - hostkey_method_ssh_rsa_initPEM, - hostkey_method_ssh_rsa_sig_verify, - hostkey_method_ssh_rsa_signv, - NULL, /* encrypt */ - hostkey_method_ssh_rsa_dtor, -}; -#endif /* LIBSSH2_RSA */ - -#if LIBSSH2_DSA -/* *********** - * ssh-dss * - *********** */ - -static int hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION * session, - void **abstract); - -/* - * hostkey_method_ssh_dss_init - * - * Initialize the server hostkey working area with p/q/g/y set - */ -static int -hostkey_method_ssh_dss_init(LIBSSH2_SESSION * session, - const unsigned char *hostkey_data, - size_t 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) { - 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; -} - -/* - * hostkey_method_ssh_dss_initPEM - * - * Load a Private Key from a PEM file - */ -static int -hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session, - const char *privkeyfile, - unsigned const char *passphrase, - void **abstract) -{ - libssh2_dsa_ctx *dsactx; - int ret; - - if (*abstract) { - hostkey_method_ssh_dss_dtor(session, abstract); - *abstract = NULL; - } - - ret = _libssh2_dsa_new_private(&dsactx, session, privkeyfile, passphrase); - if (ret) { - return -1; - } - - *abstract = dsactx; - - return 0; -} - -/* - * libssh2_hostkey_method_ssh_dss_sign - * - * Verify signature created by remote - */ -static int -hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION * session, - const unsigned char *sig, - size_t sig_len, - const unsigned char *m, - size_t 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) { - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Invalid DSS signature length"); - } - return _libssh2_dsa_sha1_verify(dsactx, sig, m, m_len); -} - -/* - * hostkey_method_ssh_dss_signv - * - * Construct a signature from an array of vectors - */ -static int -hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session, - unsigned char **signature, - size_t *signature_len, - int 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; - 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 -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 hostkey_method_ssh_dss = { - "ssh-dss", - MD5_DIGEST_LENGTH, - hostkey_method_ssh_dss_init, - hostkey_method_ssh_dss_initPEM, - hostkey_method_ssh_dss_sig_verify, - hostkey_method_ssh_dss_signv, - NULL, /* encrypt */ - hostkey_method_ssh_dss_dtor, -}; -#endif /* LIBSSH2_DSA */ - -static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { -#if LIBSSH2_RSA - &hostkey_method_ssh_rsa, -#endif /* LIBSSH2_RSA */ -#if LIBSSH2_DSA - &hostkey_method_ssh_dss, -#endif /* LIBSSH2_DSA */ - NULL -}; - -const LIBSSH2_HOSTKEY_METHOD ** -libssh2_hostkey_methods(void) -{ - return 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; - } -} - -static int hostkey_type(const unsigned char *hostkey, size_t len) -{ - const unsigned char rsa[] = { - 0, 0, 0, 0x07, 's', 's', 'h', '-', 'r', 's', 'a' - }; - const unsigned char dss[] = { - 0, 0, 0, 0x07, 's', 's', 'h', '-', 'd', 's', 's' - }; - - if (len < 11) - return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; - - if (!memcmp(rsa, hostkey, 11)) - return LIBSSH2_HOSTKEY_TYPE_RSA; - - if (!memcmp(dss, hostkey, 11)) - return LIBSSH2_HOSTKEY_TYPE_DSS; - - return LIBSSH2_HOSTKEY_TYPE_UNKNOWN; -} - -/* - * libssh2_session_hostkey() - * - * Returns the server key and length. - * - */ -LIBSSH2_API const char * -libssh2_session_hostkey(LIBSSH2_SESSION *session, size_t *len, int *type) -{ - if(session->server_hostkey_len) { - if(len) - *len = session->server_hostkey_len; - if (type) - *type = hostkey_type(session->server_hostkey, - session->server_hostkey_len); - return (char *) session->server_hostkey; - } - if(len) - *len = 0; - return NULL; -} - diff --git a/vendor/libssh2-1.4.2/src/keepalive.c b/vendor/libssh2-1.4.2/src/keepalive.c deleted file mode 100644 index 260206a..0000000 --- a/vendor/libssh2-1.4.2/src/keepalive.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2010 Simon Josefsson - * 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 "libssh2_priv.h" -#include "transport.h" /* _libssh2_transport_write */ - -/* Keep-alive stuff. */ - -LIBSSH2_API void -libssh2_keepalive_config (LIBSSH2_SESSION *session, - int want_reply, - unsigned interval) -{ - if (interval == 1) - session->keepalive_interval = 2; - else - session->keepalive_interval = interval; - session->keepalive_want_reply = want_reply ? 1 : 0; -} - -LIBSSH2_API int -libssh2_keepalive_send (LIBSSH2_SESSION *session, - int *seconds_to_next) -{ - time_t now; - - if (!session->keepalive_interval) { - if (seconds_to_next) - *seconds_to_next = 0; - return 0; - } - - now = time (NULL); - - if (session->keepalive_last_sent + session->keepalive_interval <= now) { - /* Format is - "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */ - unsigned char keepalive_data[] - = "\x50\x00\x00\x00\x15keepalive@libssh2.orgW"; - size_t len = sizeof (keepalive_data) - 1; - int rc; - - keepalive_data[len - 1] = session->keepalive_want_reply; - - rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0); - /* Silently ignore PACKET_EAGAIN here: if the write buffer is - already full, sending another keepalive is not useful. */ - if (rc && rc != LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send keepalive message"); - return rc; - } - - session->keepalive_last_sent = now; - if (seconds_to_next) - *seconds_to_next = session->keepalive_interval; - } else if (seconds_to_next) { - *seconds_to_next = (int) session->keepalive_last_sent - + session->keepalive_interval - now; - } - - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/kex.c b/vendor/libssh2-1.4.2/src/kex.c deleted file mode 100644 index 0a72cb7..0000000 --- a/vendor/libssh2-1.4.2/src/kex.c +++ /dev/null @@ -1,2008 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010, 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" - -#include "transport.h" -#include "comp.h" -#include "mac.h" - -/* TODO: Switch this to an inline and handle alloc() failures */ -/* Helper macro called from 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; \ - } \ - } - -/* - * diffie_hellman_sha1 - * - * Diffie Hellman Key Exchange, Group Agnostic - */ -static int diffie_hellman_sha1(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) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory error"); - 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_TRACE_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_transport_send(session, exchange_state->e_packet, - exchange_state->e_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Unable to send KEX init message"); - 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_TRACE_KEX, - "Waiting for badly guessed KEX packet (to be ignored)"); - burn_type = - _libssh2_packet_burn(session, &exchange_state->burn_state); - if (burn_type == LIBSSH2_ERROR_EAGAIN) { - return burn_type; - } else if (burn_type <= 0) { - /* Failed to receive a packet */ - ret = burn_type; - goto clean_exit; - } - session->burn_optimistic_kexinit = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_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(session, packet_type_reply, - &exchange_state->s_packet, - &exchange_state->s_packet_len, 0, NULL, - 0, &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - if (rc) { - ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, - "Timed out waiting for KEX reply"); - 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) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); - 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_TRACE_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_TRACE_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)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, - "Unable to initialize hostkey importer"); - 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) { - ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for K"); - 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)) { - ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN, - "Unable to verify hostkey signature"); - goto clean_exit; - } - - _libssh2_debug(session, LIBSSH2_TRACE_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_transport_send(session, &exchange_state->c, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Unable to send NEWKEYS message"); - goto clean_exit; - } - - exchange_state->state = libssh2_NB_state_sent3; - } - - if (exchange_state->state == libssh2_NB_state_sent3) { - rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS, - &exchange_state->tmp, - &exchange_state->tmp_len, 0, NULL, 0, - &exchange_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, "Timed out waiting for NEWKEYS"); - 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_TRACE_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 = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate buffer for SHA digest"); - 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_TRACE_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 = LIBSSH2_ERROR_KEX_FAILURE; - 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 = LIBSSH2_ERROR_KEX_FAILURE; - 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_TRACE_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 = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, - session->remote.crypt-> - secret_len, "D"); - if (!secret) { - LIBSSH2_FREE(session, iv); - ret = LIBSSH2_ERROR_KEX_FAILURE; - 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 = LIBSSH2_ERROR_KEX_FAILURE; - 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_TRACE_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 = LIBSSH2_ERROR_KEX_FAILURE; - 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_TRACE_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 = LIBSSH2_ERROR_KEX_FAILURE; - 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_TRACE_KEX, - "Server to Client HMAC Key calculated"); - - /* Initialize compression for each direction */ - - /* Cleanup any existing compression */ - if (session->local.comp && session->local.comp->dtor) { - session->local.comp->dtor(session, 1, - &session->local.comp_abstract); - } - - if (session->local.comp && session->local.comp->init) { - if (session->local.comp->init(session, 1, - &session->local.comp_abstract)) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Client to Server compression initialized"); - - if (session->remote.comp && session->remote.comp->dtor) { - session->remote.comp->dtor(session, 0, - &session->remote.comp_abstract); - } - - if (session->remote.comp && session->remote.comp->init) { - if (session->remote.comp->init(session, 0, - &session->remote.comp_abstract)) { - ret = LIBSSH2_ERROR_KEX_FAILURE; - goto clean_exit; - } - } - _libssh2_debug(session, LIBSSH2_TRACE_KEX, - "Server to Client compression initialized"); - - } - - 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; - } - - exchange_state->state = libssh2_NB_state_idle; - - return ret; -} - - - -/* kex_method_diffie_hellman_group1_sha1_key_exchange - * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1 - */ -static int -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_TRACE_KEX, - "Initiating Diffie-Hellman Group1 Key Exchange"); - - key_state->state = libssh2_NB_state_created; - } - ret = diffie_hellman_sha1(session, key_state->g, key_state->p, 128, - SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, - NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - _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; -} - - - -/* kex_method_diffie_hellman_group14_sha1_key_exchange - * Diffie-Hellman Group14 Key Exchange using SHA1 - */ -static int -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_TRACE_KEX, - "Initiating Diffie-Hellman Group14 Key Exchange"); - - key_state->state = libssh2_NB_state_created; - } - ret = diffie_hellman_sha1(session, key_state->g, key_state->p, - 256, SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY, - NULL, 0, &key_state->exchange_state); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - 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; -} - - - -/* 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 -kex_method_diffie_hellman_group_exchange_sha1_key_exchange -(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state) -{ - 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_TRACE_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_TRACE_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_transport_send(session, key_state->request, - key_state->request_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Unable to send Group Exchange Request"); - goto dh_gex_clean_exit; - } - - key_state->state = libssh2_NB_state_sent; - } - - if (key_state->state == libssh2_NB_state_sent) { - rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP, - &key_state->data, &key_state->data_len, - 0, NULL, 0, &key_state->req_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - ret = _libssh2_error(session, rc, - "Timeout waiting for GEX_GROUP reply"); - goto dh_gex_clean_exit; - } - - key_state->state = libssh2_NB_state_sent1; - } - - if (key_state->state == libssh2_NB_state_sent1) { - unsigned char *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); - - ret = diffie_hellman_sha1(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 == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - - 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 kex_method_diffie_helman_group1_sha1 = { - "diffie-hellman-group1-sha1", - kex_method_diffie_hellman_group1_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = { - "diffie-hellman-group14-sha1", - kex_method_diffie_hellman_group14_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD -kex_method_diffie_helman_group_exchange_sha1 = { - "diffie-hellman-group-exchange-sha1", - kex_method_diffie_hellman_group_exchange_sha1_key_exchange, - LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY, -}; - -static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { - &kex_method_diffie_helman_group14_sha1, - &kex_method_diffie_helman_group_exchange_sha1, - &kex_method_diffie_helman_group1_sha1, - NULL -}; - -typedef struct _LIBSSH2_COMMON_METHOD -{ - const char *name; -} LIBSSH2_COMMON_METHOD; - -/* 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 -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; -} - - - -/* kex_method_list - * Generate formatted preference list in buf - */ -static size_t -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) : \ - 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 += kex_method_list((buf), (prefvarlen), \ - (LIBSSH2_COMMON_METHOD**)(defaultvar)); \ - } - -/* kexinit - * Send SSH_MSG_KEXINIT packet - */ -static int 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(session)); - comp_sc_len = - LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs, - _libssh2_comp_methods(session)); - 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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory"); - } - - *(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(session)); - LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs, - _libssh2_comp_methods(session)); - 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 */ - _libssh2_htonu32(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_TRACE_KEX, "Sent KEX: %s", p); - p += kex_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent HOSTKEY: %s", p); - p += hostkey_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_CS: %s", p); - p += crypt_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent CRYPT_SC: %s", p); - p += crypt_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_CS: %s", p); - p += mac_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent MAC_SC: %s", p); - p += mac_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_CS: %s", p); - p += comp_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent COMP_SC: %s", p); - p += comp_sc_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Sent LANG_CS: %s", p); - p += lang_cs_len + 4; - _libssh2_debug(session, LIBSSH2_TRACE_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; - /* zap the variables to ensure there is NOT a double free later */ - session->kexinit_data = NULL; - session->kexinit_data_len = 0; - } - - rc = _libssh2_transport_send(session, data, data_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - session->kexinit_data = data; - session->kexinit_data_len = data_len; - return rc; - } - else if (rc) { - LIBSSH2_FREE(session, data); - session->kexinit_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send KEXINIT packet to remote host"); - - } - - 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; -} - -/* kex_agree_instr - * Kex specific variant of strstr() - * Needle must be preceed by BOL or ',', and followed by ',' or EOL - */ -static unsigned char * -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; -} - - - -/* kex_get_method_by_name - */ -static const LIBSSH2_COMMON_METHOD * -kex_get_method_by_name(const char *name, size_t 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; -} - - - -/* kex_agree_hostkey - * Agree on a Hostkey which works with this kex - */ -static int 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, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if (kex_agree_instr(hostkey, hostkey_len, s, method_len)) { - const LIBSSH2_HOSTKEY_METHOD *method = - (const LIBSSH2_HOSTKEY_METHOD *) - kex_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) && (*hostkeyp)->name) { - s = 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; -} - - - -/* kex_agree_kex_hostkey - * Agree on a Key Exchange method and a hostkey encoding type - */ -static int 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, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - if ((q = kex_agree_instr(kex, kex_len, s, method_len))) { - const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *) - kex_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 (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 = 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 (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; -} - - - -/* kex_agree_crypt - * Agree on a cipher algo - */ -static int 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, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(crypt, crypt_len, s, method_len)) { - const LIBSSH2_CRYPT_METHOD *method = - (const LIBSSH2_CRYPT_METHOD *) - kex_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 = kex_agree_instr(crypt, crypt_len, - (unsigned char *) (*cryptp)->name, - strlen((*cryptp)->name)); - if (s) { - endpoint->crypt = *cryptp; - return 0; - } - cryptp++; - } - - return -1; -} - - - -/* kex_agree_mac - * Agree on a message authentication hash - */ -static int 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, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(mac, mac_len, s, method_len)) { - const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *) - kex_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 = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name, - strlen((*macp)->name)); - if (s) { - endpoint->mac = *macp; - return 0; - } - macp++; - } - - return -1; -} - - - -/* kex_agree_comp - * Agree on a compression scheme - */ -static int 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(session); - 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, ','); - size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s)); - - if (kex_agree_instr(comp, comp_len, s, method_len)) { - const LIBSSH2_COMP_METHOD *method = - (const LIBSSH2_COMP_METHOD *) - kex_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 = 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" - */ - -/* kex_agree_methods - * Decide which specific method to use of the methods offered by each party - */ -static int 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; - 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; - 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; -#if 0 - 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; -#endif - /* If the server sent an optimistic packet, assume that it guessed wrong. - * If the guess is determined to be right (by 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 (kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) { - return -1; - } - - if (kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len) - || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) { - return -1; - } - - if (kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) || - kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) { - return -1; - } - - if (kex_agree_comp(session, &session->local, comp_cs, comp_cs_len) || - kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) { - return -1; - } - -#if 0 - 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; - } -#endif - - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on KEX method: %s", - session->kex->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on HOSTKEY method: %s", - session->hostkey->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_CS method: %s", - session->local.crypt->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on CRYPT_SC method: %s", - session->remote.crypt->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_CS method: %s", - session->local.mac->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on MAC_SC method: %s", - session->remote.mac->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_CS method: %s", - session->local.comp->name); - _libssh2_debug(session, LIBSSH2_TRACE_KEX, "Agreed on COMP_SC method: %s", - session->remote.comp->name); - - return 0; -} - - - -/* _libssh2_kex_exchange - * Exchange keys - * Returns 0 on success, non-zero on failure - * - * Returns some errors without _libssh2_error() - */ -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 = kexinit(session); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } 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(session, SSH_MSG_KEXINIT, - &key_state->data, - &key_state->data_len, 0, NULL, 0, - &key_state->req_state); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } - 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 (kex_agree_methods(session, key_state->data, - key_state->data_len)) - rc = LIBSSH2_ERROR_KEX_FAILURE; - - 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 == LIBSSH2_ERROR_EAGAIN) { - session->state &= ~LIBSSH2_STATE_KEX_ACTIVE; - return retcode; - } else if (retcode) { - rc = _libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE, - "Unrecoverable error exchanging keys"); - } - } - } - - /* 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(session); - break; - - case LIBSSH2_METHOD_COMP_SC: - prefvar = &session->remote.comp_prefs; - mlist = (const LIBSSH2_COMMON_METHOD **) - _libssh2_comp_methods(session); - 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: - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "Invalid parameter specified for method_type"); - } - - s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1); - if (!newprefs) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Error allocated space for method preferences"); - } - memcpy(s, prefs, prefs_len + 1); - - while (s && *s) { - char *p = strchr(s, ','); - int method_len = p ? (p - s) : (int) strlen(s); - - if (!kex_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_FREE(session, newprefs); - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "The requested method(s) are not currently " - "supported"); - } - - if (*prefvar) { - LIBSSH2_FREE(session, *prefvar); - } - *prefvar = newprefs; - - return 0; -} - -/* - * libssh2_session_supported_algs() - * returns a number of returned algorithms (a positive number) on success, - * a negative number on failure - */ - -LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, - int method_type, - const char*** algs) -{ - unsigned int i; - unsigned int j; - unsigned int ialg; - const LIBSSH2_COMMON_METHOD **mlist; - - /* to prevent coredumps due to dereferencing of NULL */ - if (NULL == algs) - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "algs must not be NULL"); - - switch (method_type) { - case LIBSSH2_METHOD_KEX: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods; - break; - - case LIBSSH2_METHOD_HOSTKEY: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods(); - break; - - case LIBSSH2_METHOD_CRYPT_CS: - case LIBSSH2_METHOD_CRYPT_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods(); - break; - - case LIBSSH2_METHOD_MAC_CS: - case LIBSSH2_METHOD_MAC_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods(); - break; - - case LIBSSH2_METHOD_COMP_CS: - case LIBSSH2_METHOD_COMP_SC: - mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session); - break; - - default: - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown method type"); - } /* switch */ - - /* weird situation */ - if (NULL==mlist) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "No algorithm found"); - - /* - mlist is looped through twice. The first time to find the number od - supported algorithms (needed to allocate the proper size of array) and - the second time to actually copy the pointers. Typically this function - will not be called often (typically at the beginning of a session) and - the number of algorithms (i.e. niumber of iterations in one loop) will - not be high (typically it will not exceed 20) for quite a long time. - - So double looping really shouldn't be an issue and it is definitely a - better solution than reallocation several times. - */ - - /* count the number of supported algorithms */ - for ( i=0, ialg=0; NULL!=mlist[i]; i++) { - /* do not count fields with NULL name */ - if (mlist[i]->name) - ialg++; - } - - /* weird situation, no algorithm found */ - if (0==ialg) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "No algorithm found"); - - /* allocate buffer */ - *algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*)); - if ( NULL==*algs ) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Memory allocation failed"); - } - /* Past this point *algs must be deallocated in case of an error!! */ - - /* copy non-NULL pointers only */ - for ( i=0, j=0; NULL!=mlist[i] && jname ){ - /* maybe a weird situation but if it occurs, do not include NULL - pointers */ - continue; - } - - /* note that [] has higher priority than * (dereferencing) */ - (*algs)[j++] = mlist[i]->name; - } - - /* correct number of pointers copied? (test the code above) */ - if ( j!=ialg ) { - /* deallocate buffer */ - LIBSSH2_FREE(session, (void *)*algs); - *algs = NULL; - - return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, - "Internal error"); - } - - return ialg; -} diff --git a/vendor/libssh2-1.4.2/src/knownhost.c b/vendor/libssh2-1.4.2/src/knownhost.c deleted file mode 100644 index c58dfbb..0000000 --- a/vendor/libssh2-1.4.2/src/knownhost.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * Copyright (c) 2009-2011 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" -#include "misc.h" - -struct known_host { - struct list_node node; - char *name; /* points to the name or the hash (allocated) */ - size_t name_len; /* needed for hashed data */ - int port; /* if non-zero, a specific port this key is for on this - host */ - int typemask; /* plain, sha1, custom, ... */ - char *salt; /* points to binary salt (allocated) */ - size_t salt_len; /* size of salt */ - char *key; /* the (allocated) associated key. This is kept base64 - encoded in memory. */ - char *comment; /* the (allocated) optional comment text, may be NULL */ - - /* this is the struct we expose externally */ - struct libssh2_knownhost external; -}; - -struct _LIBSSH2_KNOWNHOSTS -{ - LIBSSH2_SESSION *session; /* the session this "belongs to" */ - struct list_head head; -}; - -static void free_host(LIBSSH2_SESSION *session, struct known_host *entry) -{ - if(entry) { - if(entry->comment) - LIBSSH2_FREE(session, entry->comment); - if(entry->key) - LIBSSH2_FREE(session, entry->key); - if(entry->salt) - LIBSSH2_FREE(session, entry->salt); - if(entry->name) - LIBSSH2_FREE(session, entry->name); - LIBSSH2_FREE(session, entry); - } -} - -/* - * libssh2_knownhost_init - * - * Init a collection of known hosts. Returns the pointer to a collection. - * - */ -LIBSSH2_API LIBSSH2_KNOWNHOSTS * -libssh2_knownhost_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_KNOWNHOSTS *knh = - LIBSSH2_ALLOC(session, sizeof(struct _LIBSSH2_KNOWNHOSTS)); - - if(!knh) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for known-hosts " - "collection"); - return NULL; - } - - knh->session = session; - - _libssh2_list_init(&knh->head); - - return knh; -} - -#define KNOWNHOST_MAGIC 0xdeadcafe -/* - * knownhost_to_external() - * - * Copies data from the internal to the external representation struct. - * - */ -static struct libssh2_knownhost *knownhost_to_external(struct known_host *node) -{ - struct libssh2_knownhost *ext = &node->external; - - ext->magic = KNOWNHOST_MAGIC; - ext->node = node; - ext->name = ((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) == - LIBSSH2_KNOWNHOST_TYPE_PLAIN)? node->name:NULL; - ext->key = node->key; - ext->typemask = node->typemask; - - return ext; -} - -static int -knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, - int typemask, struct libssh2_knownhost **store) -{ - struct known_host *entry; - size_t hostlen = strlen(host); - int rc; - char *ptr; - unsigned int ptrlen; - - /* make sure we have a key type set */ - if(!(typemask & LIBSSH2_KNOWNHOST_KEY_MASK)) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "No key type set"); - - if(!(entry = LIBSSH2_ALLOC(hosts->session, sizeof(struct known_host)))) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for known host " - "entry"); - - memset(entry, 0, sizeof(struct known_host)); - - entry->typemask = typemask; - - switch(entry->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { - case LIBSSH2_KNOWNHOST_TYPE_PLAIN: - case LIBSSH2_KNOWNHOST_TYPE_CUSTOM: - entry->name = LIBSSH2_ALLOC(hosts->session, hostlen+1); - if(!entry->name) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for host name"); - goto error; - } - memcpy(entry->name, host, hostlen+1); - break; - case LIBSSH2_KNOWNHOST_TYPE_SHA1: - rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen, - host, hostlen); - if(rc) - goto error; - entry->name = ptr; - entry->name_len = ptrlen; - - rc = libssh2_base64_decode(hosts->session, &ptr, &ptrlen, - salt, strlen(salt)); - if(rc) - goto error; - entry->salt = ptr; - entry->salt_len = ptrlen; - break; - default: - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown host name type"); - goto error; - } - - if(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64) { - /* the provided key is base64 encoded already */ - if(!keylen) - keylen = strlen(key); - entry->key = LIBSSH2_ALLOC(hosts->session, keylen+1); - if(!entry->key) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for key"); - goto error; - } - memcpy(entry->key, key, keylen+1); - entry->key[keylen]=0; /* force a terminating zero trailer */ - } - else { - /* key is raw, we base64 encode it and store it as such */ - size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen, - &ptr); - if(!nlen) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded key"); - goto error; - } - - entry->key = ptr; - } - - if (comment) { - entry->comment = LIBSSH2_ALLOC(hosts->session, commentlen+1); - if(!entry->comment) { - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for comment"); - goto error; - } - memcpy(entry->comment, comment, commentlen+1); - entry->comment[commentlen]=0; /* force a terminating zero trailer */ - } - else { - entry->comment = NULL; - } - - /* add this new host to the big list of known hosts */ - _libssh2_list_add(&hosts->head, &entry->node); - - if(store) - *store = knownhost_to_external(entry); - - return LIBSSH2_ERROR_NONE; - error: - free_host(hosts->session, entry); - return rc; -} - -/* - * libssh2_knownhost_add - * - * Add a host and its associated key to the collection of known hosts. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - int typemask, struct libssh2_knownhost **store) -{ - return knownhost_add(hosts, host, salt, key, keylen, NULL, 0, typemask, - store); -} - - -/* - * libssh2_knownhost_addc - * - * Add a host and its associated key to the collection of known hosts. - * - * Takes a comment argument that may be NULL. A NULL comment indicates - * there is no comment and the entry will end directly after the key - * when written out to a file. An empty string "" comment will indicate an - * empty comment which will cause a single space to be written after the key. - * - * The 'type' argument specifies on what format the given host and keys are: - * - * plain - ascii "hostname.domain.tld" - * sha1 - SHA1( ) base64-encoded! - * custom - another hash - * - * If 'sha1' is selected as type, the salt must be provided to the salt - * argument. This too base64 encoded. - * - * The SHA-1 hash is what OpenSSH can be told to use in known_hosts files. If - * a custom type is used, salt is ignored and you must provide the host - * pre-hashed when checking for it in the libssh2_knownhost_check() function. - * - * The keylen parameter may be omitted (zero) if the key is provided as a - * NULL-terminated base64-encoded string. - */ - -LIBSSH2_API int -libssh2_knownhost_addc(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, const char *salt, - const char *key, size_t keylen, - const char *comment, size_t commentlen, - int typemask, struct libssh2_knownhost **store) -{ - return knownhost_add(hosts, host, salt, key, keylen, comment, commentlen, - typemask, store); -} - -/* - * knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -static int -knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - struct known_host *node; - struct known_host *badkey = NULL; - int type = typemask & LIBSSH2_KNOWNHOST_TYPE_MASK; - char *keyalloc = NULL; - int rc = LIBSSH2_KNOWNHOST_CHECK_NOTFOUND; - char hostbuff[270]; /* most host names can't be longer than like 256 */ - const char *host; - int numcheck; /* number of host combos to check */ - int match = 0; - - if(type == LIBSSH2_KNOWNHOST_TYPE_SHA1) - /* we can't work with a sha1 as given input */ - return LIBSSH2_KNOWNHOST_CHECK_MISMATCH; - - if(!(typemask & LIBSSH2_KNOWNHOST_KEYENC_BASE64)) { - /* we got a raw key input, convert it to base64 for the checks below */ - size_t nlen = _libssh2_base64_encode(hosts->session, key, keylen, - &keyalloc); - if(!nlen) { - _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for base64-encoded " - "key"); - return LIBSSH2_KNOWNHOST_CHECK_FAILURE; - } - - /* make the key point to this */ - key = keyalloc; - } - - /* if a port number is given, check for a '[host]:port' first before the - plain 'host' */ - if(port >= 0) { - snprintf(hostbuff, sizeof(hostbuff), "[%s]:%d", hostp, port); - host = hostbuff; - numcheck = 2; /* check both combos, start with this */ - } - else { - host = hostp; - numcheck = 1; /* only check this host version */ - } - - do { - node = _libssh2_list_first(&hosts->head); - while (node) { - switch(node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) { - case LIBSSH2_KNOWNHOST_TYPE_PLAIN: - if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) - match = !strcmp(host, node->name); - break; - case LIBSSH2_KNOWNHOST_TYPE_CUSTOM: - if(type == LIBSSH2_KNOWNHOST_TYPE_CUSTOM) - match = !strcmp(host, node->name); - break; - case LIBSSH2_KNOWNHOST_TYPE_SHA1: - if(type == LIBSSH2_KNOWNHOST_TYPE_PLAIN) { - /* when we have the sha1 version stored, we can use a - plain input to produce a hash to compare with the - stored hash. - */ - libssh2_hmac_ctx ctx; - unsigned char hash[SHA_DIGEST_LENGTH]; - - if(SHA_DIGEST_LENGTH != node->name_len) { - /* the name hash length must be the sha1 size or - we can't match it */ - break; - } - libssh2_hmac_sha1_init(&ctx, node->salt, node->salt_len); - libssh2_hmac_update(ctx, (unsigned char *)host, - strlen(host)); - libssh2_hmac_final(ctx, hash); - libssh2_hmac_cleanup(&ctx); - - if(!memcmp(hash, node->name, SHA_DIGEST_LENGTH)) - /* this is a node we're interested in */ - match = 1; - } - break; - default: /* unsupported type */ - break; - } - if(match) { - /* host name match, now compare the keys */ - if(!strcmp(key, node->key)) { - /* they match! */ - if (ext) - *ext = knownhost_to_external(node); - badkey = NULL; - rc = LIBSSH2_KNOWNHOST_CHECK_MATCH; - break; - } - else { - /* remember the first node that had a host match but a - failed key match since we continue our search from - here */ - if(!badkey) - badkey = node; - match = 0; /* don't count this as a match anymore */ - } - } - node= _libssh2_list_next(&node->node); - } - host = hostp; - } while(!match && --numcheck); - - if(badkey) { - /* key mismatch */ - if (ext) - *ext = knownhost_to_external(badkey); - rc = LIBSSH2_KNOWNHOST_CHECK_MISMATCH; - } - - if(keyalloc) - LIBSSH2_FREE(hosts->session, keyalloc); - - return rc; -} - -/* - * libssh2_knownhost_check - * - * Check a host and its associated key against the collection of known hosts. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -LIBSSH2_API int -libssh2_knownhost_check(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - return knownhost_check(hosts, hostp, -1, key, keylen, - typemask, ext); -} - -/* - * libssh2_knownhost_checkp - * - * Check a host+port and its associated key against the collection of known - * hosts. - * - * Note that if 'port' is specified as greater than zero, the check function - * will be able to check for a dedicated key for this particular host+port - * combo, and if 'port' is negative it only checks for the generic host key. - * - * The typemask is the type/format of the given host name and key - * - * plain - ascii "hostname.domain.tld" - * sha1 - NOT SUPPORTED AS INPUT - * custom - prehashed base64 encoded. Note that this cannot use any salts. - * - * Returns: - * - * LIBSSH2_KNOWNHOST_CHECK_FAILURE - * LIBSSH2_KNOWNHOST_CHECK_NOTFOUND - * LIBSSH2_KNOWNHOST_CHECK_MATCH - * LIBSSH2_KNOWNHOST_CHECK_MISMATCH - */ -LIBSSH2_API int -libssh2_knownhost_checkp(LIBSSH2_KNOWNHOSTS *hosts, - const char *hostp, int port, - const char *key, size_t keylen, - int typemask, - struct libssh2_knownhost **ext) -{ - return knownhost_check(hosts, hostp, port, key, keylen, - typemask, ext); -} - - -/* - * libssh2_knownhost_del - * - * Remove a host from the collection of known hosts. - * - */ -LIBSSH2_API int -libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *entry) -{ - struct known_host *node; - - /* check that this was retrieved the right way or get out */ - if(!entry || (entry->magic != KNOWNHOST_MAGIC)) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "Invalid host information"); - - /* get the internal node pointer */ - node = entry->node; - - /* unlink from the list of all hosts */ - _libssh2_list_remove(&node->node); - - /* clear the struct now since the memory in which it is allocated is - about to be freed! */ - memset(entry, 0, sizeof(struct libssh2_knownhost)); - - /* free all resources */ - free_host(hosts->session, node); - - return 0; -} - -/* - * libssh2_knownhost_free - * - * Free an entire collection of known hosts. - * - */ -LIBSSH2_API void -libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts) -{ - struct known_host *node; - struct known_host *next; - - for(node = _libssh2_list_first(&hosts->head); node; node = next) { - next = _libssh2_list_next(&node->node); - free_host(hosts->session, node); - } - LIBSSH2_FREE(hosts->session, hosts); -} - - -/* old style plain text: [name]([,][name])* - - for the sake of simplicity, we add them as separate hosts with the same - key -*/ -static int oldstyle_hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen, int key_type, - const char *comment, size_t commentlen) -{ - int rc = 0; - size_t namelen = 0; - const char *name = host + hostlen; - - if(hostlen < 1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(no host names)"); - - while(name > host) { - --name; - ++namelen; - - /* when we get the the start or see a comma coming up, add the host - name to the collection */ - if((name == host) || (*(name-1) == ',')) { - - char hostbuf[256]; - - /* make sure we don't overflow the buffer */ - if(namelen >= sizeof(hostbuf)-1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpected length)"); - - /* copy host name to the temp buffer and zero terminate */ - memcpy(hostbuf, name, namelen); - hostbuf[namelen]=0; - - rc = knownhost_add(hosts, hostbuf, NULL, key, keylen, - comment, commentlen, - key_type | LIBSSH2_KNOWNHOST_TYPE_PLAIN | - LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL); - if(rc) - return rc; - - if(name > host) { - namelen = 0; - --name; /* skip comma */ - } - } - } - - return rc; -} - -/* |1|[salt]|[hash] */ -static int hashed_hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen, int key_type, - const char *comment, size_t commentlen) -{ - const char *p; - char saltbuf[32]; - char hostbuf[256]; - - const char *salt = &host[3]; /* skip the magic marker */ - hostlen -= 3; /* deduct the marker */ - - /* this is where the salt starts, find the end of it */ - for(p = salt; *p && (*p != '|'); p++) - ; - - if(*p=='|') { - const char *hash = NULL; - size_t saltlen = p - salt; - if(saltlen >= (sizeof(saltbuf)-1)) /* weird length */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpectedly long salt)"); - - memcpy(saltbuf, salt, saltlen); - saltbuf[saltlen] = 0; /* zero terminate */ - salt = saltbuf; /* point to the stack based buffer */ - - hash = p+1; /* the host hash is after the separator */ - - /* now make the host point to the hash */ - host = hash; - hostlen -= saltlen+1; /* deduct the salt and separator */ - - /* check that the lengths seem sensible */ - if(hostlen >= sizeof(hostbuf)-1) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(unexpected length)"); - - memcpy(hostbuf, host, hostlen); - hostbuf[hostlen]=0; - - return knownhost_add(hosts, hostbuf, salt, key, keylen, comment, - commentlen, - key_type | LIBSSH2_KNOWNHOST_TYPE_SHA1 | - LIBSSH2_KNOWNHOST_KEYENC_BASE64, NULL); - } - else - return 0; /* XXX: This should be an error, shouldn't it? */ -} - -/* - * hostline() - * - * Parse a single known_host line pre-split into host and key. - * - * The key part may include an optional comment which will be parsed here - * for ssh-rsa and ssh-dsa keys. Comments in other key types aren't handled. - * - * The function assumes new-lines have already been removed from the arguments. - */ -static int hostline(LIBSSH2_KNOWNHOSTS *hosts, - const char *host, size_t hostlen, - const char *key, size_t keylen) -{ - const char *comment = NULL; - size_t commentlen = 0; - int key_type; - - /* make some checks that the lengths seem sensible */ - if(keylen < 20) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line " - "(key too short)"); - - switch(key[0]) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - key_type = LIBSSH2_KNOWNHOST_KEY_RSA1; - - /* Note that the old-style keys (RSA1) aren't truly base64, but we - * claim it is for now since we can get away with strcmp()ing the - * entire anything anyway! We need to check and fix these to make them - * work properly. - */ - break; - - case 's': /* ssh-dss or ssh-rsa */ - if(!strncmp(key, "ssh-dss", 7)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS; - else if(!strncmp(key, "ssh-rsa", 7)) - key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA; - else - /* unknown key type */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown key type"); - - key += 7; - keylen -= 7; - - /* skip whitespaces */ - while((*key ==' ') || (*key == '\t')) { - key++; - keylen--; - } - - comment = key; - commentlen = keylen; - - /* move over key */ - while(commentlen && *comment && - (*comment != ' ') && (*comment != '\t')) { - comment++; - commentlen--; - } - - /* reduce key by comment length */ - keylen -= commentlen; - - /* Distinguish empty comment (a space) from no comment (no space) */ - if (commentlen == 0) - comment = NULL; - - /* skip whitespaces */ - while(commentlen && *comment && - ((*comment ==' ') || (*comment == '\t'))) { - comment++; - commentlen--; - } - break; - - default: /* unknown key format */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unknown key format"); - } - - /* Figure out host format */ - if((hostlen >2) && memcmp(host, "|1|", 3)) { - /* old style plain text: [name]([,][name])* - - for the sake of simplicity, we add them as separate hosts with the - same key - */ - return oldstyle_hostline(hosts, host, hostlen, key, keylen, key_type, - comment, commentlen); - } - else { - /* |1|[salt]|[hash] */ - return hashed_hostline(hosts, host, hostlen, key, keylen, key_type, - comment, commentlen); - } -} - -/* - * libssh2_knownhost_readline() - * - * Pass in a line of a file of 'type'. - * - * LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type. - * - * OpenSSH line format: - * - * - * - * Where the two parts can be created like: - * - * can be either - * or - * - * consists of - * [name] optionally followed by [,name] one or more times - * - * consists of - * |1||hash - * - * can be one of: - * [RSA bits] [e] [n as a decimal number] - * 'ssh-dss' [base64-encoded-key] - * 'ssh-rsa' [base64-encoded-key] - * - */ -LIBSSH2_API int -libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts, - const char *line, size_t len, int type) -{ - const char *cp; - const char *hostp; - const char *keyp; - size_t hostlen; - size_t keylen; - int rc; - - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - cp = line; - - /* skip leading whitespaces */ - while(len && ((*cp==' ') || (*cp == '\t'))) { - cp++; - len--; - } - - if(!len || !*cp || (*cp == '#') || (*cp == '\n')) - /* comment or empty line */ - return LIBSSH2_ERROR_NONE; - - /* the host part starts here */ - hostp = cp; - - /* move over the host to the separator */ - while(len && *cp && (*cp!=' ') && (*cp != '\t')) { - cp++; - len--; - } - - hostlen = cp - hostp; - - /* the key starts after the whitespaces */ - while(len && *cp && ((*cp==' ') || (*cp == '\t'))) { - cp++; - len--; - } - - if(!*cp || !len) /* illegal line */ - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Failed to parse known_hosts line"); - - keyp = cp; /* the key starts here */ - keylen = len; - - /* check if the line (key) ends with a newline and if so kill it */ - while(len && *cp && (*cp != '\n')) { - cp++; - len--; - } - - /* zero terminate where the newline is */ - if(*cp == '\n') - keylen--; /* don't include this in the count */ - - /* deal with this one host+key line */ - rc = hostline(hosts, hostp, hostlen, keyp, keylen); - if(rc) - return rc; /* failed */ - - return LIBSSH2_ERROR_NONE; /* success */ -} - -/* - * libssh2_knownhost_readfile - * - * Read hosts+key pairs from a given file. - * - * Returns a negative value for error or number of successfully added hosts. - * - */ - -LIBSSH2_API int -libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type) -{ - FILE *file; - int num = 0; - char buf[2048]; - - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - file = fopen(filename, "r"); - if(file) { - while(fgets(buf, sizeof(buf), file)) { - if(libssh2_knownhost_readline(hosts, buf, strlen(buf), type)) - break; - num++; - } - fclose(file); - } - else - return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Failed to open file"); - - return num; -} - -/* - * knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. The 'outlen' field - * will then contain the size libssh2 wanted to store, which then is the - * smallest sufficient buffer it would require. - * - */ -static int -knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct known_host *node, - char *buf, size_t buflen, - size_t *outlen, int type) -{ - int rc = LIBSSH2_ERROR_NONE; - int tindex; - const char *keytypes[4]={ - "", /* not used */ - "", /* this type has no name in the file */ - " ssh-rsa", - " ssh-dss" - }; - const char *keytype; - size_t nlen; - size_t commentlen = 0; - - /* we only support this single file type for now, bail out on all other - attempts */ - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >> - LIBSSH2_KNOWNHOST_KEY_SHIFT; - - /* set the string used in the file */ - keytype = keytypes[tindex]; - - /* calculate extra space needed for comment */ - if(node->comment) - commentlen = strlen(node->comment) + 1; - - if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) == - LIBSSH2_KNOWNHOST_TYPE_SHA1) { - char *namealloc; - char *saltalloc; - nlen = _libssh2_base64_encode(hosts->session, node->name, - node->name_len, &namealloc); - if(!nlen) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded host name"); - - nlen = _libssh2_base64_encode(hosts->session, - node->salt, node->salt_len, - &saltalloc); - if(!nlen) { - free(namealloc); - return _libssh2_error(hosts->session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "base64-encoded salt"); - } - - nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) + - strlen(node->key) + commentlen + 7; - /* |1| + | + ' ' + \n + \0 = 7 */ - - if(nlen <= buflen) - if(node->comment) - snprintf(buf, buflen, "|1|%s|%s%s %s %s\n", saltalloc, namealloc, - keytype, node->key, node->comment); - else - snprintf(buf, buflen, "|1|%s|%s%s %s\n", saltalloc, namealloc, - keytype, node->key); - else - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, - "Known-host write buffer too small"); - - free(namealloc); - free(saltalloc); - } - else { - nlen = strlen(node->name) + strlen(keytype) + strlen(node->key) + - commentlen + 3; - /* ' ' + '\n' + \0 = 3 */ - if(nlen <= buflen) - /* these types have the plain name */ - if(node->comment) - snprintf(buf, buflen, "%s%s %s %s\n", node->name, keytype, node->key, - node->comment); - else - snprintf(buf, buflen, "%s%s %s\n", node->name, keytype, node->key); - else - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, - "Known-host write buffer too small"); - } - - /* we report the full length of the data with the trailing zero excluded */ - *outlen = nlen-1; - - return rc; -} - -/* - * libssh2_knownhost_writeline() - * - * Ask libssh2 to convert a known host to an output line for storage. - * - * Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given - * output buffer is too small to hold the desired output. - */ -LIBSSH2_API int -libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost *known, - char *buffer, size_t buflen, - size_t *outlen, /* the amount of written data */ - int type) -{ - struct known_host *node; - - if(known->magic != KNOWNHOST_MAGIC) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_INVAL, - "Invalid host information"); - - node = known->node; - - return knownhost_writeline(hosts, node, buffer, buflen, outlen, type); -} - -/* - * libssh2_knownhost_writefile() - * - * Write hosts+key pairs to the given file. - */ -LIBSSH2_API int -libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts, - const char *filename, int type) -{ - struct known_host *node; - FILE *file; - int rc = LIBSSH2_ERROR_NONE; - char buffer[2048]; - - /* we only support this single file type for now, bail out on all other - attempts */ - if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH) - return _libssh2_error(hosts->session, - LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, - "Unsupported type of known-host information " - "store"); - - file = fopen(filename, "w"); - if(!file) - return _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Failed to open file"); - - for(node = _libssh2_list_first(&hosts->head); - node; - node= _libssh2_list_next(&node->node) ) { - size_t wrote; - size_t nwrote; - rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote, - type); - if(rc) - break; - - nwrote = fwrite(buffer, 1, wrote, file); - if(nwrote != wrote) { - /* failed to write the whole thing, bail out */ - rc = _libssh2_error(hosts->session, LIBSSH2_ERROR_FILE, - "Write failed"); - break; - } - } - fclose(file); - - return rc; -} - - -/* - * libssh2_knownhost_get() - * - * Traverse the internal list of known hosts. Pass NULL to 'prev' to get - * the first one. - * - * Returns: - * 0 if a fine host was stored in 'store' - * 1 if end of hosts - * [negative] on errors - */ -LIBSSH2_API int -libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts, - struct libssh2_knownhost **ext, - struct libssh2_knownhost *oprev) -{ - struct known_host *node; - if(oprev && oprev->node) { - /* we have a starting point */ - struct known_host *prev = oprev->node; - - /* get the next node in the list */ - node = _libssh2_list_next(&prev->node); - - } - else - node = _libssh2_list_first(&hosts->head); - - if(!node) - /* no (more) node */ - return 1; - - *ext = knownhost_to_external(node); - - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/libgcrypt.c b/vendor/libssh2-1.4.2/src/libgcrypt.c deleted file mode 100644 index 5c2787b..0000000 --- a/vendor/libssh2-1.4.2/src/libgcrypt.c +++ /dev/null @@ -1,593 +0,0 @@ -/* Copyright (C) 2008, 2009, Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. - * 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_LIBGCRYPT /* compile only if we build with libgcrypt */ - -#include - -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, - const char *filename, unsigned const char *passphrase) -{ - FILE *fp; - 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; - - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - - ret = _libssh2_pem_parse(session, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - fp, &data, &datalen); - fclose(fp); - 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, - const char *filename, unsigned const char *passphrase) -{ - FILE *fp; - 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; - - fp = fopen(filename, "r"); - if (!fp) { - return -1; - } - - ret = _libssh2_pem_parse(session, - "-----BEGIN DSA PRIVATE KEY-----", - "-----END DSA PRIVATE KEY-----", - fp, &data, &datalen); - fclose(fp); - 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, - size_t hash_len, - unsigned char **signature, size_t *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; - } - - memset(sig, 0, 40); - -/* Extract R. */ - - data = gcry_sexp_find_token(sig_sexp, "r", 0); - if (!data) - goto err; - - tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) - goto err; - - if (tmp[0] == '\0') { - tmp++; - size--; - } - - if (size < 1 || size > 20) - goto err; - - memcpy(sig + (20 - size), tmp, size); - - gcry_sexp_release(data); - -/* Extract S. */ - - data = gcry_sexp_find_token(sig_sexp, "s", 0); - if (!data) - goto err; - - tmp = gcry_sexp_nth_data(data, 1, &size); - if (!tmp) - goto err; - - if (tmp[0] == '\0') { - tmp++; - size--; - } - - if (size < 1 || size > 20) - goto err; - - memcpy(sig + 20 + (20 - size), tmp, size); - goto out; - - err: - ret = -1; - - 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 ret; - int cipher = _libssh2_gcry_cipher (algo); - int mode = _libssh2_gcry_mode (algo); - int keylen = gcry_cipher_get_algo_keylen(cipher); - - (void) encrypt; - - ret = gcry_cipher_open(h, cipher, mode, 0); - if (ret) { - return -1; - } - - ret = gcry_cipher_setkey(*h, secret, keylen); - if (ret) { - gcry_cipher_close(*h); - return -1; - } - - if (mode != GCRY_CIPHER_MODE_STREAM) { - int blklen = gcry_cipher_get_algo_blklen(cipher); - if (mode == GCRY_CIPHER_MODE_CTR) - ret = gcry_cipher_setctr(*h, iv, blklen); - else - 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) -{ - int cipher = _libssh2_gcry_cipher (algo); - size_t blklen = gcry_cipher_get_algo_blklen(cipher); - 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; -} - -int -_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase) -{ - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to extract public key from private key file: " - "Method unimplemented in libgcrypt backend"); -} - -void _libssh2_init_aes_ctr(void) -{ - /* no implementation */ -} -#endif /* LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/libgcrypt.h b/vendor/libssh2-1.4.2/src/libgcrypt.h deleted file mode 100644 index 04516e5..0000000 --- a/vendor/libssh2-1.4.2/src/libgcrypt.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007, The Written Word, Inc. - * 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 - -#define LIBSSH2_MD5 1 - -#define LIBSSH2_HMAC_RIPEMD 1 - -#define LIBSSH2_AES 1 -#define LIBSSH2_AES_CTR 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), SHA_DIGEST_LENGTH), 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), MD5_DIGEST_LENGTH), 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_crypto_exit() - -#define libssh2_rsa_ctx struct gcry_sexp - -#define _libssh2_rsa_free(rsactx) gcry_sexp_release (rsactx) - -#define libssh2_dsa_ctx struct gcry_sexp - -#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_gcry_ciphermode(c,m) ((c << 8) | m) -#define _libssh2_gcry_cipher(c) (c >> 8) -#define _libssh2_gcry_mode(m) (m & 0xFF) - -#define _libssh2_cipher_aes256ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes192ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes128ctr \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR) -#define _libssh2_cipher_aes256 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_aes192 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_aes128 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_blowfish \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_arcfour \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM) -#define _libssh2_cipher_cast5 \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC) -#define _libssh2_cipher_3des \ - _libssh2_gcry_ciphermode(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC) - - -#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) - diff --git a/vendor/libssh2-1.4.2/src/libssh2_config.h b/vendor/libssh2-1.4.2/src/libssh2_config.h deleted file mode 100644 index 4591f5f..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef WIN32 - #include "libssh2_config_win.h" -#else - #include "libssh2_config_osx.h" -#endif diff --git a/vendor/libssh2-1.4.2/src/libssh2_config_osx.h b/vendor/libssh2-1.4.2/src/libssh2_config_osx.h deleted file mode 100644 index d8917c2..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config_osx.h +++ /dev/null @@ -1,224 +0,0 @@ -/* src/libssh2_config.h. Generated from libssh2_config.h.in by configure. */ -/* src/libssh2_config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* disabled non-blocking sockets */ -/* #undef HAVE_DISABLED_NONBLOCKING */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the `EVP_aes_128_ctr' function. */ -/* #undef HAVE_EVP_AES_128_CTR */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* use FIONBIO for non-blocking sockets */ -/* #undef HAVE_FIONBIO */ - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* use ioctlsocket() for non-blocking sockets */ -/* #undef HAVE_IOCTLSOCKET */ - -/* use Ioctlsocket() for non-blocking sockets */ -/* #undef HAVE_IOCTLSOCKET_CASE */ - -/* Define if you have the gcrypt library. */ -/* #undef HAVE_LIBGCRYPT */ - -/* Define if you have the ssl library. */ -#define HAVE_LIBSSL 1 - -/* Define if you have the z library. */ -#define HAVE_LIBZ 1 - -/* Define to 1 if the compiler supports the 'long long' data type. */ -#define HAVE_LONGLONG 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 - -/* use O_NONBLOCK for non-blocking sockets */ -#define HAVE_O_NONBLOCK 1 - -/* Define to 1 if you have the `poll' function. */ -/* #undef HAVE_POLL */ - -/* Define to 1 if you have the select function. */ -#define HAVE_SELECT 1 - -/* use SO_NONBLOCK for non-blocking sockets */ -/* #undef HAVE_SO_NONBLOCK */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_UIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_UN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINDOWS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINSOCK2_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WS2TCPIP_H */ - -/* to make a symbol visible */ -/* #undef LIBSSH2_API */ - -/* Enable "none" cipher -- NOT RECOMMENDED */ -/* #undef LIBSSH2_CRYPT_NONE */ - -/* Enable newer diffie-hellman-group-exchange-sha1 syntax */ -#define LIBSSH2_DH_GEX_NEW 1 - -/* Compile in zlib support */ -#define LIBSSH2_HAVE_ZLIB 1 - -/* Use libgcrypt */ -/* #undef LIBSSH2_LIBGCRYPT */ - -/* Enable "none" MAC -- NOT RECOMMENDED */ -/* #undef LIBSSH2_MAC_NONE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ -/* #undef NEED_REENTRANT */ - -/* Name of package */ -#define PACKAGE "libssh2" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "libssh2-devel@cool.haxx.se" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libssh2" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libssh2 -" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libssh2" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "-" - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "-" - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif diff --git a/vendor/libssh2-1.4.2/src/libssh2_config_win.h b/vendor/libssh2-1.4.2/src/libssh2_config_win.h deleted file mode 100644 index 39e438f..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_config_win.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef LIBSSH2_CONFIG_H -#define LIBSSH2_CONFIG_H - -#ifndef WIN32 -#define WIN32 -#endif -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif /* _CRT_SECURE_NO_DEPRECATE */ -#include -#include -#include - -#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 -#endif -#define strdup _strdup -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#define strncasecmp strnicmp -#define strcasecmp stricmp -#endif /* _MSC_VER */ - -/* Enable newer diffie-hellman-group-exchange-sha1 syntax */ -#define LIBSSH2_DH_GEX_NEW 1 - -#endif /* LIBSSH2_CONFIG_H */ - diff --git a/vendor/libssh2-1.4.2/src/libssh2_priv.h b/vendor/libssh2-1.4.2/src/libssh2_priv.h deleted file mode 100644 index c670a16..0000000 --- a/vendor/libssh2-1.4.2/src/libssh2_priv.h +++ /dev/null @@ -1,1038 +0,0 @@ -/* Copyright (c) 2004-2008, 2010, Sara Golemon - * Copyright (c) 2009-2011 by Daniel Stenberg - * Copyright (c) 2010 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. - */ - -#ifndef LIBSSH2_PRIV_H -#define LIBSSH2_PRIV_H 1 - -#define LIBSSH2_LIBRARY -#include "libssh2_config.h" - -#ifdef HAVE_WINDOWS_H -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#undef WIN32_LEAN_AND_MEAN -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#include -#include - -/* 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 -#else -# if defined(HAVE_SELECT) && !defined(WIN32) -# ifdef HAVE_SYS_SELECT_H -# include -# else -# include -# include -# endif -# endif -#endif - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif - -#include "libssh2.h" -#include "libssh2_publickey.h" -#include "libssh2_sftp.h" -#include "misc.h" /* for the linked list stuff */ - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -/* Provide iovec / writev on WIN32 platform. */ -#ifdef WIN32 - -struct iovec { - size_t iov_len; - void * 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 */ - -#include "crypto.h" - -#ifdef HAVE_WINSOCK2_H - -#include -#include -#include - -#ifdef _MSC_VER -/* "inline" keyword is valid only with C++ engine! */ -#define inline __inline -#endif - -#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_debug((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) - -#define LIBSSH2_SEND_FD(session, fd, buffer, length, flags) \ - session->send(fd, buffer, length, flags, &session->abstract) -#define LIBSSH2_RECV_FD(session, fd, buffer, length, flags) \ - session->recv(fd, buffer, length, flags, &session->abstract) - -#define LIBSSH2_SEND(session, buffer, length, flags) \ - LIBSSH2_SEND_FD(session, session->socket_fd, buffer, length, flags) -#define LIBSSH2_RECV(session, buffer, length, flags) \ - LIBSSH2_RECV_FD(session, session->socket_fd, buffer, length, flags) - -typedef struct _LIBSSH2_KEX_METHOD LIBSSH2_KEX_METHOD; -typedef struct _LIBSSH2_HOSTKEY_METHOD LIBSSH2_HOSTKEY_METHOD; -typedef struct _LIBSSH2_CRYPT_METHOD LIBSSH2_CRYPT_METHOD; -typedef struct _LIBSSH2_COMP_METHOD LIBSSH2_COMP_METHOD; - -typedef struct _LIBSSH2_PACKET LIBSSH2_PACKET; - -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_NB_state_jump4, - libssh2_NB_state_jump5 -} 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; - size_t e_packet_len; - size_t s_packet_len; - size_t 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; - size_t f_value_len; - size_t k_value_len; - size_t 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; - size_t request_len; - size_t 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; - size_t data_len; - unsigned char *oldlocal; - size_t 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; - LIBSSH2_CHANNEL *channel; -} 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; - LIBSSH2_CHANNEL *channel; -} packet_x11_open_state_t; - -struct _LIBSSH2_PACKET -{ - struct list_node node; /* linked list header */ - - /* the raw unencrypted payload */ - unsigned char *data; - size_t data_len; - - /* Where to start reading data from, - * used for channel data that's been partially consumed */ - size_t data_head; -}; - -typedef struct _libssh2_channel_data -{ - /* Identifier */ - uint32_t id; - - /* Limits and restrictions */ - uint32_t 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 -{ - struct list_node node; - - unsigned char *channel_type; - unsigned channel_type_len; - - /* channel's program exit status */ - int exit_status; - - /* channel's program exit signal (without the SIG prefix) */ - char *exit_signal; - - libssh2_channel_data local, remote; - /* Amount of bytes to be refunded to receive window (but not yet sent) */ - uint32_t adjust_queue; - - LIBSSH2_SESSION *session; - - 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; - size_t 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_channel_request_pty_size_ex() */ - libssh2_nonblocking_states reqPTY_state; - unsigned char reqPTY_packet[41 + 256]; - size_t 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; - size_t 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; - size_t 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; - size_t flush_refund_bytes; - size_t 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; - - uint32_t read_local_id; - - /* State variables used in libssh2_channel_write_ex() */ - libssh2_nonblocking_states write_state; - unsigned char write_packet[13]; - size_t write_packet_len; - 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_LISTENER -{ - struct list_node node; /* linked list header */ - - LIBSSH2_SESSION *session; - - char *host; - int port; - - /* a list of CHANNELs for this listener */ - struct list_head queue; - - int queue_size; - int queue_maxsize; - - /* 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; - size_t kexinit_len; - - const LIBSSH2_CRYPT_METHOD *crypt; - void *crypt_abstract; - - const struct _LIBSSH2_MAC_METHOD *mac; - uint32_t 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 (1024*16) - -struct transportpacket -{ - /* ------------- for incoming data --------------- */ - unsigned char buf[PACKETBUFSIZE]; - unsigned char init[5]; /* first 5 bytes of the incoming data stream, - still encrypted */ - size_t writeidx; /* at what array index we do the next write into - the buffer */ - size_t readidx; /* at what array index we do the next read from - the buffer */ - uint32_t packet_length; /* the most recent packet_length as read from the - network data */ - uint8_t padding_length; /* the most recent padding_length as read from the - network data */ - size_t data_num; /* How much of the total package that has been read - so far. */ - size_t 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[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */ - - int ototal_num; /* size of outbuf in number of bytes */ - const unsigned char *odata; /* original pointer to the data */ - size_t olen; /* original size of the data we stored in - outbuf */ - size_t osent; /* number of bytes already sent */ -}; - -struct _LIBSSH2_PUBLICKEY -{ - LIBSSH2_CHANNEL *channel; - uint32_t version; - - /* State variables used in libssh2_publickey_packet_receive() */ - libssh2_nonblocking_states receive_state; - unsigned char *receive_packet; - size_t 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; - size_t listFetch_data_len; -}; - -#define LIBSSH2_SCP_RESPONSE_BUFLEN 256 - -struct flags { - int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */ - int compress; /* LIBSSH2_FLAG_COMPRESS */ -}; - -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)); - LIBSSH2_SEND_FUNC((*send)); - LIBSSH2_RECV_FUNC((*recv)); - - /* Method preferences -- NULL yields "load order" */ - char *kex_prefs; - char *hostkey_prefs; - - int state; - - /* Flag options */ - struct flags flag; - - /* Agreed Key Exchange Method */ - const LIBSSH2_KEX_METHOD *kex; - int burn_optimistic_kexinit:1; - - unsigned char *session_id; - uint32_t session_id_len; - - /* this is set to TRUE if a blocking API behavior is requested */ - int api_block_mode; - - /* Timeout used when blocking API behavior is active */ - long api_timeout; - - /* 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; - uint32_t 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 linked list -- Sometimes the packet that comes in isn't the - packet we're ready for */ - struct list_head packets; - - /* Active connection channels */ - struct list_head channels; - - uint32_t next_channel; - - struct list_head listeners; /* list of LIBSSH2_LISTENER structs */ - - /* Actual I/O socket */ - libssh2_socket_t socket_fd; - int socket_state; - int socket_block_directions; - int socket_prev_blockstate; /* stores the state of the socket blockiness - when libssh2_session_startup() is called */ - - /* Error tracking */ - const char *err_msg; - int err_code; - - /* struct members for packet-level reading */ - struct transportpacket packet; -#ifdef LIBSSH2DEBUG - int showmask; /* what debug/trace messages to display */ - libssh2_trace_handler_func tracehandler; /* callback to display trace messages */ - void* tracehandler_context; /* context for the trace handler */ -#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; - size_t startup_data_len; - unsigned char startup_service[sizeof("ssh-userauth") + 5 - 1]; - size_t 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[256 + 13]; - size_t 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; - size_t 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; - size_t 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; - size_t userauth_host_data_len; - unsigned char *userauth_host_packet; - size_t userauth_host_packet_len; - unsigned char *userauth_host_method; - size_t 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; - size_t userauth_pblc_data_len; - unsigned char *userauth_pblc_packet; - size_t userauth_pblc_packet_len; - unsigned char *userauth_pblc_method; - size_t 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 libssh2_userauth_keyboard_interactive_ex() */ - libssh2_nonblocking_states userauth_kybd_state; - unsigned char *userauth_kybd_data; - size_t userauth_kybd_data_len; - unsigned char *userauth_kybd_packet; - size_t 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; - size_t open_packet_len; - unsigned char *open_data; - size_t open_data_len; - uint32_t open_local_channel; - - /* State variables used in libssh2_channel_direct_tcpip_ex() */ - libssh2_nonblocking_states direct_state; - unsigned char *direct_message; - size_t direct_host_len; - size_t direct_shost_len; - size_t direct_message_len; - - /* State variables used in libssh2_channel_forward_listen_ex() */ - libssh2_nonblocking_states fwdLstn_state; - unsigned char *fwdLstn_packet; - uint32_t fwdLstn_host_len; - uint32_t 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; - size_t pkeyInit_data_len; - /* 19 = packet_len(4) + version_len(4) + "version"(7) + version_num(4) */ - unsigned char pkeyInit_buffer[19]; - size_t pkeyInit_buffer_sent; /* how much of buffer that has been sent */ - - /* State variables used in libssh2_packet_add() */ - libssh2_nonblocking_states packAdd_state; - LIBSSH2_CHANNEL *packAdd_channelp; /* keeper of the channel during EAGAIN - states */ - 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; - size_t fullpacket_payload_len; - int 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) */ - int sftpInit_sent; /* number of bytes from the buffer that have been - sent */ - - /* State variables used in libssh2_scp_recv() */ - libssh2_nonblocking_states scpRecv_state; - unsigned char *scpRecv_command; - size_t scpRecv_command_len; - unsigned char scpRecv_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; - size_t scpRecv_response_len; - long scpRecv_mode; -#if defined(HAVE_LONGLONG) && defined(HAVE_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; - LIBSSH2_CHANNEL *scpRecv_channel; - - /* State variables used in libssh2_scp_send_ex() */ - libssh2_nonblocking_states scpSend_state; - unsigned char *scpSend_command; - size_t scpSend_command_len; - unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; - size_t scpSend_response_len; - LIBSSH2_CHANNEL *scpSend_channel; - - /* Keepalive variables used by keepalive.c. */ - int keepalive_interval; - int keepalive_want_reply; - time_t keepalive_last_sent; -}; - -/* 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)->flag.sigpipe) ? 0 : MSG_NOSIGNAL) -#define LIBSSH2_SOCKET_RECV_FLAGS(session) \ - (((session)->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, - size_t 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, - size_t sig_len, const unsigned char *m, - size_t m_len, void **abstract); - int (*signv) (LIBSSH2_SESSION * session, unsigned char **signature, - size_t *signature_len, int veccount, - const struct iovec datavec[], void **abstract); - int (*encrypt) (LIBSSH2_SESSION * session, unsigned char **dst, - size_t *dst_len, const unsigned char *src, - size_t 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 compress; /* 1 if it does compress, 0 if it doesn't */ - int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract); - int (*comp) (LIBSSH2_SESSION *session, - unsigned char *dest, - size_t *dest_len, - const unsigned char *src, - size_t src_len, - void **abstract); - int (*decomp) (LIBSSH2_SESSION *session, - unsigned char **dest, - size_t *dest_len, - size_t payload_limit, - const unsigned char *src, - size_t src_len, - void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract); -}; - -#ifdef LIBSSH2DEBUG -void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, - ...); -#else -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__GNUC__) -/* C99 supported and also by older GCC */ -#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 - -#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 - -/* Error codes returned in SSH_MSG_CHANNEL_OPEN_FAILURE message - (see RFC4254) */ -#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1 -#define SSH_OPEN_CONNECT_FAILED 2 -#define SSH_OPEN_UNKNOWN_CHANNELTYPE 3 -#define SSH_OPEN_RESOURCE_SHORTAGE 4 - -ssize_t _libssh2_recv(libssh2_socket_t socket, void *buffer, - size_t length, int flags, void **abstract); -ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer, - size_t length, int flags, void **abstract); - -#define LIBSSH2_READ_TIMEOUT 60 /* generic timeout in seconds used when - waiting for more data to arrive */ - - -int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, - key_exchange_state_t * state); - -/* Let crypt.c/hostkey.c expose their method structs */ -const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void); -const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void); - -/* 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); - -/* global.c */ -void _libssh2_init_if_needed (void); - - -#define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0])) - -/* define to output the libssh2_int64_t type in a *printf() */ -#if defined( __BORLANDC__ ) || defined( _MSC_VER ) || defined( __MINGW32__ ) -#define LIBSSH2_INT64_T_FORMAT "I64" -#else -#define LIBSSH2_INT64_T_FORMAT "ll" -#endif - -#endif /* LIBSSH2_H */ diff --git a/vendor/libssh2-1.4.2/src/mac.c b/vendor/libssh2-1.4.2/src/mac.c deleted file mode 100644 index 76894fc..0000000 --- a/vendor/libssh2-1.4.2/src/mac.c +++ /dev/null @@ -1,314 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * 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 "mac.h" - -#ifdef LIBSSH2_MAC_NONE -/* mac_none_MAC - * Minimalist MAC: No MAC - */ -static int -mac_none_MAC(LIBSSH2_SESSION * session, unsigned char *buf, - uint32_t seqno, const unsigned char *packet, - uint32_t packet_len, const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - return 0; -} - - - - -static LIBSSH2_MAC_METHOD mac_method_none = { - "none", - 0, - 0, - NULL, - mac_none_MAC, - NULL -}; -#endif /* LIBSSH2_MAC_NONE */ - -/* mac_method_common_init - * Initialize simple mac methods - */ -static int -mac_method_common_init(LIBSSH2_SESSION * session, unsigned char *key, - int *free_key, void **abstract) -{ - *abstract = key; - *free_key = 0; - (void) session; - - return 0; -} - - - -/* mac_method_common_dtor - * Cleanup simple mac methods - */ -static int -mac_method_common_dtor(LIBSSH2_SESSION * session, void **abstract) -{ - if (*abstract) { - LIBSSH2_FREE(session, *abstract); - } - *abstract = NULL; - - return 0; -} - - - -/* mac_method_hmac_sha1_hash - * Calculate hash using full sha1 value - */ -static int -mac_method_hmac_sha1_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t 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 mac_method_hmac_sha1 = { - "hmac-sha1", - 20, - 20, - mac_method_common_init, - mac_method_hmac_sha1_hash, - mac_method_common_dtor, -}; - -/* mac_method_hmac_sha1_96_hash - * Calculate hash using first 96 bits of sha1 value - */ -static int -mac_method_hmac_sha1_96_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - unsigned char temp[SHA_DIGEST_LENGTH]; - - 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 mac_method_hmac_sha1_96 = { - "hmac-sha1-96", - 12, - 20, - mac_method_common_init, - mac_method_hmac_sha1_96_hash, - mac_method_common_dtor, -}; - -#if LIBSSH2_MD5 -/* mac_method_hmac_md5_hash - * Calculate hash using full md5 value - */ -static int -mac_method_hmac_md5_hash(LIBSSH2_SESSION * session, unsigned char *buf, - uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t 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 mac_method_hmac_md5 = { - "hmac-md5", - 16, - 16, - mac_method_common_init, - mac_method_hmac_md5_hash, - mac_method_common_dtor, -}; - -/* mac_method_hmac_md5_96_hash - * Calculate hash using first 96 bits of md5 value - */ -static int -mac_method_hmac_md5_96_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t addtl_len, void **abstract) -{ - unsigned char temp[MD5_DIGEST_LENGTH]; - 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 mac_method_hmac_md5_96 = { - "hmac-md5-96", - 12, - 16, - mac_method_common_init, - mac_method_hmac_md5_96_hash, - mac_method_common_dtor, -}; -#endif /* LIBSSH2_MD5 */ - -#if LIBSSH2_HMAC_RIPEMD -/* mac_method_hmac_ripemd160_hash - * Calculate hash using ripemd160 value - */ -static int -mac_method_hmac_ripemd160_hash(LIBSSH2_SESSION * session, - unsigned char *buf, uint32_t seqno, - const unsigned char *packet, - uint32_t packet_len, - const unsigned char *addtl, - uint32_t 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 mac_method_hmac_ripemd160 = { - "hmac-ripemd160", - 20, - 20, - mac_method_common_init, - mac_method_hmac_ripemd160_hash, - mac_method_common_dtor, -}; - -static const LIBSSH2_MAC_METHOD mac_method_hmac_ripemd160_openssh_com = { - "hmac-ripemd160@openssh.com", - 20, - 20, - mac_method_common_init, - mac_method_hmac_ripemd160_hash, - mac_method_common_dtor, -}; -#endif /* LIBSSH2_HMAC_RIPEMD */ - -static const LIBSSH2_MAC_METHOD *mac_methods[] = { - &mac_method_hmac_sha1, - &mac_method_hmac_sha1_96, -#if LIBSSH2_MD5 - &mac_method_hmac_md5, - &mac_method_hmac_md5_96, -#endif -#if LIBSSH2_HMAC_RIPEMD - &mac_method_hmac_ripemd160, - &mac_method_hmac_ripemd160_openssh_com, -#endif /* LIBSSH2_HMAC_RIPEMD */ -#ifdef LIBSSH2_MAC_NONE - &mac_method_none, -#endif /* LIBSSH2_MAC_NONE */ - NULL -}; - -const LIBSSH2_MAC_METHOD ** -_libssh2_mac_methods(void) -{ - return mac_methods; -} diff --git a/vendor/libssh2-1.4.2/src/mac.h b/vendor/libssh2-1.4.2/src/mac.h deleted file mode 100644 index 66d3e61..0000000 --- a/vendor/libssh2-1.4.2/src/mac.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __LIBSSH2_MAC_H -#define __LIBSSH2_MAC_H - -/* Copyright (C) 2009-2010 by Daniel Stenberg - * - * 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" - -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, - uint32_t seqno, const unsigned char *packet, - uint32_t packet_len, const unsigned char *addtl, - uint32_t addtl_len, void **abstract); - int (*dtor) (LIBSSH2_SESSION * session, void **abstract); -}; - -typedef struct _LIBSSH2_MAC_METHOD LIBSSH2_MAC_METHOD; - -const LIBSSH2_MAC_METHOD **_libssh2_mac_methods(void); - -#endif /* __LIBSSH2_MAC_H */ diff --git a/vendor/libssh2-1.4.2/src/misc.c b/vendor/libssh2-1.4.2/src/misc.c deleted file mode 100644 index a9f423a..0000000 --- a/vendor/libssh2-1.4.2/src/misc.c +++ /dev/null @@ -1,612 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 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 "misc.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include - -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) -{ - session->err_msg = errmsg; - session->err_code = errcode; -#ifdef LIBSSH2DEBUG - if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode) - /* if this is EAGAIN and we're in non-blocking mode, don't generate - a debug output for this */ - return errcode; - _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code, - session->err_msg); -#endif - - return errcode; -} - -#ifdef WIN32 -static int wsa2errno(void) -{ - switch (WSAGetLastError()) { - case WSAEWOULDBLOCK: - return EAGAIN; - - case WSAENOTSOCK: - return EBADF; - - case WSAEINTR: - return EINTR; - - default: - /* It is most important to ensure errno does not stay at EAGAIN - * when a different error occurs so just set errno to a generic - * error */ - return EIO; - } -} -#endif - -/* _libssh2_recv - * - * Replacement for the standard recv, return -errno on failure. - */ -ssize_t -_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract) -{ - ssize_t rc = recv(sock, buffer, length, flags); -#ifdef WIN32 - if (rc < 0 ) - return -wsa2errno(); -#elif defined(__VMS) - if (rc < 0 ){ - if ( errno == EWOULDBLOCK ) - return -EAGAIN; - else - return -errno; - } -#else - if (rc < 0 ){ - /* Sometimes the first recv() function call sets errno to ENOENT on - Solaris and HP-UX */ - if ( errno == ENOENT ) - return -EAGAIN; - else - return -errno; - } -#endif - return rc; -} - -/* _libssh2_send - * - * Replacement for the standard send, return -errno on failure. - */ -ssize_t -_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, - int flags, void **abstract) -{ - ssize_t rc = send(sock, buffer, length, flags); -#ifdef WIN32 - if (rc < 0 ) - return -wsa2errno(); -#elif defined(__VMS) - if (rc < 0 ) { - if ( errno == EWOULDBLOCK ) - return -EAGAIN; - else - return -errno; - } -#else - if (rc < 0 ) - return -errno; -#endif - return rc; -} - -/* libssh2_ntohu32 - */ -unsigned int -_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 = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16) - | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3]; - lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16) - | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7]; - - return ((libssh2_uint64_t)msl <<32) | lsl; -} - -/* _libssh2_htonu32 - */ -void -_libssh2_htonu32(unsigned char *buf, uint32_t value) -{ - buf[0] = (value >> 24) & 0xFF; - buf[1] = (value >> 16) & 0xFF; - buf[2] = (value >> 8) & 0xFF; - buf[3] = value & 0xFF; -} - -/* _libssh2_store_u32 - */ -void _libssh2_store_u32(unsigned char **buf, uint32_t value) -{ - _libssh2_htonu32(*buf, value); - *buf += sizeof(uint32_t); -} - -/* _libssh2_store_str - */ -void _libssh2_store_str(unsigned char **buf, const char *str, size_t len) -{ - _libssh2_store_u32(buf, (uint32_t)len); - if(len) { - memcpy(*buf, str, len); - *buf += len; - } -} - -/* Base64 Conversion */ - -static const char 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 base64_pad = '='; - -static const short 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 _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for base64 decoding"); - } - - for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) { - if ((v = 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 _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64"); - } - - *datalen = len; - return 0; -} - -/* ---- Base64 Encoding/Decoding Table --- */ -static const char table64[]= - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * _libssh2_base64_encode() - * - * Returns the length of the newly created base64 string. The third argument - * is a pointer to an allocated area holding the base64 data. If something - * went wrong, 0 is returned. - * - */ -size_t _libssh2_base64_encode(LIBSSH2_SESSION *session, - const char *inp, size_t insize, char **outptr) -{ - unsigned char ibuf[3]; - unsigned char obuf[4]; - int i; - int inputparts; - char *output; - char *base64data; - const char *indata = inp; - - *outptr = NULL; /* set to NULL in case of failure before we reach the end */ - - if(0 == insize) - insize = strlen(indata); - - base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4); - if(NULL == output) - return 0; - - while(insize > 0) { - for (i = inputparts = 0; i < 3; i++) { - if(insize > 0) { - inputparts++; - ibuf[i] = *indata; - indata++; - insize--; - } - else - ibuf[i] = 0; - } - - obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); - obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ - ((ibuf[1] & 0xF0) >> 4)); - obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ - ((ibuf[2] & 0xC0) >> 6)); - obuf[3] = (unsigned char) (ibuf[2] & 0x3F); - - switch(inputparts) { - case 1: /* only one byte read */ - snprintf(output, 5, "%c%c==", - table64[obuf[0]], - table64[obuf[1]]); - break; - case 2: /* two bytes read */ - snprintf(output, 5, "%c%c%c=", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]]); - break; - default: - snprintf(output, 5, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]] ); - break; - } - output += 4; - } - *output=0; - *outptr = base64data; /* make it return the actual data memory */ - - return strlen(base64data); /* return the length of the new data */ -} -/* ---- End of Base64 Encoding ---- */ - -LIBSSH2_API void -libssh2_free(LIBSSH2_SESSION *session, void *ptr) -{ - LIBSSH2_FREE(session, ptr); -} - -#ifdef LIBSSH2DEBUG -LIBSSH2_API int -libssh2_trace(LIBSSH2_SESSION * session, int bitmask) -{ - session->showmask = bitmask; - return 0; -} - -LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, - libssh2_trace_handler_func callback) -{ - session->tracehandler = callback; - session->tracehandler_context = handler_context; - return 0; -} - -void -_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) -{ - char buffer[1536]; - int len, msglen, buflen = sizeof(buffer); - va_list vargs; - struct timeval now; - static int firstsec; - static const char *const contexts[] = { - "Unknown", - "Transport", - "Key Ex", - "Userauth", - "Conn", - "SCP", - "SFTP", - "Failure Event", - "Publickey", - "Socket", - }; - const char* contexttext = contexts[0]; - unsigned int contextindex; - - if (!(session->showmask & context)) { - /* no such output asked for */ - return; - } - - /* Find the first matching context string for this message */ - for (contextindex = 0; contextindex < ARRAY_SIZE(contexts); - contextindex++) { - if ((context & (1 << contextindex)) != 0) { - contexttext = contexts[contextindex]; - break; - } - } - - _libssh2_gettimeofday(&now, NULL); - if(!firstsec) { - firstsec = now.tv_sec; - } - now.tv_sec -= firstsec; - - len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ", - (int)now.tv_sec, (int)now.tv_usec, contexttext); - - if (len >= buflen) - msglen = buflen - 1; - else { - buflen -= len; - msglen = len; - va_start(vargs, format); - len = vsnprintf(buffer + msglen, buflen, format, vargs); - va_end(vargs); - msglen += len < buflen ? len : buflen - 1; - } - - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, buffer, - msglen); - else - fprintf(stderr, "%s\n", buffer); -} - -#else -LIBSSH2_API int -libssh2_trace(LIBSSH2_SESSION * session, int bitmask) -{ - (void) session; - (void) bitmask; - return 0; -} - -LIBSSH2_API int -libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context, - libssh2_trace_handler_func callback) -{ - (void) session; - (void) handler_context; - (void) callback; - return 0; -} -#endif - -/* init the list head */ -void _libssh2_list_init(struct list_head *head) -{ - head->first = head->last = NULL; -} - -/* add a node to the list */ -void _libssh2_list_add(struct list_head *head, - struct list_node *entry) -{ - /* store a pointer to the head */ - entry->head = head; - - /* we add this entry at the "top" so it has no next */ - entry->next = NULL; - - /* make our prev point to what the head thinks is last */ - entry->prev = head->last; - - /* and make head's last be us now */ - head->last = entry; - - /* make sure our 'prev' node points to us next */ - if(entry->prev) - entry->prev->next = entry; - else - head->first = entry; -} - -/* return the "first" node in the list this head points to */ -void *_libssh2_list_first(struct list_head *head) -{ - return head->first; -} - -/* return the next node in the list */ -void *_libssh2_list_next(struct list_node *node) -{ - return node->next; -} - -/* return the prev node in the list */ -void *_libssh2_list_prev(struct list_node *node) -{ - return node->prev; -} - -/* remove this node from the list */ -void _libssh2_list_remove(struct list_node *entry) -{ - if(entry->prev) - entry->prev->next = entry->next; - else - entry->head->first = entry->next; - - if(entry->next) - entry->next->prev = entry->prev; - else - entry->head->last = entry->prev; -} - -#if 0 -/* insert a node before the given 'after' entry */ -void _libssh2_list_insert(struct list_node *after, /* insert before this */ - struct list_node *entry) -{ - /* 'after' is next to 'entry' */ - bentry->next = after; - - /* entry's prev is then made to be the prev after current has */ - entry->prev = after->prev; - - /* the node that is now before 'entry' was previously before 'after' - and must be made to point to 'entry' correctly */ - if(entry->prev) - entry->prev->next = entry; - else - /* there was no node before this, so we make sure we point the head - pointer to this node */ - after->head->first = entry; - - /* after's prev entry points back to entry */ - after->prev = entry; - - /* after's next entry is still the same as before */ - - /* entry's head is the same as after's */ - entry->head = after->head; -} - -#endif - -/* this define is defined in misc.h for the correct platforms */ -#ifdef LIBSSH2_GETTIMEOFDAY_WIN32 -/* - * gettimeofday - * Implementation according to: - * The Open Group Base Specifications Issue 6 - * IEEE Std 1003.1, 2004 Edition - */ - -/* - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Contributed by: - * Danny Smith - */ - -/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ -#define _W32_FT_OFFSET (116444736000000000) - -int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp) - { - union { - unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; - - if(tp) - { - GetSystemTimeAsFileTime (&_now.ft); - tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 ); - tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000); - } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; -} - - -#endif diff --git a/vendor/libssh2-1.4.2/src/misc.h b/vendor/libssh2-1.4.2/src/misc.h deleted file mode 100644 index e25248d..0000000 --- a/vendor/libssh2-1.4.2/src/misc.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef __LIBSSH2_MISC_H -#define __LIBSSH2_MISC_H -/* Copyright (c) 2009-2011 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. - */ - -struct list_head { - struct list_node *last; - struct list_node *first; -}; - -struct list_node { - struct list_node *next; - struct list_node *prev; - struct list_head *head; -}; - -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg); - -void _libssh2_list_init(struct list_head *head); - -/* add a node last in the list */ -void _libssh2_list_add(struct list_head *head, - struct list_node *entry); - -/* return the "first" node in the list this head points to */ -void *_libssh2_list_first(struct list_head *head); - -/* return the next node in the list */ -void *_libssh2_list_next(struct list_node *node); - -/* return the prev node in the list */ -void *_libssh2_list_prev(struct list_node *node); - -/* remove this node from the list */ -void _libssh2_list_remove(struct list_node *entry); - -size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session, - const char *inp, size_t insize, char **outptr); - -unsigned int _libssh2_ntohu32(const unsigned char *buf); -libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf); -void _libssh2_htonu32(unsigned char *buf, uint32_t val); -void _libssh2_store_u32(unsigned char **buf, uint32_t value); -void _libssh2_store_str(unsigned char **buf, const char *str, size_t len); - -#if defined(LIBSSH2_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) -/* provide a private one */ -#undef HAVE_GETTIMEOFDAY -int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp); -#define HAVE_LIBSSH2_GETTIMEOFDAY -#define LIBSSH2_GETTIMEOFDAY_WIN32 /* enable the win32 implementation */ -#else -#ifdef HAVE_GETTIMEOFDAY -#define _libssh2_gettimeofday(x,y) gettimeofday(x,y) -#define HAVE_LIBSSH2_GETTIMEOFDAY -#endif -#endif - -#endif /* _LIBSSH2_MISC_H */ diff --git a/vendor/libssh2-1.4.2/src/openssl.c b/vendor/libssh2-1.4.2/src/openssl.c deleted file mode 100644 index 481982c..0000000 --- a/vendor/libssh2-1.4.2/src/openssl.c +++ /dev/null @@ -1,804 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. - * Copyright (c) 2004-2006, Sara Golemon - * - * 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 "libssh2_priv.h" - -#ifndef LIBSSH2_LIBGCRYPT /* compile only if we build with OpenSSL */ - -#include - -#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; - - libssh2_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; -} - -#if LIBSSH2_DSA -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; -} -#endif /* LIBSSH_DSA */ - -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; -} - -#if LIBSSH2_AES_CTR - -#include -#include - -typedef struct -{ - AES_KEY key; - EVP_CIPHER_CTX *aes_ctx; - unsigned char ctr[AES_BLOCK_SIZE]; -} aes_ctr_ctx; - -static int -aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) /* init key */ -{ - /* - * variable "c" is leaked from this scope, but is later freed - * in aes_ctr_cleanup - */ - aes_ctr_ctx *c = malloc(sizeof(*c)); - const EVP_CIPHER *aes_cipher; - (void) enc; - - if (c == NULL) - return 0; - - switch (ctx->key_len) { - case 16: - aes_cipher = EVP_aes_128_ecb(); - break; - case 24: - aes_cipher = EVP_aes_192_ecb(); - break; - case 32: - aes_cipher = EVP_aes_256_ecb(); - break; - default: - return 0; - } - c->aes_ctx = malloc(sizeof(EVP_CIPHER_CTX)); - if (c->aes_ctx == NULL) - return 0; - - if (EVP_EncryptInit(c->aes_ctx, aes_cipher, key, NULL) != 1) { - return 0; - } - - EVP_CIPHER_CTX_set_padding(c->aes_ctx, 0); - - memcpy(c->ctr, iv, AES_BLOCK_SIZE); - - EVP_CIPHER_CTX_set_app_data(ctx, c); - - return 1; -} - -static int -aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, - size_t inl) /* encrypt/decrypt data */ -{ - aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); - unsigned char b1[AES_BLOCK_SIZE]; - size_t i = 0; - int outlen = 0; - - if (inl != 16) /* libssh2 only ever encrypt one block */ - return 0; - - if (c == NULL) { - return 0; - } - -/* - To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each - blocks of length L), the encryptor first encrypts with - to obtain a block B1. The block B1 is then XORed with P1 to generate - the ciphertext block C1. The counter X is then incremented -*/ - - if (EVP_EncryptUpdate(c->aes_ctx, b1, &outlen, c->ctr, AES_BLOCK_SIZE) != 1) { - return 0; - } - - for (i = 0; i < 16; i++) - *out++ = *in++ ^ b1[i]; - - i = 15; - while (c->ctr[i]++ == 0xFF) { - if (i == 0) - break; - i--; - } - - return 1; -} - -static int -aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */ -{ - aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx); - - if (c == NULL) { - return 1; - } - - if (c->aes_ctx != NULL) { - _libssh2_cipher_dtor(c->aes_ctx); - free(c->aes_ctx); - } - - free(c); - - return 1; -} - -static const EVP_CIPHER * -make_ctr_evp (size_t keylen, EVP_CIPHER *aes_ctr_cipher) -{ - aes_ctr_cipher->block_size = 16; - aes_ctr_cipher->key_len = keylen; - aes_ctr_cipher->iv_len = 16; - aes_ctr_cipher->init = aes_ctr_init; - aes_ctr_cipher->do_cipher = aes_ctr_do_cipher; - aes_ctr_cipher->cleanup = aes_ctr_cleanup; - - return aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_128_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (16, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_192_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (24, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -const EVP_CIPHER * -_libssh2_EVP_aes_256_ctr(void) -{ - static EVP_CIPHER aes_ctr_cipher; - return !aes_ctr_cipher.key_len? - make_ctr_evp (32, &aes_ctr_cipher) : &aes_ctr_cipher; -} - -void _libssh2_init_aes_ctr(void) -{ - _libssh2_EVP_aes_128_ctr(); - _libssh2_EVP_aes_192_ctr(); - _libssh2_EVP_aes_256_ctr(); -} - -#else -void _libssh2_init_aes_ctr(void) {} -#endif /* LIBSSH2_AES_CTR */ - -/* 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; -} - -typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *, - void * u); - -static int -read_private_key_from_file(void ** key_ctx, - pem_read_bio_func read_private_key, - const char * filename, - unsigned const char *passphrase) -{ - BIO * bp; - - *key_ctx = NULL; - - bp = BIO_new_file(filename, "r"); - if (!bp) { - return -1; - } - - *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb, - (void *) passphrase); - - BIO_free(bp); - return (*key_ctx) ? 0 : -1; -} - -int -_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_rsa = - (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) rsa, read_rsa, - filename, passphrase); -} - -#if LIBSSH2_DSA -int -_libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, - LIBSSH2_SESSION * session, - const char *filename, unsigned const char *passphrase) -{ - pem_read_bio_func read_dsa = - (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; - (void) session; - - _libssh2_init_if_needed (); - - return read_private_key_from_file((void **) dsa, read_dsa, - filename, passphrase); -} -#endif /* LIBSSH_DSA */ - -int -_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, - libssh2_rsa_ctx * rsactx, - const unsigned char *hash, - size_t hash_len, - unsigned char **signature, size_t *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; -} - -#if LIBSSH2_DSA -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; - (void) hash_len; - - sig = DSA_do_sign(hash, SHA_DIGEST_LENGTH, dsactx); - if (!sig) { - return -1; - } - - r_len = BN_num_bytes(sig->r); - if (r_len < 1 || r_len > 20) { - DSA_SIG_free(sig); - return -1; - } - s_len = BN_num_bytes(sig->s); - if (s_len < 1 || s_len > 20) { - DSA_SIG_free(sig); - return -1; - } - - memset(signature, 0, 40); - - BN_bn2bin(sig->r, signature + (20 - r_len)); - BN_bn2bin(sig->s, signature + 20 + (20 - s_len)); - - DSA_SIG_free(sig); - - return 0; -} -#endif /* LIBSSH_DSA */ - -void -libssh2_sha1(const unsigned char *message, unsigned long len, - unsigned char *out) -{ - EVP_MD_CTX ctx; - - EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1")); - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); -} - -void -libssh2_md5(const unsigned char *message, unsigned long len, - unsigned char *out) -{ - EVP_MD_CTX ctx; - - EVP_DigestInit(&ctx, EVP_get_digestbyname("md5")); - EVP_DigestUpdate(&ctx, message, len); - EVP_DigestFinal(&ctx, out, NULL); -} - -static unsigned char * -write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes) -{ - unsigned char *p = buf; - - /* Left space for bn size which will be written below. */ - p += 4; - - *p = 0; - BN_bn2bin(bn, p + 1); - if (!(*(p + 1) & 0x80)) { - memmove(p, p + 1, --bn_bytes); - } - _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */ - - return p + bn_bytes; -} - -static unsigned char * -gen_publickey_from_rsa(LIBSSH2_SESSION *session, RSA *rsa, - size_t *key_len) -{ - int e_bytes, n_bytes; - unsigned long len; - unsigned char* key; - unsigned char* p; - - e_bytes = BN_num_bytes(rsa->e) + 1; - n_bytes = BN_num_bytes(rsa->n) + 1; - - /* Key form is "ssh-rsa" + e + n. */ - len = 4 + 7 + 4 + e_bytes + 4 + n_bytes; - - key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { - return NULL; - } - - /* Process key encoding. */ - p = key; - - _libssh2_htonu32(p, 7); /* Key type. */ - p += 4; - memcpy(p, "ssh-rsa", 7); - p += 7; - - p = write_bn(p, rsa->e, e_bytes); - p = write_bn(p, rsa->n, n_bytes); - - *key_len = (size_t)(p - key); - return key; -} - -static unsigned char * -gen_publickey_from_dsa(LIBSSH2_SESSION* session, DSA *dsa, - size_t *key_len) -{ - int p_bytes, q_bytes, g_bytes, k_bytes; - unsigned long len; - unsigned char* key; - unsigned char* p; - - p_bytes = BN_num_bytes(dsa->p) + 1; - q_bytes = BN_num_bytes(dsa->q) + 1; - g_bytes = BN_num_bytes(dsa->g) + 1; - k_bytes = BN_num_bytes(dsa->pub_key) + 1; - - /* Key form is "ssh-dss" + p + q + g + pub_key. */ - len = 4 + 7 + 4 + p_bytes + 4 + q_bytes + 4 + g_bytes + 4 + k_bytes; - - key = LIBSSH2_ALLOC(session, len); - if (key == NULL) { - return NULL; - } - - /* Process key encoding. */ - p = key; - - _libssh2_htonu32(p, 7); /* Key type. */ - p += 4; - memcpy(p, "ssh-dss", 7); - p += 7; - - p = write_bn(p, dsa->p, p_bytes); - p = write_bn(p, dsa->q, q_bytes); - p = write_bn(p, dsa->g, g_bytes); - p = write_bn(p, dsa->pub_key, k_bytes); - - *key_len = (size_t)(p - key); - return key; -} - -static int -gen_publickey_from_rsa_evp(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - EVP_PKEY *pk) -{ - RSA* rsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; - size_t key_len; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from RSA private key envelop"); - - rsa = EVP_PKEY_get1_RSA(pk); - if (rsa == NULL) { - /* Assume memory allocation error... what else could it be ? */ - goto __alloc_error; - } - - method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-rsa. */ - if (method_buf == NULL) { - goto __alloc_error; - } - - key = gen_publickey_from_rsa(session, rsa, &key_len); - if (key == NULL) { - goto __alloc_error; - } - RSA_free(rsa); - - memcpy(method_buf, "ssh-rsa", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; - return 0; - - __alloc_error: - if (rsa != NULL) { - RSA_free(rsa); - } - if (method_buf != NULL) { - LIBSSH2_FREE(session, method_buf); - } - - return _libssh2_error(session, - LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for private key data"); -} - -static int -gen_publickey_from_dsa_evp(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - EVP_PKEY *pk) -{ - DSA* dsa = NULL; - unsigned char* key; - unsigned char* method_buf = NULL; - size_t key_len; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from DSA private key envelop"); - - dsa = EVP_PKEY_get1_DSA(pk); - if (dsa == NULL) { - /* Assume memory allocation error... what else could it be ? */ - goto __alloc_error; - } - - method_buf = LIBSSH2_ALLOC(session, 7); /* ssh-dss. */ - if (method_buf == NULL) { - goto __alloc_error; - } - - key = gen_publickey_from_dsa(session, dsa, &key_len); - if (key == NULL) { - goto __alloc_error; - } - DSA_free(dsa); - - memcpy(method_buf, "ssh-dss", 7); - *method = method_buf; - *method_len = 7; - *pubkeydata = key; - *pubkeydata_len = key_len; - return 0; - - __alloc_error: - if (dsa != NULL) { - DSA_free(dsa); - } - if (method_buf != NULL) { - LIBSSH2_FREE(session, method_buf); - } - - return _libssh2_error(session, - LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for private key data"); -} - -int -_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session, - unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *pubkeydata_len, - const char *privatekey, - const char *passphrase) -{ - int st; - BIO* bp; - EVP_PKEY* pk; - - _libssh2_debug(session, - LIBSSH2_TRACE_AUTH, - "Computing public key from private key file: %s", - privatekey); - - bp = BIO_new_file(privatekey, "r"); - if (bp == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key from private key " - "file: Unable to open private key file"); - } - 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(); - } - BIO_reset(bp); - pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase); - BIO_free(bp); - - if (pk == NULL) { - return _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Wrong passphrase or invalid/unrecognized " - "private key file format"); - } - - switch (pk->type) { - case EVP_PKEY_RSA : - st = gen_publickey_from_rsa_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); - break; - - case EVP_PKEY_DSA : - st = gen_publickey_from_dsa_evp( - session, method, method_len, pubkeydata, pubkeydata_len, pk); - break; - - default : - st = _libssh2_error(session, - LIBSSH2_ERROR_FILE, - "Unable to extract public key " - "from private key file: " - "Unsupported private key file format"); - break; - } - - EVP_PKEY_free(pk); - return st; -} - -#endif /* !LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/openssl.h b/vendor/libssh2-1.4.2/src/openssl.h deleted file mode 100644 index 6d2aeed..0000000 --- a/vendor/libssh2-1.4.2/src/openssl.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (C) 2009, 2010 Simon Josefsson - * 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 -#include -#ifndef OPENSSL_NO_MD5 -#include -#endif -#include -#include -#include -#include -#include - -#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_CTR 1 -# define LIBSSH2_AES 1 -#else -# define LIBSSH2_AES_CTR 0 -# 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 EVP_MD_CTX -#define libssh2_sha1_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("sha1")) -#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_sha1_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -void libssh2_sha1(const unsigned char *message, unsigned long len, unsigned char *out); - -#define libssh2_md5_ctx EVP_MD_CTX -#define libssh2_md5_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("md5")) -#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) -void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char *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() OpenSSL_add_all_algorithms() -#define libssh2_crypto_exit() - -#define libssh2_rsa_ctx RSA - -#define _libssh2_rsa_free(rsactx) RSA_free(rsactx) - -#define libssh2_dsa_ctx DSA - - -#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_aes128ctr _libssh2_EVP_aes_128_ctr -#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr -#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr -#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 - -#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) - -const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void); -const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void); -const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void); - diff --git a/vendor/libssh2-1.4.2/src/packet.c b/vendor/libssh2-1.4.2/src/packet.c deleted file mode 100644 index bfbd56a..0000000 --- a/vendor/libssh2-1.4.2/src/packet.c +++ /dev/null @@ -1,1243 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 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 -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifdef HAVE_INTTYPES_H -#include -#endif - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#include - -#include "transport.h" -#include "channel.h" -#include "packet.h" - -/* - * libssh2_packet_queue_listener - * - * Queue a connection request for a listener - */ -static inline int -packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, - packet_queue_listener_state_t *listen_state) -{ - /* - * Look for a matching listener - */ - /* 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 *listn = _libssh2_list_first(&session->listeners); - char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; - int rc; - - (void) datalen; - - if (listen_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5; - 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); - - _libssh2_debug(session, LIBSSH2_TRACE_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 (listn) { - if ((listn->port == (int) listen_state->port) && - (strlen(listn->host) == listen_state->host_len) && - (memcmp (listn->host, listen_state->host, - listen_state->host_len) == 0)) { - /* This is our listener */ - LIBSSH2_CHANNEL *channel = NULL; - listen_state->channel = NULL; - - if (listen_state->state == libssh2_NB_state_allocated) { - if (listn->queue_maxsize && - (listn->queue_maxsize <= listn->queue_size)) { - /* Queue is full */ - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - _libssh2_debug(session, LIBSSH2_TRACE_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"); - failure_code = SSH_OPEN_RESOURCE_SHORTAGE; - listen_state->state = libssh2_NB_state_sent; - break; - } - listen_state->channel = channel; - - 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"); - LIBSSH2_FREE(session, channel); - failure_code = 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_TRACE_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_store_u32(&p, channel->remote.id); - _libssh2_store_u32(&p, channel->local.id); - _libssh2_store_u32(&p, - channel->remote.window_size_initial); - _libssh2_store_u32(&p, channel->remote.packet_size); - - listen_state->state = libssh2_NB_state_created; - } - - if (listen_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, listen_state->packet, - 17, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - listen_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Unable to send channel " - "open confirmation"); - } - - /* Link the channel into the end of the queue list */ - _libssh2_list_add(&listn->queue, - &listen_state->channel->node); - listn->queue_size++; - - listen_state->state = libssh2_NB_state_idle; - return 0; - } - } - - listn = _libssh2_list_next(&listn->node); - } - - listen_state->state = libssh2_NB_state_sent; - } - - /* We're not listening to you */ - p = listen_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; - _libssh2_store_u32(&p, listen_state->sender_channel); - _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1); - _libssh2_htonu32(p, 0); - - rc = _libssh2_transport_send(session, listen_state->packet, - packet_len, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - listen_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, "Unable to send open failure"); - - } - listen_state->state = libssh2_NB_state_idle; - return 0; -} - -/* - * packet_x11_open - * - * Accept a forwarded X11 connection - */ -static inline int -packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, - unsigned long datalen, - packet_x11_open_state_t *x11open_state) -{ - int failure_code = SSH_OPEN_CONNECT_FAILED; - /* 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 = x11open_state->channel; - int rc; - - (void) datalen; - - if (x11open_state->state == libssh2_NB_state_idle) { - unsigned char *s = data + (sizeof("x11") - 1) + 5; - 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); - - _libssh2_debug(session, LIBSSH2_TRACE_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, - "allocate a channel for new connection"); - failure_code = 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, - "allocate a channel for new connection"); - LIBSSH2_FREE(session, channel); - failure_code = 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_TRACE_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_store_u32(&p, channel->remote.id); - _libssh2_store_u32(&p, channel->local.id); - _libssh2_store_u32(&p, channel->remote.window_size_initial); - _libssh2_store_u32(&p, channel->remote.packet_size); - - x11open_state->state = libssh2_NB_state_created; - } - - if (x11open_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, x11open_state->packet, 17, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - x11open_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send channel open " - "confirmation"); - } - - /* Link the channel into the session */ - _libssh2_list_add(&session->channels, &channel->node); - - /* - * 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 = SSH_OPEN_RESOURCE_SHORTAGE; - /* fall-trough */ - x11_exit: - p = x11open_state->packet; - *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE; - _libssh2_store_u32(&p, x11open_state->sender_channel); - _libssh2_store_u32(&p, failure_code); - _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1); - _libssh2_htonu32(p, 0); - - rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - x11open_state->state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, "Unable to send open failure"); - } - x11open_state->state = libssh2_NB_state_idle; - return 0; -} - -/* - * _libssh2_packet_add - * - * Create a new packet and attach it to the brigade. Called from the transport - * layer when it has received a packet. - * - * The input pointer 'data' is pointing to allocated data that this function - * is asked to deal with so on failure OR success, it must be freed fine. - * - * This function will always be called with 'datalen' greater than zero. - */ -int -_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate) -{ - int rc = 0; - char *message=NULL; - char *language=NULL; - size_t message_len=0; - size_t language_len=0; - LIBSSH2_CHANNEL *channelp = NULL; - size_t data_head = 0; - unsigned char msg = data[0]; - - switch(session->packAdd_state) { - case libssh2_NB_state_idle: - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Packet type %d received, length=%d", - (int) msg, (int) datalen); - - if ((macstate == LIBSSH2_MAC_INVALID) && - (!session->macerror || - LIBSSH2_MACERROR(session, (char *) data, datalen))) { - /* Bad MAC input, but no callback set or non-zero return from the - callback */ - - LIBSSH2_FREE(session, data); - return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC, - "Invalid MAC received"); - } - session->packAdd_state = libssh2_NB_state_allocated; - break; - case libssh2_NB_state_jump1: - goto libssh2_packet_add_jump_point1; - case libssh2_NB_state_jump2: - goto libssh2_packet_add_jump_point2; - case libssh2_NB_state_jump3: - goto libssh2_packet_add_jump_point3; - case libssh2_NB_state_jump4: - goto libssh2_packet_add_jump_point4; - case libssh2_NB_state_jump5: - goto libssh2_packet_add_jump_point5; - default: /* nothing to do */ - break; - } - - if (session->packAdd_state == libssh2_NB_state_allocated) { - /* A couple exceptions to the packet adding rule: */ - switch (msg) { - - /* - byte SSH_MSG_DISCONNECT - uint32 reason code - string description in ISO-10646 UTF-8 encoding [RFC3629] - string language tag [RFC3066] - */ - - case SSH_MSG_DISCONNECT: - if(datalen >= 5) { - size_t reason = _libssh2_ntohu32(data + 1); - - if(datalen >= 9) { - message_len = _libssh2_ntohu32(data + 5); - - if(message_len < datalen-13) { - /* 9 = packet_type(1) + reason(4) + message_len(4) */ - message = (char *) data + 9; - - language_len = _libssh2_ntohu32(data + 9 + message_len); - language = (char *) data + 9 + message_len + 4; - - if(language_len > (datalen-13-message_len)) { - /* bad input, clear info */ - language = message = NULL; - language_len = message_len = 0; - } - } - else - /* bad size, clear it */ - message_len=0; - } - if (session->ssh_msg_disconnect) { - LIBSSH2_DISCONNECT(session, reason, message, - message_len, language, language_len); - } - _libssh2_debug(session, LIBSSH2_TRACE_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 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT, - "socket disconnect"); - /* - byte SSH_MSG_IGNORE - string data - */ - - case SSH_MSG_IGNORE: - if (datalen >= 2) { - if (session->ssh_msg_ignore) { - LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1); - } - } else if (session->ssh_msg_ignore) { - LIBSSH2_IGNORE(session, "", 0); - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_DEBUG - boolean always_display - string message in ISO-10646 UTF-8 encoding [RFC3629] - string language tag [RFC3066] - */ - - case SSH_MSG_DEBUG: - if(datalen >= 2) { - int always_display= data[1]; - - if(datalen >= 6) { - message_len = _libssh2_ntohu32(data + 2); - - if(message_len <= (datalen - 10)) { - /* 6 = packet_type(1) + display(1) + message_len(4) */ - message = (char *) data + 6; - language_len = _libssh2_ntohu32(data + 6 + message_len); - - if(language_len <= (datalen - 10 - message_len)) - language = (char *) data + 10 + message_len; - } - } - - 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_TRACE_TRANS, - "Debug Packet: %s", message); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_GLOBAL_REQUEST - string request name in US-ASCII only - boolean want reply - .... request-specific data follows - */ - - case SSH_MSG_GLOBAL_REQUEST: - if(datalen >= 5) { - uint32_t len =0; - unsigned char want_reply=0; - len = _libssh2_ntohu32(data + 1); - if(datalen >= (6 + len)) { - want_reply = data[5 + len]; - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "Received global request type %.*s (wr %X)", - len, data + 5, want_reply); - } - - - if (want_reply) { - unsigned char packet = SSH_MSG_REQUEST_FAILURE; - libssh2_packet_add_jump_point5: - session->packAdd_state = libssh2_NB_state_jump5; - rc = _libssh2_transport_send(session, &packet, 1, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_EXTENDED_DATA - uint32 recipient channel - uint32 data_type_code - string data - */ - - case SSH_MSG_CHANNEL_EXTENDED_DATA: - /* streamid(4) */ - data_head += 4; - - /* fall-through */ - - /* - byte SSH_MSG_CHANNEL_DATA - uint32 recipient channel - string data - */ - - case SSH_MSG_CHANNEL_DATA: - /* packet_type(1) + channelno(4) + datalen(4) */ - data_head += 9; - - if(datalen >= data_head) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - - if (!channelp) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN, - "Packet received for unknown channel"); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } -#ifdef LIBSSH2DEBUG - { - uint32_t stream_id = 0; - if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA) - stream_id = _libssh2_ntohu32(data + 5); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "%d bytes packet_add() for %lu/%lu/%lu", - (int) (datalen - data_head), - channelp->local.id, - channelp->remote.id, - stream_id); - } -#endif - if ((channelp->remote.extended_data_ignore_mode == - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) && - (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) { - /* Pretend we didn't receive this */ - LIBSSH2_FREE(session, data); - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Ignoring extended data and refunding %d bytes", - (int) (datalen - 13)); - session->packAdd_channelp = channelp; - - /* 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_channelp, - datalen - 13, - 1, NULL); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - - /* - * REMEMBER! remote means remote as source of data, - * NOT remote window! - */ - if (channelp->remote.packet_size < (datalen - 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"); - datalen = channelp->remote.packet_size + data_head; - } - if (channelp->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"); - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - } - /* Reset EOF status */ - channelp->remote.eof = 0; - - if ((datalen - data_head) > channelp->remote.window_size) { - _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED, - "Remote sent more data than current " - "window allows, truncating"); - datalen = channelp->remote.window_size + data_head; - channelp->remote.window_size = 0; - } - else - /* Now that we've received it, shrink our window */ - channelp->remote.window_size -= datalen - data_head; - - break; - - /* - byte SSH_MSG_CHANNEL_EOF - uint32 recipient channel - */ - - case SSH_MSG_CHANNEL_EOF: - if(datalen >= 5) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if (!channelp) - /* We may have freed already, just quietly ignore this... */ - ; - else { - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "EOF received for channel %lu/%lu", - channelp->local.id, - channelp->remote.id); - channelp->remote.eof = 1; - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string request type in US-ASCII characters only - boolean want reply - .... type-specific data follows - */ - - case SSH_MSG_CHANNEL_REQUEST: - if(datalen >= 9) { - uint32_t channel = _libssh2_ntohu32(data + 1); - uint32_t len = _libssh2_ntohu32(data + 5); - unsigned char want_reply = 1; - - if(len < (datalen - 10)) - want_reply = data[9 + len]; - - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, - "Channel %d received request type %.*s (wr %X)", - channel, len, data + 9, want_reply); - - if (len == sizeof("exit-status") - 1 - && !memcmp("exit-status", data + 9, - sizeof("exit-status") - 1)) { - - /* we've got "exit-status" packet. Set the session value */ - if(datalen >= 20) - channelp = - _libssh2_channel_locate(session, channel); - - if (channelp) { - channelp->exit_status = - _libssh2_ntohu32(data + 9 + sizeof("exit-status")); - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit status %lu received for " - "channel %lu/%lu", - channelp->exit_status, - channelp->local.id, - channelp->remote.id); - } - - } - else if (len == sizeof("exit-signal") - 1 - && !memcmp("exit-signal", data + 9, - sizeof("exit-signal") - 1)) { - /* command terminated due to signal */ - if(datalen >= 20) - channelp = _libssh2_channel_locate(session, channel); - - if (channelp) { - /* set signal name (without SIG prefix) */ - uint32_t namelen = - _libssh2_ntohu32(data + 9 + sizeof("exit-signal")); - channelp->exit_signal = - LIBSSH2_ALLOC(session, namelen + 1); - if (!channelp->exit_signal) - rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "memory for signal name"); - else { - memcpy(channelp->exit_signal, - data + 13 + sizeof("exit_signal"), namelen); - channelp->exit_signal[namelen] = '\0'; - /* TODO: save error message and language tag */ - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Exit signal %s received for " - "channel %lu/%lu", - channelp->exit_signal, - channelp->local.id, - channelp->remote.id); - } - } - } - - - if (want_reply) { - unsigned char packet[5]; - libssh2_packet_add_jump_point4: - session->packAdd_state = libssh2_NB_state_jump4; - packet[0] = SSH_MSG_CHANNEL_FAILURE; - memcpy(&packet[1], data+1, 4); - rc = _libssh2_transport_send(session, packet, 5, NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return rc; - - /* - byte SSH_MSG_CHANNEL_CLOSE - uint32 recipient channel - */ - - case SSH_MSG_CHANNEL_CLOSE: - if(datalen >= 5) - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if (!channelp) { - /* 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_TRACE_CONN, - "Close received for channel %lu/%lu", - channelp->local.id, - channelp->remote.id); - - channelp->remote.close = 1; - channelp->remote.eof = 1; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - - /* - byte SSH_MSG_CHANNEL_OPEN - string "session" - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - */ - - case SSH_MSG_CHANNEL_OPEN: - if(datalen < 17) - ; - else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) && - ((sizeof("forwarded-tcpip") - 1) == - _libssh2_ntohu32(data + 1)) - && - (memcmp(data + 5, "forwarded-tcpip", - sizeof("forwarded-tcpip") - 1) == 0)) { - - /* init the state struct */ - memset(&session->packAdd_Qlstn_state, 0, - sizeof(session->packAdd_Qlstn_state)); - - libssh2_packet_add_jump_point2: - session->packAdd_state = libssh2_NB_state_jump2; - rc = packet_queue_listener(session, data, datalen, - &session->packAdd_Qlstn_state); - } - else if ((datalen >= (sizeof("x11") + 4)) && - ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) && - (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) { - - /* init the state struct */ - memset(&session->packAdd_x11open_state, 0, - sizeof(session->packAdd_x11open_state)); - - libssh2_packet_add_jump_point3: - session->packAdd_state = libssh2_NB_state_jump3; - rc = packet_x11_open(session, data, datalen, - &session->packAdd_x11open_state); - } - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return rc; - - /* - byte SSH_MSG_CHANNEL_WINDOW_ADJUST - uint32 recipient channel - uint32 bytes to add - */ - case SSH_MSG_CHANNEL_WINDOW_ADJUST: - if(datalen < 9) - ; - else { - uint32_t bytestoadd = _libssh2_ntohu32(data + 5); - channelp = - _libssh2_channel_locate(session, - _libssh2_ntohu32(data + 1)); - if(channelp) { - channelp->local.window_size += bytestoadd; - - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Window adjust for channel %lu/%lu, " - "adding %lu bytes, new window_size=%lu", - channelp->local.id, - channelp->remote.id, - bytestoadd, - channelp->local.window_size); - } - } - LIBSSH2_FREE(session, data); - session->packAdd_state = libssh2_NB_state_idle; - return 0; - default: - break; - } - - session->packAdd_state = libssh2_NB_state_sent; - } - - if (session->packAdd_state == libssh2_NB_state_sent) { - LIBSSH2_PACKET *packetp = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET)); - if (!packetp) { - _libssh2_debug(session, LIBSSH2_ERROR_ALLOC, - "memory for packet"); - session->packAdd_state = libssh2_NB_state_idle; - return LIBSSH2_ERROR_ALLOC; - } - packetp->data = data; - packetp->data_len = datalen; - packetp->data_head = data_head; - - _libssh2_list_add(&session->packets, &packetp->node); - - session->packAdd_state = libssh2_NB_state_sent1; - } - - if ((msg == 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_TRACE_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_transport_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; - - 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 == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - 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(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, const unsigned char *match_buf, - size_t match_len) -{ - LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets); - - _libssh2_debug(session, LIBSSH2_TRACE_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; - - /* unlink struct from session->packets */ - _libssh2_list_remove(&packet->node); - - LIBSSH2_FREE(session, packet); - - return 0; - } - packet = _libssh2_list_next(&packet->node); - } - 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(LIBSSH2_SESSION * session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len) -{ - int i, packet_types_len = strlen((char *) packet_types); - - for(i = 0; i < packet_types_len; i++) { - if (0 == _libssh2_packet_ask(session, packet_types[i], data, - data_len, match_ofs, - match_buf, match_len)) { - return 0; - } - } - - return -1; -} - -/* - * _libssh2_packet_require - * - * Loops _libssh2_transport_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(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len, - packet_require_state_t *state) -{ - if (state->start == 0) { - if (_libssh2_packet_ask(session, packet_type, data, data_len, - match_ofs, match_buf, - match_len) == 0) { - /* A packet was available in the packet brigade */ - return 0; - } - - state->start = time(NULL); - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - int ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) - return ret; - 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(session, packet_type, data, data_len, - match_ofs, match_buf, match_len); - state->start = 0; - return ret; - } else if (ret == 0) { - /* nothing available, wait until data arrives or we time out */ - long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - - state->start); - - if (left <= 0) { - state->start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - return -1; /* no packet available yet */ - } - } - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* - * _libssh2_packet_burn - * - * Loops _libssh2_transport_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; - size_t 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(session, all_packets, &data, &data_len, 0, - NULL, 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_TRACE_TRANS, - "Blocking until packet becomes available to burn"); - *state = libssh2_NB_state_created; - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - ret = _libssh2_transport_read(session); - if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } 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(session, ret, &data, &data_len, 0, NULL, 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 LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* - * _libssh2_packet_requirev - * - * Loops _libssh2_transport_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(LIBSSH2_SESSION *session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, size_t match_len, - packet_requirev_state_t * state) -{ - if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs, - match_buf, match_len) == 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_transport_read(session); - if ((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) { - state->start = 0; - return ret; - } - if (ret <= 0) { - long left = LIBSSH2_READ_TIMEOUT - - (long)(time(NULL) - state->start); - - if (left <= 0) { - state->start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - else if (ret == LIBSSH2_ERROR_EAGAIN) { - return ret; - } - } - - if (strchr((char *) packet_types, ret)) { - /* Be lazy, let packet_ask pull it out of the brigade */ - return _libssh2_packet_askv(session, packet_types, data, - data_len, match_ofs, match_buf, - match_len); - } - } - - /* Only reached if the socket died */ - state->start = 0; - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - diff --git a/vendor/libssh2-1.4.2/src/packet.h b/vendor/libssh2-1.4.2/src/packet.h deleted file mode 100644 index d66b15b..0000000 --- a/vendor/libssh2-1.4.2/src/packet.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef LIBSSH2_PACKET_H -#define LIBSSH2_PACKET_H -/* - * Copyright (C) 2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * 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. - * - */ - -int _libssh2_packet_read(LIBSSH2_SESSION * session); - -int _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len); - -int _libssh2_packet_askv(LIBSSH2_SESSION * session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t match_len); -int _libssh2_packet_require(LIBSSH2_SESSION * session, - unsigned char packet_type, unsigned char **data, - size_t *data_len, int match_ofs, - const unsigned char *match_buf, - size_t match_len, - packet_require_state_t * state); -int _libssh2_packet_requirev(LIBSSH2_SESSION *session, - const unsigned char *packet_types, - unsigned char **data, size_t *data_len, - int match_ofs, - const unsigned char *match_buf, - size_t 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); - -#endif /* LIBSSH2_PACKET_H */ diff --git a/vendor/libssh2-1.4.2/src/pem.c b/vendor/libssh2-1.4.2/src/pem.c deleted file mode 100644 index 5749bc8..0000000 --- a/vendor/libssh2-1.4.2/src/pem.c +++ /dev/null @@ -1,213 +0,0 @@ -/* 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" - -#ifdef LIBSSH2_LIBGCRYPT /* compile only if we build with libgcrypt */ - -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; -} - -#endif /* LIBSSH2_LIBGCRYPT */ diff --git a/vendor/libssh2-1.4.2/src/publickey.c b/vendor/libssh2-1.4.2/src/publickey.c deleted file mode 100644 index ab76ab2..0000000 --- a/vendor/libssh2-1.4.2/src/publickey.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2010 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" -#include "libssh2_publickey.h" -#include "channel.h" -#include "session.h" - -#define LIBSSH2_PUBLICKEY_VERSION 2 - -/* Numericised response codes -- Not IETF, just 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 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 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} -}; - -/* - * publickey_status_error - * - * Format an error message from a status code - */ -static void -publickey_status_error(const LIBSSH2_PUBLICKEY *pkey, - LIBSSH2_SESSION *session, int status) -{ - const char *msg; - - /* 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) { - msg = "unknown"; - } else { - msg = publickey_status_codes[status].name; - } - - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, msg); -} - -/* - * publickey_packet_receive - * - * Read a packet from the subsystem - */ -static int -publickey_packet_receive(LIBSSH2_PUBLICKEY * pkey, - unsigned char **data, size_t *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(channel, 0, (char *) buffer, 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc != 4) { - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid response from publickey subsystem"); - } - - pkey->receive_packet_len = _libssh2_ntohu32(buffer); - pkey->receive_packet = - LIBSSH2_ALLOC(session, pkey->receive_packet_len); - if (!pkey->receive_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate publickey response " - "buffer"); - } - - pkey->receive_state = libssh2_NB_state_sent; - } - - if (pkey->receive_state == libssh2_NB_state_sent) { - rc = _libssh2_channel_read(channel, 0, (char *) pkey->receive_packet, - pkey->receive_packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc != (int)pkey->receive_packet_len) { - LIBSSH2_FREE(session, pkey->receive_packet); - pkey->receive_packet = NULL; - pkey->receive_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for publickey subsystem " - "response packet"); - } - - *data = pkey->receive_packet; - *data_len = pkey->receive_packet_len; - } - - pkey->receive_state = libssh2_NB_state_idle; - - return 0; -} - -/* 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 -publickey_response_id(unsigned char **pdata, size_t data_len) -{ - size_t response_len; - unsigned char *data = *pdata; - const LIBSSH2_PUBLICKEY_CODE_LIST *codes = publickey_response_codes; - - if (data_len < 4) { - /* Malformed response */ - return -1; - } - response_len = _libssh2_ntohu32(data); - data += 4; - data_len -= 4; - if (data_len < 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; -} - -/* publickey_response_success - * - * Generic helper routine to wait for success response and nothing else - */ -static int -publickey_response_success(LIBSSH2_PUBLICKEY * pkey) -{ - LIBSSH2_SESSION *session = pkey->channel->session; - unsigned char *data, *s; - size_t data_len; - int response; - - while (1) { - int rc = publickey_packet_receive(pkey, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - } - - s = data; - response = publickey_response_id(&s, data_len); - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error, or processing complete */ - { - unsigned long status = _libssh2_ntohu32(s); - - LIBSSH2_FREE(session, data); - - if (status == LIBSSH2_PUBLICKEY_SUCCESS) - return 0; - - publickey_status_error(pkey, session, status); - return -1; - } - default: - LIBSSH2_FREE(session, data); - if (response < 0) { - return _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response"); - } - /* Unknown/Unexpected */ - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Unexpected publickey subsystem response"); - data = NULL; - } - } - /* never reached, but include `return` to silence compiler warnings */ - return -1; -} - -/* ***************** - * Publickey API * - ***************** */ - -/* - * publickey_init - * - * Startup the publickey subsystem - */ -static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) -{ - 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_TRACE_PUBLICKEY, - "Initializing publickey subsystem"); - - session->pkeyInit_state = libssh2_NB_state_allocated; - } - - if (session->pkeyInit_state == libssh2_NB_state_allocated) { - - session->pkeyInit_channel = - _libssh2_channel_open(session, "session", - sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, - 0); - if (!session->pkeyInit_channel) { - if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) - /* The error state is already set, so leave it */ - return NULL; - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to startup channel"); - goto err_exit; - } - - 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", - sizeof("publickey") - 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting publickey subsystem"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to request publickey subsystem"); - goto err_exit; - } - - session->pkeyInit_state = libssh2_NB_state_sent1; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent1) { - unsigned char *s; - rc = _libssh2_channel_extended_data(session->pkeyInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting publickey subsystem"); - 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"); - goto err_exit; - } - memset(session->pkeyInit_pkey, 0, sizeof(LIBSSH2_PUBLICKEY)); - session->pkeyInit_pkey->channel = session->pkeyInit_channel; - session->pkeyInit_pkey->version = 0; - - s = session->pkeyInit_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); - - session->pkeyInit_buffer_sent = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_PUBLICKEY, - "Sending publickey 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(session->pkeyInit_channel, 0, - session->pkeyInit_buffer, - 19 - session->pkeyInit_buffer_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending publickey version packet"); - return NULL; - } else if (rc) { - _libssh2_error(session, rc, - "Unable to send publickey version packet"); - goto err_exit; - } - session->pkeyInit_buffer_sent += rc; - if(session->pkeyInit_buffer_sent < 19) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Need to be called again to complete this"); - return NULL; - } - - session->pkeyInit_state = libssh2_NB_state_sent3; - } - - if (session->pkeyInit_state == libssh2_NB_state_sent3) { - while (1) { - unsigned char *s; - rc = publickey_packet_receive(session->pkeyInit_pkey, - &session->pkeyInit_data, - &session->pkeyInit_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response from " - "publickey subsystem"); - return NULL; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - goto err_exit; - } - - s = session->pkeyInit_data; - if ((response = - publickey_response_id(&s, session->pkeyInit_data_len)) < 0) { - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response code"); - goto err_exit; - } - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error */ - { - unsigned long status, descr_len, lang_len; - - status = _libssh2_ntohu32(s); - s += 4; - descr_len = _libssh2_ntohu32(s); - s += 4; - /* description starts here */ - s += descr_len; - lang_len = _libssh2_ntohu32(s); - s += 4; - /* lang starts here */ - s += lang_len; - - if (s > - session->pkeyInit_data + session->pkeyInit_data_len) { - _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Malformed publickey subsystem packet"); - goto err_exit; - } - - publickey_status_error(NULL, session, status); - - 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_TRACE_PUBLICKEY, - "Truncate remote publickey version from %lu", - session->pkeyInit_pkey->version); - session->pkeyInit_pkey->version = - LIBSSH2_PUBLICKEY_VERSION; - } - _libssh2_debug(session, LIBSSH2_TRACE_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"); - 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 == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block closing channel"); - 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_init - * - * Startup the publickey subsystem - */ -LIBSSH2_API LIBSSH2_PUBLICKEY * -libssh2_publickey_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_PUBLICKEY *ptr; - - BLOCK_ADJUST_ERRNO(ptr, session, - publickey_init(session)); - return ptr; -} - - - -/* - * 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; - LIBSSH2_SESSION *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) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - if (pkey->add_state == libssh2_NB_state_idle) { - pkey->add_packet = NULL; - - _libssh2_debug(session, LIBSSH2_TRACE_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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey \"add\" packet"); - } - - 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_TRACE_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(channel, 0, pkey->add_packet, - (pkey->add_s - pkey->add_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->add_s - pkey->add_packet) != rc) { - LIBSSH2_FREE(session, pkey->add_packet); - pkey->add_packet = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey add packet"); - } - LIBSSH2_FREE(session, pkey->add_packet); - pkey->add_packet = NULL; - - pkey->add_state = libssh2_NB_state_sent; - } - - rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - - 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; - LIBSSH2_SESSION *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) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - if (pkey->remove_state == libssh2_NB_state_idle) { - pkey->remove_packet = NULL; - - pkey->remove_packet = LIBSSH2_ALLOC(session, packet_len); - if (!pkey->remove_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "publickey \"remove\" packet"); - } - - 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_TRACE_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(channel, 0, pkey->remove_packet, - (pkey->remove_s - pkey->remove_packet)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->remove_s - pkey->remove_packet) != rc) { - LIBSSH2_FREE(session, pkey->remove_packet); - pkey->remove_packet = NULL; - pkey->remove_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey remove packet"); - } - LIBSSH2_FREE(session, pkey->remove_packet); - pkey->remove_packet = NULL; - - pkey->remove_state = libssh2_NB_state_sent; - } - - rc = publickey_response_success(pkey); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - - 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; - LIBSSH2_SESSION *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) - return LIBSSH2_ERROR_BAD_USE; - - channel = pkey->channel; - session = channel->session; - - 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_TRACE_PUBLICKEY, - "Sending publickey \"list\" packet"); - - pkey->listFetch_state = libssh2_NB_state_created; - } - - if (pkey->listFetch_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, - pkey->listFetch_buffer, - (pkey->listFetch_s - - pkey->listFetch_buffer)); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((pkey->listFetch_s - pkey->listFetch_buffer) != rc) { - pkey->listFetch_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send publickey list packet"); - } - - pkey->listFetch_state = libssh2_NB_state_sent; - } - - while (1) { - rc = publickey_packet_receive(pkey, &pkey->listFetch_data, - &pkey->listFetch_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, - "Timeout waiting for response from " - "publickey subsystem"); - goto err_exit; - } - - pkey->listFetch_s = pkey->listFetch_data; - if ((response = - publickey_response_id(&pkey->listFetch_s, - pkey->listFetch_data_len)) < 0) { - _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_PROTOCOL, - "Invalid publickey subsystem response code"); - goto err_exit; - } - - switch (response) { - case LIBSSH2_PUBLICKEY_RESPONSE_STATUS: - /* Error, or processing complete */ - { - unsigned long status, descr_len, lang_len; - - status = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - descr_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* description starts at pkey->listFetch_s */ - pkey->listFetch_s += descr_len; - lang_len = _libssh2_ntohu32(pkey->listFetch_s); - pkey->listFetch_s += 4; - /* lang starts at 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"); - 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; - } - - publickey_status_error(pkey, session, status); - 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"); - 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"); - 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"); - 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; - - /* actually an ignored value */ - list[keys].attrs[i].mandatory = 0; - } - } else { - list[keys].attrs = NULL; - } - } - /* To be FREEd in libssh2_publickey_list_free() */ - list[keys].packet = pkey->listFetch_data; - 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"); - 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; - libssh2_publickey_list *p = pkey_list; - - if(!pkey || !p) - return; - - session = pkey->channel->session; - - 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; - int rc; - - if(!pkey) - return LIBSSH2_ERROR_BAD_USE; - - 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; - } - - rc = _libssh2_channel_free(pkey->channel); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - LIBSSH2_FREE(session, pkey); - return 0; -} diff --git a/vendor/libssh2-1.4.2/src/scp.c b/vendor/libssh2-1.4.2/src/scp.c deleted file mode 100644 index 6401dac..0000000 --- a/vendor/libssh2-1.4.2/src/scp.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2004-2008, Sara Golemon - * 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 -#include - -#include "channel.h" -#include "session.h" - - -/* Max. length of a quoted string after libssh2_shell_quotearg() processing */ -#define _libssh2_shell_quotedsize(s) (3 * strlen(s) + 2) - -/* - This function quotes a string in a way suitable to be used with a - shell, e.g. the file name - one two - becomes - 'one two' - - The resulting output string is crafted in a way that makes it usable - with the two most common shell types: Bourne Shell derived shells - (sh, ksh, ksh93, bash, zsh) and C-Shell derivates (csh, tcsh). - - The following special cases are handled: - o If the string contains an apostrophy itself, the apostrophy - character is written in quotation marks, e.g. "'". - The shell cannot handle the syntax 'doesn\'t', so we close the - current argument word, add the apostrophe in quotation marks "", - and open a new argument word instead (_ indicate the input - string characters): - _____ _ _ - 'doesn' "'" 't' - - Sequences of apostrophes are combined in one pair of quotation marks: - a'''b - becomes - _ ___ _ - 'a'"'''"'b' - - o If the string contains an exclamation mark (!), the C-Shell - interprets it as an event number. Using \! (not within quotation - marks or single quotation marks) is a mechanism understood by - both Bourne Shell and C-Shell. - - If a quotation was already started, the argument word is closed - first: - a!b - - become - _ _ _ - 'a'\!'b' - - The result buffer must be large enough for the expanded result. A - bad case regarding expansion is alternating characters and - apostrophes: - - a'b'c'd' (length 8) gets converted to - 'a'"'"'b'"'"'c'"'"'d'"'" (length 24) - - This is the worst case. - - Maximum length of the result: - 1 + 6 * (length(input) + 1) / 2) + 1 - - => 3 * length(input) + 2 - - Explanation: - o leading apostrophe - o one character / apostrophe pair (two characters) can get - represented as 6 characters: a' -> a'"'"' - o String terminator (+1) - - A result buffer three times the size of the input buffer + 2 - characters should be safe. - - References: - o csh-compatible quotation (special handling for '!' etc.), see - http://www.grymoire.com/Unix/Csh.html#toc-uh-10 - - Return value: - Length of the resulting string (not counting the terminating '\0'), - or 0 in case of errors, e.g. result buffer too small - - Note: this function could possible be used elsewhere within libssh2, but - until then it is kept static and in this source file. -*/ - -static unsigned -shell_quotearg(const char *path, unsigned char *buf, - unsigned bufsize) -{ - const char *src; - unsigned char *dst, *endp; - - /* - * Processing States: - * UQSTRING: unquoted string: ... -- used for quoting exclamation - * marks. This is the initial state - * SQSTRING: single-qouted-string: '... -- any character may follow - * QSTRING: quoted string: "... -- only apostrophes may follow - */ - enum { UQSTRING, SQSTRING, QSTRING } state = UQSTRING; - - endp = &buf[bufsize]; - src = path; - dst = buf; - while (*src && dst < endp - 1) { - - switch (*src) { - /* - * Special handling for apostrophe. - * An apostrophe is always written in quotation marks, e.g. - * ' -> "'". - */ - - case '\'': - switch (state) { - case UQSTRING: /* Unquoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '"'; - break; - case QSTRING: /* Continue quoted string */ - break; - case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) - return 0; - *dst++ = '\''; - *dst++ = '"'; - break; - default: - break; - } - state = QSTRING; - break; - - /* - * Special handling for exclamation marks. CSH interprets - * exclamation marks even when quoted with apostrophes. We convert - * it to the plain string \!, because both Bourne Shell and CSH - * interpret that as a verbatim exclamation mark. - */ - - case '!': - switch (state) { - case UQSTRING: - if (dst+1 >= endp) - return 0; - *dst++ = '\\'; - break; - case QSTRING: - if (dst+2 >= endp) - return 0; - *dst++ = '"'; /* Closing quotation mark */ - *dst++ = '\\'; - break; - case SQSTRING: /* Close single quoted string */ - if (dst+2 >= endp) - return 0; - *dst++ = '\''; - *dst++ = '\\'; - break; - default: - break; - } - state = UQSTRING; - break; - - /* - * Ordinary character: prefer single-quoted string - */ - - default: - switch (state) { - case UQSTRING: - if (dst+1 >= endp) - return 0; - *dst++ = '\''; - break; - case QSTRING: - if (dst+2 >= endp) - return 0; - *dst++ = '"'; /* Closing quotation mark */ - *dst++ = '\''; - break; - case SQSTRING: /* Continue single quoted string */ - break; - default: - break; - } - state = SQSTRING; /* Start single-quoted string */ - break; - } - - if (dst+1 >= endp) - return 0; - *dst++ = *src++; - } - - switch (state) { - case UQSTRING: - break; - case QSTRING: /* Close quoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '"'; - break; - case SQSTRING: /* Close single quoted string */ - if (dst+1 >= endp) - return 0; - *dst++ = '\''; - break; - default: - break; - } - - if (dst+1 >= endp) - return 0; - *dst = '\0'; - - /* The result cannot be larger than 3 * strlen(path) + 2 */ - /* assert((dst - buf) <= (3 * (src - path) + 2)); */ - - return dst - buf; -} - -/* - * scp_recv - * - * Open a channel and request a remote file via SCP - * - */ -static LIBSSH2_CHANNEL * -scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) -{ - int cmd_len; - int rc; - int tmp_err_code; - const char *tmp_err_msg; - - 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 = - _libssh2_shell_quotedsize(path) + sizeof("scp -f ") + (sb?1:0); - - 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"); - return NULL; - } - - snprintf((char *)session->scpRecv_command, - session->scpRecv_command_len, "scp -%sf ", sb?"p":""); - - cmd_len = strlen((char *)session->scpRecv_command); - - (void) shell_quotearg(path, - &session->scpRecv_command[cmd_len], - session->scpRecv_command_len - cmd_len); - - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "Opening channel for SCP receive"); - - session->scpRecv_state = libssh2_NB_state_created; - } - - if (session->scpRecv_state == libssh2_NB_state_created) { - /* Allocate a channel */ - session->scpRecv_channel = - _libssh2_channel_open(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; - } - else { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting up channel"); - } - return NULL; - } - - 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 == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting SCP startup"); - 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_TRACE_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(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending initial wakeup"); - 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(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response + - session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for SCP response"); - return NULL; - } - else if (rc < 0) { - /* error, give up */ - _libssh2_error(session, rc, "Failed reading SCP response"); - goto scp_recv_error; - } - else if(rc == 0) - goto scp_recv_empty_channel; - - session->scpRecv_response_len++; - - if (session->scpRecv_response[0] != 'T') { - size_t err_len; - char *err_msg; - - /* there can be - 01 for warnings - 02 for errors - - The following string MUST be newline terminated - */ - err_len = - _libssh2_channel_packet_data_len(session-> - scpRecv_channel, 0); - err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed to get memory "); - goto scp_recv_error; - } - - /* Read the remote error message */ - (void)_libssh2_channel_read(session->scpRecv_channel, 0, - err_msg, err_len); - /* If it failed for any reason, we ignore it anyway. */ - - /* zero terminate the error */ - err_msg[err_len]=0; - - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "got %02x %s", session->scpRecv_response[0], - err_msg); - - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Failed to recv file"); - - LIBSSH2_FREE(session, err_msg); - 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"); - 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"); - 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" ); - 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"); - goto scp_recv_error; - } - - *(p++) = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_mtime = strtol((char *) s, NULL, 10); - - 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"); - 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"); - goto scp_recv_error; - } - - *p = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_atime = strtol((char *) s, NULL, 10); - - /* 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(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting to send SCP ACK"); - return NULL; - } else if (rc != 1) { - goto scp_recv_error; - } - - _libssh2_debug(session, LIBSSH2_TRACE_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(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response + - session->scpRecv_response_len, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for SCP response"); - return NULL; - } - else if (rc < 0) { - /* error, bail out*/ - _libssh2_error(session, rc, "Failed reading SCP response"); - goto scp_recv_error; - } - else if(rc == 0) - goto scp_recv_empty_channel; - - session->scpRecv_response_len++; - - if (session->scpRecv_response[0] != 'C') { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server"); - 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)) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid data in SCP response"); - 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"); - 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"); - 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"); - goto scp_recv_error; - } - - *(p++) = '\0'; - /* Make sure we don't get fooled by leftover values */ - - session->scpRecv_mode = strtol(s, &e, 8); - if (e && *e) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid mode"); - 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"); - goto scp_recv_error; - } - - *s = '\0'; - /* Make sure we don't get fooled by leftover values */ - session->scpRecv_size = scpsize_strtol(p, &e, 10); - if (e && *e) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid response from SCP server, invalid size"); - 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(session->scpRecv_channel, 0, - session->scpRecv_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending SCP ACK"); - return NULL; - } else if (rc != 1) { - goto scp_recv_error; - } - _libssh2_debug(session, LIBSSH2_TRACE_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_empty_channel: - /* the code only jumps here as a result of a zero read from channel_read() - so we check EOF status to avoid getting stuck in a loop */ - if(libssh2_channel_eof(session->scpRecv_channel)) - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unexpected channel close"); - else - return session->scpRecv_channel; - /* fall-through */ - scp_recv_error: - tmp_err_code = session->err_code; - tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpRecv_channel) == - LIBSSH2_ERROR_EAGAIN); - session->err_code = tmp_err_code; - session->err_msg = tmp_err_msg; - session->scpRecv_channel = NULL; - session->scpRecv_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_scp_recv - * - * Open a channel and request a remote file via SCP - * - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, scp_recv(session, path, sb)); - return ptr; -} - -/* - * scp_send() - * - * Send a file using SCP - * - */ -static LIBSSH2_CHANNEL * -scp_send(LIBSSH2_SESSION * session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t atime) -{ - int cmd_len; - int rc; - int tmp_err_code; - const char *tmp_err_msg; - - if (session->scpSend_state == libssh2_NB_state_idle) { - session->scpSend_command_len = - _libssh2_shell_quotedsize(path) + sizeof("scp -t ") + - ((mtime || atime)?1:0); - - 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"); - return NULL; - } - - snprintf((char *)session->scpSend_command, session->scpSend_command_len, - "scp -%st ", (mtime || atime)?"p":""); - - cmd_len = strlen((char *)session->scpSend_command); - - (void)shell_quotearg(path, - &session->scpSend_command[cmd_len], - session->scpSend_command_len - cmd_len); - - session->scpSend_command[session->scpSend_command_len - 1] = '\0'; - - _libssh2_debug(session, LIBSSH2_TRACE_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(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; - } - else { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block starting up channel"); - } - 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 == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting SCP startup"); - 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"); - 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(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response from remote"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, rc, "SCP failure"); - goto scp_send_error; - } - else if(!rc) - /* remain in the same state */ - goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid ACK response from remote"); - 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", - (long)mtime, (long)atime); - _libssh2_debug(session, LIBSSH2_TRACE_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(session->scpSend_channel, 0, - session->scpSend_response, - session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending time data for SCP file"); - return NULL; - } else if (rc != (int)session->scpSend_response_len) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send time data for SCP file"); - 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(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, rc, "SCP failure"); - goto scp_send_error; - } - else if(!rc) - /* remain in the same state */ - goto scp_send_empty_channel; - else if (session->scpSend_response[0] != 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid SCP ACK response"); - 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 */ - const char *base = strrchr(path, '/'); - if (base) - base++; - else - base = path; - - session->scpSend_response_len = - snprintf((char *) session->scpSend_response, - LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %" - LIBSSH2_INT64_T_FORMAT "u %s\n", mode, - size, base); - _libssh2_debug(session, LIBSSH2_TRACE_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(session->scpSend_channel, 0, - session->scpSend_response, - session->scpSend_response_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block send core file data for SCP file"); - return NULL; - } else if (rc != (int)session->scpSend_response_len) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send core file data for SCP file"); - 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(session->scpSend_channel, 0, - (char *) session->scpSend_response, 1); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for response"); - return NULL; - } - else if (rc < 0) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid ACK response from remote"); - goto scp_send_error; - } - else if (rc == 0) - goto scp_send_empty_channel; - - else if (session->scpSend_response[0] != 0) { - size_t err_len; - char *err_msg; - - err_len = - _libssh2_channel_packet_data_len(session->scpSend_channel, 0); - err_msg = LIBSSH2_ALLOC(session, err_len + 1); - if (!err_msg) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "failed to get memory"); - goto scp_send_error; - } - - /* Read the remote error message */ - rc = _libssh2_channel_read(session->scpSend_channel, 0, - err_msg, err_len); - if (rc > 0) { - err_msg[err_len]=0; - _libssh2_debug(session, LIBSSH2_TRACE_SCP, - "got %02x %s", session->scpSend_response[0], - err_msg); - } - LIBSSH2_FREE(session, err_msg); - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "failed to send file"); - goto scp_send_error; - } - } - - session->scpSend_state = libssh2_NB_state_idle; - return session->scpSend_channel; - - scp_send_empty_channel: - /* the code only jumps here as a result of a zero read from channel_read() - so we check EOF status to avoid getting stuck in a loop */ - if(libssh2_channel_eof(session->scpSend_channel)) { - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Unexpected channel close"); - } - else - return session->scpSend_channel; - /* fall-through */ - scp_send_error: - tmp_err_code = session->err_code; - tmp_err_msg = session->err_msg; - while (libssh2_channel_free(session->scpSend_channel) == - LIBSSH2_ERROR_EAGAIN); - session->err_code = tmp_err_code; - session->err_msg = tmp_err_msg; - session->scpSend_channel = NULL; - session->scpSend_state = libssh2_NB_state_idle; - return NULL; -} - -/* - * libssh2_scp_send_ex - * - * Send a file using SCP. Old API. - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, - size_t size, long mtime, long atime) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - scp_send(session, path, mode, size, - (time_t)mtime, (time_t)atime)); - return ptr; -} - -/* - * libssh2_scp_send64 - * - * Send a file using SCP - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, - libssh2_int64_t size, time_t mtime, time_t atime) -{ - LIBSSH2_CHANNEL *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - scp_send(session, path, mode, size, mtime, atime)); - return ptr; -} diff --git a/vendor/libssh2-1.4.2/src/session.c b/vendor/libssh2-1.4.2/src/session.c deleted file mode 100644 index 77ab9bc..0000000 --- a/vendor/libssh2-1.4.2/src/session.c +++ /dev/null @@ -1,1751 +0,0 @@ -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2011 by Daniel Stenberg - * Copyright (c) 2010 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 -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#ifdef HAVE_GETTIMEOFDAY -#include -#endif -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include "transport.h" -#include "session.h" -#include "channel.h" -#include "mac.h" -#include "misc.h" - -/* 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); -} - -/* - * 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, LIBSSH2_ERROR_EAGAIN if read would block, negative - * on failure - */ -static int -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'; - - /* no incoming block yet! */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; - - ret = LIBSSH2_RECV(session, &c, 1, - LIBSSH2_SOCKET_RECV_FLAGS(session)); - if (ret < 0) { - if(session->api_block_mode || (ret != -EAGAIN)) - /* ignore EAGAIN when non-blocking */ - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes: %d", 1, -ret); - } - else - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Recved %d bytes banner", ret); - - if (ret < 0) { - if (ret == -EAGAIN) { - session->socket_block_directions = - LIBSSH2_SESSION_BLOCK_INBOUND; - session->banner_TxRx_total_send = banner_len; - return LIBSSH2_ERROR_EAGAIN; - } - - /* Some kinda error */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - return LIBSSH2_ERROR_SOCKET_RECV; - } - - if (ret == 0) { - session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; - return LIBSSH2_ERROR_SOCKET_DISCONNECT; - } - - 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 LIBSSH2_ERROR_BANNER_RECV; - } - - 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 LIBSSH2_ERROR_BANNER_RECV; - - session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); - if (!session->remote.banner) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Error allocating space for remote banner"); - } - memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len); - session->remote.banner[banner_len] = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s", - session->remote.banner); - return LIBSSH2_ERROR_NONE; -} - -/* - * banner_send - * - * Send the default banner, or the one set via libssh2_setopt_string - * - * Returns LIBSSH2_ERROR_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 -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_TRACE_TRANS, "Sending Banner: %s", - banner_dup); -#endif - - session->banner_TxRx_state = libssh2_NB_state_created; - } - - /* no outgoing block yet! */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; - - ret = LIBSSH2_SEND(session, - banner + session->banner_TxRx_total_send, - banner_len - session->banner_TxRx_total_send, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", - banner_len - session->banner_TxRx_total_send, -ret); - else - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", ret, - banner_len - session->banner_TxRx_total_send, - banner, session->banner_TxRx_total_send); - - if (ret != (banner_len - session->banner_TxRx_total_send)) { - if (ret >= 0 || ret == -EAGAIN) { - /* the whole packet could not be sent, save the what was */ - session->socket_block_directions = - LIBSSH2_SESSION_BLOCK_OUTBOUND; - if (ret > 0) - session->banner_TxRx_total_send += ret; - return LIBSSH2_ERROR_EAGAIN; - } - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - return LIBSSH2_ERROR_SOCKET_RECV; - } - - /* Set the state back to idle */ - session->banner_TxRx_state = libssh2_NB_state_idle; - session->banner_TxRx_total_send = 0; - - return 0; -} - -/* - * session_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 -session_nonblock(libssh2_socket_t 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 and VMS*/ - 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 -} - -/* - * get_socket_nonblocking() - * - * gets the given blocking or non-blocking state of the socket. - */ -static int -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 - -#if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0) - - /* VMS TCP/IP Services */ - - size_t sockstat = 0; - int callstat = 0; - size_t size = sizeof( int ); - - callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE, - (char *)&sockstat, &size); - if ( callstat == -1 ) return(0); - if ( (sockstat&SS_NBIO) )return(1); - return(0); - -#undef GETBLOCK -#define GETBLOCK 6 -#endif - -#ifdef HAVE_DISABLED_NONBLOCKING - return 1; /* returns blocking */ -#undef GETBLOCK -#define GETBLOCK 7 -#endif - -#if (GETBLOCK == 0) -#error "no non-blocking method was found/used/get" -#endif -} - -/* libssh2_session_banner_set - * Set the local banner to use in the server handshake. - */ -LIBSSH2_API int -libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) -{ - size_t 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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for local banner"); - } - - memcpy(session->local.banner, banner, banner_len); - - /* first zero terminate like this so that the debug output is nice */ - session->local.banner[banner_len] = '\0'; - _libssh2_debug(session, LIBSSH2_TRACE_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; -} - -/* libssh2_banner_set - * Set the local banner. DEPRECATED VERSION - */ -LIBSSH2_API int -libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) -{ - return libssh2_session_banner_set(session, banner); -} - -/* - * libssh2_session_init_ex - * - * 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->send = _libssh2_send; - session->recv = _libssh2_recv; - session->abstract = abstract; - session->api_timeout = 0; /* timeout-free API by default */ - session->api_block_mode = 1; /* blocking API by default */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "New session resource allocated"); - _libssh2_init_if_needed (); - } - 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; - - case LIBSSH2_CALLBACK_SEND: - oldcb = session->send; - session->send = callback; - return oldcb; - - case LIBSSH2_CALLBACK_RECV: - oldcb = session->recv; - session->recv = callback; - return oldcb; - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting Callback %d", cbtype); - - return NULL; -} - -/* - * _libssh2_wait_socket() - * - * Utility function that waits for action on the socket. Returns 0 when ready - * to run again or error on timeout. - */ -int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) -{ - int rc; - int seconds_to_next; - int dir; - int has_timeout; - long ms_to_next = 0; - long elapsed_ms; - - /* since libssh2 often sets EAGAIN internally before this function is - called, we can decrease some amount of confusion in user programs by - resetting the error code in this function to reduce the risk of EAGAIN - being stored as error when a blocking function has returned */ - session->err_code = LIBSSH2_ERROR_NONE; - - rc = libssh2_keepalive_send (session, &seconds_to_next); - if (rc < 0) - return rc; - - ms_to_next = seconds_to_next * 1000; - - /* figure out what to wait for */ - dir = libssh2_session_block_directions(session); - - if(!dir) { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Nothing to wait for in wait_socket"); - /* To avoid that we hang below just because there's nothing set to - wait for, we timeout on 1 second to also avoid busy-looping - during this condition */ - ms_to_next = 1000; - } - - if (session->api_timeout > 0 && - (seconds_to_next == 0 || - seconds_to_next > session->api_timeout)) { - time_t now = time (NULL); - elapsed_ms = (long)(1000*difftime(start_time, now)); - if (elapsed_ms > session->api_timeout) { - session->err_code = LIBSSH2_ERROR_TIMEOUT; - return LIBSSH2_ERROR_TIMEOUT; - } - ms_to_next = (session->api_timeout - elapsed_ms); - has_timeout = 1; - } - else if (ms_to_next > 0) { - has_timeout = 1; - } - else - has_timeout = 0; - -#ifdef HAVE_POLL - { - struct pollfd sockets[1]; - - sockets[0].fd = session->socket_fd; - sockets[0].events = 0; - sockets[0].revents = 0; - - if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) - sockets[0].events |= POLLIN; - - if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) - sockets[0].events |= POLLOUT; - - rc = poll(sockets, 1, has_timeout?ms_to_next: -1); - } -#else - { - fd_set rfd; - fd_set wfd; - fd_set *writefd = NULL; - fd_set *readfd = NULL; - struct timeval tv; - - tv.tv_sec = ms_to_next / 1000; - tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000; - - if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) { - FD_ZERO(&rfd); - FD_SET(session->socket_fd, &rfd); - readfd = &rfd; - } - - if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) { - FD_ZERO(&wfd); - FD_SET(session->socket_fd, &wfd); - writefd = &wfd; - } - - rc = select(session->socket_fd + 1, readfd, writefd, NULL, - has_timeout ? &tv : NULL); - } -#endif - if(rc <= 0) { - /* timeout (or error), bail out with a timeout error */ - session->err_code = LIBSSH2_ERROR_TIMEOUT; - return LIBSSH2_ERROR_TIMEOUT; - } - - return 0; /* ready to try again */ -} - -static int -session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) -{ - int rc; - - if (session->startup_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "session_startup for socket %d", sock); - if (LIBSSH2_INVALID_SOCKET == sock) { - /* Did we forget something? */ - return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET, - "Bad socket provided"); - } - session->socket_fd = sock; - - session->socket_prev_blockstate = - !get_socket_nonblocking(session->socket_fd); - - if (session->socket_prev_blockstate) { - /* If in blocking state chang to non-blocking */ - session_nonblock(session->socket_fd, 1); - } - - session->startup_state = libssh2_NB_state_created; - } - - if (session->startup_state == libssh2_NB_state_created) { - rc = banner_send(session); - if (rc) { - return _libssh2_error(session, rc, - "Failed sending banner"); - } - session->startup_state = libssh2_NB_state_sent; - session->banner_TxRx_state = libssh2_NB_state_idle; - } - - if (session->startup_state == libssh2_NB_state_sent) { - do { - rc = banner_receive(session); - if (rc) - return _libssh2_error(session, rc, - "Failed getting banner"); - } while(strncmp("SSH-", (char *)session->remote.banner, 4)); - - 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) - return _libssh2_error(session, rc, - "Unable to exchange encryption keys"); - - session->startup_state = libssh2_NB_state_sent2; - } - - if (session->startup_state == libssh2_NB_state_sent2) { - _libssh2_debug(session, LIBSSH2_TRACE_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_transport_send(session, session->startup_service, - sizeof("ssh-userauth") + 5 - 1, - NULL, 0); - if (rc) { - return _libssh2_error(session, rc, - "Unable to ask for ssh-userauth service"); - } - - session->startup_state = libssh2_NB_state_sent4; - } - - if (session->startup_state == libssh2_NB_state_sent4) { - rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT, - &session->startup_data, - &session->startup_data_len, 0, NULL, 0, - &session->startup_req_state); - if (rc) - return rc; - - 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; - return _libssh2_error(session, LIBSSH2_ERROR_PROTO, - "Invalid response received from server"); - } - 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; -} - -/* - * libssh2_session_handshake() - * - * session: LIBSSH2_SESSION struct allocated and owned by the calling program - * sock: *must* be populated with an opened and connected socket. - * - * Returns: 0 on success, or non-zero on failure - */ -LIBSSH2_API int -libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock) -{ - int rc; - - BLOCK_ADJUST(rc, session, session_startup(session, sock) ); - - return rc; -} - -/* - * libssh2_session_startup() - * - * DEPRECATED. Use libssh2_session_handshake() instead! This function is not - * portable enough. - * - * session: LIBSSH2_SESSION struct allocated and owned by the calling program - * sock: *must* be populated with an opened and connected socket. - * - * Returns: 0 on success, or non-zero on failure - */ -LIBSSH2_API int -libssh2_session_startup(LIBSSH2_SESSION *session, int sock) -{ - return libssh2_session_handshake(session, (libssh2_socket_t) sock); -} - -/* - * libssh2_session_free - * - * Frees the memory allocated to the session - * Also closes and frees any channels attached to this session - */ -static int -session_free(LIBSSH2_SESSION *session) -{ - int rc; - LIBSSH2_PACKET *pkg; - LIBSSH2_CHANNEL *ch; - LIBSSH2_LISTENER *l; - int packets_left = 0; - - if (session->free_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource", - session->remote.banner); - - session->state = libssh2_NB_state_created; - } - - if (session->free_state == libssh2_NB_state_created) { - while ((ch = _libssh2_list_first(&session->channels))) { - - rc = _libssh2_channel_free(ch); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - session->state = libssh2_NB_state_sent; - } - - if (session->state == libssh2_NB_state_sent) { - while ((l = _libssh2_list_first(&session->listeners))) { - rc = _libssh2_channel_forward_cancel(l); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - - 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.kexinit) { - LIBSSH2_FREE(session, session->local.kexinit); - } - 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.kexinit) { - LIBSSH2_FREE(session, session->remote.kexinit); - } - 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->kexinit_data) { - LIBSSH2_FREE(session, session->kexinit_data); - } - if (session->startup_data) { - LIBSSH2_FREE(session, session->startup_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); - } - - /* Cleanup all remaining packets */ - while ((pkg = _libssh2_list_first(&session->packets))) { - packets_left++; - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "packet left with id %d", pkg->data[0]); - /* unlink the node */ - _libssh2_list_remove(&pkg->node); - - /* free */ - LIBSSH2_FREE(session, pkg->data); - LIBSSH2_FREE(session, pkg); - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Extra packets left %d", packets_left); - - if(session->socket_prev_blockstate) - /* if the socket was previously blocking, put it back so */ - session_nonblock(session->socket_fd, 0); - - if (session->server_hostkey) { - LIBSSH2_FREE(session, session->server_hostkey); - } - - LIBSSH2_FREE(session, session); - - return 0; -} - -/* - * 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; - - BLOCK_ADJUST(rc, session, session_free(session) ); - - return rc; -} - -/* - * libssh2_session_disconnect_ex - */ -static int -session_disconnect(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_TRACE_TRANS, - "Disconnecting: reason=%d, desc=%s, lang=%s", reason, - description, lang); - if (description) - descr_len = strlen(description); - - if (lang) - lang_len = strlen(lang); - - if(descr_len > 256) - return _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "too long description"); - - /* 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; - - *(s++) = SSH_MSG_DISCONNECT; - _libssh2_store_u32(&s, reason); - _libssh2_store_str(&s, description, descr_len); - /* store length only, lang is sent separately */ - _libssh2_store_u32(&s, lang_len); - - session->disconnect_state = libssh2_NB_state_created; - } - - rc = _libssh2_transport_send(session, session->disconnect_data, - session->disconnect_data_len, - (unsigned char *)lang, lang_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - - session->disconnect_state = libssh2_NB_state_idle; - - return 0; -} - -/* - * libssh2_session_disconnect_ex - */ -LIBSSH2_API int -libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, - const char *desc, const char *lang) -{ - int rc; - - BLOCK_ADJUST(rc, session, - session_disconnect(session, reason, desc, lang)); - - return rc; -} - -/* 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 ""; - - case LIBSSH2_METHOD_LANG_SC: - return ""; - - default: - _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "Invalid parameter specified for method_type"); - return NULL; - } - - if (!method) { - _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, - "No method negotiated"); - 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) -{ - size_t msglen = 0; - - /* 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) { - const char *error = session->err_msg ? session->err_msg : ""; - - msglen = strlen(error); - - if (want_buf) { - /* Make a copy so the calling program can own it */ - *errmsg = LIBSSH2_ALLOC(session, msglen + 1); - if (*errmsg) { - memcpy(*errmsg, error, msglen); - (*errmsg)[msglen] = 0; - } - } - else - *errmsg = (char *)error; - } - - if (errmsg_len) { - *errmsg_len = msglen; - } - - return session->err_code; -} - -/* libssh2_session_last_errno - * - * Returns error code - */ -LIBSSH2_API int -libssh2_session_last_errno(LIBSSH2_SESSION * session) -{ - return session->err_code; -} - -/* libssh2_session_flag - * - * Set/Get session flags - * - * Return error code. - */ -LIBSSH2_API int -libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value) -{ - switch(flag) { - case LIBSSH2_FLAG_SIGPIPE: - session->flag.sigpipe = value; - break; - case LIBSSH2_FLAG_COMPRESS: - session->flag.compress = value; - break; - default: - /* unknown flag */ - return LIBSSH2_ERROR_INVAL; - } - - return LIBSSH2_ERROR_NONE; -} - -/* _libssh2_session_set_blocking - * - * Set a session's blocking mode on or off, return the previous status when - * this function is called. Note this function does not alter the state of the - * actual socket involved. - */ -int -_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking) -{ - int bl = session->api_block_mode; - _libssh2_debug(session, LIBSSH2_TRACE_CONN, - "Setting blocking mode %s", blocking?"ON":"OFF"); - session->api_block_mode = 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->api_block_mode; -} - - -/* libssh2_session_set_timeout - * - * Set a session's timeout (in msec) for blocking mode, - * or 0 to disable timeouts. - */ -LIBSSH2_API void -libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout) -{ - session->api_timeout = timeout; -} - -/* libssh2_session_get_timeout - * - * Returns a session's timeout, or 0 if disabled - */ -LIBSSH2_API long -libssh2_session_get_timeout(LIBSSH2_SESSION * session) -{ - return session->api_timeout; -} - -/* - * 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; - LIBSSH2_PACKET *packet; - - if(!channel) - return LIBSSH2_ERROR_BAD_USE; - - session = channel->session; - packet = _libssh2_list_first(&session->packets); - - 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 = _libssh2_list_next(&packet->node); - } - - return 0; -} - -/* - * poll_channel_write - * - * Returns 0 if writing to channel would block, - * non-0 if data can be written without blocking - */ -static inline int -poll_channel_write(LIBSSH2_CHANNEL * channel) -{ - return channel->local.window_size ? 1 : 0; -} - -/* 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 -poll_listener_queued(LIBSSH2_LISTENER * listener) -{ - return _libssh2_list_first(&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()"); - return -1; - } - } -#elif defined(HAVE_SELECT) - LIBSSH2_SESSION *session = NULL; - libssh2_socket_t 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()"); - 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 |= - 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 |= - 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_LIBSSH2_GETTIMEOFDAY - { - struct timeval tv_begin, tv_end; - - _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL); - sysret = poll(sockets, nfds, timeout_remaining); - _libssh2_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_transport_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_transport_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_LIBSSH2_GETTIMEOFDAY - { - struct timeval tv_begin, tv_end; - - _libssh2_gettimeofday((struct timeval *) &tv_begin, NULL); - sysret = select(maxfd+1, &rfds, &wfds, NULL, &tv); - _libssh2_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_transport_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_transport_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_directions - * - * 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; -} - -/* libssh2_session_banner_get - * Get the remote banner (server ID string) - */ - -LIBSSH2_API const char * -libssh2_session_banner_get(LIBSSH2_SESSION *session) -{ - /* to avoid a coredump when session is NULL */ - if (NULL == session) - return NULL; - - if (NULL==session->remote.banner) - return NULL; - - return (const char *) session->remote.banner; -} diff --git a/vendor/libssh2-1.4.2/src/session.h b/vendor/libssh2-1.4.2/src/session.h deleted file mode 100644 index aff4f2c..0000000 --- a/vendor/libssh2-1.4.2/src/session.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef LIBSSH2_SESSION_H -#define LIBSSH2_SESSION_H -/* Copyright (c) 2004-2007 Sara Golemon - * Copyright (c) 2009-2010 by Daniel Stenberg - * Copyright (c) 2010 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. - */ - -/* Conveniance-macros to allow code like this; - - int rc = BLOCK_ADJUST(rc, session, session_startup(session, sock) ); - - int rc = BLOCK_ADJUST_ERRNO(ptr, session, session_startup(session, sock) ); - - The point of course being to make sure that while in non-blocking mode - these always return no matter what the return code is, but in blocking mode - it blocks if EAGAIN is the reason for the return from the underlying - function. - -*/ -#define BLOCK_ADJUST(rc,sess,x) \ - do { \ - time_t entry_time = time (NULL); \ - do { \ - rc = x; \ - /* the order of the check below is important to properly deal with \ - the case when the 'sess' is freed */ \ - if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \ - break; \ - rc = _libssh2_wait_socket(sess, entry_time); \ - } while(!rc); \ - } while(0) - -/* - * For functions that returns a pointer, we need to check if the API is - * non-blocking and return immediately. If the pointer is non-NULL we return - * immediately. If the API is blocking and we get a NULL we check the errno - * and *only* if that is EAGAIN we loop and wait for socket action. - */ -#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \ - do { \ - time_t entry_time = time (NULL); \ - int rc; \ - do { \ - ptr = x; \ - if(!sess->api_block_mode || \ - (ptr != NULL) || \ - (libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \ - break; \ - rc = _libssh2_wait_socket(sess, entry_time); \ - } while(!rc); \ - } while(0) - - -int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time); - -/* this is the lib-internal set blocking function */ -int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking); - -#endif /* LIBSSH2_SESSION_H */ diff --git a/vendor/libssh2-1.4.2/src/sftp.c b/vendor/libssh2-1.4.2/src/sftp.c deleted file mode 100644 index ec9d033..0000000 --- a/vendor/libssh2-1.4.2/src/sftp.c +++ /dev/null @@ -1,3278 +0,0 @@ -/* Copyright (c) 2004-2008, Sara Golemon - * Copyright (c) 2007 Eli Fant - * Copyright (c) 2009-2012 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 - -#include "libssh2_priv.h" -#include "libssh2_sftp.h" -#include "channel.h" -#include "session.h" -#include "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 - -/* S_IFREG */ -#define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE 0100000 -/* S_IFDIR */ -#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000 - -#define SSH_FXE_STATVFS_ST_RDONLY 0x00000001 -#define SSH_FXE_STATVFS_ST_NOSUID 0x00000002 - -/* This is the maximum packet length to accept, as larger than this indicate - some kind of server problem. */ -#define LIBSSH2_SFTP_PACKET_MAXLEN 80000 - -static int sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle); -static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len); -static void sftp_packet_flush(LIBSSH2_SFTP *sftp); - -/* sftp_attrsize - * Size that attr with this flagset will occupy when turned into a bin struct - */ -static int sftp_attrsize(unsigned long flags) -{ - return (4 + /* flags(4) */ - ((flags & LIBSSH2_SFTP_ATTR_SIZE) ? 8 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_UIDGID) ? 8 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) ? 4 : 0) + - ((flags & LIBSSH2_SFTP_ATTR_ACMODTIME) ? 8 : 0)); - /* atime + mtime as u32 */ -} - -/* _libssh2_store_u64 - */ -static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value) -{ - uint32_t msl = (uint32_t)(value >> 32); - unsigned char *buf = *ptr; - - buf[0] = (unsigned char)((msl >> 24) & 0xFF); - buf[1] = (unsigned char)((msl >> 16) & 0xFF); - buf[2] = (unsigned char)((msl >> 8) & 0xFF); - buf[3] = (unsigned char)( msl & 0xFF); - - buf[4] = (unsigned char)((value >> 24) & 0xFF); - buf[5] = (unsigned char)((value >> 16) & 0xFF); - buf[6] = (unsigned char)((value >> 8) & 0xFF); - buf[7] = (unsigned char)( value & 0xFF); - - *ptr += 8; -} - -/* - * Search list of zombied FXP_READ request IDs. - * - * Returns NULL if ID not in list. - */ -static struct sftp_zombie_requests * -find_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - struct sftp_zombie_requests *zombie = - _libssh2_list_first(&sftp->zombie_requests); - - while(zombie) { - if(zombie->request_id == request_id) - break; - else - zombie = _libssh2_list_next(&zombie->node); - } - - return zombie; -} - -static void -remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - - struct sftp_zombie_requests *zombie = find_zombie_request(sftp, - request_id); - if(zombie) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Removing request ID %ld from the list of zombie requests", - request_id); - - _libssh2_list_remove(&zombie->node); - LIBSSH2_FREE(session, zombie); - } -} - -static int -add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - - struct sftp_zombie_requests *zombie; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Marking request ID %ld as a zombie request", request_id); - - zombie = LIBSSH2_ALLOC(sftp->channel->session, - sizeof(struct sftp_zombie_requests)); - if (!zombie) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for zombie request ID"); - else { - zombie->request_id = request_id; - _libssh2_list_add(&sftp->zombie_requests, &zombie->node); - return LIBSSH2_ERROR_NONE; - } -} - -/* - * sftp_packet_add - * - * Add a packet to the SFTP packet brigade - */ -static int -sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data, - size_t data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - LIBSSH2_SFTP_PACKET *packet; - uint32_t request_id; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet %d (len %d)", - (int) data[0], data_len); - - /* - * Experience shows that if we mess up EAGAIN handling somewhere or - * otherwise get out of sync with the channel, this is where we first get - * a wrong byte and if so we need to bail out at once to aid tracking the - * problem better. - */ - - switch(data[0]) { - case SSH_FXP_INIT: - case SSH_FXP_VERSION: - case SSH_FXP_OPEN: - case SSH_FXP_CLOSE: - case SSH_FXP_READ: - case SSH_FXP_WRITE: - case SSH_FXP_LSTAT: - case SSH_FXP_FSTAT: - case SSH_FXP_SETSTAT: - case SSH_FXP_FSETSTAT: - case SSH_FXP_OPENDIR: - case SSH_FXP_READDIR: - case SSH_FXP_REMOVE: - case SSH_FXP_MKDIR: - case SSH_FXP_RMDIR: - case SSH_FXP_REALPATH: - case SSH_FXP_STAT: - case SSH_FXP_RENAME: - case SSH_FXP_READLINK: - case SSH_FXP_SYMLINK: - case SSH_FXP_STATUS: - case SSH_FXP_HANDLE: - case SSH_FXP_DATA: - case SSH_FXP_NAME: - case SSH_FXP_ATTRS: - case SSH_FXP_EXTENDED: - case SSH_FXP_EXTENDED_REPLY: - break; - default: - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Out of sync with the world"); - } - - request_id = _libssh2_ntohu32(&data[1]); - - /* Don't add the packet if it answers a request we've given up on. */ - if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA) - && find_zombie_request(sftp, request_id)) { - - /* If we get here, the file ended before the response arrived. We - are no longer interested in the request so we discard it */ - - LIBSSH2_FREE(session, data); - - remove_zombie_request(sftp, request_id); - return LIBSSH2_ERROR_NONE; - } - - packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET)); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate datablock for SFTP packet"); - } - - packet->data = data; - packet->data_len = data_len; - packet->request_id = request_id; - - _libssh2_list_add(&sftp->packets, &packet->node); - - return LIBSSH2_ERROR_NONE; -} - -/* - * 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 *packet = NULL; - ssize_t rc; - unsigned long recv_window; - int packet_type; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet"); - - switch(sftp->packet_state) { - case libssh2_NB_state_sent: /* EAGAIN from window adjusting */ - sftp->packet_state = libssh2_NB_state_idle; - - packet = sftp->partial_packet; - goto window_adjust; - - case libssh2_NB_state_sent1: /* EAGAIN from channel read */ - sftp->packet_state = libssh2_NB_state_idle; - - packet = sftp->partial_packet; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "partial read cont, len: %lu", sftp->partial_len); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "partial read cont, already recvd: %lu", - sftp->partial_received); - /* fall-through */ - default: - if(!packet) { - /* only do this if there's not already a packet buffer allocated - to use */ - - /* each packet starts with a 32 bit length field */ - rc = _libssh2_channel_read(channel, 0, - (char *)&sftp->partial_size[ - sftp->partial_size_len], - 4 - sftp->partial_size_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc < 0) - return _libssh2_error(session, rc, "channel read"); - - sftp->partial_size_len += rc; - - if(4 != sftp->partial_size_len) - /* we got a short read for the length part */ - return LIBSSH2_ERROR_EAGAIN; - - sftp->partial_len = _libssh2_ntohu32(sftp->partial_size); - /* make sure we don't proceed if the packet size is unreasonably - large */ - if (sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) - return _libssh2_error(session, - LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED, - "SFTP packet too large"); - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Data begin - Packet Length: %lu", - sftp->partial_len); - packet = LIBSSH2_ALLOC(session, sftp->partial_len); - if (!packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate SFTP packet"); - sftp->partial_size_len = 0; - sftp->partial_received = 0; /* how much of the packet already - received */ - sftp->partial_packet = packet; - - window_adjust: - recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL); - - if(sftp->partial_len > recv_window) { - /* ask for twice the data amount we need at once */ - rc = _libssh2_channel_receive_window_adjust(channel, - sftp->partial_len*2, - 1, NULL); - /* store the state so that we continue with the correct - operation at next invoke */ - sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)? - libssh2_NB_state_sent: - libssh2_NB_state_idle; - - if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; - } - } - - /* Read as much of the packet as we can */ - while (sftp->partial_len > sftp->partial_received) { - rc = _libssh2_channel_read(channel, 0, - (char *)&packet[sftp->partial_received], - sftp->partial_len - - sftp->partial_received); - - if (rc == LIBSSH2_ERROR_EAGAIN) { - /* - * We received EAGAIN, save what we have and return EAGAIN to - * the caller. Set 'partial_packet' so that this function - * knows how to continue on the next invoke. - */ - sftp->packet_state = libssh2_NB_state_sent1; - return rc; - } - else if (rc < 0) { - LIBSSH2_FREE(session, packet); - sftp->partial_packet = NULL; - return _libssh2_error(session, rc, - "Error waiting for SFTP packet"); - } - sftp->partial_received += rc; - } - - sftp->partial_packet = NULL; - - /* sftp_packet_add takes ownership of the packet and might free it - so we take a copy of the packet type before we call it. */ - packet_type = packet[0]; - rc = sftp_packet_add(sftp, packet, sftp->partial_len); - if (rc) { - LIBSSH2_FREE(session, packet); - return rc; - } - else { - return packet_type; - } - } - /* WON'T REACH */ -} -/* - * sftp_packetlist_flush - * - * Remove all pending packets in the packet_list and the corresponding one(s) - * in the SFTP packet brigade. - */ -static void sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE *handle) -{ - struct sftp_pipeline_chunk *chunk; - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_SESSION *session = sftp->channel->session; - - /* remove pending packets, if any */ - chunk = _libssh2_list_first(&handle->packet_list); - while(chunk) { - unsigned char *data; - size_t data_len; - int rc; - struct sftp_pipeline_chunk *next = _libssh2_list_next(&chunk->node); - - rc = sftp_packet_ask(sftp, SSH_FXP_STATUS, - chunk->request_id, &data, &data_len); - if(rc) - rc = sftp_packet_ask(sftp, SSH_FXP_DATA, - chunk->request_id, &data, &data_len); - - if(!rc) - /* we found a packet, free it */ - LIBSSH2_FREE(session, data); - else if(chunk->sent) - /* there was no incoming packet for this request, mark this - request as a zombie if it ever sent the request */ - add_zombie_request(sftp, chunk->request_id); - - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - chunk = next; - } -} - - -/* - * sftp_packet_ask() - * - * Checks if there's a matching SFTP packet available. - */ -static int -sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets); - - if(!packet) - return -1; - - /* Special consideration when getting VERSION packet */ - - while (packet) { - if((packet->data[0] == packet_type) && - ((packet_type == SSH_FXP_VERSION) || - (packet->request_id == request_id))) { - - /* Match! Fetch the data */ - *data = packet->data; - *data_len = packet->data_len; - - /* unlink and free this struct */ - _libssh2_list_remove(&packet->node); - LIBSSH2_FREE(session, packet); - - return 0; - } - /* check next struct in the list */ - packet = _libssh2_list_next(&packet->node); - } - return -1; -} - -/* sftp_packet_require - * A la libssh2_packet_require - */ -static int -sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - LIBSSH2_SESSION *session = sftp->channel->session; - int rc; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld", - (int) packet_type, request_id); - - if (sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) { - /* The right packet was available in the packet brigade */ - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type); - return LIBSSH2_ERROR_NONE; - } - - while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { - rc = sftp_packet_read(sftp); - if (rc < 0) - return rc; - - /* data was read, check the queue again */ - if (!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) { - /* The right packet was available in the packet brigade */ - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d", - (int) packet_type); - return LIBSSH2_ERROR_NONE; - } - } - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* 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, - uint32_t request_id, unsigned char **data, - size_t *data_len) -{ - int i; - int rc; - - /* 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) { - /* - * Set to zero before all returns to say - * the timeout is not active - */ - sftp->requirev_start = 0; - return LIBSSH2_ERROR_NONE; - } - } - - rc = sftp_packet_read(sftp); - if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) { - sftp->requirev_start = 0; - return rc; - } else if (rc <= 0) { - /* prevent busy-looping */ - long left = - LIBSSH2_READ_TIMEOUT - (long)(time(NULL) - sftp->requirev_start); - - if (left <= 0) { - sftp->requirev_start = 0; - return LIBSSH2_ERROR_TIMEOUT; - } - else if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - } - } - - sftp->requirev_start = 0; - - /* Only reached if the socket died */ - return LIBSSH2_ERROR_SOCKET_DISCONNECT; -} - -/* sftp_attr2bin - * Populate attributes into an SFTP block - */ -static ssize_t -sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs) -{ - unsigned char *s = p; - uint32_t 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_store_u32(&s, attrs->flags & flag_mask); - - if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) { - _libssh2_store_u64(&s, attrs->filesize); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) { - _libssh2_store_u32(&s, attrs->uid); - _libssh2_store_u32(&s, attrs->gid); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { - _libssh2_store_u32(&s, attrs->permissions); - } - - if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) { - _libssh2_store_u32(&s, attrs->atime); - _libssh2_store_u32(&s, attrs->mtime); - } - - return (s - p); -} - -/* sftp_bin2attr - */ -static int -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; - - /* 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); -} - -/* - * sftp_init - * - * Startup an SFTP session - */ -static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) -{ - unsigned char *data, *s; - size_t data_len; - ssize_t rc; - LIBSSH2_SFTP *sftp_handle; - - if (session->sftpInit_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Initializing SFTP subsystem"); - - /* - * The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the - * session struct are only to be used during the setup phase. As soon - * as the SFTP session is created they are cleared and can thus be - * re-used again to allow any amount of SFTP handles per sessions. - * - * Note that you MUST NOT try to call libssh2_sftp_init() again to get - * another handle until the previous call has finished and either - * succesffully made a handle or failed and returned error (not - * including *EAGAIN). - */ - - assert(session->sftpInit_sftp == NULL); - session->sftpInit_sftp = NULL; - session->sftpInit_state = libssh2_NB_state_created; - } - - sftp_handle = session->sftpInit_sftp; - - if (session->sftpInit_state == libssh2_NB_state_created) { - session->sftpInit_channel = - _libssh2_channel_open(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"); - } - else { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to startup channel"); - session->sftpInit_state = libssh2_NB_state_idle; - } - return NULL; - } - - session->sftpInit_state = libssh2_NB_state_sent; - } - - if (session->sftpInit_state == libssh2_NB_state_sent) { - int ret = _libssh2_channel_process_startup(session->sftpInit_channel, - "subsystem", - sizeof("subsystem") - 1, "sftp", - strlen("sftp")); - if (ret == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block to request SFTP subsystem"); - return NULL; - } else if (ret) { - _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, - "Unable to request SFTP subsystem"); - goto sftp_init_error; - } - - session->sftpInit_state = libssh2_NB_state_sent1; - } - - if (session->sftpInit_state == libssh2_NB_state_sent1) { - rc = _libssh2_channel_extended_data(session->sftpInit_channel, - LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting handle extended data"); - return NULL; - } - - sftp_handle = - session->sftpInit_sftp = - LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP)); - if (!sftp_handle) { - _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate a new SFTP structure"); - goto sftp_init_error; - } - memset(sftp_handle, 0, sizeof(LIBSSH2_SFTP)); - sftp_handle->channel = session->sftpInit_channel; - sftp_handle->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); - session->sftpInit_sent = 0; /* nothing's sent yet */ - - _libssh2_debug(session, LIBSSH2_TRACE_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) { - /* sent off what's left of the init buffer to send */ - rc = _libssh2_channel_write(session->sftpInit_channel, 0, - session->sftpInit_buffer + - session->sftpInit_sent, - 9 - session->sftpInit_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending SSH_FXP_INIT"); - return NULL; - } - else if(rc < 0) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send SSH_FXP_INIT"); - goto sftp_init_error; - } - else { - /* add up the number of bytes sent */ - session->sftpInit_sent += rc; - - if(session->sftpInit_sent == 9) - /* move on */ - session->sftpInit_state = libssh2_NB_state_sent3; - - /* if less than 9, we remain in this state to send more later on */ - } - } - - rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION, - 0, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return NULL; - else if (rc) { - _libssh2_error(session, rc, - "Timeout waiting for response from SFTP subsystem"); - goto sftp_init_error; - } - if (data_len < 5) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Invalid SSH_FXP_VERSION response"); - goto sftp_init_error; - } - - s = data + 1; - sftp_handle->version = _libssh2_ntohu32(s); - s += 4; - if (sftp_handle->version > LIBSSH2_SFTP_VERSION) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Truncating remote SFTP version from %lu", - sftp_handle->version); - sftp_handle->version = LIBSSH2_SFTP_VERSION; - } - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Enabling SFTP version %lu compatability", - sftp_handle->version); - while (s < (data + data_len)) { - size_t extname_len, extdata_len; - - extname_len = _libssh2_ntohu32(s); - s += 4; - /* the extension name starts here */ - s += extname_len; - - extdata_len = _libssh2_ntohu32(s); - s += 4; - - /* TODO: Actually process extensions */ - s += extdata_len; - - } - LIBSSH2_FREE(session, data); - - /* Make sure that when the channel gets closed, the SFTP service is shut - down too */ - sftp_handle->channel->abstract = sftp_handle; - sftp_handle->channel->close_cb = libssh2_sftp_dtor; - - session->sftpInit_state = libssh2_NB_state_idle; - - /* clear the sftp and channel pointers in this session struct now */ - session->sftpInit_sftp = NULL; - session->sftpInit_channel = NULL; - - _libssh2_list_init(&sftp_handle->sftp_handles); - - return sftp_handle; - - sftp_init_error: - while (_libssh2_channel_free(session->sftpInit_channel) == - LIBSSH2_ERROR_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_init - * - * Startup an SFTP session - */ -LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session) -{ - LIBSSH2_SFTP *ptr; - - if(!session) - return NULL; - - if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) { - _libssh2_error(session, LIBSSH2_ERROR_INVAL, - "session not authenticated yet"); - return NULL; - } - - BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session)); - return ptr; -} - -/* - * sftp_shutdown - * - * Shutsdown the SFTP subsystem - */ -static int -sftp_shutdown(LIBSSH2_SFTP *sftp) -{ - int rc; - LIBSSH2_SESSION *session = sftp->channel->session; - /* - * Make sure all memory used in the state variables are free - */ - if (sftp->partial_packet) { - LIBSSH2_FREE(session, sftp->partial_packet); - sftp->partial_packet = NULL; - } - if (sftp->open_packet) { - LIBSSH2_FREE(session, sftp->open_packet); - sftp->open_packet = NULL; - } - if (sftp->readdir_packet) { - LIBSSH2_FREE(session, sftp->readdir_packet); - sftp->readdir_packet = NULL; - } - if (sftp->fstat_packet) { - LIBSSH2_FREE(session, sftp->fstat_packet); - sftp->fstat_packet = NULL; - } - if (sftp->unlink_packet) { - LIBSSH2_FREE(session, sftp->unlink_packet); - sftp->unlink_packet = NULL; - } - if (sftp->rename_packet) { - LIBSSH2_FREE(session, sftp->rename_packet); - sftp->rename_packet = NULL; - } - if (sftp->fstatvfs_packet) { - LIBSSH2_FREE(session, sftp->fstatvfs_packet); - sftp->fstatvfs_packet = NULL; - } - if (sftp->statvfs_packet) { - LIBSSH2_FREE(session, sftp->statvfs_packet); - sftp->statvfs_packet = NULL; - } - if (sftp->mkdir_packet) { - LIBSSH2_FREE(session, sftp->mkdir_packet); - sftp->mkdir_packet = NULL; - } - if (sftp->rmdir_packet) { - LIBSSH2_FREE(session, sftp->rmdir_packet); - sftp->rmdir_packet = NULL; - } - if (sftp->stat_packet) { - LIBSSH2_FREE(session, sftp->stat_packet); - sftp->stat_packet = NULL; - } - if (sftp->symlink_packet) { - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - } - - sftp_packet_flush(sftp); - - /* TODO: We should consider walking over the sftp_handles list and kill - * any remaining sftp handles ... */ - - rc = _libssh2_channel_free(sftp->channel); - - return rc; -} - -/* libssh2_sftp_shutdown - * Shutsdown the SFTP subsystem - */ -LIBSSH2_API int -libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp)); - return rc; -} - -/* ******************************* - * SFTP File and Directory Ops * - ******************************* */ - -/* sftp_open - */ -static LIBSSH2_SFTP_HANDLE * -sftp_open(LIBSSH2_SFTP *sftp, const char *filename, - size_t filename_len, uint32_t 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 char *s; - ssize_t rc; - int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0; - - 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_file? (4 + sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0); - - /* surprise! this starts out with nothing sent */ - sftp->open_packet_sent = 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"); - return NULL; - } - /* Filetype in SFTP 3 and earlier */ - attrs.permissions = mode | - (open_file ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE : - LIBSSH2_SFTP_ATTR_PFILETYPE_DIR); - - _libssh2_store_u32(&s, sftp->open_packet_len - 4); - *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR; - sftp->open_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->open_request_id); - _libssh2_store_str(&s, filename, filename_len); - - if (open_file) { - _libssh2_store_u32(&s, flags); - s += sftp_attr2bin(s, &attrs); - } - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request", - open_file? "file" : "directory"); - - sftp->open_state = libssh2_NB_state_created; - } - - if (sftp->open_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->open_packet+ - sftp->open_packet_sent, - sftp->open_packet_len - - sftp->open_packet_sent); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block sending FXP_OPEN or FXP_OPENDIR command"); - return NULL; - } - else if(rc < 0) { - _libssh2_error(session, rc, "Unable to send FXP_OPEN*"); - LIBSSH2_FREE(session, sftp->open_packet); - sftp->open_packet = NULL; - sftp->open_state = libssh2_NB_state_idle; - return NULL; - } - - /* bump the sent counter and remain in this state until the whole - data is off */ - sftp->open_packet_sent += rc; - - if(sftp->open_packet_len == sftp->open_packet_sent) { - 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) { - size_t data_len; - unsigned char *data; - static const unsigned char fopen_responses[2] = - { SSH_FXP_HANDLE, SSH_FXP_STATUS }; - rc = sftp_packet_requirev(sftp, 2, fopen_responses, - sftp->open_request_id, &data, - &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting for status message"); - return NULL; - } - sftp->open_state = libssh2_NB_state_idle; - if (rc) { - _libssh2_error(session, rc, "Timeout waiting for status message"); - return NULL; - } - - /* 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; - - if(data_len < 9) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Too small FXP_STATUS"); - LIBSSH2_FREE(session, data); - return NULL; - } - - sftp->last_errno = _libssh2_ntohu32(data + 5); - - if(LIBSSH2_FX_OK == sftp->last_errno) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got HANDLE FXOK!"); - - LIBSSH2_FREE(session, data); - - /* silly situation, but check for a HANDLE */ - rc = sftp_packet_require(sftp, SSH_FXP_HANDLE, - sftp->open_request_id, &data, - &data_len); - if(rc == LIBSSH2_ERROR_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"); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "got FXP_STATUS %d", - sftp->last_errno); - LIBSSH2_FREE(session, data); - return NULL; - } - } - - if(data_len < 10) { - _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Too small FXP_HANDLE"); - 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"); - LIBSSH2_FREE(session, data); - return NULL; - } - memset(fp, 0, sizeof(LIBSSH2_SFTP_HANDLE)); - fp->handle_type = open_file ? 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; - - if(fp->handle_len > (data_len - 9)) - /* do not reach beyond the end of the data we got */ - fp->handle_len = data_len - 9; - - memcpy(fp->handle, data + 9, fp->handle_len); - - LIBSSH2_FREE(session, data); - - /* add this file handle to the list kept in the sftp session */ - _libssh2_list_add(&sftp->sftp_handles, &fp->node); - - fp->sftp = sftp; /* point to the parent struct */ - - fp->u.file.offset = 0; - fp->u.file.offset_sent = 0; - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful"); - return fp; - } - return NULL; -} - -/* 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_SFTP_HANDLE *hnd; - - if(!sftp) - return NULL; - - BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session, - sftp_open(sftp, filename, filename_len, flags, mode, - open_type)); - return hnd; -} - -/* - * sftp_read - * - * Read from an SFTP file handle - * - */ -static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, - size_t buffer_size) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t count = 0; - struct sftp_pipeline_chunk *chunk; - struct sftp_pipeline_chunk *next; - ssize_t rc; - struct _libssh2_sftp_handle_file_data *filep = - &handle->u.file; - - /* This function can be interrupted in three different places where it - might need to wait for data from the network. It returns EAGAIN to - allow non-blocking clients to do other work but these client are - expected to call this function again (possibly many times) to finish - the operation. - - The tricky part is that if we previously aborted a sftp_read due to - EAGAIN, we must continue at the same spot to continue the previously - interrupted operation. This is done using a state machine to record - what phase of execution we were at. The state is stored in - sftp->read_state. - - libssh2_NB_state_idle: The first phase is where we prepare multiple - FXP_READ packets to do optimistic read-ahead. We send off as many as - possible in the second phase without waiting for a response to each - one; this is the key to fast reads. But we may have to adjust the - channel window size to do this which may interrupt this function while - waiting. The state machine saves the phase as libssh2_NB_state_idle so - it returns here on the next call. - - libssh2_NB_state_sent: The second phase is where we send the FXP_READ - packets. Writing them to the channel can be interrupted with EAGAIN - but the state machine ensures we skip the first phase on the next call - and resume sending. - - libssh2_NB_state_sent2: In the third phase (indicated by ) we read the - data from the responses that have arrived so far. Reading can be - interrupted with EAGAIN but the state machine ensures we skip the first - and second phases on the next call and resume sending. - */ - - switch (sftp->read_state) { - case libssh2_NB_state_idle: - - /* Some data may already have been read from the server in the - previous call but didn't fit in the buffer at the time. If so, we - return that now as we can't risk being interrupted later with data - partially written to the buffer. */ - if(filep->data_left) { - size_t copy = MIN(buffer_size, filep->data_left); - - memcpy(buffer, &filep->data[ filep->data_len - filep->data_left], - copy); - - filep->data_left -= copy; - filep->offset += copy; - - if(!filep->data_left) { - LIBSSH2_FREE(session, filep->data); - filep->data = NULL; - } - - return copy; - } - - /* We allow a number of bytes being requested at any given time - without having been acked - until we reach EOF. */ - if(!filep->eof) { - /* Number of bytes asked for that haven't been acked yet */ - size_t already = (filep->offset_sent - filep->offset); - - size_t max_read_ahead = buffer_size*4; - unsigned long recv_window; - - if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4) - max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4; - - /* if the buffer_size passed in now is smaller than what has - already been sent, we risk getting count become a very large - number */ - if(max_read_ahead > already) - count = max_read_ahead - already; - - /* 'count' is how much more data to ask for, and 'already' is how - much data that already has been asked for but not yet returned. - Specificly, 'count' means how much data that have or will be - asked for by the nodes that are already added to the linked - list. Some of those read requests may not actually have been - sent off successfully yet. - - If 'already' is very large it should be perfectly fine to have - count set to 0 as then we don't have to ask for more data - (right now). - - buffer_size*4 is just picked more or less out of the air. The - idea is that when reading SFTP from a remote server, we send - away multiple read requests guessing that the client will read - more than only this 'buffer_size' amount of memory. So we ask - for maximum buffer_size*4 amount of data so that we can return - them very fast in subsequent calls. - */ - - recv_window = libssh2_channel_window_read_ex(sftp->channel, - NULL, NULL); - if(max_read_ahead > recv_window) { - /* more data will be asked for than what the window currently - allows, expand it! */ - - rc = _libssh2_channel_receive_window_adjust(sftp->channel, - max_read_ahead*8, - 1, NULL); - /* if this returns EAGAIN, we will get back to this function - at next call */ - assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left); - assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof); - if (rc) - return rc; - } - } - - while(count > 0) { - unsigned char *s; - uint32_t size = MIN(MAX_SFTP_READ_SIZE, count); - - /* 25 = packet_len(4) + packet_type(1) + request_id(4) + - handle_len(4) + offset(8) + count(4) */ - uint32_t packet_len = (uint32_t)handle->handle_len + 25; - uint32_t request_id; - - chunk = LIBSSH2_ALLOC(session, packet_len + - sizeof(struct sftp_pipeline_chunk)); - if (!chunk) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for FXP_WRITE"); - - chunk->len = size; - chunk->lefttosend = packet_len; - chunk->sent = 0; - - s = chunk->packet; - - _libssh2_store_u32(&s, packet_len - 4); - *s++ = SSH_FXP_READ; - request_id = sftp->request_id++; - chunk->request_id = request_id; - _libssh2_store_u32(&s, request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - _libssh2_store_u64(&s, filep->offset_sent); - filep->offset_sent += size; /* advance offset at once */ - _libssh2_store_u32(&s, size); - - /* add this new entry LAST in the list */ - _libssh2_list_add(&handle->packet_list, &chunk->node); - count -= size; /* deduct the size we used, as we might have - to create more packets */ - } - - case libssh2_NB_state_sent: - - sftp->read_state = libssh2_NB_state_idle; - - /* move through the READ packets that haven't been sent and send as - many as possible - remember that we don't block */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) { - - rc = _libssh2_channel_write(channel, 0, - &chunk->packet[chunk->sent], - chunk->lefttosend); - if(rc < 0) { - sftp->read_state = libssh2_NB_state_sent; - return rc; - } - - /* remember where to continue sending the next time */ - chunk->lefttosend -= rc; - chunk->sent += rc; - - if(chunk->lefttosend) - /* data left to send, get out of loop */ - break; - } - - /* move on to the next chunk with data to send */ - chunk = _libssh2_list_next(&chunk->node); - } - - case libssh2_NB_state_sent2: - - sftp->read_state = libssh2_NB_state_idle; - - /* - * Count all ACKed packets and act on the contents of them. - */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - unsigned char *data; - size_t data_len; - uint32_t rc32; - static const unsigned char read_responses[2] = { - SSH_FXP_DATA, SSH_FXP_STATUS - }; - - if(chunk->lefttosend) - /* if the chunk still has data left to send, we shouldn't wait - for an ACK for it just yet */ - break; - - rc = sftp_packet_requirev(sftp, 2, read_responses, - chunk->request_id, &data, &data_len); - if (rc < 0) { - sftp->read_state = libssh2_NB_state_sent2; - return rc; - } - - /* - * We get DATA or STATUS back. STATUS can be error, or it is - * FX_EOF when we reach the end of the file. - */ - - switch (data[0]) { - case SSH_FXP_STATUS: - /* remove the chunk we just processed keeping track of the - * next one in case we need it */ - next = _libssh2_list_next(&chunk->node); - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - - /* we must remove all outstanding READ requests, as either we - got an error or we're at end of file */ - sftp_packetlist_flush(handle); - - rc32 = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (rc32 == LIBSSH2_FX_EOF) { - filep->eof = TRUE; - return 0; - } - else { - sftp->last_errno = rc32; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP READ error"); - } - break; - - case SSH_FXP_DATA: - rc32 = _libssh2_ntohu32(data + 5); - if (rc32 > (data_len - 9)) - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol badness"); - - if(rc32 != chunk->len) { - /* a short read does not imply end of file, but we must - adjust the offset_sent since it was advanced with a - full chunk->len before */ - filep->offset_sent -= (chunk->len - rc32); - } - - if(rc32 > buffer_size) { - /* figure out the overlap amount */ - filep->data_left = rc32 - buffer_size; - - /* getting the full packet would overflow the buffer, so - only get the correct amount and keep the remainder */ - rc32 = (uint32_t)buffer_size; - - /* store data to keep for next call */ - filep->data = data; - filep->data_len = data_len; - } - else - filep->data_len = 0; - - /* copy the received data from the received FXP_DATA packet to - the buffer at the correct index */ - memcpy(buffer, data + 9, rc32); - filep->offset += rc32; - - if(filep->data_len == 0) - /* free the allocated data if not stored to keep */ - LIBSSH2_FREE(session, data); - - - /* remove the chunk we just processed keeping track of the - * next one in case we need it */ - next = _libssh2_list_next(&chunk->node); - _libssh2_list_remove(&chunk->node); - LIBSSH2_FREE(session, chunk); - chunk = NULL; - - if(rc32 > 0) { - /* we must return as we wrote some data to the buffer */ - return rc32; - } else { - /* A zero-byte read is not necessarily EOF so we must not - * return 0 (that would signal EOF to the caller) so - * instead we carry on to the next chunk */ - chunk = next; - } - - break; - default: - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol badness: unrecognised " - "read request response"); - } - } - - break; - - default: - assert(!"State machine error; unrecognised read state"); - } - - return 0; -} - -/* libssh2_sftp_read - * Read from an SFTP file handle - */ -LIBSSH2_API ssize_t -libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, - size_t buffer_maxlen) -{ - ssize_t rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_read(hnd, buffer, buffer_maxlen)); - return rc; -} - -/* sftp_readdir - * Read from an SFTP directory handle - */ -static ssize_t sftp_readdir(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; - size_t data_len; - uint32_t num_names; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = handle->handle_len + 13; - unsigned char *s, *data; - static const unsigned char read_responses[2] = { - SSH_FXP_NAME, SSH_FXP_STATUS }; - ssize_t 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 - */ - LIBSSH2_SFTP_ATTRIBUTES attrs_dummy; - size_t real_longentry_len; - size_t real_filename_len; - size_t filename_len; - size_t longentry_len; - - s = (unsigned char *) handle->u.dir.next_name; - real_filename_len = _libssh2_ntohu32(s); - - s += 4; - - filename_len = real_filename_len; - if (filename_len >= buffer_maxlen) { - filename_len = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - goto end; - } - - memcpy(buffer, s, filename_len); - buffer[filename_len] = '\0'; /* zero terminate */ - s += real_filename_len; - - real_longentry_len = _libssh2_ntohu32(s); - s += 4; - - if (longentry && (longentry_maxlen>1)) { - longentry_len = real_longentry_len; - - if (longentry_len >= longentry_maxlen) { - filename_len = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - goto end; - } - - memcpy(longentry, s, longentry_len); - longentry[longentry_len] = '\0'; /* zero terminate */ - } - s += real_longentry_len; - - if (attrs) - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - - s += sftp_bin2attr(attrs ? attrs : &attrs_dummy, s); - - handle->u.dir.next_name = (char *) s; - end: - - if ((--handle->u.dir.names_left) == 0) - LIBSSH2_FREE(session, handle->u.dir.names_packet); - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "libssh2_sftp_readdir_ex() return %d", - filename_len); - return (ssize_t)filename_len; - } - - /* Request another entry(entries?) */ - - s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->readdir_packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "FXP_READDIR packet"); - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_READDIR; - sftp->readdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->readdir_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - sftp->readdir_state = libssh2_NB_state_created; - } - - if (sftp->readdir_state == libssh2_NB_state_created) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Reading entries from directory handle"); - retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet, - packet_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) { - return retcode; - } - else if ((ssize_t)packet_len != retcode) { - LIBSSH2_FREE(session, sftp->readdir_packet); - sftp->readdir_packet = NULL; - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - - 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 == LIBSSH2_ERROR_EAGAIN) - return retcode; - else if (retcode) { - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Timeout waiting for status message"); - } - - 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; - sftp->readdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - sftp->readdir_state = libssh2_NB_state_idle; - - num_names = _libssh2_ntohu32(data + 5); - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned", - num_names); - if (!num_names) { - LIBSSH2_FREE(session, data); - return 0; - } - - handle->u.dir.names_left = num_names; - handle->u.dir.names_packet = data; - handle->u.dir.next_name = (char *) data + 9; - - /* use the name popping mechanism from the start of the function */ - return sftp_readdir(handle, buffer, buffer_maxlen, longentry, - longentry_maxlen, attrs); -} - -/* libssh2_sftp_readdir_ex - * Read from an SFTP directory handle - */ -LIBSSH2_API int -libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer, - size_t buffer_maxlen, char *longentry, - size_t longentry_maxlen, - LIBSSH2_SFTP_ATTRIBUTES *attrs) -{ - int rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_readdir(hnd, buffer, buffer_maxlen, longentry, - longentry_maxlen, attrs)); - return rc; -} - -/* - * sftp_write - * - * Write data to an SFTP handle. Returns the number of bytes written, or - * a negative error code. - * - * We recommend sending very large data buffers to this function! - * - * Concept: - * - * - Detect how much of the given buffer that was already sent in a previous - * call by inspecting the linked list of outgoing chunks. Make sure to skip - * passed the data that has already been taken care of. - * - * - Split all (new) outgoing data in chunks no larger than N. - * - * - Each N bytes chunk gets created as a separate SFTP packet. - * - * - Add all created outgoing packets to the linked list. - * - * - Walk through the list and send the chunks that haven't been sent, - * as many as possible until EAGAIN. Some of the chunks may have been put - * in the list in a previous invoke. - * - * - For all the chunks in the list that have been completely sent off, check - * for ACKs. If a chunk has been ACKed, it is removed from the linked - * list and the "acked" counter gets increased with that data amount. - * - * - Return TOTAL bytes acked so far. - * - * Caveats: - * - be careful: we must not return a higher number than what was given! - * - * TODO: - * Introduce an option that disables this sort of "speculative" ahead writing - * as there's a risk that it will do harm to some app. - */ - -static ssize_t 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; - size_t data_len; - uint32_t retcode; - uint32_t packet_len; - unsigned char *s, *data; - ssize_t rc; - struct sftp_pipeline_chunk *chunk; - struct sftp_pipeline_chunk *next; - size_t acked = 0; - size_t org_count = count; - size_t already; - - switch(sftp->write_state) { - default: - case libssh2_NB_state_idle: - - /* Number of bytes sent off that haven't been acked and therefor we - will get passed in here again. - - Also, add up the number of bytes that actually already have been - acked but we haven't been able to return as such yet, so we will - get that data as well passed in here again. - */ - already = (handle->u.file.offset_sent - handle->u.file.offset)+ - handle->u.file.acked; - - if(count >= already) { - /* skip the part already made into packets */ - buffer += already; - count -= already; - } - else - /* there is more data already fine than what we got in this call */ - count = 0; - - sftp->write_state = libssh2_NB_state_idle; - while(count) { - /* TODO: Possibly this should have some logic to prevent a very - very small fraction to be left but lets ignore that for now */ - uint32_t size = MIN(MAX_SFTP_OUTGOING_SIZE, count); - uint32_t request_id; - - /* 25 = packet_len(4) + packet_type(1) + request_id(4) + - handle_len(4) + offset(8) + count(4) */ - packet_len = handle->handle_len + size + 25; - - chunk = LIBSSH2_ALLOC(session, packet_len + - sizeof(struct sftp_pipeline_chunk)); - if (!chunk) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "malloc fail for FXP_WRITE"); - - chunk->len = size; - chunk->sent = 0; - chunk->lefttosend = packet_len; - - s = chunk->packet; - _libssh2_store_u32(&s, packet_len - 4); - - *(s++) = SSH_FXP_WRITE; - request_id = sftp->request_id++; - chunk->request_id = request_id; - _libssh2_store_u32(&s, request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - _libssh2_store_u64(&s, handle->u.file.offset_sent); - handle->u.file.offset_sent += size; /* advance offset at once */ - _libssh2_store_str(&s, buffer, size); - - /* add this new entry LAST in the list */ - _libssh2_list_add(&handle->packet_list, &chunk->node); - - buffer += size; - count -= size; /* deduct the size we used, as we might have - to create more packets */ - } - - /* move through the WRITE packets that haven't been sent and send as many - as possible - remember that we don't block */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) { - rc = _libssh2_channel_write(channel, 0, - &chunk->packet[chunk->sent], - chunk->lefttosend); - if(rc < 0) - /* remain in idle state */ - return rc; - - /* remember where to continue sending the next time */ - chunk->lefttosend -= rc; - chunk->sent += rc; - - if(chunk->lefttosend) - /* data left to send, get out of loop */ - break; - } - - /* move on to the next chunk with data to send */ - chunk = _libssh2_list_next(&chunk->node); - } - - /* fall-through */ - case libssh2_NB_state_sent: - - sftp->write_state = libssh2_NB_state_idle; - /* - * Count all ACKed packets - */ - chunk = _libssh2_list_first(&handle->packet_list); - - while(chunk) { - if(chunk->lefttosend) - /* if the chunk still has data left to send, we shouldn't wait - for an ACK for it just yet */ - break; - - else if(acked) - /* if we have sent data that is acked, we must return that - info before we call a function that might return EAGAIN */ - break; - - /* we check the packets in order */ - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, - chunk->request_id, &data, &data_len); - if (rc < 0) { - if (rc == LIBSSH2_ERROR_EAGAIN) - sftp->write_state = libssh2_NB_state_sent; - return rc; - } - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - sftp->last_errno = retcode; - if (retcode == LIBSSH2_FX_OK) { - acked += chunk->len; /* number of payload data that was acked - here */ - - /* we increase the offset value for all acks */ - handle->u.file.offset += chunk->len; - - next = _libssh2_list_next(&chunk->node); - - _libssh2_list_remove(&chunk->node); /* remove from list */ - LIBSSH2_FREE(session, chunk); /* free memory */ - - chunk = next; - } - else { - /* flush all pending packets from the outgoing list */ - sftp_packetlist_flush(handle); - - /* since we return error now, the applicaton will not get any - outstanding data acked, so we need to rewind the offset to - where the application knows it has reached with acked data */ - handle->u.file.offset -= handle->u.file.acked; - - /* then reset the offset_sent to be the same as the offset */ - handle->u.file.offset_sent = handle->u.file.offset; - - /* clear the acked counter since we can have no pending data to - ack after an error */ - handle->u.file.acked = 0; - - /* the server returned an error for that written chunk, propagate - this back to our parent function */ - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "FXP write failed"); - } - } - break; - } - - /* if there were acked data in a previous call that wasn't returned then, - add that up and try to return it all now. This can happen if the app - first sends a huge buffer of data, and then in a second call it sends a - smaller one. */ - acked += handle->u.file.acked; - - if(acked) { - ssize_t ret = MIN(acked, org_count); - /* we got data acked so return that amount, but no more than what - was asked to get sent! */ - - /* store the remainder. 'ret' is always equal to or less than 'acked' - here */ - handle->u.file.acked = acked - ret; - - return ret; - } - - else - return 0; /* nothing was acked, and no EAGAIN was received! */ -} - -/* libssh2_sftp_write - * Write data to a file handle - */ -LIBSSH2_API ssize_t -libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer, - size_t count) -{ - ssize_t rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_write(hnd, buffer, count)); - return rc; - -} - -/* - * sftp_fstat - * - * Get or Set stat on a file - */ -static int sftp_fstat(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; - size_t data_len; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = - handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0); - unsigned char *s, *data; - static const unsigned char fstat_responses[2] = - { SSH_FXP_ATTRS, SSH_FXP_STATUS }; - ssize_t rc; - - if (sftp->fstat_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command", - setstat ? "set-stat" : "stat"); - s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->fstat_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "FSTAT/FSETSTAT packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT; - sftp->fstat_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->fstat_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - if (setstat) { - s += sftp_attr2bin(s, attrs); - } - - sftp->fstat_state = libssh2_NB_state_created; - } - - if (sftp->fstat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->fstat_packet); - sftp->fstat_packet = NULL; - sftp->fstat_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - (setstat ? "Unable to send FXP_FSETSTAT" - : "Unable to send FXP_FSTAT command")); - } - 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 == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - sftp->fstat_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Timeout waiting for status message"); - } - - sftp->fstat_state = libssh2_NB_state_idle; - - if (data[0] == SSH_FXP_STATUS) { - uint32_t retcode; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - if (retcode == LIBSSH2_FX_OK) { - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - sftp_bin2attr(attrs, data + 5); - LIBSSH2_FREE(session, data); - - return 0; -} - -/* libssh2_sftp_fstat_ex - * Get or Set stat on a file - */ -LIBSSH2_API int -libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd, - LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat) -{ - int rc; - if(!hnd || !attrs) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, - sftp_fstat(hnd, attrs, setstat)); - return rc; -} - - -/* 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) -{ - if(handle) { - handle->u.file.offset = handle->u.file.offset_sent = offset; - /* discard all pending requests and currently read data */ - sftp_packetlist_flush(handle); - - /* free the left received buffered data */ - if (handle->u.file.data_left) { - LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data); - handle->u.file.data_left = handle->u.file.data_len = 0; - handle->u.file.data = NULL; - } - - /* reset EOF to False */ - handle->u.file.eof = FALSE; - } -} - -/* 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) -{ - libssh2_sftp_seek64(handle, (libssh2_uint64_t)offset); -} - -/* libssh2_sftp_tell - * Return the current read/write pointer's offset - */ -LIBSSH2_API size_t -libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle) -{ - if(!handle) - return 0; /* no handle, no size */ - - /* NOTE: this may very well truncate the size if it is larger than what - size_t can hold, so libssh2_sftp_tell64() is really the function you - should use */ - return (size_t)(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) -{ - if(!handle) - return 0; /* no handle, no size */ - - return handle->u.file.offset; -} - -/* - * Flush all remaining incoming SFTP packets and zombies. - */ -static void sftp_packet_flush(LIBSSH2_SFTP *sftp) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets); - struct sftp_zombie_requests *zombie = - _libssh2_list_first(&sftp->zombie_requests); - - while(packet) { - LIBSSH2_SFTP_PACKET *next; - - /* check next struct in the list */ - next = _libssh2_list_next(&packet->node); - _libssh2_list_remove(&packet->node); - LIBSSH2_FREE(session, packet->data); - LIBSSH2_FREE(session, packet); - - packet = next; - } - - while(zombie) { - /* figure out the next node */ - struct sftp_zombie_requests *next = _libssh2_list_next(&zombie->node); - /* unlink the current one */ - _libssh2_list_remove(&zombie->node); - /* free the memory */ - LIBSSH2_FREE(session, zombie); - zombie = next; - } - -} - -/* sftp_close_handle - * - * Close a file or directory handle - * Also frees handle resource and unlinks it from the SFTP structure - */ -static int -sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */ - uint32_t packet_len = handle->handle_len + 13; - unsigned char *s, *data = NULL; - int rc; - - if (handle->close_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle"); - s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len); - if (!handle->close_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_CLOSE " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_CLOSE; - handle->close_request_id = sftp->request_id++; - _libssh2_store_u32(&s, handle->close_request_id); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - handle->close_state = libssh2_NB_state_created; - } - - if (handle->close_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, handle->close_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, handle->close_packet); - handle->close_packet = NULL; - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_CLOSE command"); - } - 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 == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for status message"); - } - - handle->close_state = libssh2_NB_state_sent1; - } - - if(!data) - /* if it reaches this point with data unset, something unwanted - happened (like this function is called again when in - libssh2_NB_state_sent1 state) and we just bail out */ - return LIBSSH2_ERROR_INVAL; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode != LIBSSH2_FX_OK) { - sftp->last_errno = retcode; - handle->close_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - - /* remove this handle from the parent's list */ - _libssh2_list_remove(&handle->node); - - if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) - && handle->u.dir.names_left) { - LIBSSH2_FREE(session, handle->u.dir.names_packet); - } - else { - if(handle->u.file.data) - LIBSSH2_FREE(session, handle->u.file.data); - } - - sftp_packetlist_flush(handle); - sftp->read_state = libssh2_NB_state_idle; - - handle->close_state = libssh2_NB_state_idle; - - LIBSSH2_FREE(session, handle); - - return 0; -} - -/* 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 *hnd) -{ - int rc; - if(!hnd) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd)); - return rc; -} - -/* sftp_unlink - * Delete a file from the remote server - */ -static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, - size_t filename_len) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */ - uint32_t packet_len = filename_len + 13; - unsigned char *s, *data; - int rc; - - if (sftp->unlink_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename); - s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->unlink_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_REMOVE " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_REMOVE; - sftp->unlink_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->unlink_request_id); - _libssh2_store_str(&s, filename, filename_len); - sftp->unlink_state = libssh2_NB_state_created; - } - - if (sftp->unlink_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->unlink_packet); - sftp->unlink_packet = NULL; - sftp->unlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_REMOVE command"); - } - 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 == LIBSSH2_ERROR_EAGAIN) { - return rc; - } - else if (rc) { - sftp->unlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - 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; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* libssh2_sftp_unlink_ex - * Delete a file from the remote server - */ -LIBSSH2_API int -libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename, - unsigned int filename_len) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_unlink(sftp, filename, filename_len)); - return rc; -} - -/* - * sftp_rename - * - * Rename a file on the remote server - */ -static int sftp_rename(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; - size_t data_len; - int retcode; - uint32_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; - ssize_t rc; - - if (sftp->version < 2) { - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Server does not support RENAME"); - } - - if (sftp->rename_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s", - source_filename, dest_filename); - sftp->rename_s = sftp->rename_packet = - LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rename_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_RENAME " - "packet"); - } - - _libssh2_store_u32(&sftp->rename_s, packet_len - 4); - *(sftp->rename_s++) = SSH_FXP_RENAME; - sftp->rename_request_id = sftp->request_id++; - _libssh2_store_u32(&sftp->rename_s, sftp->rename_request_id); - _libssh2_store_str(&sftp->rename_s, source_filename, - source_filename_len); - _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len); - - if (sftp->version >= 5) - _libssh2_store_u32(&sftp->rename_s, flags); - - sftp->rename_state = libssh2_NB_state_created; - } - - if (sftp->rename_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->rename_packet, - sftp->rename_s - sftp->rename_packet); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if ((ssize_t)packet_len != rc) { - LIBSSH2_FREE(session, sftp->rename_packet); - sftp->rename_packet = NULL; - sftp->rename_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_RENAME command"); - } - 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 == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->rename_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->rename_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - sftp->last_errno = retcode; - - /* now convert the SFTP error code to libssh2 return code or error - message */ - switch (retcode) { - case LIBSSH2_FX_OK: - retcode = LIBSSH2_ERROR_NONE; - break; - - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "File already exists and " - "SSH_FXP_RENAME_OVERWRITE not specified"); - break; - - case LIBSSH2_FX_OP_UNSUPPORTED: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Operation Not Supported"); - break; - - default: - retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - break; - } - - return retcode; -} - -/* 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) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_rename(sftp, source_filename, source_filename_len, - dest_filename, dest_filename_len, flags)); - return rc; -} - -/* - * sftp_fstatvfs - * - * Get file system statistics - */ -static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) -{ - LIBSSH2_SFTP *sftp = handle->sftp; - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4) - + handle_len (4) */ - /* 20 = strlen ("fstatvfs@openssh.com") */ - uint32_t packet_len = handle->handle_len + 20 + 17; - unsigned char *packet, *s, *data; - ssize_t rc; - unsigned int flag; - - if (sftp->fstatvfs_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Getting file system statistics"); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_EXTENDED " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_EXTENDED; - sftp->fstatvfs_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->fstatvfs_request_id); - _libssh2_store_str(&s, "fstatvfs@openssh.com", 20); - _libssh2_store_str(&s, handle->handle, handle->handle_len); - - sftp->fstatvfs_state = libssh2_NB_state_created; - } - else { - packet = sftp->fstatvfs_packet; - } - - if (sftp->fstatvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || - (0 <= rc && rc < (ssize_t)packet_len)) { - sftp->fstatvfs_packet = packet; - return LIBSSH2_ERROR_EAGAIN; - } - - LIBSSH2_FREE(session, packet); - sftp->fstatvfs_packet = NULL; - - if (rc < 0) { - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - sftp->fstatvfs_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_EXTENDED_REPLY, - sftp->fstatvfs_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP EXTENDED REPLY"); - } else if (data_len < 93) { - LIBSSH2_FREE(session, data); - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error: short response"); - } - - sftp->fstatvfs_state = libssh2_NB_state_idle; - - st->f_bsize = _libssh2_ntohu64(data + 5); - st->f_frsize = _libssh2_ntohu64(data + 13); - st->f_blocks = _libssh2_ntohu64(data + 21); - st->f_bfree = _libssh2_ntohu64(data + 29); - st->f_bavail = _libssh2_ntohu64(data + 37); - st->f_files = _libssh2_ntohu64(data + 45); - st->f_ffree = _libssh2_ntohu64(data + 53); - st->f_favail = _libssh2_ntohu64(data + 61); - st->f_fsid = _libssh2_ntohu64(data + 69); - flag = _libssh2_ntohu64(data + 77); - st->f_namemax = _libssh2_ntohu64(data + 85); - - st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY) - ? LIBSSH2_SFTP_ST_RDONLY : 0; - st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID) - ? LIBSSH2_SFTP_ST_NOSUID : 0; - - LIBSSH2_FREE(session, data); - return 0; -} - -/* libssh2_sftp_fstatvfs - * Get filesystem space and inode utilization (requires fstatvfs@openssh.com - * support on the server) - */ -LIBSSH2_API int -libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) -{ - int rc; - if(!handle || !st) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, handle->sftp->channel->session, sftp_fstatvfs(handle, st)); - return rc; -} - -/* - * sftp_statvfs - * - * Get file system statistics - */ -static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, LIBSSH2_SFTP_STATVFS *st) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4) - + path_len (4) */ - /* 19 = strlen ("statvfs@openssh.com") */ - uint32_t packet_len = path_len + 19 + 17; - unsigned char *packet, *s, *data; - ssize_t rc; - unsigned int flag; - - if (sftp->statvfs_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Getting file system statistics of %s", path); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_EXTENDED " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_EXTENDED; - sftp->statvfs_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->statvfs_request_id); - _libssh2_store_str(&s, "statvfs@openssh.com", 19); - _libssh2_store_str(&s, path, path_len); - - sftp->statvfs_state = libssh2_NB_state_created; - } - else { - packet = sftp->statvfs_packet; - } - - if (sftp->statvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN || - (0 <= rc && rc < (ssize_t)packet_len)) { - sftp->statvfs_packet = packet; - return LIBSSH2_ERROR_EAGAIN; - } - - LIBSSH2_FREE(session, packet); - sftp->statvfs_packet = NULL; - - if (rc < 0) { - sftp->statvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - sftp->statvfs_state = libssh2_NB_state_sent; - } - - rc = sftp_packet_require(sftp, SSH_FXP_EXTENDED_REPLY, - sftp->statvfs_request_id, &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->statvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP EXTENDED REPLY"); - } else if (data_len < 93) { - LIBSSH2_FREE(session, data); - sftp->fstatvfs_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error: short response"); - } - - sftp->statvfs_state = libssh2_NB_state_idle; - - st->f_bsize = _libssh2_ntohu64(data + 5); - st->f_frsize = _libssh2_ntohu64(data + 13); - st->f_blocks = _libssh2_ntohu64(data + 21); - st->f_bfree = _libssh2_ntohu64(data + 29); - st->f_bavail = _libssh2_ntohu64(data + 37); - st->f_files = _libssh2_ntohu64(data + 45); - st->f_ffree = _libssh2_ntohu64(data + 53); - st->f_favail = _libssh2_ntohu64(data + 61); - st->f_fsid = _libssh2_ntohu64(data + 69); - flag = _libssh2_ntohu64(data + 77); - st->f_namemax = _libssh2_ntohu64(data + 85); - - st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY) - ? LIBSSH2_SFTP_ST_RDONLY : 0; - st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID) - ? LIBSSH2_SFTP_ST_NOSUID : 0; - - LIBSSH2_FREE(session, data); - return 0; -} - -/* libssh2_sftp_statvfs_ex - * Get filesystem space and inode utilization (requires statvfs@openssh.com - * support on the server) - */ -LIBSSH2_API int -libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, - size_t path_len, LIBSSH2_SFTP_STATVFS *st) -{ - int rc; - if(!sftp || !st) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len, - st)); - return rc; -} - - -/* - * sftp_mkdir - * - * Create an SFTP directory - */ -static int sftp_mkdir(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 - }; - size_t data_len; - int retcode; - /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ - ssize_t packet_len = path_len + 13 + - sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS); - unsigned char *packet, *s, *data; - int rc; - - if (sftp->mkdir_state == libssh2_NB_state_idle) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, - "Creating directory %s with mode 0%lo", path, mode); - s = packet = LIBSSH2_ALLOC(session, packet_len); - if (!packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_MKDIR " - "packet"); - } - /* Filetype in SFTP 3 and earlier */ - attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR; - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_MKDIR; - sftp->mkdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->mkdir_request_id); - _libssh2_store_str(&s, path, path_len); - - s += sftp_attr2bin(s, &attrs); - - sftp->mkdir_state = libssh2_NB_state_created; - } - else { - packet = sftp->mkdir_packet; - } - - if (sftp->mkdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - sftp->mkdir_packet = packet; - return rc; - } - if (packet_len != rc) { - LIBSSH2_FREE(session, packet); - sftp->mkdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "_libssh2_channel_write() failed"); - } - LIBSSH2_FREE(session, packet); - sftp->mkdir_state = libssh2_NB_state_sent; - sftp->mkdir_packet = NULL; - } - - rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id, - &data, &data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->mkdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - sftp->mkdir_state = libssh2_NB_state_idle; - - retcode = _libssh2_ntohu32(data + 5); - LIBSSH2_FREE(session, data); - - if (retcode == LIBSSH2_FX_OK) { - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!"); - return 0; - } else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* - * 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) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_mkdir(sftp, path, path_len, mode)); - return rc; -} - -/* sftp_rmdir - * Remove a directory - */ -static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len) -{ - LIBSSH2_CHANNEL *channel = sftp->channel; - LIBSSH2_SESSION *session = channel->session; - size_t data_len; - int 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_TRACE_SFTP, "Removing directory: %s", - path); - s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->rmdir_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_RMDIR " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 4); - *(s++) = SSH_FXP_RMDIR; - sftp->rmdir_request_id = sftp->request_id++; - _libssh2_store_u32(&s, sftp->rmdir_request_id); - _libssh2_store_str(&s, path, path_len); - - sftp->rmdir_state = libssh2_NB_state_created; - } - - if (sftp->rmdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->rmdir_packet); - sftp->rmdir_packet = NULL; - sftp->rmdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send FXP_RMDIR command"); - } - 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 == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (rc) { - sftp->rmdir_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Error waiting for FXP STATUS"); - } - - 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; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } -} - -/* libssh2_sftp_rmdir_ex - * Remove a directory - */ -LIBSSH2_API int -libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_rmdir(sftp, path, path_len)); - return rc; -} - -/* sftp_stat - * Stat a file or symbolic link - */ -static int sftp_stat(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; - size_t 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) ? sftp_attrsize(attrs->flags) : 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_TRACE_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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for FXP_*STAT " - "packet"); - } - - _libssh2_store_u32(&s, packet_len - 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_store_u32(&s, sftp->stat_request_id); - _libssh2_store_str(&s, path, path_len); - - if (stat_type == LIBSSH2_SFTP_SETSTAT) - s += sftp_attr2bin(s, attrs); - - sftp->stat_state = libssh2_NB_state_created; - } - - if (sftp->stat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->stat_packet); - sftp->stat_packet = NULL; - sftp->stat_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send STAT/LSTAT/SETSTAT command"); - } - 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 == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (rc) { - sftp->stat_state = libssh2_NB_state_idle; - return _libssh2_error(session, rc, - "Timeout waiting for status message"); - } - - 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; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - sftp_bin2attr(attrs, data + 5); - LIBSSH2_FREE(session, data); - - return 0; -} - -/* libssh2_sftp_stat_ex - * Stat a file or symbolic link - */ -LIBSSH2_API int -libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path, - unsigned int path_len, int stat_type, - LIBSSH2_SFTP_ATTRIBUTES *attrs) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_stat(sftp, path, path_len, stat_type, attrs)); - return rc; -} - -/* sftp_symlink - * Read or set a symlink - */ -static int sftp_symlink(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; - size_t 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 retcode; - - if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) { - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Server does not support SYMLINK or READLINK"); - } - - if (sftp->symlink_state == libssh2_NB_state_idle) { - s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len); - if (!sftp->symlink_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "SYMLINK/READLINK/REALPATH packet"); - } - - _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s", - (link_type == - LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading", - (link_type == - LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path); - - _libssh2_store_u32(&s, packet_len - 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_store_u32(&s, sftp->symlink_request_id); - _libssh2_store_str(&s, path, path_len); - - if (link_type == LIBSSH2_SFTP_SYMLINK) - _libssh2_store_str(&s, target, target_len); - - sftp->symlink_state = libssh2_NB_state_created; - } - - if (sftp->symlink_state == libssh2_NB_state_created) { - ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet, - packet_len); - if (rc == LIBSSH2_ERROR_EAGAIN) - return rc; - else if (packet_len != rc) { - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - sftp->symlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send SYMLINK/READLINK command"); - } - LIBSSH2_FREE(session, sftp->symlink_packet); - sftp->symlink_packet = NULL; - - sftp->symlink_state = libssh2_NB_state_sent; - } - - retcode = sftp_packet_requirev(sftp, 2, link_responses, - sftp->symlink_request_id, &data, - &data_len); - if (retcode == LIBSSH2_ERROR_EAGAIN) - return retcode; - else if (retcode) { - sftp->symlink_state = libssh2_NB_state_idle; - return _libssh2_error(session, retcode, - "Error waiting for status message"); - } - - 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 LIBSSH2_ERROR_NONE; - else { - sftp->last_errno = retcode; - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "SFTP Protocol Error"); - } - } - - if (_libssh2_ntohu32(data + 5) < 1) { - LIBSSH2_FREE(session, data); - return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, - "Invalid READLINK/REALPATH response, " - "no name entries"); - } - - /* this reads a u32 and stores it into a signed 32bit value */ - link_len = _libssh2_ntohu32(data + 9); - if (link_len < target_len) { - memcpy(target, data + 13, link_len); - target[link_len] = 0; - retcode = (int)link_len; - } - else - retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL; - LIBSSH2_FREE(session, data); - - return retcode; -} - -/* 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) -{ - int rc; - if(!sftp) - return LIBSSH2_ERROR_BAD_USE; - BLOCK_ADJUST(rc, sftp->channel->session, - sftp_symlink(sftp, path, path_len, target, target_len, - link_type)); - return rc; -} - -/* libssh2_sftp_last_error - * Returns the last error code reported by SFTP - */ -LIBSSH2_API unsigned long -libssh2_sftp_last_error(LIBSSH2_SFTP *sftp) -{ - if(!sftp) - return 0; - - return sftp->last_errno; -} - -/* libssh2_sftp_get_channel - * Return the channel of sftp, then caller can control the channel's behavior. - */ -LIBSSH2_API LIBSSH2_CHANNEL * -libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp) -{ - if (!sftp) - return NULL; - - return sftp->channel; -} diff --git a/vendor/libssh2-1.4.2/src/sftp.h b/vendor/libssh2-1.4.2/src/sftp.h deleted file mode 100644 index 55bdb46..0000000 --- a/vendor/libssh2-1.4.2/src/sftp.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef _LIBSSH2_SFTP_H -#define _LIBSSH2_SFTP_H -/* - * Copyright (C) 2010 - 2012 by Daniel Stenberg - * Author: Daniel Stenberg - * - * 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. - * - */ - -/* - * MAX_SFTP_OUTGOING_SIZE MUST not be larger than 32500 or so. This is the - * amount of data sent in each FXP_WRITE packet - */ -#define MAX_SFTP_OUTGOING_SIZE 30000 - -/* MAX_SFTP_READ_SIZE is how much data is asked for at max in each FXP_READ - * packets. - */ -#define MAX_SFTP_READ_SIZE 2000 - -struct sftp_pipeline_chunk { - struct list_node node; - size_t len; /* WRITE: size of the data to write - READ: how many bytes that was asked for */ - size_t sent; - ssize_t lefttosend; /* if 0, the entire packet has been sent off */ - uint32_t request_id; - unsigned char packet[1]; /* data */ -}; - -struct sftp_zombie_requests { - struct list_node node; - uint32_t request_id; -}; - -#ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -struct _LIBSSH2_SFTP_PACKET -{ - struct list_node node; /* linked list header */ - uint32_t request_id; - unsigned char *data; - size_t data_len; /* payload size */ -}; - -typedef struct _LIBSSH2_SFTP_PACKET LIBSSH2_SFTP_PACKET; - -#define SFTP_HANDLE_MAXLEN 256 /* according to spec! */ - -struct _LIBSSH2_SFTP_HANDLE -{ - struct list_node node; - - LIBSSH2_SFTP *sftp; - - char handle[SFTP_HANDLE_MAXLEN]; - size_t handle_len; - - enum { - LIBSSH2_SFTP_HANDLE_FILE, - LIBSSH2_SFTP_HANDLE_DIR - } handle_type; - - union _libssh2_sftp_handle_data - { - struct _libssh2_sftp_handle_file_data - { - libssh2_uint64_t offset; - libssh2_uint64_t offset_sent; - size_t acked; /* container for acked data that hasn't been - returned to caller yet, used for sftp_write */ - - /* 'data' is used by sftp_read() and is allocated data that has - been received already from the server but wasn't returned to - the caller yet. It is of size 'data_len' and 'data_left is the - number of bytes not yet returned, counted from the end of the - buffer. */ - unsigned char *data; - size_t data_len; - size_t data_left; - - char eof; /* we have read to the end */ - } file; - struct _libssh2_sftp_handle_dir_data - { - uint32_t names_left; - void *names_packet; - char *next_name; - } dir; - } u; - - /* State variables used in libssh2_sftp_close_handle() */ - libssh2_nonblocking_states close_state; - uint32_t close_request_id; - unsigned char *close_packet; - - /* list of outstanding packets sent to server */ - struct list_head packet_list; - -}; - -struct _LIBSSH2_SFTP -{ - LIBSSH2_CHANNEL *channel; - - uint32_t request_id, version; - - struct list_head packets; - - /* List of FXP_READ responses to ignore because EOF already received. */ - struct list_head zombie_requests; - - /* a list of _LIBSSH2_SFTP_HANDLE structs */ - struct list_head sftp_handles; - - uint32_t last_errno; - - /* Holder for partial packet, use in libssh2_sftp_packet_read() */ - unsigned char partial_size[4]; /* buffer for size field */ - size_t partial_size_len; /* size field length */ - unsigned char *partial_packet; /* The data */ - uint32_t partial_len; /* Desired number of bytes */ - size_t 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; - uint32_t open_packet_len; /* 32 bit on the wire */ - size_t open_packet_sent; - uint32_t open_request_id; - - /* State variable used in sftp_read() */ - libssh2_nonblocking_states read_state; - - /* State variable used in sftp_packet_read() */ - libssh2_nonblocking_states packet_state; - - /* State variable used in sftp_write() */ - libssh2_nonblocking_states write_state; - - /* State variables used in libssh2_sftp_readdir() */ - libssh2_nonblocking_states readdir_state; - unsigned char *readdir_packet; - uint32_t readdir_request_id; - - /* State variables used in libssh2_sftp_fstat_ex() */ - libssh2_nonblocking_states fstat_state; - unsigned char *fstat_packet; - uint32_t fstat_request_id; - - /* State variables used in libssh2_sftp_unlink_ex() */ - libssh2_nonblocking_states unlink_state; - unsigned char *unlink_packet; - uint32_t unlink_request_id; - - /* State variables used in libssh2_sftp_rename_ex() */ - libssh2_nonblocking_states rename_state; - unsigned char *rename_packet; - unsigned char *rename_s; - uint32_t rename_request_id; - - /* State variables used in libssh2_sftp_fstatvfs() */ - libssh2_nonblocking_states fstatvfs_state; - unsigned char *fstatvfs_packet; - uint32_t fstatvfs_request_id; - - /* State variables used in libssh2_sftp_statvfs() */ - libssh2_nonblocking_states statvfs_state; - unsigned char *statvfs_packet; - uint32_t statvfs_request_id; - - /* State variables used in libssh2_sftp_mkdir() */ - libssh2_nonblocking_states mkdir_state; - unsigned char *mkdir_packet; - uint32_t mkdir_request_id; - - /* State variables used in libssh2_sftp_rmdir() */ - libssh2_nonblocking_states rmdir_state; - unsigned char *rmdir_packet; - uint32_t rmdir_request_id; - - /* State variables used in libssh2_sftp_stat() */ - libssh2_nonblocking_states stat_state; - unsigned char *stat_packet; - uint32_t stat_request_id; - - /* State variables used in libssh2_sftp_symlink() */ - libssh2_nonblocking_states symlink_state; - unsigned char *symlink_packet; - uint32_t symlink_request_id; -}; - -#endif diff --git a/vendor/libssh2-1.4.2/src/transport.c b/vendor/libssh2-1.4.2/src/transport.c deleted file mode 100644 index 95b9a3a..0000000 --- a/vendor/libssh2-1.4.2/src/transport.c +++ /dev/null @@ -1,873 +0,0 @@ -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * 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 -#include -#include -#ifdef LIBSSH2DEBUG -#include -#endif - -#include - -#include "transport.h" -#include "mac.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, const unsigned char *ptr, size_t size) -{ - size_t i; - size_t c; - unsigned int width = 0x10; - char buffer[256]; /* Must be enough for width*4 + about 30 or so */ - size_t used; - static const char* hex_chars = "0123456789ABCDEF"; - - if (!(session->showmask & LIBSSH2_TRACE_TRANS)) { - /* not asked for, bail out */ - return; - } - - used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", - desc, (int) size); - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, - buffer, used); - else - fprintf(stderr, "%s", buffer); - - for(i = 0; i < size; i += width) { - - used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i); - - /* hex not disabled, show it */ - for(c = 0; c < width; c++) { - if (i + c < size) { - buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF]; - buffer[used++] = hex_chars[ptr[i+c] & 0xF]; - } - else { - buffer[used++] = ' '; - buffer[used++] = ' '; - } - - buffer[used++] = ' '; - if ((width/2) - 1 == c) - buffer[used++] = ' '; - } - - buffer[used++] = ':'; - buffer[used++] = ' '; - - for(c = 0; (c < width) && (i + c < size); c++) { - buffer[used++] = isprint(ptr[i + c]) ? - ptr[i + c] : UNPRINTABLE_CHAR; - } - buffer[used++] = '\n'; - buffer[used] = 0; - - if (session->tracehandler) - (session->tracehandler)(session, session->tracehandler_context, - buffer, used); - else - fprintf(stderr, "%s", buffer); - } -} -#else -#define debugdump(a,x,y,z) -#endif - - -/* decrypt() decrypts 'len' bytes from 'source' to 'dest'. - * - * returns 0 on success and negative on failure - */ - -static int -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_FREE(session, p->payload); - return LIBSSH2_ERROR_DECRYPT; - } - - /* 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 LIBSSH2_ERROR_NONE; /* all is fine */ -} - -/* - * fullpacket() gets called when a full packet has been received and properly - * collected. - */ -static int -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 && - session->remote.comp->compress && - session->remote.comp_abstract) { - /* - * The buffer for the decompression (remote.comp_abstract) is - * initialised in time when it is needed so as long it is NULL we - * cannot decompress. - */ - - unsigned char *data; - size_t data_len; - rc = session->remote.comp->decomp(session, - &data, &data_len, - LIBSSH2_PACKET_MAXDECOMP, - p->payload, - session->fullpacket_payload_len, - &session->remote.comp_abstract); - LIBSSH2_FREE(session, p->payload); - if(rc) - return rc; - - p->payload = data; - session->fullpacket_payload_len = data_len; - } - - session->fullpacket_packet_type = p->payload[0]; - - debugdump(session, "libssh2_transport_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) - return rc; - } - - session->fullpacket_state = libssh2_NB_state_idle; - - return session->fullpacket_packet_type; -} - - -/* - * _libssh2_transport_read - * - * Collect a packet into the input queue. - * - * Returns packet type added to input queue (0 if nothing added), or a - * negative error number. - */ - -/* - * This function reads the binary stream as specified in chapter 6 of RFC4253 - * "The Secure Shell (SSH) Transport Layer Protocol" - * - * DOES NOT call _libssh2_error() for ANY error case. - */ -int _libssh2_transport_read(LIBSSH2_SESSION * session) -{ - int rc; - struct transportpacket *p = &session->packet; - int remainbuf; - int remainpack; - int numbytes; - int numdecrypt; - unsigned char block[MAX_BLOCKSIZE]; - int blocksize; - int encrypted = 1; - size_t total_num; - - /* default clear the bit */ - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; - - /* - * 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_TRACE_TRANS, "Redirecting into the" - " key re-exchange from _libssh2_transport_read"); - rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) - return rc; - } - - /* - * =============================== 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_transport_read_point1; - } - - do { - if (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) { - return LIBSSH2_ERROR_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 = - LIBSSH2_RECV(session, &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 */ - if ((nread < 0) && (nread == -EAGAIN)) { - session->socket_block_directions |= - LIBSSH2_SESSION_BLOCK_INBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error recving %d bytes (got %d)", - PACKETBUFSIZE - remainbuf, -nread); - return LIBSSH2_ERROR_SOCKET_RECV; - } - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Recved %d/%d bytes to %p+%d", nread, - PACKETBUFSIZE - remainbuf, p->buf, remainbuf); - - debugdump(session, "libssh2_transport_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 - */ - session->socket_block_directions |= - LIBSSH2_SESSION_BLOCK_INBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - - if (encrypted) { - rc = decrypt(session, &p->buf[p->readidx], block, blocksize); - if (rc != LIBSSH2_ERROR_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); - if (p->packet_length < 1) - return LIBSSH2_ERROR_DECRYPT; - - p->padding_length = block[4]; - - /* total_num is the number of bytes following the initial - (5 bytes) packet length and padding length fields */ - 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 (total_num > LIBSSH2_PACKET_MAXPAYLOAD) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; - } - - /* Get a packet handle put data into. We get one to - hold all data, including padding and MAC. */ - p->payload = LIBSSH2_ALLOC(session, total_num); - if (!p->payload) { - return LIBSSH2_ERROR_ALLOC; - } - p->total_num = total_num; - /* 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 != LIBSSH2_ERROR_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_transport_read_point1: - rc = fullpacket(session, encrypted); - if (rc == LIBSSH2_ERROR_EAGAIN) { - - if (session->packAdd_state != libssh2_NB_state_idle) - { - /* fullpacket only returns LIBSSH2_ERROR_EAGAIN if - * libssh2_packet_add returns LIBSSH2_ERROR_EAGAIN. If that - * returns LIBSSH2_ERROR_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 rc; - } - - p->total_num = 0; /* no packet buffer available */ - - return rc; - } - } while (1); /* loop */ - - return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */ -} - -static int -send_existing(LIBSSH2_SESSION *session, const unsigned char *data, - size_t data_len, ssize_t *ret) -{ - ssize_t rc; - ssize_t length; - struct transportpacket *p = &session->packet; - - if (!p->olen) { - *ret = 0; - return LIBSSH2_ERROR_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 LIBSSH2_ERROR_BAD_USE; - } - - *ret = 1; /* set to make our parent return */ - - /* number of bytes left to send */ - length = p->ototal_num - p->osent; - - rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (rc < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", length, -rc); - else { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Sent %d/%d bytes at %p+%d", rc, length, p->outbuf, - p->osent); - debugdump(session, "libssh2_transport_write send()", - &p->outbuf[p->osent], rc); - } - - if (rc == length) { - /* the remainder of the package was sent */ - p->ototal_num = 0; - p->olen = 0; - /* we leave *ret set so that the parent returns as we MUST return back - a send success now, so that we don't risk sending EAGAIN later - which then would confuse the parent function */ - return LIBSSH2_ERROR_NONE; - - } - else if (rc < 0) { - /* nothing was sent */ - if (rc != -EAGAIN) - /* send failure! */ - return LIBSSH2_ERROR_SOCKET_SEND; - - session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND; - return LIBSSH2_ERROR_EAGAIN; - } - - p->osent += rc; /* we sent away this much data */ - - return rc < length ? LIBSSH2_ERROR_EAGAIN : LIBSSH2_ERROR_NONE; -} - -/* - * libssh2_transport_send - * - * Send a packet, encrypting it and adding a MAC code if necessary - * Returns 0 on success, non-zero on failure. - * - * The data is provided as _two_ data areas that are combined by this - * function. The 'data' part is sent immediately before 'data2'. 'data2' may - * be set to NULL to only use a single part. - * - * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was - * not sent yet. If it does so, the caller should call this function again as - * soon as it is likely that more data can be sent, and this function MUST - * then be called with the same argument set (same data pointer and same - * data_len) until ERROR_NONE or failure is returned. - * - * This function DOES NOT call _libssh2_error() on any errors. - */ -int _libssh2_transport_send(LIBSSH2_SESSION *session, - const unsigned char *data, size_t data_len, - const unsigned char *data2, size_t data2_len) -{ - int blocksize = - (session->state & LIBSSH2_STATE_NEWKEYS) ? - session->local.crypt->blocksize : 8; - int padding_length; - size_t packet_length; - int total_length; -#ifdef RANDOM_PADDING - int rand_max; - int seed = data[0]; /* FIXME: make this random */ -#endif - struct transportpacket *p = &session->packet; - int encrypted; - ssize_t ret; - int rc; - const unsigned char *orgdata = data; - size_t orgdata_len = data_len; - - /* - * If the last read operation was interrupted in the middle of a key - * exchange, we must complete that key exchange before continuing to write - * further data. - * - * See the similar block in _libssh2_transport_read for more details. - */ - if (session->state & LIBSSH2_STATE_EXCHANGING_KEYS && - !(session->state & LIBSSH2_STATE_KEX_ACTIVE)) { - /* Don't write any new packets if we're still in the middle of a key - * exchange. */ - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Redirecting into the" - " key re-exchange from _libssh2_transport_send"); - rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state); - if (rc) - return rc; - } - - debugdump(session, "libssh2_transport_write plain", data, data_len); - if(data2) - debugdump(session, "libssh2_transport_write plain2", data2, data2_len); - - /* FIRST, check if we have a pending write to complete. send_existing - only sanity-check data and data_len and not data2 and data2_len!! */ - rc = send_existing(session, data, data_len, &ret); - if (rc) - return rc; - - session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; - - if (ret) - /* set by send_existing if data was sent */ - return rc; - - encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0; - - if (encrypted && session->local.comp->compress) { - /* the idea here is that these function must fail if the output gets - larger than what fits in the assigned buffer so thus they don't - check the input size as we don't know how much it compresses */ - size_t dest_len = MAX_SSH_PACKET_LEN-5-256; - size_t dest2_len = dest_len; - - /* compress directly to the target buffer */ - rc = session->local.comp->comp(session, - &p->outbuf[5], &dest_len, - data, data_len, - &session->local.comp_abstract); - if(rc) - return rc; /* compression failure */ - - if(data2 && data2_len) { - /* compress directly to the target buffer right after where the - previous call put data */ - dest2_len -= dest_len; - - rc = session->local.comp->comp(session, - &p->outbuf[5+dest_len], &dest2_len, - data2, data2_len, - &session->local.comp_abstract); - } - else - dest2_len = 0; - if(rc) - return rc; /* compression failure */ - - data_len = dest_len + dest2_len; /* use the combined length */ - } - else { - if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100)) - /* too large packet, return error for this until we make this - function split it up and send multiple SSH packets */ - return LIBSSH2_ERROR_INVAL; - - /* copy the payload data */ - memcpy(&p->outbuf[5], data, data_len); - if(data2 && data2_len) - memcpy(&p->outbuf[5+data_len], data2, data2_len); - data_len += data2_len; /* use the combined length */ - } - - - /* 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); - - /* 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; - - /* fill the padding area with random junk */ - _libssh2_random(p->outbuf + 5 + data_len, padding_length); - - if (encrypted) { - size_t i; - - /* 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 LIBSSH2_ERROR_ENCRYPT; /* encryption failure */ - } - } - - session->local.seqno++; - - ret = LIBSSH2_SEND(session, p->outbuf, total_length, - LIBSSH2_SOCKET_SEND_FLAGS(session)); - if (ret < 0) - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, - "Error sending %d bytes: %d", total_length, -ret); - else { - _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p", - ret, total_length, p->outbuf); - debugdump(session, "libssh2_transport_write send()", p->outbuf, ret); - } - - if (ret != total_length) { - if (ret >= 0 || ret == -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 <= 0 ? 0 : ret; - p->ototal_num = total_length; - return LIBSSH2_ERROR_EAGAIN; - } - return LIBSSH2_ERROR_SOCKET_SEND; - } - - /* the whole thing got sent away */ - p->odata = NULL; - p->olen = 0; - - return LIBSSH2_ERROR_NONE; /* all is good */ -} diff --git a/vendor/libssh2-1.4.2/src/transport.h b/vendor/libssh2-1.4.2/src/transport.h deleted file mode 100644 index 89982a6..0000000 --- a/vendor/libssh2-1.4.2/src/transport.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef __LIBSSH2_TRANSPORT_H -#define __LIBSSH2_TRANSPORT_H - -/* Copyright (C) 2007 The Written Word, Inc. All rights reserved. - * Copyright (C) 2009-2010 by Daniel Stenberg - * Author: Daniel Stenberg - * - * 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 "packet.h" - - -/* - * libssh2_transport_send - * - * Send a packet, encrypting it and adding a MAC code if necessary - * Returns 0 on success, non-zero on failure. - * - * The data is provided as _two_ data areas that are combined by this - * function. The 'data' part is sent immediately before 'data2'. 'data2' can - * be set to NULL (or data2_len to 0) to only use a single part. - * - * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was - * not sent yet. If it does so, the caller should call this function again as - * soon as it is likely that more data can be sent, and this function MUST - * then be called with the same argument set (same data pointer and same - * data_len) until ERROR_NONE or failure is returned. - * - * This function DOES NOT call _libssh2_error() on any errors. - */ -int _libssh2_transport_send(LIBSSH2_SESSION *session, - const unsigned char *data, size_t data_len, - const unsigned char *data2, size_t data2_len); - -/* - * _libssh2_transport_read - * - * Collect a packet into the input brigade block only controls whether or not - * to wait for a packet to start. - * - * 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" - */ -int _libssh2_transport_read(LIBSSH2_SESSION * session); - -#endif /* __LIBSSH2_TRANSPORT_H */ diff --git a/vendor/libssh2-1.4.2/src/userauth.c b/vendor/libssh2-1.4.2/src/userauth.c deleted file mode 100644 index a0733d5..0000000 --- a/vendor/libssh2-1.4.2/src/userauth.c +++ /dev/null @@ -1,1687 +0,0 @@ -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2009-2011 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" - -#include -#include - -#include - -/* Needed for struct iovec on some platforms */ -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#include "transport.h" -#include "session.h" -#include "userauth.h" - -/* 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 - */ -static char *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) = 27 */ - 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 + 27; - - 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"); - return NULL; - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", 14); - _libssh2_store_u32(&s, 4); /* send "none" separately */ - - session->userauth_list_state = libssh2_NB_state_created; - } - - if (session->userauth_list_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_list_data, - session->userauth_list_data_len, - (unsigned char *)"none", 4); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - return NULL; - } - /* now free the packet that was sent */ - LIBSSH2_FREE(session, session->userauth_list_data); - session->userauth_list_data = NULL; - - if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-none request"); - session->userauth_list_state = libssh2_NB_state_idle; - return NULL; - } - - session->userauth_list_state = libssh2_NB_state_sent; - } - - if (session->userauth_list_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_list_data, - &session->userauth_list_data_len, 0, - NULL, 0, - &session->userauth_list_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - return NULL; - } else if (rc) { - _libssh2_error(session, rc, "Failed getting response"); - 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"); - 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_TRACE_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_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 *user, - unsigned int user_len) -{ - char *ptr; - BLOCK_ADJUST_ERRNO(ptr, session, - userauth_list(session, user, user_len)); - return ptr; -} - -/* - * libssh2_userauth_authenticated - * - * Returns: 0 if not yet authenticated - * 1 if already authenticated - */ -LIBSSH2_API int -libssh2_userauth_authenticated(LIBSSH2_SESSION * session) -{ - return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0; -} - - - -/* userauth_password - * Plain ol' login - */ -static int -userauth_password(LIBSSH2_SESSION *session, - const char *username, unsigned int username_len, - const unsigned 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 + 40; - - session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; - - /* TODO: remove this alloc with a fixed buffer in the session - struct */ - s = session->userauth_pswd_data = - LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "userauth-password request"); - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); - _libssh2_store_str(&s, "password", sizeof("password") - 1); - *s++ = '\0'; - _libssh2_store_u32(&s, password_len); - /* 'password' is sent separately */ - - _libssh2_debug(session, LIBSSH2_TRACE_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_transport_send(session, session->userauth_pswd_data, - session->userauth_pswd_data_len, - password, password_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block writing password request"); - } - - /* now free the sent packet */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - - if (rc) { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-password request"); - } - - 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(session, reply_codes, - &session->userauth_pswd_data, - &session->userauth_pswd_data_len, - 0, NULL, 0, - &session-> - userauth_pswd_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting"); - } else if (rc) { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, - "Would block waiting"); - } - - if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_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; - } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) { - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Password authentication failed"); - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed " - "(username/password)"); - } - - 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_TRACE_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) { - return _libssh2_error(session, - LIBSSH2_ERROR_PASSWORD_EXPIRED, - "Password expired, and " - "callback failed"); - } - - /* basic data_len + newpw_len(4) */ - session->userauth_pswd_data_len = - username_len + password_len + 44; - - s = session->userauth_pswd_data = - LIBSSH2_ALLOC(session, - session->userauth_pswd_data_len); - if (!session->userauth_pswd_data) { - LIBSSH2_FREE(session, - session->userauth_pswd_newpw); - session->userauth_pswd_newpw = NULL; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory " - "for userauth password " - "change request"); - } - - *(s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", - sizeof("ssh-connection") - 1); - _libssh2_store_str(&s, "password", - sizeof("password") - 1); - *s++ = 0x01; - _libssh2_store_str(&s, (char *)password, password_len); - _libssh2_store_u32(&s, - session->userauth_pswd_newpw_len); - /* send session->userauth_pswd_newpw separately */ - - session->userauth_pswd_state = libssh2_NB_state_sent2; - } - - if (session->userauth_pswd_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_send(session, - session->userauth_pswd_data, - session->userauth_pswd_data_len, - (unsigned char *) - session->userauth_pswd_newpw, - session->userauth_pswd_newpw_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block waiting"); - } - - /* free the allocated packets again */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - LIBSSH2_FREE(session, session->userauth_pswd_newpw); - session->userauth_pswd_newpw = NULL; - - if (rc) { - return _libssh2_error(session, - LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth " - "password-change request"); - } - - /* - * Ugliest use of goto ever. Blame it on the - * askN => requirev migration. - */ - session->userauth_pswd_state = libssh2_NB_state_sent; - goto password_response; - } - } - } else { - session->userauth_pswd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, - "Password Expired, and no callback " - "specified"); - } - } - } - - /* FAILURE */ - LIBSSH2_FREE(session, session->userauth_pswd_data); - session->userauth_pswd_data = NULL; - session->userauth_pswd_state = libssh2_NB_state_idle; - - return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed"); -} - -/* - * libssh2_userauth_password_ex - * - * 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))) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_password(session, username, username_len, - (unsigned char *)password, password_len, - passwd_change_cb)); - return rc; -} - -/* - * file_read_publickey - * - * Read a public key from an id_???.pub style file - * - * Returns an allocated string containing the decoded key in *pubkeydata - * on success. - * Returns an allocated string containing the key method (e.g. "ssh-dss") - * in method on success. - */ -static int -file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, - size_t *method_len, - unsigned char **pubkeydata, - size_t *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_TRACE_AUTH, "Loading public key file: %s", - pubkeyfile); - /* Read Public Key */ - fd = fopen(pubkeyfile, "r"); - if (!fd) { - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to open public key file"); - } - while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') - pubkey_len++; - if (feof(fd)) { - /* the last character was EOF */ - pubkey_len--; - } - rewind(fd); - - if (pubkey_len <= 1) { - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid data in public key file"); - } - - pubkey = LIBSSH2_ALLOC(session, pubkey_len); - if (!pubkey) { - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for public key data"); - } - if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { - LIBSSH2_FREE(session, pubkey); - fclose(fd); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to read public key from file"); - } - fclose(fd); - /* - * Remove trailing whitespace - */ - while (pubkey_len && isspace(pubkey[pubkey_len - 1])) - pubkey_len--; - - if (!pubkey_len) { - LIBSSH2_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Missing public key data"); - } - - if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) { - LIBSSH2_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid public key data"); - } - - sp1++; - - if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == 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_FREE(session, pubkey); - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Invalid key data, not base64 encoded"); - } - - /* 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 - 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 -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_TRACE_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) { - return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, - "No handler for specified private key"); - } - - if ((*hostkey_method)-> - initPEM(session, privkeyfile, (unsigned char *) passphrase, - hostkey_abstract)) { - return _libssh2_error(session, LIBSSH2_ERROR_FILE, - "Unable to initialize private key from file"); - } - - return 0; -} - -struct privkey_file { - const char *filename; - const char *passphrase; -}; - -static int -sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, - const unsigned char *data, size_t data_len, void **abstract) -{ - struct privkey_file *privkey_file = (struct privkey_file *) (*abstract); - const LIBSSH2_HOSTKEY_METHOD *privkeyobj; - void *hostkey_abstract; - struct iovec datavec; - int rc; - - rc = file_read_privatekey(session, &privkeyobj, &hostkey_abstract, - session->userauth_pblc_method, - session->userauth_pblc_method_len, - privkey_file->filename, - privkey_file->passphrase); - if(rc) - return rc; - - datavec.iov_base = (void *)data; - datavec.iov_len = data_len; - - if (privkeyobj->signv(session, sig, sig_len, 1, &datavec, - &hostkey_abstract)) { - if (privkeyobj->dtor) { - privkeyobj->dtor(session, abstract); - } - return -1; - } - - if (privkeyobj->dtor) { - privkeyobj->dtor(session, &hostkey_abstract); - } - return 0; -} - - - -/* userauth_hostbased_fromfile - * Authenticate using a keypair found in the named files - */ -static int -userauth_hostbased_fromfile(LIBSSH2_SESSION *session, - const char *username, size_t username_len, - const char *publickey, const char *privatekey, - const char *passphrase, const char *hostname, - size_t hostname_len, - const char *local_username, - size_t local_username_len) -{ - int rc; - - if (session->userauth_host_state == libssh2_NB_state_idle) { - const LIBSSH2_HOSTKEY_METHOD *privkeyobj; - unsigned char *pubkeydata, *sig; - size_t pubkeydata_len; - size_t 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 (publickey) { - rc = file_read_publickey(session, &session->userauth_host_method, - &session->userauth_host_method_len, - &pubkeydata, &pubkeydata_len, publickey); - if(rc) - /* Note: file_read_publickey() calls _libssh2_error() */ - return rc; - } - else { - /* Compute public key from private key. */ - rc = _libssh2_pub_priv_keyfile(session, - &session->userauth_host_method, - &session->userauth_host_method_len, - &pubkeydata, &pubkeydata_len, - privatekey, passphrase); - if (rc) - /* libssh2_pub_priv_keyfile calls _libssh2_error() */ - return rc; - } - - /* - * 52 = 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) + - * hostname_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 + 52; - - /* - * 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; - LIBSSH2_FREE(session, pubkeydata); - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory"); - } - - *(session->userauth_host_s++) = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&session->userauth_host_s, username, username_len); - _libssh2_store_str(&session->userauth_host_s, "ssh-connection", 14); - _libssh2_store_str(&session->userauth_host_s, "hostbased", 9); - _libssh2_store_str(&session->userauth_host_s, - (const char *)session->userauth_host_method, - session->userauth_host_method_len); - _libssh2_store_str(&session->userauth_host_s, (const char *)pubkeydata, - pubkeydata_len); - LIBSSH2_FREE(session, pubkeydata); - _libssh2_store_str(&session->userauth_host_s, hostname, hostname_len); - _libssh2_store_str(&session->userauth_host_s, local_username, - local_username_len); - - rc = file_read_privatekey(session, &privkeyobj, &abstract, - session->userauth_host_method, - session->userauth_host_method_len, - privatekey, passphrase); - if(rc) { - /* Note: file_read_privatekey() calls _libssh2_error() */ - 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 rc; - } - - _libssh2_htonu32(buf, session->session_id_len); - datavec[0].iov_base = (void *)buf; - datavec[0].iov_len = 4; - datavec[1].iov_base = (void *)session->session_id; - datavec[1].iov_len = session->session_id_len; - datavec[2].iov_base = (void *)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_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 _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed allocating additional space for " - "userauth-hostbased packet"); - } - session->userauth_host_packet = newpacket; - } - - session->userauth_host_s = - session->userauth_host_packet + session->userauth_host_packet_len; - - _libssh2_store_u32(&session->userauth_host_s, - 4 + session->userauth_host_method_len + 4 + sig_len); - _libssh2_store_str(&session->userauth_host_s, - (const char *)session->userauth_host_method, - session->userauth_host_method_len); - LIBSSH2_FREE(session, session->userauth_host_method); - session->userauth_host_method = NULL; - - _libssh2_store_str(&session->userauth_host_s, (const char *)sig, - sig_len); - LIBSSH2_FREE(session, sig); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting hostbased authentication"); - - session->userauth_host_state = libssh2_NB_state_created; - } - - if (session->userauth_host_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_host_packet, - session->userauth_host_s - - session->userauth_host_packet, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - else if (rc) { - LIBSSH2_FREE(session, session->userauth_host_packet); - session->userauth_host_packet = NULL; - session->userauth_host_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-hostbased request"); - } - 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) { - static const unsigned char reply_codes[3] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; - size_t data_len; - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_host_data, - &data_len, 0, NULL, 0, - &session-> - userauth_host_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - - session->userauth_host_state = libssh2_NB_state_idle; - if (rc) { - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Auth failed"); - } - - if (session->userauth_host_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_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; - 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; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid signature for supplied public key, or bad " - "username/public key combination"); -} - -/* 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 *user, - unsigned int user_len, - const char *publickey, - const char *privatekey, - const char *passphrase, - const char *host, - unsigned int host_len, - const char *localuser, - unsigned int localuser_len) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_hostbased_fromfile(session, user, user_len, - publickey, privatekey, - passphrase, host, host_len, - localuser, localuser_len)); - return rc; -} - - - -int -_libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const unsigned char *pubkeydata, - unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void *abstract) -{ - unsigned char reply_codes[4] = - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, - SSH_MSG_USERAUTH_PK_OK, 0 - }; - int rc; - unsigned char *s; - - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - - /* - * The call to _libssh2_ntohu32 later relies on pubkeydata having at - * least 4 valid bytes containing the length of the method name. - */ - if (pubkeydata_len < 4) - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key, too short"); - - /* Zero the whole thing out */ - memset(&session->userauth_pblc_packet_requirev_state, 0, - sizeof(session->userauth_pblc_packet_requirev_state)); - - /* - * As an optimisation, userauth_publickey_fromfile reuses a - * previously allocated copy of the method name to avoid an extra - * allocation/free. - * For other uses, we allocate and populate it here. - */ - if (!session->userauth_pblc_method) { - session->userauth_pblc_method_len = _libssh2_ntohu32(pubkeydata); - - if(session->userauth_pblc_method_len > pubkeydata_len) - /* the method length simply cannot be longer than the entire - passed in data, so we use this to detect crazy input - data */ - return _libssh2_error(session, - LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key"); - - session->userauth_pblc_method = - LIBSSH2_ALLOC(session, session->userauth_pblc_method_len); - if (!session->userauth_pblc_method) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for public key " - "data"); - } - memcpy(session->userauth_pblc_method, pubkeydata + 4, - session->userauth_pblc_method_len); - } - /* - * The length of the method name read from plaintext prefix in the - * file must match length embedded in the key. - * TODO: The data should match too but we don't check that. Should we? - */ - else if (session->userauth_pblc_method_len != - _libssh2_ntohu32(pubkeydata)) - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid public key"); - - /* - * 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. - * - * Note that the 'pubkeydata_len' extra bytes allocated here will not - * be used in this first send, but will be used in the later one where - * this same allocation is re-used. - */ - 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; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Out of memory"); - } - - *s++ = SSH_MSG_USERAUTH_REQUEST; - _libssh2_store_str(&s, username, username_len); - _libssh2_store_str(&s, "ssh-connection", 14); - _libssh2_store_str(&s, "publickey", 9); - - session->userauth_pblc_b = s; - /* Not sending signature with *this* packet */ - *s++ = 0; - - _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, - session->userauth_pblc_method_len); - _libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting publickey authentication"); - - session->userauth_pblc_state = libssh2_NB_state_created; - } - - if (session->userauth_pblc_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_pblc_packet, - session->userauth_pblc_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - 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 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-publickey request"); - } - - session->userauth_pblc_state = libssh2_NB_state_sent; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent) { - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pblc_data, - &session->userauth_pblc_data_len, 0, - NULL, 0, - &session-> - userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } - 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 _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Waiting for USERAUTH response"); - } - - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_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; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Username/PublicKey combination invalid"); - } - - /* Semi-Success! */ - LIBSSH2_FREE(session, session->userauth_pblc_data); - session->userauth_pblc_data = NULL; - - *session->userauth_pblc_b = 0x01; - session->userauth_pblc_state = libssh2_NB_state_sent1; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent1) { - unsigned char *buf; - unsigned char *sig; - size_t sig_len; - - s = buf = LIBSSH2_ALLOC(session, 4 + session->session_id_len - + session->userauth_pblc_packet_len); - if (!buf) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "userauth-publickey signed data"); - } - - _libssh2_store_str(&s, (const char *)session->session_id, - session->session_id_len); - - memcpy (s, session->userauth_pblc_packet, - session->userauth_pblc_packet_len); - s += session->userauth_pblc_packet_len; - - rc = sign_callback(session, &sig, &sig_len, buf, s - buf, abstract); - LIBSSH2_FREE(session, buf); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - 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 _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Callback returned error"); - } - - /* - * 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_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 _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Failed allocating additional space for " - "userauth-publickey packet"); - } - session->userauth_pblc_packet = newpacket; - } - - s = session->userauth_pblc_packet + session->userauth_pblc_packet_len; - session->userauth_pblc_b = NULL; - - _libssh2_store_u32(&s, - 4 + session->userauth_pblc_method_len + 4 + sig_len); - _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, - session->userauth_pblc_method_len); - - LIBSSH2_FREE(session, session->userauth_pblc_method); - session->userauth_pblc_method = NULL; - - _libssh2_store_str(&s, (const char *)sig, sig_len); - LIBSSH2_FREE(session, sig); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting publickey authentication -- phase 2"); - - session->userauth_pblc_s = s; - session->userauth_pblc_state = libssh2_NB_state_sent2; - } - - if (session->userauth_pblc_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_send(session, session->userauth_pblc_packet, - session->userauth_pblc_s - - session->userauth_pblc_packet, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-publickey request"); - } - LIBSSH2_FREE(session, session->userauth_pblc_packet); - session->userauth_pblc_packet = NULL; - - session->userauth_pblc_state = libssh2_NB_state_sent3; - } - - /* PK_OK is no longer valid */ - reply_codes[2] = 0; - - rc = _libssh2_packet_requirev(session, reply_codes, - &session->userauth_pblc_data, - &session->userauth_pblc_data_len, 0, NULL, 0, - &session->userauth_pblc_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block requesting userauth list"); - } else if (rc) { - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Waiting for publickey USERAUTH response"); - } - - if (session->userauth_pblc_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_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; - session->userauth_pblc_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, - "Invalid signature for supplied public key, or bad " - "username/public key combination"); -} - -/* - * userauth_publickey_fromfile - * Authenticate using a keypair found in the named files - */ -static int -userauth_publickey_fromfile(LIBSSH2_SESSION *session, - const char *username, - size_t username_len, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ - unsigned char *pubkeydata = NULL; - size_t pubkeydata_len = 0; - struct privkey_file privkey_file; - void *abstract = &privkey_file; - int rc; - - privkey_file.filename = privatekey; - privkey_file.passphrase = passphrase; - - if (session->userauth_pblc_state == libssh2_NB_state_idle) { - if (publickey) { - rc = file_read_publickey(session, &session->userauth_pblc_method, - &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len,publickey); - if (rc) - return rc; - } - else { - /* Compute public key from private key. */ - rc = _libssh2_pub_priv_keyfile(session, - &session->userauth_pblc_method, - &session->userauth_pblc_method_len, - &pubkeydata, &pubkeydata_len, - privatekey, passphrase); - - /* _libssh2_pub_priv_keyfile calls _libssh2_error() */ - if (rc) - return rc; - } - } - - rc = _libssh2_userauth_publickey(session, username, username_len, - pubkeydata, pubkeydata_len, - sign_fromfile, &abstract); - if(pubkeydata) - LIBSSH2_FREE(session, pubkeydata); - - return rc; -} - -/* 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 *user, - unsigned int user_len, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ - int rc; - - if(NULL == passphrase) - /* if given a NULL pointer, make it point to a zero-length - string to save us from having to check this all over */ - passphrase=""; - - BLOCK_ADJUST(rc, session, - userauth_publickey_fromfile(session, user, user_len, - publickey, privatekey, - passphrase)); - return rc; -} - -/* libssh2_userauth_publickey_ex - * Authenticate using an external callback function - */ -LIBSSH2_API int -libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *user, - const unsigned char *pubkeydata, - size_t pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void **abstract) -{ - int rc; - - if(!session) - return LIBSSH2_ERROR_BAD_USE; - - BLOCK_ADJUST(rc, session, - _libssh2_userauth_publickey(session, user, strlen(user), - pubkeydata, pubkeydata_len, - sign_callback, abstract)); - return rc; -} - - - -/* - * userauth_keyboard_interactive - * - * Authenticate using a challenge-response authentication - */ -static int -userauth_keyboard_interactive(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) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "keyboard-interactive authentication"); - } - - *s++ = SSH_MSG_USERAUTH_REQUEST; - - /* user name */ - _libssh2_store_str(&s, username, username_len); - - /* service name */ - _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); - - /* "keyboard-interactive" */ - _libssh2_store_str(&s, "keyboard-interactive", - sizeof("keyboard-interactive") - 1); - /* language tag */ - _libssh2_store_u32(&s, 0); - - /* submethods */ - _libssh2_store_u32(&s, 0); - - _libssh2_debug(session, LIBSSH2_TRACE_AUTH, - "Attempting keyboard-interactive authentication"); - - session->userauth_kybd_state = libssh2_NB_state_created; - } - - if (session->userauth_kybd_state == libssh2_NB_state_created) { - rc = _libssh2_transport_send(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); - } else if (rc) { - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send keyboard-interactive request"); - } - 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(session, reply_codes, - &session->userauth_kybd_data, - &session->userauth_kybd_data_len, - 0, NULL, 0, - &session-> - userauth_kybd_packet_requirev_state); - if (rc == LIBSSH2_ERROR_EAGAIN) { - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block"); - } else if (rc) { - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Waiting for keyboard USERAUTH response"); - } - - if (session->userauth_kybd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { - _libssh2_debug(session, LIBSSH2_TRACE_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_debug(session, LIBSSH2_TRACE_AUTH, - "Keyboard-interactive authentication failed"); - LIBSSH2_FREE(session, session->userauth_kybd_data); - session->userauth_kybd_data = NULL; - session->userauth_kybd_state = libssh2_NB_state_idle; - return _libssh2_error(session, - LIBSSH2_ERROR_AUTHENTICATION_FAILED, - "Authentication failed " - "(keyboard-interactive)"); - } - - /* 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; - if(session->userauth_kybd_auth_name_len) { - 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"); - 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; - if(session->userauth_kybd_auth_instruction_len) { - 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"); - 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; - - if(session->userauth_kybd_num_prompts) { - 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"); - 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"); - 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"); - 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_TRACE_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; - } - - /* A new userauth_kybd_data area is to be allocated, free the - former one. */ - LIBSSH2_FREE(session, session->userauth_kybd_data); - - 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"); - goto cleanup; - } - - *s = SSH_MSG_USERAUTH_INFO_RESPONSE; - s++; - _libssh2_store_u32(&s, session->userauth_kybd_num_prompts); - - for(i = 0; i != session->userauth_kybd_num_prompts; ++i) { - _libssh2_store_str(&s, - session->userauth_kybd_responses[i].text, - 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_transport_send(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len, - NULL, 0); - if (rc == LIBSSH2_ERROR_EAGAIN) - return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, - "Would block"); - if (rc) { - _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, - "Unable to send userauth-keyboard-interactive" - " request"); - 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; - } - } - - if(session->userauth_kybd_prompts) { - LIBSSH2_FREE(session, session->userauth_kybd_prompts); - session->userauth_kybd_prompts = NULL; - } - if(session->userauth_kybd_responses) { - LIBSSH2_FREE(session, session->userauth_kybd_responses); - session->userauth_kybd_responses = NULL; - } - if(session->userauth_kybd_auth_name) { - LIBSSH2_FREE(session, session->userauth_kybd_auth_name); - session->userauth_kybd_auth_name = NULL; - } - if(session->userauth_kybd_auth_instruction) { - LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction); - session->userauth_kybd_auth_instruction = 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; - } -} - -/* - * libssh2_userauth_keyboard_interactive_ex - * - * Authenticate using a challenge-response authentication - */ -LIBSSH2_API int -libssh2_userauth_keyboard_interactive_ex(LIBSSH2_SESSION *session, - const char *user, - unsigned int user_len, - LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback))) -{ - int rc; - BLOCK_ADJUST(rc, session, - userauth_keyboard_interactive(session, user, user_len, - response_callback)); - return rc; -} diff --git a/vendor/libssh2-1.4.2/src/userauth.h b/vendor/libssh2-1.4.2/src/userauth.h deleted file mode 100644 index c0442ae..0000000 --- a/vendor/libssh2-1.4.2/src/userauth.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef LIBSSH2_USERAUTH_H -#define LIBSSH2_USERAUTH_H -/* Copyright (c) 2004-2007, Sara Golemon - * Copyright (c) 2009-2010 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. - */ - -int -_libssh2_userauth_publickey(LIBSSH2_SESSION *session, - const char *username, - unsigned int username_len, - const unsigned char *pubkeydata, - unsigned long pubkeydata_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), - void *abstract); - -#endif /* LIBSSH2_USERAUTH_H */ diff --git a/vendor/libssh2-1.4.2/src/version.c b/vendor/libssh2-1.4.2/src/version.c deleted file mode 100644 index 408f83a..0000000 --- a/vendor/libssh2-1.4.2/src/version.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2009 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" - -/* - libssh2_version() can be used like this: - - if (!libssh2_version(LIBSSH2_VERSION_NUM)) { - fprintf (stderr, "Runtime libssh2 version too old!\n"); - exit(1); - } -*/ -LIBSSH2_API -const char *libssh2_version(int req_version_num) -{ - if(req_version_num <= LIBSSH2_VERSION_NUM) - return LIBSSH2_VERSION; - return NULL; /* this is not a suitable library! */ -} From b35f6880c64976ff530cf45b9fc2a6bc0a8826c6 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 12 Dec 2012 12:31:21 -0500 Subject: [PATCH 02/14] advanced error reporting / stack capture --- CMakeLists.txt | 1 + include/fc/error_report.hpp | 60 ++++++++++++++++++++++++++++++ src/error_report.cpp | 73 +++++++++++++++++++++++++++++++++++++ src/json_rpc_connection.cpp | 7 ++++ 4 files changed, 141 insertions(+) create mode 100644 include/fc/error_report.hpp create mode 100644 src/error_report.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ad7a161..80263d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ set( sources src/json_rpc_tcp_connection.cpp src/json_rpc_tcp_server.cpp src/json_rpc_error_object.cpp + src/error_report.cpp src/value.cpp src/lexical_cast.cpp src/spin_lock.cpp diff --git a/include/fc/error_report.hpp b/include/fc/error_report.hpp new file mode 100644 index 0000000..9d59e4e --- /dev/null +++ b/include/fc/error_report.hpp @@ -0,0 +1,60 @@ +#pragma once +#include +#include +#include +#include + +namespace fc { + + /** + * Represents one stack frame within an error_report. + */ + class error_frame { + public: + error_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value m ); + error_frame(){} + error_frame(const error_frame& ); + error_frame(error_frame&& ); + + error_frame& operator=(const error_frame& ); + error_frame& operator=(error_frame&& ); + + fc::string desc; + fc::string file; + int64_t line; + fc::string method; + uint64_t time; + fc::optional meta; + }; + typedef fc::vector error_context; + + /** + * This class is used for rich error reporting that captures relevant errors the + * whole way up the stack. By using FC_THROW_REPORT(...) and FC_REPORT_PUSH( e, ...) + * you can capture the file, line, and method where the error was caught / rethrown. + */ + class error_report { + public: + error_report(); + error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); + + error_frame& current(); + error_report& pop_frame(); + error_report& push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); + error_report& append( const error_report& e ); + + error_context stack; ///< Human readable stack of what we were atempting to do. + }; + +} // namespace fc + +#include +FC_REFLECT( fc::error_frame, (desc)(file)(line)(method)(time)(meta) ) +FC_REFLECT( fc::error_report, (stack) ) + +#include +#define FC_REPORT( X, ... ) fc::error_report X( __FILE__, __LINE__, __func__, __VA_ARGS__ ) +#define FC_THROW_REPORT( ... ) FC_THROW( fc::error_report( __FILE__, __LINE__, __func__, __VA_ARGS__ )) +#define FC_REPORT_CURRENT(ER, ... ) (ER).pop_frame().push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ ) +#define FC_REPORT_PUSH( ER, ... ) (ER).push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ ); +#define FC_REPORT_POP(ER) (ER).pop_frame() diff --git a/src/error_report.cpp b/src/error_report.cpp new file mode 100644 index 0000000..577543d --- /dev/null +++ b/src/error_report.cpp @@ -0,0 +1,73 @@ +#include + +namespace fc { + +error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) +:desc(d),file(f),line(l),method(m),meta(fc::move(met)){} + +error_report::error_report() +{ +} +error_frame::error_frame(const fc::error_frame& e) +:desc(e.desc),file(e.file),line(e.line),method(e.method),time(e.time),meta(e.meta){} + +error_frame::error_frame(fc::error_frame&& e) +:desc(fc::move(e.desc)), + file(fc::move(e.file)), + line(e.line), + method(fc::move(e.method)), + time(e.time), + meta(fc::move(e.meta)) + {} + +fc::error_frame& fc::error_frame::operator=(const fc::error_frame& f ) { + auto tmp = f; + fc_swap( tmp, *this ); + return *this; +} +fc::error_frame& fc::error_frame::operator=(fc::error_frame&& e ) +{ + desc=fc::move(e.desc); + file=fc::move(e.file); + line=fc::move(e.line); + method=fc::move(e.method); + time=e.time; + meta=fc::move(e.meta); + return *this; +} + +error_report::error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta ) +{ + push_frame( file, line, method, desc, meta ); +} + + +fc::error_frame& error_report::current() +{ + if( !stack.size() ) stack.resize(1); + return stack.back(); +} + +fc::error_report& error_report::pop_frame() +{ + stack.pop_back(); + return *this; +} + +fc::error_report& error_report::push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta ) +{ + stack.push_back( fc::error_frame( file, line, method, desc, meta ) ); + return *this; +} + +fc::error_report& error_report::append( const error_report& e ) +{ + // TODO: what to do about the 'failure...?' + stack.reserve( stack.size()+e.stack.size()); + for( uint32_t i = 0; i < e.stack.size(); ++i ) { + stack.push_back( e.stack[i] ); + } + return *this; +} + +} // namespace fc diff --git a/src/json_rpc_connection.cpp b/src/json_rpc_connection.cpp index 32ca5ab..6f00d0b 100644 --- a/src/json_rpc_connection.cpp +++ b/src/json_rpc_connection.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,12 @@ namespace fc { namespace json { auto id = value_cast(id_itr->val); try { send_result( id, smeth->second->call(params) ); + } catch ( fc::error_report& eo ) { + if( eo.stack.size() ) { + send_error( id, error_object( eo.current().desc, fc::value(eo) ) ); + } else { + send_error( id, error_object( "error report", fc::value(eo) ) ); + } } catch ( const fc::json::error_object& eo ) { send_error( id, eo ); } catch ( ... ) { From 7ca7aede5f26c4bb1b18e850ac037007ff410c58 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 12 Dec 2012 13:26:41 -0500 Subject: [PATCH 03/14] implementing fc::absolute for path --- include/fc/filesystem.hpp | 1 + src/filesystem.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/fc/filesystem.hpp b/include/fc/filesystem.hpp index 041c0bb..fbd5276 100644 --- a/include/fc/filesystem.hpp +++ b/include/fc/filesystem.hpp @@ -62,6 +62,7 @@ namespace fc { bool is_directory( const path& p ); bool is_regular_file( const path& p ); void create_directories( const path& p ); + path absolute( const path& p ); path canonical( const path& p ); uint64_t file_size( const path& p ); bool remove( const path& p ); diff --git a/src/filesystem.cpp b/src/filesystem.cpp index c102785..ee001a9 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -94,6 +94,7 @@ namespace fc { void copy( const path& f, const path& t ) { boost::filesystem::copy( f, t ); } bool remove( const path& f ) { return boost::filesystem::remove( f ); } fc::path canonical( const fc::path& p ) { return boost::filesystem::canonical(p); } + fc::path absolute( const fc::path& p ) { return boost::filesystem::absolute(p); } path unique_path() { return boost::filesystem::unique_path(); } path temp_directory_path() { return boost::filesystem::temp_directory_path(); } } From a02edaebd3694fdc5fd901c6323f1cf8295dab10 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 12 Dec 2012 13:41:33 -0500 Subject: [PATCH 04/14] remove full path from error messages --- src/error_report.cpp | 4 ++-- src/log.cpp | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/error_report.cpp b/src/error_report.cpp index 577543d..44a78c7 100644 --- a/src/error_report.cpp +++ b/src/error_report.cpp @@ -1,9 +1,9 @@ #include - +#include namespace fc { error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) -:desc(d),file(f),line(l),method(m),meta(fc::move(met)){} +:desc(d),file(fc::path(f).filename().generic_string()),line(l),method(m),meta(fc::move(met)){} error_report::error_report() { diff --git a/src/log.cpp b/src/log.cpp index f731119..199190d 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -8,12 +8,14 @@ #include #endif +#include #include namespace fc { const char* thread_name(); void* thread_ptr(); + /* const char* short_name( const char* file_name ) { const char* end = file_name + strlen(file_name); --end; @@ -25,6 +27,7 @@ namespace fc { } return file_name; } + */ #ifdef WIN32 #define isatty _isatty @@ -39,7 +42,7 @@ namespace fc { std::cerr<<"\r"< Date: Wed, 12 Dec 2012 15:56:48 -0500 Subject: [PATCH 05/14] updates... --- CMakeLists.txt | 1 + include/fc/http/connection.hpp | 5 ++--- include/fc/shared_impl.cpp | 4 ++++ include/fc/shared_impl.hpp | 2 ++ include/fc/shared_ptr.hpp | 4 ++++ include/fc/value_io.hpp | 3 +++ src/http_connection.cpp | 7 ++----- src/tcp_socket.cpp | 15 ++++++++++++--- 8 files changed, 30 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad7a161..c55e2bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ set( sources src/ssh.cpp src/process.cpp src/http_connection.cpp + src/http_server.cpp src/json_rpc_connection.cpp src/json_rpc_stream_connection.cpp src/json_rpc_tcp_connection.cpp diff --git a/include/fc/http/connection.hpp b/include/fc/http/connection.hpp index e975eda..557f57a 100644 --- a/include/fc/http/connection.hpp +++ b/include/fc/http/connection.hpp @@ -47,10 +47,9 @@ namespace fc { http::reply request( const fc::string& method, const fc::string& url, const fc::string& body ); // used for servers - fc::tcp_socket& get_socket(); + fc::tcp_socket& get_socket()const; - http::request read_request(); - void send_reply( const http::reply& ); + http::request read_request()const; FC_REFERENCE_TYPE(connection) }; diff --git a/include/fc/shared_impl.cpp b/include/fc/shared_impl.cpp index da73f9a..51948d6 100644 --- a/include/fc/shared_impl.cpp +++ b/include/fc/shared_impl.cpp @@ -14,6 +14,8 @@ shared_impl::shared_impl( U&& u ):_impl(fc::forward(u)){} template shared_impl::shared_impl( const shared_impl& u ):_impl(u._impl){} +template +shared_impl::shared_impl( shared_impl& u ):_impl(u._impl){} template shared_impl::shared_impl( shared_impl&& u ):_impl(fc::move(u._impl)){} @@ -55,6 +57,8 @@ TYPE::TYPE( TYPE&& c )\ :my(fc::move(c.my)){}\ TYPE::TYPE( const TYPE& c )\ :my(c.my){}\ +TYPE::TYPE( TYPE& c )\ +:my(c.my){}\ TYPE::TYPE() \ :my( new fc::shared_impl::impl( ) ){}\ TYPE::~TYPE(){}\ diff --git a/include/fc/shared_impl.hpp b/include/fc/shared_impl.hpp index bb6e7c8..3e3a73b 100644 --- a/include/fc/shared_impl.hpp +++ b/include/fc/shared_impl.hpp @@ -113,6 +113,7 @@ namespace fc { shared_impl( U&& u ); shared_impl( const shared_impl& u ); + shared_impl( shared_impl& u ); shared_impl( shared_impl&& u ); shared_impl& operator=( shared_impl&& u ); shared_impl& operator=( const shared_impl& u ); @@ -131,6 +132,7 @@ namespace fc { TYPE( TYPE* ); \ TYPE( TYPE&& ); \ TYPE( const TYPE& ); \ + TYPE( TYPE& ); \ template \ TYPE( A1&& ); \ template \ diff --git a/include/fc/shared_ptr.hpp b/include/fc/shared_ptr.hpp index 859467a..856aa7c 100644 --- a/include/fc/shared_ptr.hpp +++ b/include/fc/shared_ptr.hpp @@ -40,6 +40,10 @@ namespace fc { _ptr = p._ptr; if( _ptr ) _ptr->retain(); } + shared_ptr( shared_ptr& p ) { + _ptr = p._ptr; + if( _ptr ) _ptr->retain(); + } shared_ptr( shared_ptr&& p ) { _ptr = p._ptr; p._ptr = nullptr; diff --git a/include/fc/value_io.hpp b/include/fc/value_io.hpp index de9c678..fa23dba 100644 --- a/include/fc/value_io.hpp +++ b/include/fc/value_io.hpp @@ -93,16 +93,19 @@ namespace fc { */ template inline void pack_helper( const T& v, const char* name )const { + slog( "%s", name ); fc::pack( obj[name], v ); } template inline void pack_helper( const fc::optional& v, const char* name )const { + slog( "%s", name ); if( !!v ) { fc::pack( obj[name], *v ); } } template inline void operator()( const char* name )const { + slog( "%s", name ); pack_helper( c.*p, name ); } diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 621b1ad..0a28c5d 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -114,16 +114,13 @@ http::reply connection::request( const fc::string& method, } // used for servers -fc::tcp_socket& connection::get_socket() { +fc::tcp_socket& connection::get_socket()const { return my->sock; } -http::request connection::read_request() { +http::request connection::read_request()const { http::request r; return r; } -void connection::send_reply( const http::reply& ) { - -} } } // fc::http diff --git a/src/tcp_socket.cpp b/src/tcp_socket.cpp index 4df563c..ddfa3d2 100644 --- a/src/tcp_socket.cpp +++ b/src/tcp_socket.cpp @@ -9,7 +9,7 @@ namespace fc { class tcp_socket::impl { public: - impl():_sock( fc::asio::default_io_service() ){ } + impl():_sock( fc::asio::default_io_service() ){ slog( "creating socket %p", &_sock); } ~impl(){ if( _sock.is_open() ) _sock.close(); } @@ -85,7 +85,10 @@ namespace fc { class tcp_server::impl { public: - impl(uint16_t port):_accept( fc::asio::default_io_service(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) ){} + impl(uint16_t port): + _accept( fc::asio::default_io_service(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) ){ + slog( "... tcp server port %d", port ); + } ~impl(){ _accept.close(); } @@ -105,17 +108,23 @@ namespace fc { bool tcp_server::accept( tcp_socket& s ) { - fc::promise::ptr p( new promise("mace::cmt::asio::tcp::accept") ); + fc::promise::ptr p( new promise("tcp::accept") ); + slog( "accept socket %p", &s.my->_sock ); my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) { p->set_value(e); } ); + slog( "."); auto ec = p->wait(); + slog( "."); if( !ec ) s.my->_sock.non_blocking(true); + slog( "."); if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); + slog( "."); return true; } void tcp_server::listen( uint16_t port ) { if( my ) delete my; + slog( "Listen %d", port ); my = new impl(port); } From c885981c656b1334acfe5f9fb51bdf3064421317 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 12 Dec 2012 22:08:32 -0500 Subject: [PATCH 06/14] fixes to http/tcp server --- include/fc/value_io.hpp | 3 --- src/http_connection.cpp | 2 ++ src/tcp_socket.cpp | 10 ++-------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/include/fc/value_io.hpp b/include/fc/value_io.hpp index 51edb5e..b18ce56 100644 --- a/include/fc/value_io.hpp +++ b/include/fc/value_io.hpp @@ -93,19 +93,16 @@ namespace fc { */ template inline void pack_helper( const T& v, const char* name )const { - slog( "%s", name ); fc::pack( obj[name], v ); } template inline void pack_helper( const fc::optional& v, const char* name )const { - slog( "%s", name ); if( !!v ) { fc::pack( obj[name], *v ); } } template inline void operator()( const char* name )const { - slog( "%s", name ); pack_helper( c.*p, name ); } diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 0a28c5d..648305c 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -9,6 +9,8 @@ FC_START_SHARED_IMPL(fc::http::connection) fc::tcp_socket sock; fc::ip::endpoint ep; + impl() { + } int read_until( char* buffer, char* end, char c = '\n' ) { char* p = buffer; diff --git a/src/tcp_socket.cpp b/src/tcp_socket.cpp index ddfa3d2..541184a 100644 --- a/src/tcp_socket.cpp +++ b/src/tcp_socket.cpp @@ -9,7 +9,7 @@ namespace fc { class tcp_socket::impl { public: - impl():_sock( fc::asio::default_io_service() ){ slog( "creating socket %p", &_sock); } + impl():_sock( fc::asio::default_io_service() ){ } ~impl(){ if( _sock.is_open() ) _sock.close(); } @@ -87,7 +87,6 @@ namespace fc { public: impl(uint16_t port): _accept( fc::asio::default_io_service(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) ){ - slog( "... tcp server port %d", port ); } ~impl(){ _accept.close(); @@ -108,23 +107,18 @@ namespace fc { bool tcp_server::accept( tcp_socket& s ) { + if( !my ) return false; fc::promise::ptr p( new promise("tcp::accept") ); - slog( "accept socket %p", &s.my->_sock ); my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) { p->set_value(e); } ); - slog( "."); auto ec = p->wait(); - slog( "."); if( !ec ) s.my->_sock.non_blocking(true); - slog( "."); if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); - slog( "."); return true; } void tcp_server::listen( uint16_t port ) { if( my ) delete my; - slog( "Listen %d", port ); my = new impl(port); } From eeee86be6bc2c58527ffceab624175cd537ec6fd Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 13 Dec 2012 12:25:12 -0500 Subject: [PATCH 07/14] clean up error handling --- CMakeLists.txt | 2 +- include/fc/iostream_wrapper.hpp | 7 ++++- include/fc/json_rpc_process_client.hpp | 5 ++++ src/context.hpp | 1 - src/json.cpp | 8 ++++-- src/json_rpc_stream_connection.cpp | 37 +++++++++++++++----------- src/process.cpp | 17 +++++++++--- 7 files changed, 53 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7da9be8..5e691bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ set( sources src/ssh.cpp src/process.cpp src/http_connection.cpp - src/http_server.cpp +# src/http_server.cpp src/json_rpc_connection.cpp src/json_rpc_stream_connection.cpp src/json_rpc_tcp_connection.cpp diff --git a/include/fc/iostream_wrapper.hpp b/include/fc/iostream_wrapper.hpp index ed3affa..a369916 100644 --- a/include/fc/iostream_wrapper.hpp +++ b/include/fc/iostream_wrapper.hpp @@ -64,14 +64,18 @@ namespace fc { virtual ~istream_wrapper(){}; - virtual size_t readsome( char* buf, size_t len ) { return my->readsome(buf,len); } + virtual size_t readsome( char* buf, size_t len ) { + return my->readsome(buf,len); + } virtual istream& read( char* buf, size_t len ) { + // slog( "%p %lld", my.get(), len ); my->read(buf,len); return *this; } virtual void close() { } virtual bool eof()const{ return my->eof(); } + /* virtual istream& read( int64_t& ) { return *this; } virtual istream& read( uint64_t& ) { return *this; } virtual istream& read( int32_t& ) { return *this; } @@ -85,6 +89,7 @@ namespace fc { virtual istream& read( bool& ) { return *this; } virtual istream& read( char& ) { return *this; } virtual istream& read( fc::string& ) { return *this; } + */ protected: struct impl_base : public fc::retainable { diff --git a/include/fc/json_rpc_process_client.hpp b/include/fc/json_rpc_process_client.hpp index 6886a30..d1022e5 100644 --- a/include/fc/json_rpc_process_client.hpp +++ b/include/fc/json_rpc_process_client.hpp @@ -42,6 +42,11 @@ namespace fc { namespace json { void on_close( T&& f) { _con->on_close( fc::forward(f) ); } const fc::json::rpc_stream_connection::ptr& connection()const { return _con; } + + ~rpc_process_client() { + if(_con) + _con->close(); + } private: fc::process _proc; fc::json::rpc_stream_connection::ptr _con; diff --git a/src/context.hpp b/src/context.hpp index 57086fd..fb1cfe4 100644 --- a/src/context.hpp +++ b/src/context.hpp @@ -34,7 +34,6 @@ namespace fc { cur_task(0) { my_context.fc_stack.base = alloc.allocate( bc::default_stacksize() ); - // slog( "new stack %1% bytes at %2%", bc::default_stacksize(), my_context.fc_stack.base ); my_context.fc_stack.limit = static_cast( my_context.fc_stack.base) - bc::default_stacksize(); make_fcontext( &my_context, sf ); diff --git a/src/json.cpp b/src/json.cpp index 2105a97..895d743 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -918,15 +919,18 @@ fc::string pretty_print( fc::vector&& v, uint8_t indent ) { value from_file( const fc::path& local_path ) { if( !exists(local_path) ) { - FC_THROW_MSG( "Source file '%s' does not exist", local_path.string() ); + slog("..."); + FC_THROW_REPORT( "Source file '${filename}' does not exist", value().set("filename",local_path.string()) ); } if( is_directory( local_path ) ) { + wlog("..."); FC_THROW_MSG( "Source path '%s' is a directory, expected a file.", local_path.string() ); } // memory map the file - file_mapping fmap( local_path.string().c_str(), read_only ); size_t fsize = static_cast(file_size(local_path)); + if( fsize == 0 ) { return value(); } + file_mapping fmap( local_path.string().c_str(), read_only ); mapped_region mr( fmap, fc::read_only, 0, fsize ); diff --git a/src/json_rpc_stream_connection.cpp b/src/json_rpc_stream_connection.cpp index f173b82..cacd983 100644 --- a/src/json_rpc_stream_connection.cpp +++ b/src/json_rpc_stream_connection.cpp @@ -28,21 +28,24 @@ namespace fc { namespace json { fc::future _read_loop_complete; void read_loop() { - fc::string line; - fc::getline( in, line ); - while( !in.eof() ) { - try { - fc::value v= fc::json::from_string( line ); - //slog( "%s", fc::json::to_string(v).c_str() ); - self.handle_message(v); - } catch (...) { - wlog( "%s", fc::except_str().c_str() ); - return; - } - fc::getline( in, line ); - } - self.cancel_pending_requests(); - if( !!on_close ) on_close(); + try { + fc::string line; + fc::getline( in, line ); + while( !in.eof() ) { + try { + fc::value v= fc::json::from_string( line ); + self.handle_message(v); + } catch (...) { + wlog( "%s", fc::except_str().c_str() ); + return; + } + fc::getline( in, line ); + } + } catch ( ... ) { + wlog( "%s", fc::except_str().c_str() ); + } + self.cancel_pending_requests(); + if( !!on_close ) on_close(); } }; @@ -80,24 +83,28 @@ namespace fc { namespace json { ss<<"{\"id\":"<out.write( o.c_str(), o.size() ); + my->out.flush(); } void rpc_stream_connection::send_notice( const fc::string& m, value&& param ) { fc::stringstream ss; ss<<"{\"method\":\""<out.write( o.c_str(), o.size() ); + my->out.flush(); } void rpc_stream_connection::send_error( uint64_t id, const json::error_object& eo ) { fc::stringstream ss; ss<<"{\"id\":"<out.write( o.c_str(), o.size() ); + my->out.flush(); } void rpc_stream_connection::send_result( uint64_t id, value&& r ) { fc::stringstream ss; ss<<"{\"id\":"<out.write( o.c_str(), o.size() ); + my->out.flush(); } } } // fc::json diff --git a/src/process.cpp b/src/process.cpp index 3f4d42a..d87ee71 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -43,9 +43,13 @@ namespace fc { try { return static_cast(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast(n) ) )); } catch ( const boost::system::system_error& e ) { + wlog( "%s", fc::except_str().c_str() ); if( e.code() == boost::asio::error::eof ) return -1; throw; + } catch ( ... ) { + wlog( "%s", fc::except_str().c_str() ); + return -1; } } private: @@ -69,9 +73,13 @@ FC_START_SHARED_IMPL( fc::process ) if( inp ) { inp->close(); } - child->terminate(); + if( _exited.valid() && !_exited.ready()) { + slog( "terminate..."); + child->terminate(); + _exited.wait(); + } }catch(...) { - wlog( "caught exception cleaning up process" ); + wlog( "caught exception cleaning up process: %s", fc::except_str().c_str() ); } } @@ -88,6 +96,8 @@ FC_START_SHARED_IMPL( fc::process ) io::stream std_err; io::stream std_in; + fc::future _exited; + // adapt to ostream and istream interfaces fc::ostream_wrapper _ins; fc::istream_wrapper _outs; @@ -163,8 +173,7 @@ fc::future process::exec( const fc::path& exe, fc::vector&& arg } else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); }); - return p; - + return my->_exited = p; } /** From cf10bac3dbaefc4226402c733a14a760591b17cf Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 13 Dec 2012 13:08:25 -0500 Subject: [PATCH 08/14] add error_report::to_string and to_detail_string --- include/fc/error_report.hpp | 5 +++ include/fc/string.hpp | 2 +- src/error_report.cpp | 68 +++++++++++++++++++++++++++++++++++++ src/json.cpp | 7 ++-- src/string.cpp | 2 +- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/include/fc/error_report.hpp b/include/fc/error_report.hpp index 9d59e4e..cd91a61 100644 --- a/include/fc/error_report.hpp +++ b/include/fc/error_report.hpp @@ -19,6 +19,9 @@ namespace fc { error_frame& operator=(const error_frame& ); error_frame& operator=(error_frame&& ); + fc::string to_string()const; + fc::string to_detail_string()const; + fc::string desc; fc::string file; int64_t line; @@ -43,6 +46,8 @@ namespace fc { error_report& push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta = fc::value() ); error_report& append( const error_report& e ); + fc::string to_string()const; + fc::string to_detail_string()const; error_context stack; ///< Human readable stack of what we were atempting to do. }; diff --git a/include/fc/string.hpp b/include/fc/string.hpp index 04a613b..370bb40 100644 --- a/include/fc/string.hpp +++ b/include/fc/string.hpp @@ -82,7 +82,7 @@ namespace fc { friend string operator + ( const string&, const string& ); friend string operator + ( const string&, char c ); - fc::string substr( int32_t start, int32_t len = 0x7fffffff ); + fc::string substr( int32_t start, int32_t len = 0x7fffffff )const; private: fc::fwd my; diff --git a/src/error_report.cpp b/src/error_report.cpp index 44a78c7..7df1b09 100644 --- a/src/error_report.cpp +++ b/src/error_report.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include namespace fc { error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) @@ -70,4 +73,69 @@ fc::error_report& error_report::append( const error_report& e ) return *this; } +fc::string error_frame::to_detail_string()const { + fc::stringstream ss; + ss << to_string() << "\n\t"; + ss << file << ":" << line << "\t"<find( key.c_str() ); + if( itr != meta->end() ) { + ss << fc::json::to_string( itr->val ); + } else { + ss << "???"; + } + } + prev = next + 1; + // find the next $ + next = desc.find( '$', prev ); + } else { + // we didn't find it.. continue to while... + } + } else { + ss << desc[prev]; + ++prev; + next = desc.find( '$', prev ); + } + } + return ss.str(); +} +fc::string error_report::to_string()const { + fc::stringstream ss; + for( int i = 0; i < stack.size(); ++i ) { + ss << stack[i].to_string() << "\n"; + } + return ss.str(); +} +fc::string error_report::to_detail_string()const { + fc::stringstream ss; + for( int i = 0; i < stack.size(); ++i ) { + ss << stack[i].to_detail_string() << "\n"; + } + return ss.str(); +} + } // namespace fc diff --git a/src/json.cpp b/src/json.cpp index 895d743..9eeafeb 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -919,12 +919,11 @@ fc::string pretty_print( fc::vector&& v, uint8_t indent ) { value from_file( const fc::path& local_path ) { if( !exists(local_path) ) { - slog("..."); - FC_THROW_REPORT( "Source file '${filename}' does not exist", value().set("filename",local_path.string()) ); + FC_THROW_REPORT( "Source file ${filename} does not exist", value().set("filename",local_path.string()) ); } if( is_directory( local_path ) ) { - wlog("..."); - FC_THROW_MSG( "Source path '%s' is a directory, expected a file.", local_path.string() ); + FC_THROW_REPORT( "Source path ${path} is a directory; a file was expected", + value().set("path",local_path.string()) ); } // memory map the file diff --git a/src/string.cpp b/src/string.cpp index 5839e69..203e2c2 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -36,7 +36,7 @@ namespace fc { void string::clear() { my->clear(); } void string::resize( uint64_t s ) { my->resize(s); } - fc::string string::substr( int32_t start, int32_t len ) { return my->substr(start,len); } + fc::string string::substr( int32_t start, int32_t len )const { return my->substr(start,len); } const char* string::c_str()const { return my->c_str(); } bool string::operator == ( const char* s )const { return *my == s; } From e42af7c0665fed814828b0ae7edbfc4350d57e13 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 13 Dec 2012 13:57:49 -0500 Subject: [PATCH 09/14] fc::error_report to fc::exception_ptr to enable inter-thread, inter-process error reports --- include/fc/error_report.hpp | 5 ++++- include/fc/exception.hpp | 2 +- src/error_report.cpp | 4 ++++ src/json_rpc_connection.cpp | 10 ++++------ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/fc/error_report.hpp b/include/fc/error_report.hpp index cd91a61..7822018 100644 --- a/include/fc/error_report.hpp +++ b/include/fc/error_report.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace fc { @@ -49,15 +50,17 @@ namespace fc { fc::string to_string()const; fc::string to_detail_string()const; error_context stack; ///< Human readable stack of what we were atempting to do. + + fc::exception_ptr copy_exception(); }; + } // namespace fc #include FC_REFLECT( fc::error_frame, (desc)(file)(line)(method)(time)(meta) ) FC_REFLECT( fc::error_report, (stack) ) -#include #define FC_REPORT( X, ... ) fc::error_report X( __FILE__, __LINE__, __func__, __VA_ARGS__ ) #define FC_THROW_REPORT( ... ) FC_THROW( fc::error_report( __FILE__, __LINE__, __func__, __VA_ARGS__ )) #define FC_REPORT_CURRENT(ER, ... ) (ER).pop_frame().push_frame( __FILE__, __LINE__, __func__, __VA_ARGS__ ) diff --git a/include/fc/exception.hpp b/include/fc/exception.hpp index b7d9fd2..3b4fc55 100644 --- a/include/fc/exception.hpp +++ b/include/fc/exception.hpp @@ -48,7 +48,7 @@ namespace fc { try { throw e; } catch (...) { return current_exception(); } return exception_ptr(); } - void rethrow_exception( const exception_ptr& e ); + void rethrow_exception( const exception_ptr& e ); void throw_exception( const char* func, const char* file, int line, const char* msg ); void throw_exception_( const char* func, const char* file, int line, const char* msg, diff --git a/src/error_report.cpp b/src/error_report.cpp index 7df1b09..4a817e9 100644 --- a/src/error_report.cpp +++ b/src/error_report.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace fc { error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met ) @@ -137,5 +138,8 @@ fc::string error_report::to_detail_string()const { } return ss.str(); } +fc::exception_ptr error_report::copy_exception() { + return boost::copy_exception(*this); +} } // namespace fc diff --git a/src/json_rpc_connection.cpp b/src/json_rpc_connection.cpp index 6f00d0b..f790e8f 100644 --- a/src/json_rpc_connection.cpp +++ b/src/json_rpc_connection.cpp @@ -106,13 +106,11 @@ namespace fc { namespace json { } else { auto e_itr = v.find( "error" ); if( e_itr != end ) { - cur->set_exception( - fc::copy_exception( - fc::generic_exception( - value_cast( - e_itr->val["message"] ) ) ) ); + cur->set_exception( fc::value_cast(e_itr->val["data"]).copy_exception() ); + } else { + elog( "no result nor error field" ); } - } + } } catch( ... ) { cur->set_exception( fc::current_exception() ); } From 47b19bc0e698376e61f18deee2146af15c60e1d6 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 13 Dec 2012 20:23:49 -0500 Subject: [PATCH 10/14] adding missing file --- src/http_server.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/http_server.cpp diff --git a/src/http_server.cpp b/src/http_server.cpp new file mode 100644 index 0000000..90be148 --- /dev/null +++ b/src/http_server.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + + +namespace fc { namespace http { + + class server::response::impl : public fc::retainable { + public: + impl( const fc::http::connection& c, const std::function& cont = std::function() ) + :con(c),handle_next_req(cont) + {} + + http::connection con; + std::function handle_next_req; + }; + + + class server::impl : public fc::retainable { + public: + impl(){} + impl(uint16_t p ) { + tcp_serv.listen(p); + accept_complete = fc::async([this](){ this->accept_loop(); }); + } + fc::future accept_complete; + ~impl() { + try { + tcp_serv.close(); + accept_complete.wait(); + }catch(...){} + } + void accept_loop() { + try { + http::connection con; + while( tcp_serv.accept( con.get_socket() ) ) { + fc::async( [=](){ handle_connection( con, on_req ); } ); + con = http::connection(); + } + } catch ( ... ) { + wlog( "tcp listen failed...%s", fc::except_str().c_str() ); + } + } + + void handle_connection( const http::connection& c, + std::function do_on_req ) { + http::server::response rep( fc::shared_ptr( new response::impl(c, [=](){ this->handle_connection(c,do_on_req); } ) ) ); + auto req = c.read_request(); + if( do_on_req ) do_on_req( req, rep ); + } + std::function on_req; + fc::tcp_server tcp_serv; + }; + + + + server::server(){} + server::server( uint16_t port ) :my( new impl(port) ){} + server::server( const server& s ):my(s.my){} + server::server( server&& s ):my(fc::move(s.my)){} + + server& server::operator=(const server& s) { my = s.my; return *this; } + server& server::operator=(server&& s) { fc_swap(my,s.my); return *this; } + + server::~server(){} + + void server::listen( uint16_t p ) { + my.reset( new impl(p) ); + } + + + + server::response::response(){} + server::response::response( const server::response& s ):my(s.my){} + server::response::response( server::response&& s ):my(fc::move(s.my)){} + server::response::response( const fc::shared_ptr& m ):my(m){} + + server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; } + server::response& server::response::operator=(server::response&& s) { fc_swap(my,s.my); return *this; } + + server::response::~response(){} + + + + +} } From 8c39a39dd629cfa50c4d92e0af7a4acb1cbf17f4 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Thu, 13 Dec 2012 21:05:44 -0500 Subject: [PATCH 11/14] implemented http server --- CMakeLists.txt | 2 +- include/fc/http/connection.hpp | 3 ++ src/http_connection.cpp | 33 +++++++++++++++++++-- src/http_server.cpp | 54 +++++++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e691bf..7da9be8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ set( sources src/ssh.cpp src/process.cpp src/http_connection.cpp -# src/http_server.cpp + src/http_server.cpp src/json_rpc_connection.cpp src/json_rpc_stream_connection.cpp src/json_rpc_tcp_connection.cpp diff --git a/include/fc/http/connection.hpp b/include/fc/http/connection.hpp index 557f57a..41e94e5 100644 --- a/include/fc/http/connection.hpp +++ b/include/fc/http/connection.hpp @@ -10,6 +10,9 @@ namespace fc { namespace http { struct header { + header( fc::string k, fc::string v ) + :key(fc::move(k)),val(fc::move(v)){} + header(){} fc::string key; fc::string val; }; diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 648305c..38b745e 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -121,8 +121,37 @@ fc::tcp_socket& connection::get_socket()const { } http::request connection::read_request()const { - http::request r; - return r; + http::request req; + fc::vector line(1024*8); + int s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // METHOD + req.method = line.data(); + s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // PATH + req.path = line.data(); + s = my->read_until( line.data(), line.data()+line.size(), '\n' ); // HTTP/1.0 + + while( (s = my->read_until( line.data(), line.data()+line.size(), '\n' )) > 1 ) { + fc::http::header h; + char* end = line.data(); + while( *end != ':' )++end; + h.key = fc::string(line.data(),end); + ++end; // skip ':' + ++end; // skip space + char* skey = end; + while( *end != '\r' ) ++end; + h.val = fc::string(skey,end); + req.headers.push_back(h); + if( h.key == "Content-Length" ) { + req.body.resize( fc::lexical_cast( fc::string(h.val) ) ); + } + if( h.key == "Host" ) { + req.domain = h.val; + } + } + if( req.body.size() ) { + slog( "Reading body size %d", req.body.size() ); + my->sock.read( req.body.data(), req.body.size() ); + } + return req; } } } // fc::http diff --git a/src/http_server.cpp b/src/http_server.cpp index 90be148..09db676 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace fc { namespace http { @@ -8,9 +9,30 @@ namespace fc { namespace http { class server::response::impl : public fc::retainable { public: impl( const fc::http::connection& c, const std::function& cont = std::function() ) - :con(c),handle_next_req(cont) + :body_bytes_sent(0),body_length(0),con(c),handle_next_req(cont) {} + void send_header() { + fc::stringstream ss; + ss << "HTTP/1.1 " << rep.status << " "; + switch( rep.status ) { + case fc::http::reply::OK: ss << "OK\n\r"; break; + case fc::http::reply::RecordCreated: ss << "Record Created\n\r"; break; + case fc::http::reply::NotFound: ss << "Not Found\n\r"; break; + case fc::http::reply::Found: ss << "Found\n\r"; break; + case fc::http::reply::InternalServerError: ss << "Internal Server Error\r\n"; break; + } + for( uint32_t i = 0; i < rep.headers.size(); ++i ) { + ss << rep.headers[i].key <<": "< handle_next_req; }; @@ -78,7 +100,37 @@ namespace fc { namespace http { server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; } server::response& server::response::operator=(server::response&& s) { fc_swap(my,s.my); return *this; } + void server::response::add_header( const fc::string& key, const fc::string& val )const { + wlog( "Attempt to add header after sending headers" ); + my->rep.headers.push_back( fc::http::header( key, val ) ); + } + void server::response::set_status( const http::reply::status_code& s )const { + if( my->body_bytes_sent != 0 ) { + wlog( "Attempt to set status after sending headers" ); + } + my->rep.status = s; + } + void server::response::set_length( uint64_t s )const { + if( my->body_bytes_sent != 0 ) { + wlog( "Attempt to set length after sending headers" ); + } + my->body_length = s; + } + void server::response::write( const char* data, uint64_t len )const { + if( my->body_bytes_sent + len > my->body_length ) { + wlog( "Attempt to send to many bytes.." ); + len = my->body_bytes_sent + len - my->body_length; + } + if( my->body_bytes_sent == 0 ) { + my->send_header(); + } + my->body_bytes_sent += len; + my->con.get_socket().write( data, len ); + } + server::response::~response(){} + void server::on_request( const std::function& cb ) + { my->on_req = cb; } From 47da9e06f918026ebf5563e57173969dc3a552b1 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Fri, 14 Dec 2012 20:05:09 -0500 Subject: [PATCH 12/14] adding missing file --- include/fc/http/server.hpp | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 include/fc/http/server.hpp diff --git a/include/fc/http/server.hpp b/include/fc/http/server.hpp new file mode 100644 index 0000000..e8764f1 --- /dev/null +++ b/include/fc/http/server.hpp @@ -0,0 +1,60 @@ +#pragma once +#include +#include +#include + +namespace fc { namespace http { + + /** + * Listens on a given port for incomming http + * connections and then calls a user provided callback + * function for every http request. + * + */ + class server { + public: + server(); + server( uint16_t port ); + server( const server& s ); + server( server&& s ); + ~server(); + + server& operator=(const server& s); + server& operator=(server&& s); + + class response { + public: + class impl; + + response(); + response( const fc::shared_ptr& my); + response( const response& r); + response( response&& r ); + ~response(); + response& operator=(const response& ); + response& operator=( response&& ); + + void add_header( const fc::string& key, const fc::string& val )const; + void set_status( const http::reply::status_code& s )const; + void set_length( uint64_t s )const; + + void write( const char* data, uint64_t len )const; + + private: + fc::shared_ptr my; + }; + + void listen( uint16_t p ); + + /** + * Set the callback to be called for every http request made. + */ + void on_request( const std::function& cb ); + + private: + class impl; + fc::shared_ptr my; + + }; + +} } From 4be0f82dc9ba04863cc9aa11ce91e11842cb3b13 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Sat, 15 Dec 2012 09:41:55 -0500 Subject: [PATCH 13/14] adding url --- include/fc/url.hpp | 40 ++++++++++++++++++ src/url.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 include/fc/url.hpp create mode 100644 src/url.cpp diff --git a/include/fc/url.hpp b/include/fc/url.hpp new file mode 100644 index 0000000..a1bfc91 --- /dev/null +++ b/include/fc/url.hpp @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include + +namespace fc { + + typedef fc::optional ostring; + + struct url { + url(){} + url( const string& url ); + /* + url( const url& u ); + + url( url&& u ); + url& operator=(url&& c); + url& operator=(const url& c); + */ + + operator string()const { return to_string(); } + string to_string()const; + url& from_string( const string& s ); + + bool operator==( const url& cmp )const; + + string proto; // file, ssh, tcp, http, ssl, etc... + ostring host; + ostring user; + ostring pass; + ostring path; + ostring args; + fc::optional port; + }; + +} // namespace fc + +#include +FC_REFLECT( fc::url, (proto)(host)(user)(pass)(path)(args)(port) ) + diff --git a/src/url.cpp b/src/url.cpp new file mode 100644 index 0000000..32208f1 --- /dev/null +++ b/src/url.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include + +namespace fc { + +// url::url( const url& u ); +#if 0 + url::url( url&& u ) + :proto(fc::move(u.proto)), + host(fc::move(u.host)), + user(fc::move(u.user)), + pass(fc::move(u.pass)), + path(fc::move(u.path)), + args(fc::move(u.args)), + port(u.port){} + + url& url::operator=(url&& c) + { + fc::swap(*this,c); + return *this; + } + + // url::url& operator=(const url& c) { + // } +#endif + url::url( const string& s ) { + from_string(s); + } + string url::to_string()const { + fc::stringstream ss; + ss<( host_port.substr( pos+1 ) ); + } catch ( ... ) { + FC_THROW_REPORT( "Unable to parse port field in url", value().set( "url", s ) ); + } + host = host_port.substr(0,pos); + } else { + host = fc::move(host_port); + } + fc::getline( ss, _path, '?' ); + fc::getline( ss, _args ); + path = fc::move(_path); + if( _args.size() ) args = fc::move(_args); + + return *this; + } + + bool url::operator==( const url& cmp )const { + return cmp.proto == proto && + cmp.host == host && + cmp.user == user && + cmp.pass == pass && + cmp.path == path && + cmp.args == args && + cmp.port == port; + } + +} // namespace fc From 9a8767a645199de470620e6f2de26d55c2b810ee Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Sat, 15 Dec 2012 10:26:03 -0500 Subject: [PATCH 14/14] Fixed error_report to_string Updated fc::datastream and base64 to use error_report Added url to cmake lists various other bug fixes --- CMakeLists.txt | 1 + include/fc/base58.hpp | 4 ++-- include/fc/datastream.hpp | 15 +++++++++------ include/fc/task.hpp | 14 ++++++++------ include/fc/thread.hpp | 5 +++-- src/base58.cpp | 3 ++- src/error_report.cpp | 4 +++- src/http_server.cpp | 19 ++++++++++++++++--- 8 files changed, 44 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7da9be8..12106a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ include_directories( include ) set( sources src/ssh.cpp + src/url.cpp src/process.cpp src/http_connection.cpp src/http_server.cpp diff --git a/include/fc/base58.hpp b/include/fc/base58.hpp index 4198bfb..3c5a714 100644 --- a/include/fc/base58.hpp +++ b/include/fc/base58.hpp @@ -3,7 +3,7 @@ #include namespace fc { -fc::string to_base58( const char* d, uint32_t s ); -size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len ); + fc::string to_base58( const char* d, uint32_t s ); + size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len ); } #endif // _FC_BASE58_HPP_ diff --git a/include/fc/datastream.hpp b/include/fc/datastream.hpp index c333935..f56945b 100644 --- a/include/fc/datastream.hpp +++ b/include/fc/datastream.hpp @@ -1,7 +1,7 @@ #ifndef _FC_DATASTREAM_HPP_ #define _FC_DATASTREAM_HPP_ #include -#include +#include #include #include @@ -40,8 +40,8 @@ struct datastream { m_pos += s; return true; } - FC_THROW_MSG( "Attempt to read %s bytes beyond end of buffer of size %s", - int64_t(-((m_end-m_pos) - s)), int64_t(m_end-m_start) ); + FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", + fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - s))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } @@ -51,7 +51,8 @@ struct datastream { m_pos += s; return true; } - FC_THROW_MSG( "Attempt to write %s bytes beyond end of buffer of size %s", int64_t(-((m_end-m_pos) - s)),int64_t(m_end-m_start) ); + FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", + fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - s))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } @@ -61,7 +62,8 @@ struct datastream { ++m_pos; return true; } - FC_THROW_MSG( "Attempt to write %s byte beyond end of buffer of size %s", int64_t(-((m_end-m_pos) - 1)), int64_t(m_end-m_start) ); + FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", + fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - 1))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } @@ -72,7 +74,8 @@ struct datastream { ++m_pos; return true; } - FC_THROW_MSG( "Attempt to read %s byte beyond end of buffer of size %s", int64_t(-((m_end-m_pos) - 1)), int64_t(m_end-m_start) ); + FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer of size ${buffer_size} ", + fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - 1))).set("buffer_size", int64_t(m_end-m_start)) ); ++m_pos; return false; } diff --git a/include/fc/task.hpp b/include/fc/task.hpp index 6c3cdcb..9c36e6d 100644 --- a/include/fc/task.hpp +++ b/include/fc/task.hpp @@ -61,12 +61,13 @@ namespace fc { public: template task( Functor&& f ):task_base(&_functor) { + typedef typename fc::deduce::type FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) Functor( fc::forward(f) ); - _destroy_functor = &detail::functor_destructor::destroy; + new ((char*)&_functor) FunctorType( fc::forward(f) ); + _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); - _run_functor = &detail::functor_run::run; + _run_functor = &detail::functor_run::run; } aligned _functor; private: @@ -77,12 +78,13 @@ namespace fc { public: template task( Functor&& f ):task_base(&_functor) { + typedef typename fc::deduce::type FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) Functor( fc::forward(f) ); - _destroy_functor = &detail::functor_destructor::destroy; + new ((char*)&_functor) FunctorType( fc::forward(f) ); + _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); - _run_functor = &detail::void_functor_run::run; + _run_functor = &detail::void_functor_run::run; } aligned _functor; private: diff --git a/include/fc/thread.hpp b/include/fc/thread.hpp index 334b56f..3d8c960 100644 --- a/include/fc/thread.hpp +++ b/include/fc/thread.hpp @@ -52,8 +52,9 @@ namespace fc { template auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future { typedef decltype(f()) Result; - fc::task* tsk = - new fc::task( fc::forward(f) ); + typedef typename fc::deduce::type FunctorType; + fc::task* tsk = + new fc::task( fc::forward(f) ); fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); async_task(tsk,prio,desc); return r; diff --git a/src/base58.cpp b/src/base58.cpp index 1fc5dc9..9145db6 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -616,7 +617,7 @@ size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_dat //slog( "%s", base58_str.c_str() ); std::vector out; if( !DecodeBase58( base58_str.c_str(), out ) ) { - FC_THROW_MSG( "Unable to decode base58 string '%s'", base58_str ); + FC_THROW_REPORT( "Unable to decode base58 string ${base58_str}", fc::value().set("base58_str",base58_str) ); } memcpy( out_data, out.data(), out.size() ); diff --git a/src/error_report.cpp b/src/error_report.cpp index 4a817e9..c14e393 100644 --- a/src/error_report.cpp +++ b/src/error_report.cpp @@ -86,8 +86,9 @@ fc::string error_frame::to_string()const { int64_t prev = 0; auto next = desc.find( '$' ); while( prev != int64_t(fc::string::npos) && prev < int64_t(desc.size()) ) { + // slog( "prev: %d next %d %s", prev, next, desc.substr(prev,next).c_str() ); // print everything from the last pos until the first '$' - ss << desc.substr( prev, next ); + ss << desc.substr( prev, next-prev ); // if we got to the end, return it. if( next == string::npos ) { return ss.str(); } @@ -102,6 +103,7 @@ fc::string error_frame::to_string()const { if( next != fc::string::npos ) { // the key is between prev and next fc::string key = desc.substr( prev+1, (next-prev-1) ); + //slog( "key '%s'", key.c_str() ); if( meta ) { auto itr = meta->find( key.c_str() ); if( itr != meta->end() ) { diff --git a/src/http_server.cpp b/src/http_server.cpp index 09db676..6349f06 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -56,6 +56,7 @@ namespace fc { namespace http { try { http::connection con; while( tcp_serv.accept( con.get_socket() ) ) { + slog( "Accept Connection" ); fc::async( [=](){ handle_connection( con, on_req ); } ); con = http::connection(); } @@ -66,9 +67,14 @@ namespace fc { namespace http { void handle_connection( const http::connection& c, std::function do_on_req ) { - http::server::response rep( fc::shared_ptr( new response::impl(c, [=](){ this->handle_connection(c,do_on_req); } ) ) ); - auto req = c.read_request(); - if( do_on_req ) do_on_req( req, rep ); + wlog( "reading request.." ); + try { + http::server::response rep( fc::shared_ptr( new response::impl(c, [=](){ this->handle_connection(c,do_on_req); } ) ) ); + auto req = c.read_request(); + if( do_on_req ) do_on_req( req, rep ); + } catch ( ... ) { + wlog( "unable to read request %s", fc::except_str().c_str()); + } } std::function on_req; fc::tcp_server tcp_serv; @@ -126,6 +132,13 @@ namespace fc { namespace http { } my->body_bytes_sent += len; my->con.get_socket().write( data, len ); + if( my->body_bytes_sent == int64_t(my->body_length) ) { + if( my->handle_next_req ) { + slog( "handle next request..." ); + //fc::async( std::function(my->handle_next_req) ); + fc::async( my->handle_next_req ); + } + } } server::response::~response(){}