#ifndef RSM_RSMCORE_SESSION_HH_ #define RSM_RSMCORE_SESSION_HH_ #include #include "rsmcore/declspec.hh" #include "rsmcore/sessionlog.hh" namespace rsm { enum class SessionAuthState { SUCCESS = 0, DENIED, PARTIAL, INFO, AGAIN, ERROR = -1 }; #define SessionAuthMethodUNKNOWN 0x0000u #define SessionAuthMethodNONE 0x0001u #define SessionAuthMethodPASSWORD 0x0002u #define SessionAuthMethodPUBLICKEY 0x0004u #define SessionAuthMethodHOSTBASED 0x0008u #define SessionAuthMethodINTERACTIVE 0x0010u #define SessionAuthMethodGSSAPI_MIC 0x0020u /** * @brief The SessionHostState enum */ enum class SessionHostState { /** * There had been an error checking the host. */ ERROR = -2, /** * 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; class SFTPSessionImpl; class SFTPSession; class SFTPFileImpl; class SFTPFile; class SFTPDirImpl; class SFTPDir; 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 */ QString host() const; /** * 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 */ QString user() const; /** * 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 */ QString getError() const; /** * 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 */ Channel newChannel(); /** * @brief newSFTPSession Allocates a new SFTP session from this SSH session * @return */ SFTPSession* newSFTPSession(); }; // class Session // ---------------------------------------------------------------------------- class RSM_PUBLIC SFTPSession { private: SFTPSession(const SFTPSession&) = delete; 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 SFTPFile* openFile(QString fileName, int accessType); SFTPDir* openDir(QString dirName); QString error(); QString canonicalize(QString path); friend Session; friend SFTPFile; friend SFTPDir; }; // class SFTPSession // ---------------------------------------------------------------------------- class RSM_PUBLIC SFTPFile { private: SFTPFile(const SFTPFile&) = delete; // Private implementation SFTPFileImpl* p; public: SFTPFile(SFTPSession& sftpSession, QString filename, int accessType); ~SFTPFile(); bool isOpen(); ssize_t write(QString str); QString read(size_t nBytes); bool close(); bool seek(size_t offset); ssize_t tell(); }; // class SFTPFile // ---------------------------------------------------------------------------- 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; }; // ---------------------------------------------------------------------------- class RSM_PUBLIC SFTPDir { private: SFTPDir(const SFTPDir&) = delete; // Private implementation SFTPDirImpl* p; public: SFTPDir(SFTPSession* sftpSession, QString dirName); ~SFTPDir(); bool isOpen(); bool hasNext(); SFTPAttributes* next(); bool close(); }; // class SFTPDir } // namespace rsm #endif /* RSM_RSMCORE_SESSION_HH_*/