Merge branch 'master' of github.com:bytemaster/fc

This commit is contained in:
Daniel Larimer 2012-12-15 12:45:56 -08:00
commit 7114399f47
107 changed files with 775 additions and 29257 deletions

View file

@ -50,13 +50,16 @@ include_directories( include )
set( sources set( sources
src/ssh.cpp src/ssh.cpp
src/url.cpp
src/process.cpp src/process.cpp
src/http_connection.cpp src/http_connection.cpp
src/http_server.cpp
src/json_rpc_connection.cpp src/json_rpc_connection.cpp
src/json_rpc_stream_connection.cpp src/json_rpc_stream_connection.cpp
src/json_rpc_tcp_connection.cpp src/json_rpc_tcp_connection.cpp
src/json_rpc_tcp_server.cpp src/json_rpc_tcp_server.cpp
src/json_rpc_error_object.cpp src/json_rpc_error_object.cpp
src/error_report.cpp
src/value.cpp src/value.cpp
src/lexical_cast.cpp src/lexical_cast.cpp
src/spin_lock.cpp src/spin_lock.cpp

View file

@ -3,7 +3,7 @@
#include <fc/string.hpp> #include <fc/string.hpp>
namespace fc { namespace fc {
fc::string to_base58( const char* d, uint32_t s ); 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 ); size_t from_base58( const fc::string& base58_str, char* out_data, size_t out_data_len );
} }
#endif // _FC_BASE58_HPP_ #endif // _FC_BASE58_HPP_

View file

@ -1,7 +1,7 @@
#ifndef _FC_DATASTREAM_HPP_ #ifndef _FC_DATASTREAM_HPP_
#define _FC_DATASTREAM_HPP_ #define _FC_DATASTREAM_HPP_
#include <fc/utility.hpp> #include <fc/utility.hpp>
#include <fc/exception.hpp> #include <fc/error_report.hpp>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
@ -40,8 +40,8 @@ struct datastream {
m_pos += s; m_pos += s;
return true; return true;
} }
FC_THROW_MSG( "Attempt to read %s bytes beyond end of buffer of size %s", FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ",
int64_t(-((m_end-m_pos) - s)), int64_t(m_end-m_start) ); fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - s))).set("buffer_size", int64_t(m_end-m_start)) );
return false; return false;
} }
@ -51,7 +51,8 @@ struct datastream {
m_pos += s; m_pos += s;
return true; 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; return false;
} }
@ -61,7 +62,8 @@ struct datastream {
++m_pos; ++m_pos;
return true; 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; return false;
} }
@ -72,7 +74,8 @@ struct datastream {
++m_pos; ++m_pos;
return true; 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; ++m_pos;
return false; return false;
} }

View file

@ -0,0 +1,68 @@
#pragma once
#include <fc/vector.hpp>
#include <fc/string.hpp>
#include <fc/value.hpp>
#include <fc/optional.hpp>
#include <fc/exception.hpp>
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 to_string()const;
fc::string to_detail_string()const;
fc::string desc;
fc::string file;
int64_t line;
fc::string method;
uint64_t time;
fc::optional<fc::value> meta;
};
typedef fc::vector<error_frame> 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 );
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.hpp>
FC_REFLECT( fc::error_frame, (desc)(file)(line)(method)(time)(meta) )
FC_REFLECT( fc::error_report, (stack) )
#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()

View file

@ -48,7 +48,7 @@ namespace fc {
try { throw e; } catch (...) { return current_exception(); } try { throw e; } catch (...) { return current_exception(); }
return exception_ptr(); 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 );
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,

View file

@ -62,6 +62,7 @@ namespace fc {
bool is_directory( const path& p ); bool is_directory( const path& p );
bool is_regular_file( const path& p ); bool is_regular_file( const path& p );
void create_directories( const path& p ); void create_directories( const path& p );
path absolute( const path& p );
path canonical( const path& p ); path canonical( const path& p );
uint64_t file_size( const path& p ); uint64_t file_size( const path& p );
bool remove( const path& p ); bool remove( const path& p );

View file

@ -10,6 +10,9 @@ namespace fc {
namespace http { namespace http {
struct header { struct header {
header( fc::string k, fc::string v )
:key(fc::move(k)),val(fc::move(v)){}
header(){}
fc::string key; fc::string key;
fc::string val; fc::string val;
}; };
@ -47,10 +50,9 @@ namespace fc {
http::reply request( const fc::string& method, const fc::string& url, const fc::string& body ); http::reply request( const fc::string& method, const fc::string& url, const fc::string& body );
// used for servers // used for servers
fc::tcp_socket& get_socket(); fc::tcp_socket& get_socket()const;
http::request read_request(); http::request read_request()const;
void send_reply( const http::reply& );
FC_REFERENCE_TYPE(connection) FC_REFERENCE_TYPE(connection)
}; };

View file

@ -0,0 +1,60 @@
#pragma once
#include <fc/http/connection.hpp>
#include <fc/shared_ptr.hpp>
#include <functional>
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<impl>& 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<impl> my;
};
void listen( uint16_t p );
/**
* Set the callback to be called for every http request made.
*/
void on_request( const std::function<void(const http::request&, const server::response& s )>& cb );
private:
class impl;
fc::shared_ptr<impl> my;
};
} }

View file

@ -64,14 +64,18 @@ namespace fc {
virtual ~istream_wrapper(){}; 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 ) { virtual istream& read( char* buf, size_t len ) {
// slog( "%p %lld", my.get(), len );
my->read(buf,len); my->read(buf,len);
return *this; return *this;
} }
virtual void close() { } virtual void close() { }
virtual bool eof()const{ return my->eof(); } virtual bool eof()const{ return my->eof(); }
/*
virtual istream& read( int64_t& ) { return *this; } virtual istream& read( int64_t& ) { return *this; }
virtual istream& read( uint64_t& ) { return *this; } virtual istream& read( uint64_t& ) { return *this; }
virtual istream& read( int32_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( bool& ) { return *this; }
virtual istream& read( char& ) { return *this; } virtual istream& read( char& ) { return *this; }
virtual istream& read( fc::string& ) { return *this; } virtual istream& read( fc::string& ) { return *this; }
*/
protected: protected:
struct impl_base : public fc::retainable { struct impl_base : public fc::retainable {

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <fc/json_rpc_error_object.hpp>
#include <fc/json.hpp> #include <fc/json.hpp>
#include <fc/future.hpp> #include <fc/future.hpp>
#include <fc/function.hpp> #include <fc/function.hpp>
@ -6,6 +7,7 @@
namespace fc { namespace json { namespace fc { namespace json {
class rpc_connection; class rpc_connection;
class error_object;
struct rpc_server_method : public fc::retainable { struct rpc_server_method : public fc::retainable {
typedef fc::shared_ptr<rpc_server_method> ptr; typedef fc::shared_ptr<rpc_server_method> ptr;
@ -141,7 +143,7 @@ namespace fc { namespace json {
void handle_message( const value& m ); void handle_message( const value& m );
virtual void send_notice( const fc::string& m, value&& param ) = 0; 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_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; virtual void send_result( uint64_t id, value&& r ) = 0;

View file

@ -2,18 +2,26 @@
#include <fc/string.hpp> #include <fc/string.hpp>
#include <fc/optional.hpp> #include <fc/optional.hpp>
#include <fc/value.hpp> #include <fc/value.hpp>
#include <fc/reflect.hpp>
namespace fc { namespace json {
struct error_object { namespace fc {
error_object( const fc::string& msg = fc::string(), fc::value v = fc::value(), int64_t c = -32000); class value;
int64_t code; namespace json {
fc::string message;
fc::optional<fc::value> data; 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<fc::value> data;
}; };
} } } }
#include <fc/reflect.hpp>
FC_REFLECT( fc::json::error_object, (code)(message)(data) ) FC_REFLECT( fc::json::error_object, (code)(message)(data) )

View file

@ -42,6 +42,11 @@ namespace fc { namespace json {
void on_close( T&& f) { _con->on_close( fc::forward<T>(f) ); } void on_close( T&& f) { _con->on_close( fc::forward<T>(f) ); }
const fc::json::rpc_stream_connection::ptr& connection()const { return _con; } const fc::json::rpc_stream_connection::ptr& connection()const { return _con; }
~rpc_process_client() {
if(_con)
_con->close();
}
private: private:
fc::process _proc; fc::process _proc;
fc::json::rpc_stream_connection::ptr _con; fc::json::rpc_stream_connection::ptr _con;

View file

@ -30,7 +30,7 @@ namespace fc {
~rpc_stream_connection(); ~rpc_stream_connection();
virtual void send_invoke( uint64_t id, const fc::string& m, value&& param ); 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_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 ); virtual void send_result( uint64_t id, value&& r );
private: private:

View file

@ -17,6 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include <fc/exception.hpp> #include <fc/exception.hpp>
#include <fc/typename.hpp>
namespace fc { namespace fc {
@ -79,8 +80,7 @@ struct reflector{
#endif #endif
//#include <boost/typeof/typeof.hpp> //#include <boost/typeof/typeof.hpp>
#define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \ #define FC_REFLECT_VISIT_MEMBER( r, visitor, elem ) \
visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
// visitor.TEMPLATE operator()<decltype(((type*)0)->elem), type, &type::elem>( BOOST_PP_STRINGIZE(elem) );
#define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \ #define FC_REFLECT_BASE_MEMBER_COUNT( r, OP, elem ) \
@ -147,6 +147,7 @@ template<> struct reflector<ENUM> { \
*/ */
#define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \ #define FC_REFLECT_DERIVED( TYPE, INHERITS, MEMBERS ) \
namespace fc { \ namespace fc { \
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
template<> struct reflector<TYPE> {\ template<> struct reflector<TYPE> {\
typedef TYPE type; \ typedef TYPE type; \
typedef fc::true_type is_defined; \ typedef fc::true_type is_defined; \
@ -172,6 +173,7 @@ template<> struct reflector<TYPE> {\
#define FC_REFLECT_FWD( TYPE ) \ #define FC_REFLECT_FWD( TYPE ) \
namespace fc { \ namespace fc { \
template<> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
template<> struct reflector<TYPE> {\ template<> struct reflector<TYPE> {\
typedef TYPE type; \ typedef TYPE type; \
typedef fc::true_type is_defined; \ typedef fc::true_type is_defined; \

View file

@ -14,6 +14,8 @@ shared_impl<T>::shared_impl( U&& u ):_impl(fc::forward<U>(u)){}
template<typename T> template<typename T>
shared_impl<T>::shared_impl( const shared_impl<T>& u ):_impl(u._impl){} shared_impl<T>::shared_impl( const shared_impl<T>& u ):_impl(u._impl){}
template<typename T>
shared_impl<T>::shared_impl( shared_impl<T>& u ):_impl(u._impl){}
template<typename T> template<typename T>
shared_impl<T>::shared_impl( shared_impl<T>&& u ):_impl(fc::move(u._impl)){} shared_impl<T>::shared_impl( shared_impl<T>&& u ):_impl(fc::move(u._impl)){}
@ -55,6 +57,8 @@ TYPE::TYPE( TYPE&& c )\
:my(fc::move(c.my)){}\ :my(fc::move(c.my)){}\
TYPE::TYPE( const TYPE& c )\ TYPE::TYPE( const TYPE& c )\
:my(c.my){}\ :my(c.my){}\
TYPE::TYPE( TYPE& c )\
:my(c.my){}\
TYPE::TYPE() \ TYPE::TYPE() \
:my( new fc::shared_impl<TYPE>::impl( ) ){}\ :my( new fc::shared_impl<TYPE>::impl( ) ){}\
TYPE::~TYPE(){}\ TYPE::~TYPE(){}\

View file

@ -113,6 +113,7 @@ namespace fc {
shared_impl( U&& u ); shared_impl( U&& u );
shared_impl( const shared_impl& u ); shared_impl( const shared_impl& u );
shared_impl( shared_impl& u );
shared_impl( shared_impl&& u ); shared_impl( shared_impl&& u );
shared_impl& operator=( shared_impl&& u ); shared_impl& operator=( shared_impl&& u );
shared_impl& operator=( const shared_impl& u ); shared_impl& operator=( const shared_impl& u );
@ -131,6 +132,7 @@ namespace fc {
TYPE( TYPE* ); \ TYPE( TYPE* ); \
TYPE( TYPE&& ); \ TYPE( TYPE&& ); \
TYPE( const TYPE& ); \ TYPE( const TYPE& ); \
TYPE( TYPE& ); \
template<typename A1> \ template<typename A1> \
TYPE( A1&& ); \ TYPE( A1&& ); \
template<typename A1,typename A2> \ template<typename A1,typename A2> \

View file

@ -40,6 +40,10 @@ namespace fc {
_ptr = p._ptr; _ptr = p._ptr;
if( _ptr ) _ptr->retain(); if( _ptr ) _ptr->retain();
} }
shared_ptr( shared_ptr& p ) {
_ptr = p._ptr;
if( _ptr ) _ptr->retain();
}
shared_ptr( shared_ptr&& p ) { shared_ptr( shared_ptr&& p ) {
_ptr = p._ptr; _ptr = p._ptr;
p._ptr = nullptr; p._ptr = nullptr;

View file

@ -82,7 +82,7 @@ namespace fc {
friend string operator + ( const string&, const string& ); friend string operator + ( const string&, const string& );
friend string operator + ( const string&, char c ); 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: private:
fc::fwd<std::string,32> my; fc::fwd<std::string,32> my;

View file

@ -61,12 +61,13 @@ namespace fc {
public: public:
template<typename Functor> template<typename Functor>
task( Functor&& f ):task_base(&_functor) { task( Functor&& f ):task_base(&_functor) {
typedef typename fc::deduce<Functor>::type FunctorType;
static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
new ((char*)&_functor) Functor( fc::forward<Functor>(f) ); new ((char*)&_functor) FunctorType( fc::forward<Functor>(f) );
_destroy_functor = &detail::functor_destructor<Functor>::destroy; _destroy_functor = &detail::functor_destructor<FunctorType>::destroy;
_promise_impl = static_cast<promise<R>*>(this); _promise_impl = static_cast<promise<R>*>(this);
_run_functor = &detail::functor_run<Functor>::run; _run_functor = &detail::functor_run<FunctorType>::run;
} }
aligned<FunctorSize> _functor; aligned<FunctorSize> _functor;
private: private:
@ -77,12 +78,13 @@ namespace fc {
public: public:
template<typename Functor> template<typename Functor>
task( Functor&& f ):task_base(&_functor) { task( Functor&& f ):task_base(&_functor) {
typedef typename fc::deduce<Functor>::type FunctorType;
static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
new ((char*)&_functor) Functor( fc::forward<Functor>(f) ); new ((char*)&_functor) FunctorType( fc::forward<Functor>(f) );
_destroy_functor = &detail::functor_destructor<Functor>::destroy; _destroy_functor = &detail::functor_destructor<FunctorType>::destroy;
_promise_impl = static_cast<promise<void>*>(this); _promise_impl = static_cast<promise<void>*>(this);
_run_functor = &detail::void_functor_run<Functor>::run; _run_functor = &detail::void_functor_run<FunctorType>::run;
} }
aligned<FunctorSize> _functor; aligned<FunctorSize> _functor;
private: private:

View file

@ -52,8 +52,9 @@ namespace fc {
template<typename Functor> template<typename Functor>
auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> { auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> {
typedef decltype(f()) Result; typedef decltype(f()) Result;
fc::task<Result,sizeof(Functor)>* tsk = typedef typename fc::deduce<Functor>::type FunctorType;
new fc::task<Result,sizeof(Functor)>( fc::forward<Functor>(f) ); fc::task<Result,sizeof(FunctorType)>* tsk =
new fc::task<Result,sizeof(FunctorType)>( fc::forward<Functor>(f) );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) ); fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
async_task(tsk,prio,desc); async_task(tsk,prio,desc);
return r; return r;

40
include/fc/url.hpp Normal file
View file

@ -0,0 +1,40 @@
#pragma once
#include <fc/string.hpp>
#include <fc/optional.hpp>
#include <stdint.h>
namespace fc {
typedef fc::optional<fc::string> 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<uint16_t> port;
};
} // namespace fc
#include <fc/reflect.hpp>
FC_REFLECT( fc::url, (proto)(host)(user)(pass)(path)(args)(port) )

View file

@ -85,6 +85,7 @@ namespace fc {
value& operator=( value&& v ); value& operator=( value&& v );
value& operator=( const value& v ); value& operator=( const value& v );
value& operator=( value& v );
/** /**

View file

@ -7,8 +7,9 @@
#include <fc/value_io.hpp> #include <fc/value_io.hpp>
#include <fc/tuple.hpp> #include <fc/tuple.hpp>
#include <fc/vector.hpp> #include <fc/vector.hpp>
#include <fc/typename.hpp>
#include <typeinfo> //#include <typeinfo>
namespace fc { namespace fc {

View file

@ -177,11 +177,12 @@ namespace fc {
template<typename T> template<typename T>
static inline void pack(fc::value& s, const T& v ) { static inline void pack(fc::value& s, const T& v ) {
v.did_not_implement_reflect_macro(); v.did_not_implement_reflect_macro();
wlog( "warning, ignoring unknown type" );
} }
template<typename T> template<typename T>
static inline void unpack( const fc::value& s, T& v ) { static inline void unpack( const fc::value& s, T& v ) {
v.did_not_implement_reflect_macro(); v.did_not_implement_reflect_macro();
//wlog( "warning, ignoring unknown type" ); wlog( "warning, ignoring unknown type" );
} }
}; };

View file

@ -24,6 +24,7 @@
#include <fc/log.hpp> #include <fc/log.hpp>
#include <fc/string.hpp> #include <fc/string.hpp>
#include <fc/exception.hpp> #include <fc/exception.hpp>
#include <fc/error_report.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
@ -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() ); //slog( "%s", base58_str.c_str() );
std::vector<unsigned char> out; std::vector<unsigned char> out;
if( !DecodeBase58( base58_str.c_str(), 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() ); memcpy( out_data, out.data(), out.size() );

View file

@ -34,7 +34,6 @@ namespace fc {
cur_task(0) cur_task(0)
{ {
my_context.fc_stack.base = alloc.allocate( bc::default_stacksize() ); 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 = my_context.fc_stack.limit =
static_cast<char*>( my_context.fc_stack.base) - bc::default_stacksize(); static_cast<char*>( my_context.fc_stack.base) - bc::default_stacksize();
make_fcontext( &my_context, sf ); make_fcontext( &my_context, sf );

147
src/error_report.cpp Normal file
View file

@ -0,0 +1,147 @@
#include <fc/error_report.hpp>
#include <fc/filesystem.hpp>
#include <fc/sstream.hpp>
#include <fc/value.hpp>
#include <fc/json.hpp>
#include <boost/exception_ptr.hpp>
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(fc::path(f).filename().generic_string()),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;
}
fc::string error_frame::to_detail_string()const {
fc::stringstream ss;
ss << to_string() << "\n\t";
ss << file << ":" << line << "\t"<<method;
if( meta ) ss << "\t" <<fc::json::to_string(*meta);
return ss.str();
}
fc::string error_frame::to_string()const {
fc::stringstream ss;
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-prev );
// if we got to the end, return it.
if( next == string::npos ) { return ss.str(); }
// if we are not at the end, then update the start
prev = next + 1;
if( desc[prev] == '{' ) {
// if the next char is a open, then find close
next = desc.find( '}', prev );
// if we found close...
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() ) {
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();
}
fc::exception_ptr error_report::copy_exception() {
return boost::copy_exception(*this);
}
} // namespace fc

View file

@ -94,6 +94,7 @@ namespace fc {
void copy( const path& f, const path& t ) { boost::filesystem::copy( f, t ); } void copy( const path& f, const path& t ) { boost::filesystem::copy( f, t ); }
bool remove( const path& f ) { return boost::filesystem::remove( f ); } bool remove( const path& f ) { return boost::filesystem::remove( f ); }
fc::path canonical( const fc::path& p ) { return boost::filesystem::canonical(p); } 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 unique_path() { return boost::filesystem::unique_path(); }
path temp_directory_path() { return boost::filesystem::temp_directory_path(); } path temp_directory_path() { return boost::filesystem::temp_directory_path(); }
} }

View file

@ -9,6 +9,8 @@
FC_START_SHARED_IMPL(fc::http::connection) FC_START_SHARED_IMPL(fc::http::connection)
fc::tcp_socket sock; fc::tcp_socket sock;
fc::ip::endpoint ep; fc::ip::endpoint ep;
impl() {
}
int read_until( char* buffer, char* end, char c = '\n' ) { int read_until( char* buffer, char* end, char c = '\n' ) {
char* p = buffer; char* p = buffer;
@ -114,16 +116,42 @@ http::reply connection::request( const fc::string& method,
} }
// used for servers // used for servers
fc::tcp_socket& connection::get_socket() { fc::tcp_socket& connection::get_socket()const {
return my->sock; return my->sock;
} }
http::request connection::read_request() { http::request connection::read_request()const {
http::request r; http::request req;
return r; fc::vector<char> line(1024*8);
} int s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // METHOD
void connection::send_reply( const http::reply& ) { 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<int>( 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 } } // fc::http

151
src/http_server.cpp Normal file
View file

@ -0,0 +1,151 @@
#include <fc/http/server.hpp>
#include <fc/thread.hpp>
#include <fc/tcp_socket.hpp>
#include <fc/sstream.hpp>
namespace fc { namespace http {
class server::response::impl : public fc::retainable {
public:
impl( const fc::http::connection& c, const std::function<void()>& cont = std::function<void()>() )
: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 <<": "<<rep.headers[i].val <<"\r\n";
}
ss << "Content-Length: "<<body_length<<"\r\n\r\n";
auto s = ss.str();
con.get_socket().write( s.c_str(), s.size() );
}
http::reply rep;
int64_t body_bytes_sent;
uint64_t body_length;
http::connection con;
std::function<void()> 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<void> 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() ) ) {
slog( "Accept Connection" );
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<void(const http::request&, const server::response& s )> do_on_req ) {
wlog( "reading request.." );
try {
http::server::response rep( fc::shared_ptr<response::impl>( 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<void(const http::request&, const server::response& s )> 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<server::response::impl>& 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; }
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 );
if( my->body_bytes_sent == int64_t(my->body_length) ) {
if( my->handle_next_req ) {
slog( "handle next request..." );
//fc::async( std::function<void()>(my->handle_next_req) );
fc::async( my->handle_next_req );
}
}
}
server::response::~response(){}
void server::on_request( const std::function<void(const http::request&, const server::response& s )>& cb )
{ my->on_req = cb; }
} }

View file

@ -4,6 +4,7 @@
#include <fc/sstream.hpp> #include <fc/sstream.hpp>
#include <fc/filesystem.hpp> #include <fc/filesystem.hpp>
#include <fc/interprocess/file_mapping.hpp> #include <fc/interprocess/file_mapping.hpp>
#include <fc/error_report.hpp>
#include <map> #include <map>
@ -918,15 +919,17 @@ fc::string pretty_print( fc::vector<char>&& v, uint8_t indent ) {
value from_file( const fc::path& local_path ) { value from_file( const fc::path& local_path ) {
if( !exists(local_path) ) { if( !exists(local_path) ) {
FC_THROW_MSG( "Source file '%s' does not exist", local_path.string() ); FC_THROW_REPORT( "Source file ${filename} does not exist", value().set("filename",local_path.string()) );
} }
if( is_directory( local_path ) ) { if( is_directory( local_path ) ) {
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 // memory map the file
file_mapping fmap( local_path.string().c_str(), read_only );
size_t fsize = static_cast<size_t>(file_size(local_path)); size_t fsize = static_cast<size_t>(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 ); mapped_region mr( fmap, fc::read_only, 0, fsize );

View file

@ -2,6 +2,8 @@
#include <fc/log.hpp> #include <fc/log.hpp>
#include <fc/thread.hpp> #include <fc/thread.hpp>
#include <fc/error.hpp> #include <fc/error.hpp>
#include <fc/error_report.hpp>
#include <fc/json_rpc_error_object.hpp>
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
@ -57,7 +59,7 @@ namespace fc { namespace json {
if( id_itr != end ) { if( id_itr != end ) {
// TODO: send invalid method reply // TODO: send invalid method reply
auto id = value_cast<uint64_t>(id_itr->val); auto id = value_cast<uint64_t>(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 // nothing to do, unknown method
} else { // known method, attempt to call it and send reply; } else { // known method, attempt to call it and send reply;
@ -65,14 +67,22 @@ namespace fc { namespace json {
value nul; value nul;
const value& params = (p_itr != end) ? p_itr->val : 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 if( id_itr != end ) { // capture reply
auto id = value_cast<uint64_t>(id_itr->val); auto id = value_cast<uint64_t>(id_itr->val);
try { try {
send_result( id, smeth->second->call(params) ); 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 ( ... ) { } catch ( ... ) {
send_error( id, -1, fc::except_str() ); send_error( id, error_object( fc::except_str(), fc::value() ) );
} }
} else { // ignore exception + result } else { // ignore exception + result
try { smeth->second->call( params ); }catch(...){} try { smeth->second->call( params ); }catch(...){}
@ -96,13 +106,11 @@ namespace fc { namespace json {
} else { } else {
auto e_itr = v.find( "error" ); auto e_itr = v.find( "error" );
if( e_itr != end ) { if( e_itr != end ) {
cur->set_exception( cur->set_exception( fc::value_cast<error_report>(e_itr->val["data"]).copy_exception() );
fc::copy_exception( } else {
fc::generic_exception( elog( "no result nor error field" );
value_cast<fc::string>(
e_itr->val["message"] ) ) ) );
} }
} }
} catch( ... ) { } catch( ... ) {
cur->set_exception( fc::current_exception() ); cur->set_exception( fc::current_exception() );
} }

View file

@ -1,6 +1,13 @@
#include <fc/json_rpc_error_object.hpp> #include <fc/json_rpc_error_object.hpp>
#include <fc/json.hpp>
namespace fc { namespace json { namespace fc { namespace json {
error_object::error_object( const fc::string& m, fc::value v, int64_t c ) error_object::error_object( const fc::string& m, const fc::value& v, int64_t c )
:code(c),message(m),data(fc::move(v)){} :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(){}
}} }}

View file

@ -1,4 +1,5 @@
#include <fc/json_rpc_stream_connection.hpp> #include <fc/json_rpc_stream_connection.hpp>
#include <fc/json_rpc_error_object.hpp>
#include <fc/iostream.hpp> #include <fc/iostream.hpp>
#include <fc/sstream.hpp> #include <fc/sstream.hpp>
#include <fc/thread.hpp> #include <fc/thread.hpp>
@ -27,21 +28,24 @@ namespace fc { namespace json {
fc::future<void> _read_loop_complete; fc::future<void> _read_loop_complete;
void read_loop() { void read_loop() {
fc::string line; try {
fc::getline( in, line ); fc::string line;
while( !in.eof() ) { fc::getline( in, line );
try { while( !in.eof() ) {
fc::value v= fc::json::from_string( line ); try {
//slog( "%s", fc::json::to_string(v).c_str() ); fc::value v= fc::json::from_string( line );
self.handle_message(v); self.handle_message(v);
} catch (...) { } catch (...) {
wlog( "%s", fc::except_str().c_str() ); wlog( "%s", fc::except_str().c_str() );
return; return;
} }
fc::getline( in, line ); fc::getline( in, line );
} }
self.cancel_pending_requests(); } catch ( ... ) {
if( !!on_close ) on_close(); wlog( "%s", fc::except_str().c_str() );
}
self.cancel_pending_requests();
if( !!on_close ) on_close();
} }
}; };
@ -79,24 +83,28 @@ namespace fc { namespace json {
ss<<"{\"id\":"<<id<<",\"method\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n"; ss<<"{\"id\":"<<id<<",\"method\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n";
fc::string o = ss.str(); fc::string o = ss.str();
my->out.write( o.c_str(), o.size() ); my->out.write( o.c_str(), o.size() );
my->out.flush();
} }
void rpc_stream_connection::send_notice( const fc::string& m, value&& param ) { void rpc_stream_connection::send_notice( const fc::string& m, value&& param ) {
fc::stringstream ss; fc::stringstream ss;
ss<<"{\"method\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n"; ss<<"{\"method\":\""<<m<<"\",\"params\":"<<fc::json::to_string(param)<<"}\n";
fc::string o = ss.str(); fc::string o = ss.str();
my->out.write( o.c_str(), o.size() ); my->out.write( o.c_str(), o.size() );
my->out.flush();
} }
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; fc::stringstream ss;
ss<<"{\"id\":"<<id<<",\"error\":{\"code\":"<<code<<",\"message\":"<<fc::json::to_string(fc::value(msg))<<"}}\n"; ss<<"{\"id\":"<<id<<",\"error\":"<<fc::json::to_string(eo)<<"}\n";
fc::string o = ss.str(); fc::string o = ss.str();
my->out.write( o.c_str(), o.size() ); my->out.write( o.c_str(), o.size() );
my->out.flush();
} }
void rpc_stream_connection::send_result( uint64_t id, value&& r ) { void rpc_stream_connection::send_result( uint64_t id, value&& r ) {
fc::stringstream ss; fc::stringstream ss;
ss<<"{\"id\":"<<id<<",\"result\":"<<fc::json::to_string(r)<<"}\n"; ss<<"{\"id\":"<<id<<",\"result\":"<<fc::json::to_string(r)<<"}\n";
fc::string o = ss.str(); fc::string o = ss.str();
my->out.write( o.c_str(), o.size() ); my->out.write( o.c_str(), o.size() );
my->out.flush();
} }
} } // fc::json } } // fc::json

View file

@ -8,12 +8,14 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <fc/filesystem.hpp>
#include <iostream> #include <iostream>
namespace fc { namespace fc {
const char* thread_name(); const char* thread_name();
void* thread_ptr(); void* thread_ptr();
/*
const char* short_name( const char* file_name ) { const char* short_name( const char* file_name ) {
const char* end = file_name + strlen(file_name); const char* end = file_name + strlen(file_name);
--end; --end;
@ -25,6 +27,7 @@ namespace fc {
} }
return file_name; return file_name;
} }
*/
#ifdef WIN32 #ifdef WIN32
#define isatty _isatty #define isatty _isatty
@ -39,7 +42,7 @@ namespace fc {
std::cerr<<"\r"<<color; std::cerr<<"\r"<<color;
#endif #endif
fprintf( stderr, "%-15s %-15s %-5zd %-15s ", thread_name(), short_name(file_name), line_num, method_name ); fprintf( stderr, "%-15s %-15s %-5zd %-15s ", thread_name(), fc::path(file_name).filename().generic_string().c_str(), line_num, method_name );
//std::cerr<<thread_ptr()<< thread_name()<< short_name(file_name)<< line_num<< method_name ; //std::cerr<<thread_ptr()<< thread_name()<< short_name(file_name)<< line_num<< method_name ;
va_list args; va_list args;
va_start(args,format); va_start(args,format);

View file

@ -43,9 +43,13 @@ namespace fc {
try { try {
return static_cast<std::streamsize>(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast<size_t>(n) ) )); return static_cast<std::streamsize>(fc::asio::read_some( *m_pi, boost::asio::buffer( s, static_cast<size_t>(n) ) ));
} catch ( const boost::system::system_error& e ) { } catch ( const boost::system::system_error& e ) {
wlog( "%s", fc::except_str().c_str() );
if( e.code() == boost::asio::error::eof ) if( e.code() == boost::asio::error::eof )
return -1; return -1;
throw; throw;
} catch ( ... ) {
wlog( "%s", fc::except_str().c_str() );
return -1;
} }
} }
private: private:
@ -69,9 +73,13 @@ FC_START_SHARED_IMPL( fc::process )
if( inp ) { if( inp ) {
inp->close(); inp->close();
} }
child->terminate(); if( _exited.valid() && !_exited.ready()) {
slog( "terminate...");
child->terminate();
_exited.wait();
}
}catch(...) { }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<fc::process_source> std_err; io::stream<fc::process_source> std_err;
io::stream<fc::process_sink> std_in; io::stream<fc::process_sink> std_in;
fc::future<int> _exited;
// adapt to ostream and istream interfaces // adapt to ostream and istream interfaces
fc::ostream_wrapper _ins; fc::ostream_wrapper _ins;
fc::istream_wrapper _outs; fc::istream_wrapper _outs;
@ -163,8 +173,7 @@ fc::future<int> process::exec( const fc::path& exe, fc::vector<fc::string>&& arg
} }
else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) );
}); });
return p; return my->_exited = p;
} }
/** /**

View file

@ -36,7 +36,7 @@ namespace fc {
void string::clear() { my->clear(); } void string::clear() { my->clear(); }
void string::resize( uint64_t s ) { my->resize(s); } 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(); } const char* string::c_str()const { return my->c_str(); }
bool string::operator == ( const char* s )const { return *my == s; } bool string::operator == ( const char* s )const { return *my == s; }

View file

@ -9,7 +9,7 @@ namespace fc {
class tcp_socket::impl { class tcp_socket::impl {
public: public:
impl():_sock( fc::asio::default_io_service() ){ } impl():_sock( fc::asio::default_io_service() ){ }
~impl(){ ~impl(){
if( _sock.is_open() ) _sock.close(); if( _sock.is_open() ) _sock.close();
} }
@ -85,7 +85,9 @@ namespace fc {
class tcp_server::impl { class tcp_server::impl {
public: 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) ){
}
~impl(){ ~impl(){
_accept.close(); _accept.close();
} }
@ -105,7 +107,8 @@ namespace fc {
bool tcp_server::accept( tcp_socket& s ) { bool tcp_server::accept( tcp_socket& s ) {
fc::promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("mace::cmt::asio::tcp::accept") ); if( !my ) return false;
fc::promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("tcp::accept") );
my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) { my->_accept.async_accept( s.my->_sock, [=]( const boost::system::error_code& e ) {
p->set_value(e); p->set_value(e);
} ); } );

103
src/url.cpp Normal file
View file

@ -0,0 +1,103 @@
#include <fc/url.hpp>
#include <fc/Value.hpp>
#include <fc/error_report.hpp>
#include <fc/lexical_cast.hpp>
#include <fc/value_cast.hpp>
#include <fc/sstream.hpp>
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<<proto<<"://";
if( user ) {
ss << *user;
if( pass ) {
ss<<":"<<*pass;
}
ss<<"@";
}
ss<<*host;
if( port ) ss<<":"<<*port;
if( path ) ss<<"/"<<*path;
if( args ) ss<<"?"<<*args;
return ss.str();
}
/**
* proto://user:pass@host:port/~/path?args
* proto://user:pass@host:port/absolute?args
*/
url& url::from_string( const string& s ) {
fc::stringstream ss(s);
fc::string _proto,skip,_user,_pass,_host,_port,_path,_args;
fc::getline( ss, _proto, ':' );
fc::getline( ss, skip, '/' );
fc::getline( ss, skip, '/' );
if( s.find('@') != fc::string::npos ) {
fc::string user_pass;
fc::getline( ss, user_pass, '@' );
fc::stringstream upss(user_pass);
if( user_pass.find( ':' ) != fc::string::npos ) {
fc::getline( upss, _user, ':' );
fc::getline( upss, _pass, ':' );
user = fc::move(_user);
pass = fc::move(_pass);
} else {
user = fc::move(user_pass);
}
}
fc::string host_port;
fc::getline( ss, host_port, '/' );
auto pos = host_port.find( ':' );
if( pos != fc::string::npos ) {
try {
port = fc::lexical_cast<uint16_t>( 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

View file

@ -276,6 +276,12 @@ value& value::operator=( const value& v ){
gh(v.holder)->copy_helper(holder); gh(v.holder)->copy_helper(holder);
return *this; 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 { bool value::is_null()const {
return strcmp(gh(holder)->type(), "void") == 0; return strcmp(gh(holder)->type(), "void") == 0;
} }

View file

@ -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 <boost/process/all.hpp>
#endif

View file

@ -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 <boost/process/child.hpp>
#include <boost/process/context.hpp>
#include <boost/process/environment.hpp>
#include <boost/process/handle.hpp>
#include <boost/process/operations.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/process/pipe.hpp>
#include <boost/process/pistream.hpp>
#include <boost/process/postream.hpp>
#include <boost/process/process.hpp>
#include <boost/process/self.hpp>
#include <boost/process/status.hpp>
#include <boost/process/stream_behavior.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_type.hpp>
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/process.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/handle.hpp>
#include <map>
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<stream_id, handle> 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<stream_id, handle> 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<stream_id, handle>::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<stream_id, handle> handles_;
};
}
}
#endif

View file

@ -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 <boost/config.hpp>
#include <boost/system/config.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#if defined(BOOST_POSIX_API)
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#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

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#endif
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_type.hpp>
#include <boost/process/environment.hpp>
#include <boost/process/self.hpp>
#include <boost/process/stream_behavior.hpp>
#include <boost/function.hpp>
#include <string>
#include <map>
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<stream_id, boost::function<stream_ends (stream_type)> >
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<void ()> setup;
#elif defined(BOOST_WINDOWS_API)
boost::function<void (STARTUPINFOA&)> setup;
#endif
};
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#include <boost/process/pid_type.hpp>
#include <boost/asio.hpp>
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 <typename Service>
class basic_status
: public boost::asio::basic_io_object<Service>
{
public:
explicit basic_status(boost::asio::io_service &io_service)
: boost::asio::basic_io_object<Service>(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 <typename Handler>
void async_wait(pid_type pid, Handler handler)
{
this->service.async_wait(this->implementation, pid, handler);
}
};
}
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/process/operations.hpp>
# include <string>
# include <sys/types.h>
# include <sys/wait.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
#include <boost/process/detail/status_impl.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/system/error_code.hpp>
#include <boost/unordered_map.hpp>
#include <vector>
#include <algorithm>
namespace boost {
namespace process {
namespace detail {
/**
* The basic_status_service class provides the service to wait for processes
* synchronously and asynchronously.
*/
template <typename StatusImplementation = status_impl>
class basic_status_service
: public boost::asio::detail::service_base<StatusImplementation>
{
public:
explicit basic_status_service(boost::asio::io_service &io_service)
: boost::asio::detail::service_base<StatusImplementation>(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<StatusImplementation>::work_thread, this);
#endif
}
~basic_status_service()
{
#if defined(BOOST_POSIX_API)
boost::unique_lock<boost::mutex> 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<StatusImplementation> implementation_type;
void construct(implementation_type &impl)
{
impl = boost::make_shared<StatusImplementation>();
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
impls_.push_back(impl);
}
void destroy(implementation_type &impl)
{
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
typename std::vector<implementation_type>::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<boost::mutex> lock(work_thread_mutex_);
boost::unordered_map<pid_t, int>::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 <typename Handler>
void async_wait(implementation_type &impl, pid_type pid, Handler handler)
{
#if defined(BOOST_POSIX_API)
boost::unique_lock<boost::mutex> 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<StatusImplementation>::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<boost::mutex> 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<boost::mutex> 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<boost::mutex> lock(work_thread_mutex_);
bool regchild = false;
for (typename std::vector<implementation_type>::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<pid_t, int>::
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<boost::mutex> 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<boost::mutex> lock(work_thread_mutex_);
for (typename std::vector<implementation_type>::iterator it =
impls_.begin(); it != impls_.end(); ++it)
(*it)->complete(handle, exit_code);
std::vector<HANDLE>::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<std::string> 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<boost::asio::io_service::work> work_;
std::vector<implementation_type> 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<pid_t, int> statuses_;
#elif defined(BOOST_WINDOWS_API)
bool run_;
std::vector<HANDLE> handles_;
#endif
};
}
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#include <boost/process/environment.hpp>
#include <string>
#include <utility>
#include <cstring>
#include <cstddef>
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<std::size_t, char**> 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<std::size_t, char**>(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 <class Arguments>
inline std::pair<std::size_t, char**> 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<std::size_t, char**>(nargs, argv);
}
}
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
# include <signal.h>
# include <sys/wait.h>
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
#include <boost/system/error_code.hpp>
#include <boost/ptr_container/ptr_unordered_map.hpp>
#include <algorithm>
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 <typename Handler>
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 <typename Container>
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 <typename Handler>
void async_wait(phandle ph, Handler handler)
{
ops_.insert(ph, new wrapped_handler<Handler>(handler));
}
bool complete(phandle ph, int exit_code)
{
boost::iterator_range<operations_type::iterator> 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<phandle, operation> operations_type;
operations_type ops_;
};
}
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <boost/assert.hpp>
#include <streambuf>
#include <cstddef>
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<traits_type::char_type>(
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<long>(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<char> read_buf_;
/**
* Internal buffer used during write operations.
*/
boost::scoped_array<char> write_buf_;
};
}
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#include <boost/process/environment.hpp>
#include <boost/shared_array.hpp>
#include <string>
#include <vector>
#include <cstddef>
#include <string.h>
#include <windows.h>
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<char> environment_to_windows_strings(environment
&env)
{
boost::shared_array<char> 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 <class Arguments>
inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments
&args)
{
typedef std::vector<std::string> 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<char> 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

View file

@ -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 <map>
#include <string>
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<std::string, std::string> environment;
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
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<impl>(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> 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

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/process/detail/posix_helpers.hpp>
# include <utility>
# include <cstddef>
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# if defined(__CYGWIN__)
# include <boost/scoped_array.hpp>
# include <sys/cygwin.h>
# endif
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/detail/windows_helpers.hpp>
# include <boost/scoped_array.hpp>
# include <boost/shared_array.hpp>
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/child.hpp>
#include <boost/process/context.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/stream_ends.hpp>
#include <boost/process/handle.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <string>
#include <vector>
#include <map>
#include <utility>
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<char> 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 <typename Arguments, typename Context>
inline child create_child(const std::string &executable, Arguments args,
Context ctx)
{
typedef std::map<stream_id, stream_ends> 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<bool> closeflags(maxdescs, true);
std::pair<std::size_t, char**> argv = detail::collection_to_argv(args);
std::pair<std::size_t, char**> 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<stream_id, handle> 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<char> cmdline =
detail::collection_to_windows_cmdline(args);
boost::scoped_array<char> 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<char> 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<char> 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<stream_id, handle> 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<std::string>(), context());
}
/**
* \overload
*/
template <typename Arguments>
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 <typename Context>
inline child shell(const std::string &command, Context ctx)
{
#if defined(BOOST_POSIX_API)
std::string executable = "/bin/sh";
std::vector<std::string> 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<std::string> 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

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#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

View file

@ -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 <boost/process/config.hpp>
#include <boost/asio.hpp>
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

View file

@ -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 <boost/process/handle.hpp>
#include <boost/process/detail/systembuf.hpp>
#include <boost/noncopyable.hpp>
#include <istream>
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

View file

@ -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 <boost/process/handle.hpp>
#include <boost/process/detail/systembuf.hpp>
#include <boost/noncopyable.hpp>
#include <ostream>
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

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <unistd.h>
# include <sys/types.h>
# include <signal.h>
# include <sys/wait.h>
# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/handle.hpp>
# include <cstdlib>
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/pid_type.hpp>
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

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <boost/scoped_array.hpp>
# include <errno.h>
# include <unistd.h>
# include <limits.h>
# if defined(__APPLE__)
# include <crt_externs.h>
# endif
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
# error "Unsupported platform."
#endif
#include <boost/process/process.hpp>
#include <boost/process/environment.hpp>
#include <boost/noncopyable.hpp>
#include <boost/assert.hpp>
#include <string>
#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<char> 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

View file

@ -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 <boost/process/config.hpp>
#include <boost/process/detail/basic_status.hpp>
#include <boost/process/detail/basic_status_service.hpp>
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<detail::basic_status_service<> > status;
}
}
#endif

View file

@ -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 <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
# include <rpc.h>
#endif
#include <boost/process/stream_ends.hpp>
#include <boost/process/stream_type.hpp>
#include <boost/process/handle.hpp>
#include <string>
#include <algorithm>
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<char*>(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

View file

@ -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 <boost/process/config.hpp>
#include <boost/process/handle.hpp>
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

View file

@ -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 <boost/process/config.hpp>
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

View file

@ -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 <boost/process/config.hpp>
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

View file

@ -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 )

File diff suppressed because it is too large Load diff

View file

@ -1,118 +0,0 @@
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/* Note: This include file is only needed for using the
* publickey SUBSYSTEM which is not the same as publickey
* authentication. For authentication you only need libssh2.h
*
* For more information on the publickey subsystem,
* refer to IETF draft: secsh-publickey
*/
#ifndef LIBSSH2_PUBLICKEY_H
#define LIBSSH2_PUBLICKEY_H 1
#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 */

View file

@ -1,345 +0,0 @@
/* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef LIBSSH2_SFTP_H
#define LIBSSH2_SFTP_H 1
#include "libssh2.h"
#ifndef WIN32
#include <unistd.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Note: Version 6 was documented at the time of writing
* However it was marked as "DO NOT IMPLEMENT" due to pending changes
*
* Let's start with Version 3 (The version found in OpenSSH) and go from there
*/
#define LIBSSH2_SFTP_VERSION 3
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 */

View file

@ -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 <errno.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#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);
}

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -1,390 +0,0 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_HAVE_ZLIB
# include <zlib.h>
#endif
#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;
}

View file

@ -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 */

View file

@ -1,334 +0,0 @@
/* Copyright (c) 2009, 2010 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_CRYPT_NONE
/* 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;
}

View file

@ -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

View file

@ -1,78 +0,0 @@
/* Copyright (c) 2010 Lars Nordin <Lars.Nordin@SDlabs.se>
* Copyright (C) 2010 Simon Josefsson <simon@josefsson.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
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);
}

View file

@ -1,485 +0,0 @@
/* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
* 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 <sys/uio.h>
#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;
}

View file

@ -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;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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 <string.h>
int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen)
{
int rc;
(void) e1data;
(void) e1len;
(void) e2data;
(void) e2len;
if (ddata) {
rc = gcry_sexp_build
(rsa, NULL,
"(private-key(rsa(n%b)(e%b)(d%b)(q%b)(p%b)(u%b)))",
nlen, ndata, elen, edata, dlen, ddata, plen, pdata,
qlen, qdata, coefflen, coeffdata);
} else {
rc = gcry_sexp_build(rsa, NULL, "(public-key(rsa(n%b)(e%b)))",
nlen, ndata, elen, edata);
}
if (rc) {
*rsa = NULL;
return -1;
}
return 0;
}
int
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsa,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len)
{
unsigned char hash[SHA_DIGEST_LENGTH];
gcry_sexp_t s_sig, s_hash;
int rc = -1;
libssh2_sha1(m, m_len, hash);
rc = gcry_sexp_build(&s_hash, NULL,
"(data (flags pkcs1) (hash sha1 %b))",
SHA_DIGEST_LENGTH, hash);
if (rc != 0) {
return -1;
}
rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s %b)))", sig_len, sig);
if (rc != 0) {
gcry_sexp_release(s_hash);
return -1;
}
rc = gcry_pk_verify(s_sig, s_hash, rsa);
gcry_sexp_release(s_sig);
gcry_sexp_release(s_hash);
return (rc == 0) ? 0 : -1;
}
int
_libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
const unsigned char *p,
unsigned long p_len,
const unsigned char *q,
unsigned long q_len,
const unsigned char *g,
unsigned long g_len,
const unsigned char *y,
unsigned long y_len,
const unsigned char *x, unsigned long x_len)
{
int rc;
if (x_len) {
rc = gcry_sexp_build
(dsactx, NULL,
"(private-key(dsa(p%b)(q%b)(g%b)(y%b)(x%b)))",
p_len, p, q_len, q, g_len, g, y_len, y, x_len, x);
} else {
rc = gcry_sexp_build(dsactx, NULL,
"(public-key(dsa(p%b)(q%b)(g%b)(y%b)))",
p_len, p, q_len, q, g_len, g, y_len, y);
}
if (rc) {
*dsactx = NULL;
return -1;
}
return 0;
}
int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
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 */

View file

@ -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 <gcrypt.h>
#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)

View file

@ -1,5 +0,0 @@
#ifdef WIN32
#include "libssh2_config_win.h"
#else
#include "libssh2_config_osx.h"
#endif

View file

@ -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 <alloca.h> and it should be used (not on Ultrix).
*/
#define HAVE_ALLOCA_H 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* disabled non-blocking sockets */
/* #undef HAVE_DISABLED_NONBLOCKING */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <errno.h> 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 <fcntl.h> 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 <inttypes.h> 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 <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <netinet/in.h> 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 <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> 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 <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <sys/un.h> header file. */
#define HAVE_SYS_UN_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to 1 if you have the <winsock2.h> header file. */
/* #undef HAVE_WINSOCK2_H */
/* Define to 1 if you have the <ws2tcpip.h> 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

View file

@ -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 <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#ifdef __MINGW32__
#define HAVE_UNISTD_H
#define HAVE_INTTYPES_H
#define HAVE_SYS_TIME_H
#endif
#define HAVE_WINSOCK2_H
#define HAVE_IOCTLSOCKET
#define HAVE_SELECT
#ifdef _MSC_VER
#define snprintf _snprintf
#if _MSC_VER < 1500
#define vsnprintf _vsnprintf
#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 */

File diff suppressed because it is too large Load diff

View file

@ -1,314 +0,0 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#include "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;
}

View file

@ -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 */

View file

@ -1,612 +0,0 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* 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 <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <stdio.h>
#include <errno.h>
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 <dannysmith@users.sourceforge.net>
*/
/* 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

View file

@ -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 */

View file

@ -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 <sarag@libssh2.org>
*
* 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 <string.h>
#ifndef EVP_MAX_BLOCK_LENGTH
#define EVP_MAX_BLOCK_LENGTH 32
#endif
int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
unsigned long elen,
const unsigned char *ndata,
unsigned long nlen,
const unsigned char *ddata,
unsigned long dlen,
const unsigned char *pdata,
unsigned long plen,
const unsigned char *qdata,
unsigned long qlen,
const unsigned char *e1data,
unsigned long e1len,
const unsigned char *e2data,
unsigned long e2len,
const unsigned char *coeffdata, unsigned long coefflen)
{
*rsa = RSA_new();
(*rsa)->e = BN_new();
BN_bin2bn(edata, elen, (*rsa)->e);
(*rsa)->n = BN_new();
BN_bin2bn(ndata, nlen, (*rsa)->n);
if (ddata) {
(*rsa)->d = BN_new();
BN_bin2bn(ddata, dlen, (*rsa)->d);
(*rsa)->p = BN_new();
BN_bin2bn(pdata, plen, (*rsa)->p);
(*rsa)->q = BN_new();
BN_bin2bn(qdata, qlen, (*rsa)->q);
(*rsa)->dmp1 = BN_new();
BN_bin2bn(e1data, e1len, (*rsa)->dmp1);
(*rsa)->dmq1 = BN_new();
BN_bin2bn(e2data, e2len, (*rsa)->dmq1);
(*rsa)->iqmp = BN_new();
BN_bin2bn(coeffdata, coefflen, (*rsa)->iqmp);
}
return 0;
}
int
_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx,
const unsigned char *sig,
unsigned long sig_len,
const unsigned char *m, unsigned long m_len)
{
unsigned char hash[SHA_DIGEST_LENGTH];
int ret;
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 <openssl/aes.h>
#include <openssl/evp.h>
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 <X> with <cipher>
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 */

View file

@ -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 <openssl/opensslconf.h>
#include <openssl/sha.h>
#ifndef OPENSSL_NO_MD5
#include <openssl/md5.h>
#endif
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#ifdef OPENSSL_NO_RSA
# define LIBSSH2_RSA 0
#else
# define LIBSSH2_RSA 1
#endif
#ifdef OPENSSL_NO_DSA
# define LIBSSH2_DSA 0
#else
# define LIBSSH2_DSA 1
#endif
#ifdef OPENSSL_NO_MD5
# define LIBSSH2_MD5 0
#else
# define LIBSSH2_MD5 1
#endif
#ifdef OPENSSL_NO_RIPEMD
# define LIBSSH2_HMAC_RIPEMD 0
#else
# define LIBSSH2_HMAC_RIPEMD 1
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
# define LIBSSH2_AES_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);

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
#ifndef LIBSSH2_PACKET_H
#define LIBSSH2_PACKET_H
/*
* Copyright (C) 2010 by Daniel Stenberg
* Author: Daniel Stenberg <daniel@haxx.se>
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
*/
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 */

View file

@ -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 */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,93 +0,0 @@
#ifndef LIBSSH2_SESSION_H
#define LIBSSH2_SESSION_H
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2009-2010 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/* 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 */

Some files were not shown because too many files have changed in this diff Show more