libssh  0.6.3
libsshpp.hpp
1 /*
2  * This file is part of the SSH Library
3  *
4  * Copyright (c) 2010 by Aris Adamantiadis
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef LIBSSHPP_HPP_
22 #define LIBSSHPP_HPP_
23 
51 /* do not use deprecated functions */
52 #define LIBSSH_LEGACY_0_4
53 
54 #include <libssh/libssh.h>
55 #include <libssh/server.h>
56 #include <stdlib.h>
57 #include <stdarg.h>
58 #include <stdio.h>
59 
60 namespace ssh {
61 
62 class Channel;
67 #ifndef SSH_NO_CPP_EXCEPTIONS
68 
74 public:
75  SshException(ssh_session csession){
76  code=ssh_get_error_code(csession);
77  description=std::string(ssh_get_error(csession));
78  }
79  SshException(const SshException &e){
80  code=e.code;
81  description=e.description;
82  }
88  int getCode(){
89  return code;
90  }
95  std::string getError(){
96  return description;
97  }
98 private:
99  int code;
100  std::string description;
101 };
102 
106 #define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession())
107 #define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession)
108 #define void_throwable void
109 #define return_throwable return
110 
111 #else
112 
113 /* No exception at all. All functions will return an error code instead
114  * of an exception
115  */
116 #define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR
117 #define ssh_throw_null(CSession,x) if((x)==NULL) return NULL
118 #define void_throwable int
119 #define return_throwable return SSH_OK
120 #endif
121 
125 class Session {
126  friend class Channel;
127 public:
128  Session(){
129  c_session=ssh_new();
130  }
131  ~Session(){
132  ssh_free(c_session);
133  c_session=NULL;
134  }
141  void_throwable setOption(enum ssh_options_e type, const char *option){
142  ssh_throw(ssh_options_set(c_session,type,option));
143  return_throwable;
144  }
151  void_throwable setOption(enum ssh_options_e type, long int option){
152  ssh_throw(ssh_options_set(c_session,type,&option));
153  return_throwable;
154  }
161  void_throwable setOption(enum ssh_options_e type, void *option){
162  ssh_throw(ssh_options_set(c_session,type,option));
163  return_throwable;
164  }
169  void_throwable connect(){
170  int ret=ssh_connect(c_session);
171  ssh_throw(ret);
172  return_throwable;
173  }
180  int ret=ssh_userauth_publickey_auto(c_session, NULL, NULL);
181  ssh_throw(ret);
182  return ret;
183  }
192  int ret=ssh_userauth_none(c_session,NULL);
193  ssh_throw(ret);
194  return ret;
195  }
202  int userauthPassword(const char *password){
203  int ret=ssh_userauth_password(c_session,NULL,password);
204  ssh_throw(ret);
205  return ret;
206  }
214  int userauthTryPublickey(ssh_key pubkey){
215  int ret=ssh_userauth_try_publickey(c_session, NULL, pubkey);
216  ssh_throw(ret);
217  return ret;
218  }
225  int userauthPublickey(ssh_key privkey){
226  int ret=ssh_userauth_publickey(c_session, NULL, privkey);
227  ssh_throw(ret);
228  return ret;
229  }
230  int userauthPrivatekeyFile(const char *filename,
231  const char *passphrase);
237  int getAuthList(){
238  int ret=ssh_userauth_list(c_session, NULL);
239  ssh_throw(ret);
240  return ret;
241  }
245  void disconnect(){
246  ssh_disconnect(c_session);
247  }
252  const char *getDisconnectMessage(){
253  const char *msg=ssh_get_disconnect_message(c_session);
254  return msg;
255  }
259  const char *getError(){
260  return ssh_get_error(c_session);
261  }
265  int getErrorCode(){
266  return ssh_get_error_code(c_session);
267  }
274  socket_t getSocket(){
275  return ssh_get_fd(c_session);
276  }
281  std::string getIssueBanner(){
282  char *banner=ssh_get_issue_banner(c_session);
283  std::string ret= std::string(banner);
284  ::free(banner);
285  return ret;
286  }
292  return ssh_get_openssh_version(c_session);
293  }
298  int getVersion(){
299  return ssh_get_version(c_session);
300  }
308  int ret=ssh_is_server_known(c_session);
309  ssh_throw(ret);
310  return ret;
311  }
312  void log(int priority, const char *format, ...){
313  char buffer[1024];
314  va_list va;
315 
316  va_start(va, format);
317  vsnprintf(buffer, sizeof(buffer), format, va);
318  va_end(va);
319  _ssh_log(priority, "libsshpp", "%s", buffer);
320  }
321 
326  void_throwable optionsCopy(const Session &source){
327  ssh_throw(ssh_options_copy(source.c_session,&c_session));
328  return_throwable;
329  }
335  void_throwable optionsParseConfig(const char *file){
336  ssh_throw(ssh_options_parse_config(c_session,file));
337  return_throwable;
338  }
343  ssh_silent_disconnect(c_session);
344  }
351  int ret = ssh_write_knownhost(c_session);
352  ssh_throw(ret);
353  return ret;
354  }
355 
364  Channel *acceptForward(int timeout_ms);
365  /* acceptForward is implemented later in this file */
366 
367  void_throwable cancelForward(const char *address, int port){
368  int err=ssh_forward_cancel(c_session, address, port);
369  ssh_throw(err);
370  return_throwable;
371  }
372 
373  void_throwable listenForward(const char *address, int port,
374  int &boundport){
375  int err=ssh_forward_listen(c_session, address, port, &boundport);
376  ssh_throw(err);
377  return_throwable;
378  }
379 
380 private:
381  ssh_session c_session;
382  ssh_session getCSession(){
383  return c_session;
384  }
385  /* No copy constructor, no = operator */
386  Session(const Session &);
387  Session& operator=(const Session &);
388 };
389 
394 class Channel {
395  friend class Session;
396 public:
397  Channel(Session &session){
398  channel=ssh_channel_new(session.getCSession());
399  this->session=&session;
400  }
401  ~Channel(){
402  ssh_channel_free(channel);
403  channel=NULL;
404  }
405 
414  Channel *acceptX11(int timeout_ms){
415  ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms);
416  ssh_throw_null(getCSession(),x11chan);
417  Channel *newchan = new Channel(getSession(),x11chan);
418  return newchan;
419  }
426  void_throwable changePtySize(int cols, int rows){
427  int err=ssh_channel_change_pty_size(channel,cols,rows);
428  ssh_throw(err);
429  return_throwable;
430  }
431 
436  void_throwable close(){
437  ssh_throw(ssh_channel_close(channel));
438  return_throwable;
439  }
440 
441  int getExitStatus(){
442  return ssh_channel_get_exit_status(channel);
443  }
444  Session &getSession(){
445  return *session;
446  }
450  bool isClosed(){
451  return ssh_channel_is_closed(channel) != 0;
452  }
456  bool isEof(){
457  return ssh_channel_is_eof(channel) != 0;
458  }
462  bool isOpen(){
463  return ssh_channel_is_open(channel) != 0;
464  }
465  int openForward(const char *remotehost, int remoteport,
466  const char *sourcehost=NULL, int localport=0){
467  int err=ssh_channel_open_forward(channel,remotehost,remoteport,
468  sourcehost, localport);
469  ssh_throw(err);
470  return err;
471  }
472  /* TODO: completely remove this ? */
473  void_throwable openSession(){
474  int err=ssh_channel_open_session(channel);
475  ssh_throw(err);
476  return_throwable;
477  }
478  int poll(bool is_stderr=false){
479  int err=ssh_channel_poll(channel,is_stderr);
480  ssh_throw(err);
481  return err;
482  }
483  int read(void *dest, size_t count, bool is_stderr=false){
484  int err;
485  /* handle int overflow */
486  if(count > 0x7fffffff)
487  count = 0x7fffffff;
488  err=ssh_channel_read(channel,dest,count,is_stderr);
489  ssh_throw(err);
490  return err;
491  }
492  int readNonblocking(void *dest, size_t count, bool is_stderr=false){
493  int err;
494  /* handle int overflow */
495  if(count > 0x7fffffff)
496  count = 0x7fffffff;
497  err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr);
498  ssh_throw(err);
499  return err;
500  }
501  void_throwable requestEnv(const char *name, const char *value){
502  int err=ssh_channel_request_env(channel,name,value);
503  ssh_throw(err);
504  return_throwable;
505  }
506 
507  void_throwable requestExec(const char *cmd){
508  int err=ssh_channel_request_exec(channel,cmd);
509  ssh_throw(err);
510  return_throwable;
511  }
512  void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){
513  int err;
514  if(term != NULL && cols != 0 && rows != 0)
515  err=ssh_channel_request_pty_size(channel,term,cols,rows);
516  else
517  err=ssh_channel_request_pty(channel);
518  ssh_throw(err);
519  return_throwable;
520  }
521 
522  void_throwable requestShell(){
523  int err=ssh_channel_request_shell(channel);
524  ssh_throw(err);
525  return_throwable;
526  }
527  void_throwable requestSendSignal(const char *signum){
528  int err=ssh_channel_request_send_signal(channel, signum);
529  ssh_throw(err);
530  return_throwable;
531  }
532  void_throwable requestSubsystem(const char *subsystem){
533  int err=ssh_channel_request_subsystem(channel,subsystem);
534  ssh_throw(err);
535  return_throwable;
536  }
537  int requestX11(bool single_connection,
538  const char *protocol, const char *cookie, int screen_number){
539  int err=ssh_channel_request_x11(channel,single_connection,
540  protocol, cookie, screen_number);
541  ssh_throw(err);
542  return err;
543  }
544  void_throwable sendEof(){
545  int err=ssh_channel_send_eof(channel);
546  ssh_throw(err);
547  return_throwable;
548  }
558  int write(const void *data, size_t len, bool is_stderr=false){
559  int ret;
560  if(is_stderr){
561  ret=ssh_channel_write_stderr(channel,data,len);
562  } else {
563  ret=ssh_channel_write(channel,data,len);
564  }
565  ssh_throw(ret);
566  return ret;
567  }
568 private:
569  ssh_session getCSession(){
570  return session->getCSession();
571  }
572  Channel (Session &session, ssh_channel c_channel){
573  this->channel=c_channel;
574  this->session=&session;
575  }
576  Session *session;
577  ssh_channel channel;
578  /* No copy and no = operator */
579  Channel(const Channel &);
580  Channel &operator=(const Channel &);
581 };
582 
583 
584 /* This code cannot be put inline due to references to Channel */
586  ssh_channel forward = ssh_forward_accept(c_session,
587  timeout_ms);
588  ssh_throw_null(c_session,forward);
589  Channel *newchan = new Channel(*this,forward);
590  return newchan;
591  }
592 
593 } // namespace ssh
594 
596 #endif /* LIBSSHPP_HPP_ */