libssh  0.5.4
libsshpp.hpp
1 /*
2  * This file is part of the SSH Library
3  *
4  * Copyright (c) 2010 by Aris Adamantiadis
5  *
6  * The SSH Library is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or (at your
9  * option) any later version.
10  *
11  * The SSH Library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14  * License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with the SSH Library; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19  * MA 02111-1307, USA.
20  */
21 
22 #ifndef LIBSSHPP_HPP_
23 #define LIBSSHPP_HPP_
24 
52 /* do not use deprecated functions */
53 #define LIBSSH_LEGACY_0_4
54 
55 #include <libssh/libssh.h>
56 #include <libssh/server.h>
57 #include <stdlib.h>
58 #include <stdarg.h>
59 #include <stdio.h>
60 
61 namespace ssh {
62 
63 class Channel;
68 #ifndef SSH_NO_CPP_EXCEPTIONS
69 
75 public:
76  SshException(ssh_session csession){
77  code=ssh_get_error_code(csession);
78  description=std::string(ssh_get_error(csession));
79  }
80  SshException(const SshException &e){
81  code=e.code;
82  description=e.description;
83  }
89  int getCode(){
90  return code;
91  }
96  std::string getError(){
97  return description;
98  }
99 private:
100  int code;
101  std::string description;
102 };
103 
107 #define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession())
108 #define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession)
109 #define void_throwable void
110 #define return_throwable return
111 
112 #else
113 
114 /* No exception at all. All functions will return an error code instead
115  * of an exception
116  */
117 #define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR
118 #define ssh_throw_null(CSession,x) if((x)==NULL) return NULL
119 #define void_throwable int
120 #define return_throwable return SSH_OK
121 #endif
122 
126 class Session {
127  friend class Channel;
128 public:
129  Session(){
130  c_session=ssh_new();
131  }
132  ~Session(){
133  ssh_free(c_session);
134  c_session=NULL;
135  }
142  void_throwable setOption(enum ssh_options_e type, const char *option){
143  ssh_throw(ssh_options_set(c_session,type,option));
144  return_throwable;
145  }
152  void_throwable setOption(enum ssh_options_e type, long int option){
153  ssh_throw(ssh_options_set(c_session,type,&option));
154  return_throwable;
155  }
162  void_throwable setOption(enum ssh_options_e type, void *option){
163  ssh_throw(ssh_options_set(c_session,type,option));
164  return_throwable;
165  }
170  void_throwable connect(){
171  int ret=ssh_connect(c_session);
172  ssh_throw(ret);
173  return_throwable;
174  }
181  int ret=ssh_userauth_autopubkey(c_session,NULL);
182  ssh_throw(ret);
183  return ret;
184  }
193  int ret=ssh_userauth_none(c_session,NULL);
194  ssh_throw(ret);
195  return ret;
196  }
203  int userauthPassword(const char *password){
204  int ret=ssh_userauth_password(c_session,NULL,password);
205  ssh_throw(ret);
206  return ret;
207  }
216  int userauthOfferPubkey(int type, ssh_string pubkey){
217  int ret=ssh_userauth_offer_pubkey(c_session,NULL,type,pubkey);
218  ssh_throw(ret);
219  return ret;
220  }
228  int userauthPubkey(ssh_string pubkey, ssh_private_key privkey){
229  int ret=ssh_userauth_pubkey(c_session,NULL,pubkey,privkey);
230  ssh_throw(ret);
231  return ret;
232  }
233  int userauthPubkey(ssh_private_key privkey){
234  int ret=ssh_userauth_pubkey(c_session,NULL,NULL,privkey);
235  ssh_throw(ret);
236  return ret;
237  }
238  int userauthPrivatekeyFile(const char *filename,
239  const char *passphrase);
245  int getAuthList(){
246  int ret=ssh_userauth_list(c_session, NULL);
247  ssh_throw(ret);
248  return ret;
249  }
253  void disconnect(){
254  ssh_disconnect(c_session);
255  }
260  const char *getDisconnectMessage(){
261  const char *msg=ssh_get_disconnect_message(c_session);
262  return msg;
263  }
267  const char *getError(){
268  return ssh_get_error(c_session);
269  }
273  int getErrorCode(){
274  return ssh_get_error_code(c_session);
275  }
282  socket_t getSocket(){
283  return ssh_get_fd(c_session);
284  }
289  std::string getIssueBanner(){
290  char *banner=ssh_get_issue_banner(c_session);
291  std::string ret= std::string(banner);
292  ::free(banner);
293  return ret;
294  }
300  return ssh_get_openssh_version(c_session);
301  }
306  int getVersion(){
307  return ssh_get_version(c_session);
308  }
316  int ret=ssh_is_server_known(c_session);
317  ssh_throw(ret);
318  return ret;
319  }
320  void log(int priority, const char *format, ...){
321  char buffer[1024];
322  va_list va;
323 
324  va_start(va, format);
325  vsnprintf(buffer, sizeof(buffer), format, va);
326  va_end(va);
327  ssh_log(c_session,priority, "%s", buffer);
328  }
329 
334  void_throwable optionsCopy(const Session &source){
335  ssh_throw(ssh_options_copy(source.c_session,&c_session));
336  return_throwable;
337  }
343  void_throwable optionsParseConfig(const char *file){
344  ssh_throw(ssh_options_parse_config(c_session,file));
345  return_throwable;
346  }
351  ssh_silent_disconnect(c_session);
352  }
359  int ret = ssh_write_knownhost(c_session);
360  ssh_throw(ret);
361  return ret;
362  }
363 
372  Channel *acceptForward(int timeout_ms);
373  /* acceptForward is implemented later in this file */
374 
375  void_throwable cancelForward(const char *address, int port){
376  int err=ssh_forward_cancel(c_session, address, port);
377  ssh_throw(err);
378  return_throwable;
379  }
380 
381  void_throwable listenForward(const char *address, int port,
382  int &boundport){
383  int err=ssh_forward_listen(c_session, address, port, &boundport);
384  ssh_throw(err);
385  return_throwable;
386  }
387 
388 private:
389  ssh_session c_session;
390  ssh_session getCSession(){
391  return c_session;
392  }
393  /* No copy constructor, no = operator */
394  Session(const Session &);
395  Session& operator=(const Session &);
396 };
397 
402 class Channel {
403  friend class Session;
404 public:
405  Channel(Session &session){
406  channel=ssh_channel_new(session.getCSession());
407  this->session=&session;
408  }
409  ~Channel(){
410  ssh_channel_free(channel);
411  channel=NULL;
412  }
413 
422  Channel *acceptX11(int timeout_ms){
423  ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms);
424  ssh_throw_null(getCSession(),x11chan);
425  Channel *newchan = new Channel(getSession(),x11chan);
426  return newchan;
427  }
434  void_throwable changePtySize(int cols, int rows){
435  int err=ssh_channel_change_pty_size(channel,cols,rows);
436  ssh_throw(err);
437  return_throwable;
438  }
439 
444  void_throwable close(){
445  ssh_throw(ssh_channel_close(channel));
446  return_throwable;
447  }
448 
449  int getExitStatus(){
450  return ssh_channel_get_exit_status(channel);
451  }
452  Session &getSession(){
453  return *session;
454  }
458  bool isClosed(){
459  return ssh_channel_is_closed(channel) != 0;
460  }
464  bool isEof(){
465  return ssh_channel_is_eof(channel) != 0;
466  }
470  bool isOpen(){
471  return ssh_channel_is_open(channel) != 0;
472  }
473  int openForward(const char *remotehost, int remoteport,
474  const char *sourcehost=NULL, int localport=0){
475  int err=ssh_channel_open_forward(channel,remotehost,remoteport,
476  sourcehost, localport);
477  ssh_throw(err);
478  return err;
479  }
480  /* TODO: completely remove this ? */
481  void_throwable openSession(){
482  int err=ssh_channel_open_session(channel);
483  ssh_throw(err);
484  return_throwable;
485  }
486  int poll(bool is_stderr=false){
487  int err=ssh_channel_poll(channel,is_stderr);
488  ssh_throw(err);
489  return err;
490  }
491  int read(void *dest, size_t count, bool is_stderr=false){
492  int err;
493  /* handle int overflow */
494  if(count > 0x7fffffff)
495  count = 0x7fffffff;
496  err=ssh_channel_read(channel,dest,count,is_stderr);
497  ssh_throw(err);
498  return err;
499  }
500  int readNonblocking(void *dest, size_t count, bool is_stderr=false){
501  int err;
502  /* handle int overflow */
503  if(count > 0x7fffffff)
504  count = 0x7fffffff;
505  err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr);
506  ssh_throw(err);
507  return err;
508  }
509  void_throwable requestEnv(const char *name, const char *value){
510  int err=ssh_channel_request_env(channel,name,value);
511  ssh_throw(err);
512  return_throwable;
513  }
514 
515  void_throwable requestExec(const char *cmd){
516  int err=ssh_channel_request_exec(channel,cmd);
517  ssh_throw(err);
518  return_throwable;
519  }
520  void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
521  int err;
522  if(term != NULL && cols != 0 && rows != 0)
523  err=ssh_channel_request_pty_size(channel,term,cols,rows);
524  else
525  err=ssh_channel_request_pty(channel);
526  ssh_throw(err);
527  return_throwable;
528  }
529 
530  void_throwable requestShell(){
531  int err=ssh_channel_request_shell(channel);
532  ssh_throw(err);
533  return_throwable;
534  }
535  void_throwable requestSendSignal(const char *signum){
536  int err=ssh_channel_request_send_signal(channel, signum);
537  ssh_throw(err);
538  return_throwable;
539  }
540  void_throwable requestSubsystem(const char *subsystem){
541  int err=ssh_channel_request_subsystem(channel,subsystem);
542  ssh_throw(err);
543  return_throwable;
544  }
545  int requestX11(bool single_connection,
546  const char *protocol, const char *cookie, int screen_number){
547  int err=ssh_channel_request_x11(channel,single_connection,
548  protocol, cookie, screen_number);
549  ssh_throw(err);
550  return err;
551  }
552  void_throwable sendEof(){
553  int err=ssh_channel_send_eof(channel);
554  ssh_throw(err);
555  return_throwable;
556  }
566  int write(const void *data, size_t len, bool is_stderr=false){
567  int ret;
568  if(is_stderr){
569  ret=ssh_channel_write_stderr(channel,data,len);
570  } else {
571  ret=ssh_channel_write(channel,data,len);
572  }
573  ssh_throw(ret);
574  return ret;
575  }
576 private:
577  ssh_session getCSession(){
578  return session->getCSession();
579  }
580  Channel (Session &session, ssh_channel c_channel){
581  this->channel=c_channel;
582  this->session=&session;
583  }
584  Session *session;
585  ssh_channel channel;
586  /* No copy and no = operator */
587  Channel(const Channel &);
588  Channel &operator=(const Channel &);
589 };
590 
591 
592 /* This code cannot be put inline due to references to Channel */
594  ssh_channel forward = ssh_forward_accept(c_session,
595  timeout_ms);
596  ssh_throw_null(c_session,forward);
597  Channel *newchan = new Channel(*this,forward);
598  return newchan;
599  }
600 
601 } // namespace ssh
602 
604 #endif /* LIBSSHPP_HPP_ */