#ifndef LIBSSHPP_HPP_
#define LIBSSHPP_HPP_
#define LIBSSH_LEGACY_0_4
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string>
namespace ssh {
class Channel;
#ifndef SSH_NO_CPP_EXCEPTIONS
class SshException{
public:
SshException(ssh_session csession){
code=ssh_get_error_code(csession);
description=std::string(ssh_get_error(csession));
}
SshException(const SshException &e){
code=e.code;
description=e.description;
}
int getCode(){
return code;
}
std::string getError(){
return description;
}
private:
int code;
std::string description;
};
#define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession())
#define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession)
#define void_throwable void
#define return_throwable return
#else
#define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR
#define ssh_throw_null(CSession,x) if((x)==NULL) return NULL
#define void_throwable int
#define return_throwable return SSH_OK
#endif
class Session {
friend class Channel;
public:
Session(){
c_session=ssh_new();
}
~Session(){
ssh_free(c_session);
c_session=NULL;
}
void_throwable setOption(enum ssh_options_e type, const char *option){
ssh_throw(ssh_options_set(c_session,type,option));
return_throwable;
}
void_throwable setOption(enum ssh_options_e type, long int option){
ssh_throw(ssh_options_set(c_session,type,&option));
return_throwable;
}
void_throwable setOption(enum ssh_options_e type, void *option){
ssh_throw(ssh_options_set(c_session,type,option));
return_throwable;
}
void_throwable connect(){
int ret=ssh_connect(c_session);
ssh_throw(ret);
return_throwable;
}
int userauthPublickeyAuto(void){
int ret=ssh_userauth_publickey_auto(c_session, NULL, NULL);
ssh_throw(ret);
return ret;
}
int userauthNone(){
int ret=ssh_userauth_none(c_session,NULL);
ssh_throw(ret);
return ret;
}
int userauthKbdint(const char* username, const char* submethods){
int ret = ssh_userauth_kbdint(c_session, username, submethods);
ssh_throw(ret);
return ret;
}
int userauthKbdintGetNPrompts(){
return ssh_userauth_kbdint_getnprompts(c_session);
}
int userauthKbdintSetAnswer(unsigned int index, const char *answer)
{
int ret = ssh_userauth_kbdint_setanswer(c_session, index, answer);
ssh_throw(ret);
return ret;
}
int userauthPassword(const char *password){
int ret=ssh_userauth_password(c_session,NULL,password);
ssh_throw(ret);
return ret;
}
int userauthTryPublickey(ssh_key pubkey){
int ret=ssh_userauth_try_publickey(c_session, NULL, pubkey);
ssh_throw(ret);
return ret;
}
int userauthPublickey(ssh_key privkey){
int ret=ssh_userauth_publickey(c_session, NULL, privkey);
ssh_throw(ret);
return ret;
}
int getAuthList(){
int ret=ssh_userauth_list(c_session, NULL);
ssh_throw(ret);
return ret;
}
void disconnect(){
ssh_disconnect(c_session);
}
const char *getDisconnectMessage(){
const char *msg=ssh_get_disconnect_message(c_session);
return msg;
}
const char *getError(){
return ssh_get_error(c_session);
}
int getErrorCode(){
return ssh_get_error_code(c_session);
}
socket_t getSocket(){
return ssh_get_fd(c_session);
}
std::string getIssueBanner(){
char *banner = ssh_get_issue_banner(c_session);
std::string ret = "";
if (banner != NULL) {
ret = std::string(banner);
::free(banner);
}
return ret;
}
int getOpensshVersion(){
return ssh_get_openssh_version(c_session);
}
int getVersion(){
return ssh_get_version(c_session);
}
int isServerKnown(){
int state = ssh_session_is_known_server(c_session);
ssh_throw(state);
return state;
}
void log(int priority, const char *format, ...){
va_list va;
va_start(va, format);
ssh_vlog(priority, "libsshpp", format, &va);
va_end(va);
}
void_throwable optionsCopy(const Session &source){
ssh_throw(ssh_options_copy(source.c_session,&c_session));
return_throwable;
}
void_throwable optionsParseConfig(const char *file){
ssh_throw(ssh_options_parse_config(c_session,file));
return_throwable;
}
void silentDisconnect(){
ssh_silent_disconnect(c_session);
}
int writeKnownhost(){
int ret = ssh_session_update_known_hosts(c_session);
ssh_throw(ret);
return ret;
}
inline Channel *acceptForward(int timeout_ms);
void_throwable cancelForward(const char *address, int port){
int err=ssh_channel_cancel_forward(c_session, address, port);
ssh_throw(err);
return_throwable;
}
void_throwable listenForward(const char *address, int port,
int &boundport){
int err=ssh_channel_listen_forward(c_session, address, port, &boundport);
ssh_throw(err);
return_throwable;
}
ssh_session getCSession(){
return c_session;
}
protected:
ssh_session c_session;
private:
Session(const Session &);
Session& operator=(const Session &);
};
class Channel {
friend class Session;
public:
Channel(Session &ssh_session){
channel = ssh_channel_new(ssh_session.getCSession());
this->session = &ssh_session;
}
~Channel(){
ssh_channel_free(channel);
channel=NULL;
}
Channel *acceptX11(int timeout_ms){
ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms);
ssh_throw_null(getCSession(),x11chan);
Channel *newchan = new Channel(getSession(),x11chan);
return newchan;
}
void_throwable changePtySize(int cols, int rows){
int err=ssh_channel_change_pty_size(channel,cols,rows);
ssh_throw(err);
return_throwable;
}
void_throwable close(){
ssh_throw(ssh_channel_close(channel));
return_throwable;
}
int getExitStatus(){
return ssh_channel_get_exit_status(channel);
}
Session &getSession(){
return *session;
}
bool isClosed(){
return ssh_channel_is_closed(channel) != 0;
}
bool isEof(){
return ssh_channel_is_eof(channel) != 0;
}
bool isOpen(){
return ssh_channel_is_open(channel) != 0;
}
int openForward(const char *remotehost, int remoteport,
const char *sourcehost=NULL, int localport=0){
int err=ssh_channel_open_forward(channel,remotehost,remoteport,
sourcehost, localport);
ssh_throw(err);
return err;
}
void_throwable openSession(){
int err=ssh_channel_open_session(channel);
ssh_throw(err);
return_throwable;
}
int poll(bool is_stderr=false){
int err=ssh_channel_poll(channel,is_stderr);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count){
int err;
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_timeout(channel,dest,count,false,-1);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, int timeout){
int err;
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_timeout(channel,dest,count,false,timeout);
ssh_throw(err);
return err;
}
int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){
int err;
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_timeout(channel,dest,count,is_stderr,timeout);
ssh_throw(err);
return err;
}
int readNonblocking(void *dest, size_t count, bool is_stderr=false){
int err;
if(count > 0x7fffffff)
count = 0x7fffffff;
err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr);
ssh_throw(err);
return err;
}
void_throwable requestEnv(const char *name, const char *value){
int err=ssh_channel_request_env(channel,name,value);
ssh_throw(err);
return_throwable;
}
void_throwable requestExec(const char *cmd){
int err=ssh_channel_request_exec(channel,cmd);
ssh_throw(err);
return_throwable;
}
void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
int err;
if(term != NULL && cols != 0 && rows != 0)
err=ssh_channel_request_pty_size(channel,term,cols,rows);
else
err=ssh_channel_request_pty(channel);
ssh_throw(err);
return_throwable;
}
void_throwable requestShell(){
int err=ssh_channel_request_shell(channel);
ssh_throw(err);
return_throwable;
}
void_throwable requestSendSignal(const char *signum){
int err=ssh_channel_request_send_signal(channel, signum);
ssh_throw(err);
return_throwable;
}
void_throwable requestSubsystem(const char *subsystem){
int err=ssh_channel_request_subsystem(channel,subsystem);
ssh_throw(err);
return_throwable;
}
int requestX11(bool single_connection,
const char *protocol, const char *cookie, int screen_number){
int err=ssh_channel_request_x11(channel,single_connection,
protocol, cookie, screen_number);
ssh_throw(err);
return err;
}
void_throwable sendEof(){
int err=ssh_channel_send_eof(channel);
ssh_throw(err);
return_throwable;
}
int write(const void *data, size_t len, bool is_stderr=false){
int ret;
if(is_stderr){
ret=ssh_channel_write_stderr(channel,data,len);
} else {
ret=ssh_channel_write(channel,data,len);
}
ssh_throw(ret);
return ret;
}
ssh_session getCSession(){
return session->getCSession();
}
ssh_channel getCChannel() {
return channel;
}
protected:
Session *session;
ssh_channel channel;
private:
Channel (Session &ssh_session, ssh_channel c_channel){
this->channel=c_channel;
this->session = &ssh_session;
}
Channel(const Channel &);
Channel &operator=(const Channel &);
};
inline Channel *Session::acceptForward(int timeout_ms){
ssh_channel forward =
ssh_channel_accept_forward(c_session, timeout_ms, NULL);
ssh_throw_null(c_session,forward);
Channel *newchan = new Channel(*this,forward);
return newchan;
}
}
#endif