session.hh 8.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#ifndef RSM_RSMCORE_SESSION_HH_
#define RSM_RSMCORE_SESSION_HH_

#include <QObject>

#include "rsmcore/declspec.hh"
#include "rsmcore/sessionlog.hh"

namespace rsm
{
enum class SessionAuthState
{
  SUCCESS = 0,
  DENIED,
  PARTIAL,
  INFO,
  AGAIN,
18
  ERROR_STATE = -1
19 20
};

21 22 23 24 25 26 27
#define SessionAuthMethodUNKNOWN 0x0000u
#define SessionAuthMethodNONE 0x0001u
#define SessionAuthMethodPASSWORD 0x0002u
#define SessionAuthMethodPUBLICKEY 0x0004u
#define SessionAuthMethodHOSTBASED 0x0008u
#define SessionAuthMethodINTERACTIVE 0x0010u
#define SessionAuthMethodGSSAPI_MIC 0x0020u
28 29 30 31 32 33 34 35

/**
 * @brief The SessionHostState enum
 */
enum class SessionHostState
{ /**
   * There had been an error checking the host.
   */
36
  ERROR_STATE = -2,
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

  /**
   * The known host file does not exist. The host is thus unknown. File will
   * be created if host key is accepted.
   */
  NOT_FOUND = -1,

  /**
   * The server is unknown. User should confirm the public key hash is
   * correct.
   */
  UNKNOWN = 0,

  /**
   * The server is known and has not changed.
   */
  OK,

  /**
   * The server key has changed. Either you are under attack or the
   * administrator changed the key. You HAVE to warn the user about a
   * possible attack.
   */
  CHANGED,

  /**
   * The server gave use a key of a type while we had another type recorded.
   * It is a possible attack.
   */
  OTHER,
};

/** Forward declaration of private implementation */
class ChannelImpl;
class SessionImpl;
class Session;
73 74 75 76 77 78
class SFTPSessionImpl;
class SFTPSession;
class SFTPFileImpl;
class SFTPFile;
class SFTPDirImpl;
class SFTPDir;
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

class RSM_PUBLIC Channel
{
 protected:
  // Private implementation
  ChannelImpl* p;

  // constructor is protected to only be used by "friend Session"
  Channel();

 public:
  ~Channel();
  /**
   * @brief open Opens the channel for execution
   * @return
   */
  bool open();
  /**
   * @brief isOpen Checks if the channel is open for execution
   * @return
   */
  bool isOpen() const;

  /**
   * @brief close Close channel of execution
   * Channel is no longer usable
   * @return
   */
  void close();

  /**
   * @brief exec Execute command on remote system
   * @param command
   * @return true on success, false on failure
   */
  bool exec(QString command);

  /**
   * @brief readExecOut Read execution's standard output
   * @return
   */
  QString readExecOut();
  /**
   * @brief readExecErr Read execution's standard error
   * @return
   */
  QString readExecErr();

  friend Session;
};  // class Channel

class RSM_PUBLIC Session
{
 private:
  // Private implementation
  SessionImpl* p;

 public:
  /**
   * Basic Constructor
   */
  Session();
  /**
   * Contructs with host name
   */
  Session(QString host);
  ~Session();

  /**
   * Set the remote host to connect to
   */
  void setHost(QString host);
  /**
   * @brief host Get the host name of the session
   */
154
  QString host() const;
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
  /**
   * Set the Log verbosity
   */
  void setLogVerbosity(SessionVerbosity level);
  /**
   * Set the ssh port number
   */
  void setPort(int port);
  /**
   * Set the user
   * Defaults to system user
   */
  void setUser(QString name);

  /**
   * @brief user get the username
   * @return
   */
173
  QString user() const;
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

  /**
   * Set the proxy command
   * @param command
   */
  void setProxyCommand(QString command);
  /**
   * Perform hand-shake to connect to host.
   */
  bool connect();

  /**
   * @brief isConnected Checks if session is currently connected
   * @return
   */
  bool isConnected() const;

  /**
   * @brief getError Retrieve error message
   * @return
   */
195
  QString getError() const;
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 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
  /**
   * Disconnect ssh session
   */
  bool disconnect();

  /**
   * @brief getHexa Retrieve public key hash hexa
   * Returns empty string on error
   * @return QString
   */
  QString getHexa() const;
  /**
   * Perform known host verification.
   * Checks known_host file to validate remote host SHA
   */
  SessionHostState verifyKnownHost() const;
  /**
   * @brief updateKnownHosts Updates the known host file
   * @return true on success, false on failure.
   */
  bool updateKnownHosts();

  /**
   * @brief authenticationMethodList Get the list of authentication methods
   *
   * UNKNOWN
   * NONE
   * PASSWORD
   * PUBLICKEY
   * HOSTBASED
   * INTERACTIVE
   * GSSAPI_MIC
   * @return
   */
  int authenticationMethodList() const;

  /**
   * @brief authenticateWithPublicKey Attempt authentication using public key
   * @return Authentication state
   * SUCCESS = 0,
   * DENIED,
   * PARTIAL,
   * INFO,
   * AGAIN,
   * ERROR = -1
   */
  SessionAuthState authenticateWithPublicKey();

  /**
   * @brief authenticateInteractively Attempt interactive keyboard
   * authentication (multiple prompts)
   * @return Authentication state
   * SUCCESS = 0,
   * DENIED,
   * PARTIAL,
   * INFO,
   * AGAIN,
   * ERROR = -1
   */
  SessionAuthState authenticateInteractively();

  /**
   * @brief keyboardInteractiveName Get name of interactive authentication
   * @return QString
   */
  QString keyboardInteractiveName() const;
  /**
   * @brief keyboardInteractiveInstruction Get instruction for interactive
   * authentication
   * @return QString
   */
  QString keyboardInteractiveInstruction() const;
  /**
   * @brief keyboardInteractivePrompts Get prompts for interactive
   * authentication
   * @return QStringList
   */
  QStringList keyboardInteractivePrompts() const;

  /**
   * @brief authenticateWithPassword Attempt password authentication
   * @return Authentication state
   * SUCCESS = 0,
   * DENIED,
   * PARTIAL,
   * INFO,
   * AGAIN,
   * ERROR = -1
   */
  SessionAuthState authenticateWithPassword(QString pswd);

  /**
   * @brief getIssueBanner Get the login issued banner
   * @return Login banner or empty string
   */
  QString loginIssueBanner() const;

  /**
   * @brief authenticatePrompts
   * @param responses
   * @return
   */
  SessionAuthState authenticatePrompts(QStringList responses);

  /**
   * @brief newChannel Allocates a new execution channel from this session
   * @return
   */
304
  Channel* newChannel();
305

306 307 308 309
  /**
   * @brief newSFTPSession Allocates a new SFTP session from this SSH session
   * @return
   */
310
  SFTPSession* newSFTPSession();
311 312 313 314 315 316

};  // class Session

// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPSession
{
317 318 319
 private:
  SFTPSession(const SFTPSession&) = delete;

320 321 322 323 324 325 326 327 328 329
 protected:
  // Private implementation
  SFTPSessionImpl* p;

 public:
  SFTPSession();
  ~SFTPSession();
  bool mkdir(QString dirName);
  bool rmdir(QString dirName);
  // int accessType = O_RDONLY | O_WRONLY | ...; see fcntl.h
330 331
  SFTPFile* openFile(QString fileName, int accessType);
  SFTPDir* openDir(QString dirName);
332 333 334 335 336 337 338 339 340 341 342 343
  QString error();
  QString canonicalize(QString path);

  friend Session;
  friend SFTPFile;
  friend SFTPDir;
};  // class SFTPSession

// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPFile
{
 private:
344 345
  SFTPFile(const SFTPFile&) = delete;

346 347 348 349
  // Private implementation
  SFTPFileImpl* p;

 public:
350
  SFTPFile(SFTPSession* sftpSession, QString filename, int accessType);
351 352
  ~SFTPFile();
  bool isOpen();
353
  int64_t write(QString str);
354 355
  QString read(size_t nBytes);
  bool close();
356
  bool seek(size_t offset);
357
  int64_t tell();
358 359
};  // class SFTPFile

360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
// ----------------------------------------------------------------------------
struct SFTPAttributes
{
  QString name;
  QString longname;
  uint32_t flags;
  uint8_t type;
  uint64_t size;
  uint32_t uid;
  uint32_t gid;
  QString owner;
  QString group;
  uint32_t permissions;
  uint64_t atime64;
  uint32_t atime;
  uint32_t atime_nseconds;
  uint64_t createtime;
  uint32_t createtime_nseconds;
  uint64_t mtime64;
  uint32_t mtime;
  uint32_t mtime_nseconds;
  QString acl;
  uint32_t extended_count;
  QString extended_type;
  QString extended_data;
};

387 388 389 390
// ----------------------------------------------------------------------------
class RSM_PUBLIC SFTPDir
{
 private:
391 392
  SFTPDir(const SFTPDir&) = delete;

393 394 395 396
  // Private implementation
  SFTPDirImpl* p;

 public:
397
  SFTPDir(SFTPSession* sftpSession, QString dirName);
398
  ~SFTPDir();
399
  bool isOpen();
400
  bool hasNext();
401
  SFTPAttributes* next();
402 403 404
  bool close();
};  // class SFTPDir

405 406
}  // namespace rsm
#endif /* RSM_RSMCORE_SESSION_HH_*/