update ssh error reporting
This commit is contained in:
parent
ecd5fd4b96
commit
178dcea0c2
1 changed files with 97 additions and 57 deletions
102
src/ssh.cpp
102
src/ssh.cpp
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <fc/filesystem.hpp>
|
||||||
|
#include <fc/value_cast.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include <fc/ssh/client.hpp>
|
#include <fc/ssh/client.hpp>
|
||||||
#include <fc/ssh/process.hpp>
|
#include <fc/ssh/process.hpp>
|
||||||
#include <fc/exception.hpp>
|
#include <fc/exception.hpp>
|
||||||
|
|
@ -8,6 +11,7 @@
|
||||||
#include <fc/interprocess/file_mapping.hpp>
|
#include <fc/interprocess/file_mapping.hpp>
|
||||||
#include <fc/unique_lock.hpp>
|
#include <fc/unique_lock.hpp>
|
||||||
#include <fc/mutex.hpp>
|
#include <fc/mutex.hpp>
|
||||||
|
#include <fc/error_report.hpp>
|
||||||
#include <libssh2.h>
|
#include <libssh2.h>
|
||||||
#include <libssh2_sftp.h>
|
#include <libssh2_sftp.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -146,11 +150,11 @@ namespace fc { namespace ssh {
|
||||||
|
|
||||||
void connect() {
|
void connect() {
|
||||||
try {
|
try {
|
||||||
if( libssh2_init(0) < 0 ) { FC_THROW_MSG( "Unable to init libssh2" ); }
|
if( libssh2_init(0) < 0 ) { FC_THROW_REPORT( "Unable to init libssh2" ); }
|
||||||
|
|
||||||
auto eps = fc::asio::tcp::resolve( hostname, fc::lexical_cast<fc::string>(port) );
|
auto eps = fc::asio::tcp::resolve( hostname, fc::lexical_cast<fc::string>(port) );
|
||||||
if( eps.size() == 0 ) {
|
if( eps.size() == 0 ) {
|
||||||
FC_THROW_MSG( "Unable to resolve '%s'", hostname );
|
FC_THROW_REPORT( "Unable to resolve host '${host}'", fc::value().set("host",hostname) );
|
||||||
}
|
}
|
||||||
sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) );
|
sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) );
|
||||||
|
|
||||||
|
|
@ -173,15 +177,16 @@ namespace fc { namespace ssh {
|
||||||
if( ec < 0 ) {
|
if( ec < 0 ) {
|
||||||
char* msg;
|
char* msg;
|
||||||
libssh2_session_last_error( session, &msg, 0, 0 );
|
libssh2_session_last_error( session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "Handshake error: %s - %s", ec, msg );
|
FC_THROW_REPORT( "SSH Handshake error: ${code} - ${message}",
|
||||||
|
fc::value().set("code",ec).set("message", msg) );
|
||||||
}
|
}
|
||||||
/*const char* fingerprint = */libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
/*const char* fingerprint = */libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||||
|
|
||||||
// try to authenticate, throw on error.
|
// try to authenticate, throw on error.
|
||||||
authenticate();
|
authenticate();
|
||||||
} catch (...) {
|
} catch ( error_report& er ) {
|
||||||
close();
|
close();
|
||||||
throw;
|
throw FC_REPORT_PUSH( er, "Unable to connect to ssh server" );;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +243,7 @@ namespace fc { namespace ssh {
|
||||||
}
|
}
|
||||||
|
|
||||||
void authenticate() {
|
void authenticate() {
|
||||||
|
try {
|
||||||
char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size());
|
char * alist = libssh2_userauth_list(session, uname.c_str(),uname.size());
|
||||||
char * msg = 0;
|
char * msg = 0;
|
||||||
int ec = 0;
|
int ec = 0;
|
||||||
|
|
@ -254,7 +260,8 @@ namespace fc { namespace ssh {
|
||||||
ec = libssh2_session_last_error(session,&msg,NULL,0);
|
ec = libssh2_session_last_error(session,&msg,NULL,0);
|
||||||
}
|
}
|
||||||
if( !alist ) {
|
if( !alist ) {
|
||||||
FC_THROW_MSG( "Error getting authorization list: %s - %s", ec, msg );
|
FC_THROW_REPORT( "Error getting authorization list: ${code} - ${message}",
|
||||||
|
fc::value().set("code",ec).set("message",msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,7 +297,10 @@ namespace fc { namespace ssh {
|
||||||
if( try_keyboard() )
|
if( try_keyboard() )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FC_THROW_MSG( "Unable to authenticate" );
|
} catch ( error_report er ) {
|
||||||
|
throw FC_REPORT_PUSH( er, "Unable to authenticate ssh connection" );
|
||||||
|
}
|
||||||
|
FC_THROW_REPORT( "Unable to authenticate ssh connection" );
|
||||||
} // authenticate()
|
} // authenticate()
|
||||||
|
|
||||||
bool try_pass() {
|
bool try_pass() {
|
||||||
|
|
@ -386,10 +396,14 @@ namespace fc { namespace ssh {
|
||||||
}
|
}
|
||||||
} else if( rprom ) {
|
} else if( rprom ) {
|
||||||
if( rprom->wait() ) {
|
if( rprom->wait() ) {
|
||||||
FC_THROW( boost::system::system_error(rprom->wait() ) );
|
FC_THROW_REPORT( "Socket Error ${message}",
|
||||||
|
fc::value().set( "message", boost::system::system_error(rprom->wait() ).what() ) );
|
||||||
}
|
}
|
||||||
} else if( wprom ) {
|
} else if( wprom ) {
|
||||||
if( wprom->wait() ) { FC_THROW( boost::system::system_error(wprom->wait() ) ); }
|
if( wprom->wait() ) {
|
||||||
|
FC_THROW_REPORT( "Socket Error ${message}",
|
||||||
|
fc::value().set( "message", boost::system::system_error(wprom->wait() ).what() ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void init_sftp() {
|
void init_sftp() {
|
||||||
|
|
@ -402,7 +416,7 @@ namespace fc { namespace ssh {
|
||||||
wait_on_socket();
|
wait_on_socket();
|
||||||
sftp = libssh2_sftp_init(session);
|
sftp = libssh2_sftp_init(session);
|
||||||
} else {
|
} else {
|
||||||
FC_THROW_MSG( "init sftp error %s: %s", ec, msg );
|
FC_THROW_REPORT( "init sftp error ${code} - ${message}", fc::value().set("code",ec).set("message",msg) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -450,10 +464,10 @@ namespace fc { namespace ssh {
|
||||||
|
|
||||||
// using namespace boost::filesystem;
|
// using namespace boost::filesystem;
|
||||||
if( !fc::exists(local_path) ) {
|
if( !fc::exists(local_path) ) {
|
||||||
FC_THROW_MSG( "Source file '%s' does not exist", local_path.string() );
|
FC_THROW_REPORT( "Source file '${file}' does not exist", fc::value().set("file",local_path) ) ;
|
||||||
}
|
}
|
||||||
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 file '${file}' is a directory, expected a file", fc::value().set("file",local_path) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory map the file
|
// memory map the file
|
||||||
|
|
@ -474,7 +488,8 @@ namespace fc { namespace ssh {
|
||||||
my->wait_on_socket();
|
my->wait_on_socket();
|
||||||
chan = libssh2_scp_send64( my->session, local_path.generic_string().c_str(), 0700, fsize, now, now );
|
chan = libssh2_scp_send64( my->session, local_path.generic_string().c_str(), 0700, fsize, now, now );
|
||||||
} else {
|
} else {
|
||||||
FC_THROW_MSG( "scp %s to %s failed %s - %s",local_path.string(), remote_path.string(), ec, msg );
|
FC_THROW_REPORT( "scp ${local_file} to ${remote_file} failed ${code} - ${message}",
|
||||||
|
fc::value().set("local_file", local_path).set("remote_file",remote_path).set("code",ec).set("message",msg) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -489,7 +504,8 @@ namespace fc { namespace ssh {
|
||||||
if( r < 0 ) {
|
if( r < 0 ) {
|
||||||
char* msg = 0;
|
char* msg = 0;
|
||||||
int ec = libssh2_session_last_error( my->session, &msg, 0, 0 );
|
int ec = libssh2_session_last_error( my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "scp failed %s - %s", ec, msg );
|
FC_THROW_REPORT( "scp failed ${code} - ${message}",
|
||||||
|
fc::value().set("code",ec).set("message",msg) );
|
||||||
}
|
}
|
||||||
wrote += r;
|
wrote += r;
|
||||||
pos += r;
|
pos += r;
|
||||||
|
|
@ -511,16 +527,18 @@ namespace fc { namespace ssh {
|
||||||
if( ec < 0 ) {
|
if( ec < 0 ) {
|
||||||
char* msg = 0;
|
char* msg = 0;
|
||||||
int ec = libssh2_session_last_error( my->session, &msg, 0, 0 );
|
int ec = libssh2_session_last_error( my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "scp failed %s - %s", ec, msg );
|
FC_THROW_REPORT( "scp failed ${code} - ${message}",
|
||||||
|
fc::value().set("code",ec).set("message",msg) );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void client::rm( const fc::path& remote_path ) {
|
void client::rm( const fc::path& remote_path ) {
|
||||||
|
try {
|
||||||
auto s = stat(remote_path);
|
auto s = stat(remote_path);
|
||||||
if( s.is_directory() ) {
|
if( s.is_directory() ) {
|
||||||
FC_THROW_MSG( "Directory exists at path %s", remote_path.string() );
|
FC_THROW_REPORT( "sftp cannot remove directory ${path}", fc::value().set("path",remote_path) );
|
||||||
}
|
}
|
||||||
else if( !s.exists() ) {
|
else if( !s.exists() ) {
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
|
|
@ -533,7 +551,10 @@ namespace fc { namespace ssh {
|
||||||
}
|
}
|
||||||
if( 0 != rc ) {
|
if( 0 != rc ) {
|
||||||
rc = libssh2_sftp_last_error(my->sftp);
|
rc = libssh2_sftp_last_error(my->sftp);
|
||||||
FC_THROW_MSG( "rm error %s", rc );
|
FC_THROW_REPORT( "sftp rm failed ${code}", fc::value().set("code",rc) );
|
||||||
|
}
|
||||||
|
} catch ( error_report& er ) {
|
||||||
|
throw FC_REPORT_PUSH( er, "sftp remove '${remote_path}' failed", fc::value().set("remote_path",remote_path) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,12 +574,25 @@ namespace fc { namespace ssh {
|
||||||
ft.permissions = att.permissions;
|
ft.permissions = att.permissions;
|
||||||
return ft;
|
return ft;
|
||||||
}
|
}
|
||||||
|
void client::create_directories( const fc::path& rdir, int mode ) {
|
||||||
|
boost::filesystem::path dir = rdir;
|
||||||
|
boost::filesystem::path p;
|
||||||
|
auto pitr = dir.begin();
|
||||||
|
while( pitr != dir.end() ) {
|
||||||
|
p /= *pitr;
|
||||||
|
if( !stat( p ).exists() ) {
|
||||||
|
mkdir(p,mode);
|
||||||
|
}
|
||||||
|
++pitr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void client::mkdir( const fc::path& rdir, int mode ) {
|
void client::mkdir( const fc::path& rdir, int mode ) {
|
||||||
|
try {
|
||||||
auto s = stat(rdir);
|
auto s = stat(rdir);
|
||||||
if( s.is_directory() ) return;
|
if( s.is_directory() ) return;
|
||||||
else if( s.exists() ) {
|
else if( s.exists() ) {
|
||||||
FC_THROW_MSG( "Non directory exists at path %s", rdir.generic_string().c_str() );
|
FC_THROW_REPORT( "File already exists at path ${path}", fc::value().set("path",rdir) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode );
|
int rc = libssh2_sftp_mkdir(my->sftp, rdir.generic_string().c_str(), mode );
|
||||||
|
|
@ -568,7 +602,10 @@ namespace fc { namespace ssh {
|
||||||
}
|
}
|
||||||
if( 0 != rc ) {
|
if( 0 != rc ) {
|
||||||
rc = libssh2_sftp_last_error(my->sftp);
|
rc = libssh2_sftp_last_error(my->sftp);
|
||||||
FC_THROW_MSG( "mkdir error %s", rc );
|
FC_THROW_REPORT( "sftp mkdir error", fc::value().set("code",rc) );
|
||||||
|
}
|
||||||
|
} catch ( error_report& er ) {
|
||||||
|
throw FC_REPORT_PUSH( er, "sftp failed to create directory '${directory}'", fc::value().set( "directory", rdir ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,11 +730,11 @@ namespace fc { namespace ssh {
|
||||||
ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA );
|
ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA );
|
||||||
}
|
}
|
||||||
if( ec < 0 ) {
|
if( ec < 0 ) {
|
||||||
FC_THROW_MSG( "flush failed: channel error %d", ec );
|
FC_THROW_REPORT( "ssh flush failed", fc::value().set( "channel_error", ec) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int detail::process_impl::read_some( char* data, size_t len, int stream_id ){
|
int detail::process_impl::read_some( char* data, size_t len, int stream_id ){
|
||||||
if( !sshc.my->session ) { FC_THROW_MSG( "Session closed" ); }
|
if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); }
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
char* buf = data;
|
char* buf = data;
|
||||||
|
|
@ -725,16 +762,16 @@ namespace fc { namespace ssh {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char* msg;
|
char* msg;
|
||||||
if( !sshc.my || !sshc.my->session ) { FC_THROW_MSG( "Session closed" ); }
|
if( !sshc.my || !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); }
|
||||||
rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "read failed: %s - %s", rc, msg ); return buf-data;
|
FC_THROW_REPORT( "read failed: ${message}", fc::value().set("message", msg).set("code", rc) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while( rc >= 0 && buflen);
|
} while( rc >= 0 && buflen);
|
||||||
return buf-data;
|
return buf-data;
|
||||||
}
|
}
|
||||||
int detail::process_impl::write_some( const char* data, size_t len, int stream_id ) {
|
int detail::process_impl::write_some( const char* data, size_t len, int stream_id ) {
|
||||||
if( !sshc.my->session ) { FC_THROW_MSG( "Session closed" ); }
|
if( !sshc.my->session ) { FC_THROW_REPORT( "Session closed" ); }
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
const char* buf = data;
|
const char* buf = data;
|
||||||
|
|
@ -747,8 +784,7 @@ namespace fc { namespace ssh {
|
||||||
return buf-data;
|
return buf-data;
|
||||||
} else if( rc == 0 ) {
|
} else if( rc == 0 ) {
|
||||||
if( libssh2_channel_eof( chan ) ) {
|
if( libssh2_channel_eof( chan ) ) {
|
||||||
elog( "return %1%", -1 );
|
FC_THROW_REPORT( "EOF" );
|
||||||
FC_THROW_MSG( "EOF" );
|
|
||||||
//return -1; // eof
|
//return -1; // eof
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -765,7 +801,7 @@ namespace fc { namespace ssh {
|
||||||
} else {
|
} else {
|
||||||
char* msg;
|
char* msg;
|
||||||
rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
rc = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "write failed: %s - %s", rc, msg );
|
FC_THROW_REPORT( "write failed: ${message}", fc::value().set("message",msg).set("code",rc) );
|
||||||
return buf-data;
|
return buf-data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -782,7 +818,7 @@ namespace fc { namespace ssh {
|
||||||
if( ec ) {
|
if( ec ) {
|
||||||
char* msg = 0;
|
char* msg = 0;
|
||||||
ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "send eof failed: %s - %s", ec, msg );
|
FC_THROW_REPORT( "send eof failed: ${message}", fc::value().set("message",msg).set("code",ec) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -854,7 +890,7 @@ namespace fc { namespace ssh {
|
||||||
if( ec ) {
|
if( ec ) {
|
||||||
char* msg = 0;
|
char* msg = 0;
|
||||||
ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
ec = libssh2_session_last_error( sshc.my->session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "libssh2_channel_exec failed: %s - %s", ec, msg );
|
FC_THROW_REPORT( "exec failed: ${message}", fc::value().set("message",msg).set("code",ec) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LIBSSH2_CHANNEL* detail::client_impl::open_channel( const fc::string& pty_type ) {
|
LIBSSH2_CHANNEL* detail::client_impl::open_channel( const fc::string& pty_type ) {
|
||||||
|
|
@ -869,7 +905,7 @@ namespace fc { namespace ssh {
|
||||||
ec = libssh2_session_last_error( session, &msg, 0, 0 );
|
ec = libssh2_session_last_error( session, &msg, 0, 0 );
|
||||||
}
|
}
|
||||||
if( !chan ) {
|
if( !chan ) {
|
||||||
FC_THROW_MSG( "libssh2_channel_open_session failed: %s - %s", ec, msg );
|
FC_THROW_REPORT( "libssh2_channel_open_session failed: ${message}", fc::value().set("message",msg).set("code",ec) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -882,10 +918,14 @@ namespace fc { namespace ssh {
|
||||||
if( 0 != ec ) {
|
if( 0 != ec ) {
|
||||||
char* msg;
|
char* msg;
|
||||||
ec = libssh2_session_last_error( session, &msg, 0, 0 );
|
ec = libssh2_session_last_error( session, &msg, 0, 0 );
|
||||||
FC_THROW_MSG( "libssh2_channel_req_pty failed: %s - %s", ec, msg );
|
FC_THROW_REPORT( "libssh2_channel_req_pty failed: ${message}", fc::value().set("message",msg).set("code",ec) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process& process::operator=( const process& p ) {
|
||||||
|
my = p.my;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue