aboutsummaryrefslogtreecommitdiff
path: root/include/libssh/libsshpp.hpp
blob: 7eea8c20ea5b5b39979e6327213a124079bb161a (plain)
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 * This file is part of the SSH Library
 *
 * Copyright (c) 2010 by Aris Adamantiadis
 *
 * The SSH Library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * The SSH Library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the SSH Library; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#ifndef LIBSSHPP_HPP_
#define LIBSSHPP_HPP_

/** @defgroup ssh_cpp libssh C++ wrapper
 * @addtogroup ssh_cpp
 * @{
 * The C++ bindings for libssh are completely embedded in a single .hpp file, and
 * this for two reasons:
 * - C++ is hard to keep binary compatible, C is easy. We try to keep libssh C version
 *   as much as possible binary compatible between releases, while this would be hard for
 *   C++. If you compile your program with these headers, you will only link to the C version
 *   of libssh which will be kept ABI compatible. No need to recompile your C++ program
 *   each time a new binary-compatible version of libssh is out
 * - Most of the functions in this file are really short and are probably worth the "inline"
 *   linking mode, which the compiler can decide to do in some case. There would be nearly no
 *   performance penalty of using the wrapper rather than native calls.
 */

#include <libssh/libssh.h>
#include <libssh/server.h>
namespace ssh {

/** @brief This class describes a SSH Exception object. This object can be throwed
 * by several SSH functions that interact with the network, and may fail because of
 * socket, protocol or memory errors.
 */
class SshException{
public:
  SshException(ssh_session csession){
    code=ssh_get_error_code(csession);
    description=ssh_get_error(csession);
  }
  SshException(const SshException &e){
    code=e.code;
    description=e.description;
  }
  /** @brief returns the Error code
   * @returns SSH_FATAL Fatal error happened (not recoverable)
   * @returns SSH_REQUEST_DENIED Request was denied by remote host
   * @see ssh_get_error_code
   */
  int getCode(){
    return code;
  }
  /** @brief returns the error message of the last exception
   * @returns pointer to a c string containing the description of error
   * @see ssh_get_error
   */
  const char *getError(){
    return description;
  }
private:
  int code;
  const char *description;
};

#define ssh_throw(x) if(x!=SSH_OK) throw SshException(getCSession());

/**
 * The ssh::Session class contains the state of a SSH connection.
 */
class Session {
  friend class Channel;
public:
  Session(){
    c_session=ssh_new();
  }
  ~Session(){
    ssh_free(c_session);
    c_session=NULL;
  }
  /** @brief sets an SSH session options
   * @param type Type of option
   * @param option cstring containing the value of option
   * @throws SshException on error
   * @see ssh_options_set
   */
  void setOption(enum ssh_options_e type, const char *option){
    ssh_throw(ssh_options_set(c_session,type,option));
  }
  /** @brief sets an SSH session options
   * @param type Type of option
   * @param option long integer containing the value of option
   * @throws SshException on error
   * @see ssh_options_set
   */
  void setOption(enum ssh_options_e type, long int option){
    ssh_throw(ssh_options_set(c_session,type,&option));
  }
  /** @brief sets an SSH session options
   * @param type Type of option
   * @param option void pointer containing the value of option
   * @throws SshException on error
   * @see ssh_options_set
   */
  void setOption(enum ssh_options_e type, void *option){
    ssh_throw(ssh_options_set(c_session,type,option));
  }
  /** @brief connects to the remote host
   * @throws SshException on error
   * @see ssh_connect
   */
  void connect(){
    int ret=ssh_connect(c_session);
    ssh_throw(ret);
  }
  /** @brief Authenticates automatically using public key
   * @throws SshException on error
   * @see ssh_userauth_autopubkey
   */
  int userauthAutopubkey(){
    int ret=ssh_userauth_autopubkey(c_session,NULL);
    if(ret==SSH_ERROR)
      ssh_throw(ret);
  }
  int userauthNone();
  int userauthPassword(const char *password);
  int userauthOfferPubkey(ssh_string pubkey);
  int userauthPubkey(ssh_string pubkey, ssh_private_key privkey);
  int userauthPubkey(ssh_private_key privkey);
  int userauthPrivatekeyFile(const char *filename, const char *passphrase);
  int getAuthList();
  int disconnect();
  const char *getDisconnectMessage();
  const char *getError();
  int getErrorCode();
  socket_t getSocket();
  const char *getIssueBanner();
  int getOpensshVersion();
  int getVersion();
  int isServerKnown();
  void log(int priority, const char *format, ...);
  void optionsCopy(const Session &source);
  void optionsParseConfig(const char *file);
  void silentDisconnect();
  int writeKnownhost();
private:
  ssh_session c_session;
  ssh_session getCSession(){
    return c_session;
  }
  /* No copy constructor, no = operator */
  Session(const Session &);
  Session& operator=(const Session &);
};

/** @brief the ssh::Channel class describes the state of an SSH
 * channel.
 * @see ssh_channel
 */
class Channel {
public:
  Channel(Session &session){
    channel=channel_new(session.getCSession());
    this->session=&session;
  }
  ~Channel(){
    channel_free(channel);
    channel=NULL;
  }
  int acceptX11(int timeout_ms);
  int changePtySize(int cols, int rows);
  int acceptForward(int timeout_ms);
  int close();
  int cancelForward(const char *address, int port);
  int listenForward(const char *address, int port, int &boundport);
  int getExitStatus();
  Session &getSession(){
    return *session;
  }
  int isClosed();
  int isEof();
  int isOpen();
  int openForward(const char *remotehost, int remoteport,
      const char *sourcehost=NULL, int localport=0);
  int openSession();
  int poll(bool is_stderr=false);
  int read(void *dest, size_t count, bool is_stderr=false);
  int readNonblocking(void *dest, size_t count, bool is_stderr=false);
  int requestEnv(const char *name, const char *value);
  int requestExec(const char *cmd);
  int requestPty(const char *term=NULL, int cols=0, int rows=0);
  int requestShell();
  int requestSendSignal(const char *signum);
  int requestSubsystem(const char *subsystem);
  int requestX11(bool single_connection, const char *protocol, const char *cookie,
      int screen_number);
  int sendEof();
  /** @brief Writes on a channel
   * @param data data to write.
   * @param len number of bytes to write.
   * @param is_stderr write should be done on the stderr channel (server only)
   * @returns number of bytes written
   * @throws SshException in case of error
   * @see channel_write
   * @see channel_write_stderr
   */
  int write(const void *data, size_t len, bool is_stderr=false){
    int ret;
    if(is_stderr){
      ret=channel_write_stderr(channel,data,len);
    } else {
      ret=channel_write(channel,data,len);
    }
    if(ret==SSH_ERROR)
      ssh_throw(ret);
    return ret;
  }
private:
  ssh_session getCSession(){
    return session->getCSession();
  }
  Session *session;
  ssh_channel channel;
  /* No copy and no = operator */
  Channel(const Channel &);
  Channel &operator=(const Channel &);
};

} // namespace ssh
/** @}
 */
#endif /* LIBSSHPP_HPP_ */