diff --git a/include/libssh/libsshpp.hpp b/include/libssh/libsshpp.hpp index 553a7777..2e3309b6 100644 --- a/include/libssh/libsshpp.hpp +++ b/include/libssh/libsshpp.hpp @@ -67,38 +67,60 @@ class Channel; */ #ifndef SSH_NO_CPP_EXCEPTIONS -/** @brief This class describes a SSH Exception object. This object can be thrown - * by several SSH functions that interact with the network, and may fail because of - * socket, protocol or memory errors. +/** @brief This class describes a SSH Exception object. This object can be + * thrown 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=std::string(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 - */ - std::string getError(){ - return description; - } -private: - int code; - std::string description; +class SshException { + public: + /** @brief Construct an exception from a libssh session error state. + * Captures the current error code and error string associated with + * the given session. + * + * @param[in] csession libssh session handle used to query error details. + * + * @see ssh_get_error_code + * @see ssh_get_error + */ + SshException(ssh_session csession) + { + code = ssh_get_error_code(csession); + description = std::string(ssh_get_error(csession)); + } + /** @brief Copy-construct an exception. + * + * @param[in] e Source exception. + */ + 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 + */ + std::string getError() + { + return description; + } + + private: + int code; + std::string description; }; /** @internal @@ -134,9 +156,12 @@ public: c_session=NULL; } /** @brief sets an SSH session options - * @param type Type of option - * @param option cstring containing the value of option + * + * @param[in] type Type of option + * @param[in] option cstring containing the value of option + * * @throws SshException on error + * * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, const char *option){ @@ -144,9 +169,12 @@ public: return_throwable; } /** @brief sets an SSH session options - * @param type Type of option - * @param option long integer containing the value of option + * + * @param[in] type Type of option + * @param[in] option long integer containing the value of option + * * @throws SshException on error + * * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, long int option){ @@ -154,9 +182,12 @@ public: return_throwable; } /** @brief sets an SSH session options - * @param type Type of option - * @param option void pointer containing the value of option + * + * @param[in] type Type of option + * @param[in] option void pointer containing the value of option + * * @throws SshException on error + * * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, void *option){ @@ -164,7 +195,9 @@ public: return_throwable; } /** @brief connects to the remote host + * * @throws SshException on error + * * @see ssh_connect */ void_throwable connect(){ @@ -173,8 +206,11 @@ public: return_throwable; } /** @brief Authenticates automatically using public key + * * @throws SshException on error - * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED + * + * @returns `SSH_AUTH_SUCCESS`, `SSH_AUTH_PARTIAL`, `SSH_AUTH_DENIED` + * * @see ssh_userauth_autopubkey */ int userauthPublickeyAuto(void){ @@ -184,9 +220,13 @@ public: } /** @brief Authenticates using the "none" method. Prefer using autopubkey if * possible. + * * @throws SshException on error - * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED + * + * @returns `SSH_AUTH_SUCCESS`, `SSH_AUTH_PARTIAL`, `SSH_AUTH_DENIED` + * * @see ssh_userauth_none + * * @see Session::userauthAutoPubkey */ int userauthNone(){ @@ -198,16 +238,16 @@ public: /** * @brief Authenticate through the "keyboard-interactive" method. * - * @param[in] username The username to authenticate. You can specify NULL if - * ssh_option_set_username() has been used. You cannot - * try two different logins in a row. - * + * @param[in] username The username to authenticate. You can specify NULL + * If ssh_option_set_username()has been used. You cannot + * try two different logins in a row. * @param[in] submethods Undocumented. Set it to NULL. * * @throws SshException on error * - * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED, - * SSH_AUTH_ERROR, SSH_AUTH_INFO, SSH_AUTH_AGAIN + * @returns `SSH_AUTH_SUCCESS`, `SSH_AUTH_PARTIAL`, + * `SSH_AUTH_DENIED`, `SSH_AUTH_ERROR`, `SSH_AUTH_INFO`, + * `SSH_AUTH_AGAIN` * * @see ssh_userauth_kbdint */ @@ -218,6 +258,7 @@ public: } /** @brief Get the number of prompts (questions) the server has given. + * * @returns The number of prompts. * @see ssh_userauth_kbdint_getnprompts */ @@ -228,17 +269,16 @@ public: /** * @brief Set the answer for a question from a message block. * - * @param[in] index The index number of the prompt. - * @param[in] answer The answer to give to the server. The answer MUST be - * encoded UTF-8. It is up to the server how to interpret - * the value and validate it. However, if you read the - * answer in some other encoding, you MUST convert it to - * UTF-8. + * @param[in] index The index number of the prompt. + * @param[in] answer The answer to give to the server. The answer MUST be + * encoded UTF-8.It is up to the server how to interpret + * the value and validate it. However, if you read the + * answer in some other encoding, you MUST convert it to + * UTF-8. * * @throws SshException on error * * @returns 0 on success, < 0 on error - * * @see ssh_userauth_kbdint_setanswer */ int userauthKbdintSetAnswer(unsigned int index, const char *answer) @@ -248,12 +288,13 @@ public: return ret; } - - /** @brief Authenticates using the password method. + * * @param[in] password password to use for authentication + * * @throws SshException on error - * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED + * @returns `SSH_AUTH_SUCCESS`, `SSH_AUTH_PARTIAL`, `SSH_AUTH_DENIED` + * * @see ssh_userauth_password */ int userauthPassword(const char *password){ @@ -262,10 +303,14 @@ public: return ret; } /** @brief Try to authenticate using the publickey method. + * * @param[in] pubkey public key to use for authentication + * * @throws SshException on error - * @returns SSH_AUTH_SUCCESS if the pubkey is accepted, - * @returns SSH_AUTH_DENIED if the pubkey is denied + * + * @returns `SSH_AUTH_SUCCESS` if the pubkey is accepted, + * @returns `SSH_AUTH_DENIED` if the pubkey is denied + * * @see ssh_userauth_try_pubkey */ int userauthTryPublickey(ssh_key pubkey){ @@ -274,9 +319,12 @@ public: return ret; } /** @brief Authenticates using the publickey method. + * * @param[in] privkey private key to use for authentication + * * @throws SshException on error - * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED + * @returns `SSH_AUTH_SUCCESS`, `SSH_AUTH_PARTIAL`, `SSH_AUTH_DENIED` + * * @see ssh_userauth_pubkey */ int userauthPublickey(ssh_key privkey){ @@ -286,7 +334,9 @@ public: } /** @brief Returns the available authentication methods from the server + * * @throws SshException on error + * * @returns Bitfield of available methods. * @see ssh_userauth_list */ @@ -302,8 +352,9 @@ public: ssh_disconnect(c_session); } /** @brief Returns the disconnect message from the server, if any - * @returns pointer to the message, or NULL. Do not attempt to free - * the pointer. + * + * @returns pointer to the message, or NULL. Do not attempt to free the + * pointer. */ const char *getDisconnectMessage(){ const char *msg=ssh_get_disconnect_message(c_session); @@ -312,25 +363,30 @@ public: /** @internal * @brief gets error message */ - const char *getError(){ - return ssh_get_error(c_session); + const char *getError() + { + return ssh_get_error(c_session); } /** @internal * @brief returns error code */ - int getErrorCode(){ - return ssh_get_error_code(c_session); + int getErrorCode() + { + return ssh_get_error_code(c_session); } /** @brief returns the file descriptor used for the communication + * * @returns the file descriptor + * * @warning if a proxycommand is used, this function will only return - * one of the two file descriptors being used + * one of the two file descriptors being used. * @see ssh_get_fd */ socket_t getSocket(){ return ssh_get_fd(c_session); } /** @brief gets the Issue banner from the ssh server + * * @returns the issue banner. This is generally a MOTD from server * @see ssh_get_issue_banner */ @@ -344,6 +400,7 @@ public: return ret; } /** @brief returns the OpenSSH version (server) if possible + * * @returns openssh version code * @see ssh_get_openssh_version */ @@ -351,6 +408,7 @@ public: return ssh_get_openssh_version(c_session); } /** @brief returns the version of the SSH protocol being used + * * @returns the SSH protocol version * @see ssh_get_version */ @@ -358,9 +416,10 @@ public: return ssh_get_version(c_session); } /** @brief verifies that the server is known + * * @throws SshException on error - * @returns Integer value depending on the knowledge of the - * server key + * + * @returns Integer value depending on the knowledge of the server key * @see ssh_session_update_known_hosts */ int isServerKnown(){ @@ -377,6 +436,7 @@ public: } /** @brief copies options from a session to another + * * @throws SshException on error * @see ssh_options_copy */ @@ -385,8 +445,11 @@ public: return_throwable; } /** @brief parses a configuration file for options + * * @throws SshException on error + * * @param[in] file configuration file name + * * @see ssh_options_parse_config */ void_throwable optionsParseConfig(const char *file){ @@ -399,8 +462,8 @@ public: void silentDisconnect(){ ssh_silent_disconnect(c_session); } - /** @brief Writes the known host file with current - * host key + /** @brief Writes the known host file with current host key + * * @throws SshException on error * @see ssh_write_knownhost */ @@ -411,11 +474,15 @@ public: } /** @brief accept an incoming forward connection + * * @param[in] timeout_ms timeout for waiting, in ms + * * @returns new Channel pointer on the forward connection * @returns NULL in case of error + * * @warning you have to delete this pointer after use * @see ssh_channel_forward_accept + * * @see Session::listenForward */ inline Channel *acceptForward(int timeout_ms); @@ -439,6 +506,9 @@ public: } protected: + /** @internal + * @brief Underlying libssh session handle. + */ ssh_session c_session; private: @@ -447,8 +517,7 @@ private: Session& operator=(const Session &); }; -/** @brief the ssh::Channel class describes the state of an SSH - * channel. +/** @brief the ssh::Channel class describes the state of an SSH channel. * @see ssh_channel */ class Channel { @@ -464,11 +533,15 @@ public: } /** @brief accept an incoming X11 connection + * * @param[in] timeout_ms timeout for waiting, in ms + * * @returns new Channel pointer on the X11 connection * @returns NULL in case of error + * * @warning you have to delete this pointer after use * @see ssh_channel_accept_x11 + * * @see Channel::requestX11 */ Channel *acceptX11(int timeout_ms){ @@ -478,8 +551,10 @@ public: return newchan; } /** @brief change the size of a pseudoterminal + * * @param[in] cols number of columns * @param[in] rows number of rows + * * @throws SshException on error * @see ssh_channel_change_pty_size */ @@ -490,6 +565,7 @@ public: } /** @brief closes a channel + * * @throws SshException on error * @see ssh_channel_close */ @@ -536,6 +612,21 @@ public: bool isOpen(){ return ssh_channel_is_open(channel) != 0; } + /** @brief Open a TCP forward channel. + * + * @param[in] remotehost Remote host to connect to. + * @param[in] remoteport Remote port to connect to. + * @param[in] sourcehost Source address to report (can be NULL depending on + * server policy). + * @param[in] localport Local port to report (0 lets the server pick if + * applicable). + * + * @returns `SSH_OK` (0) on success. + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_open_forward + */ int openForward(const char *remotehost, int remoteport, const char *sourcehost, int localport=0){ int err=ssh_channel_open_forward(channel,remotehost,remoteport, @@ -549,20 +640,55 @@ public: ssh_throw(err); return_throwable; } - int poll(bool is_stderr=false){ - int err=ssh_channel_poll(channel,is_stderr); - ssh_throw(err); - return err; + /** @brief Poll the channel for available data. + * + * @param[in] is_stderr If true, poll stderr stream; otherwise stdout. + * + * @returns Number of bytes available to read (>= 0). + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_poll + */ + int poll(bool is_stderr = false) + { + int err = ssh_channel_poll(channel, is_stderr); + ssh_throw(err); + return err; } - int read(void *dest, size_t count){ - int err; - /* handle int overflow */ - if(count > 0x7fffffff) - count = 0x7fffffff; - err=ssh_channel_read_timeout(channel,dest,count,false,-1); - ssh_throw(err); - return err; + /** @brief Read data from the channel (blocking). + * + * @param[out] dest Destination buffer. + * @param[in] count Maximum number of bytes to read. + * + * @returns Number of bytes read (>= 0). A return of 0 indicates EOF/no data. + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_read_timeout + */ + int read(void *dest, size_t count) + { + int err; + if (count > 0x7fffffff) + count = 0x7fffffff; + err = ssh_channel_read_timeout(channel, dest, count, false, -1); + ssh_throw(err); + return err; } + /** @brief Read data from the channel with a timeout. + * + * @param[out] dest Destination buffer. + * @param[in] count Maximum number of bytes to read. + * @param[in] timeout Timeout in milliseconds. A negative value means + * infinite timeout. + * + * @returns Number of bytes read (>= 0). A return value of 0 indicates EOF. + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_read_timeout + */ int read(void *dest, size_t count, int timeout){ int err; /* handle int overflow */ @@ -572,6 +698,22 @@ public: ssh_throw(err); return err; } + /** @brief Read data from the channel with optional stderr selection and + * timeout. + * + * @param[out] dest Destination buffer. + * @param[in] count Maximum number of bytes to read. + * @param[in] is_stderr If true, read from the stderr stream; otherwise + * read from stdout. + * @param[in] timeout Timeout in milliseconds. A negative value means + * infinite timeout. + * + * @returns Number of bytes read (>= 0). A return value of 0 indicates EOF. + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_read_timeout + */ int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){ int err; /* handle int overflow */ @@ -581,6 +723,19 @@ public: ssh_throw(err); return err; } + /** @brief Read data from the channel without blocking. + * + * @param[out] dest Destination buffer. + * @param[in] count Maximum number of bytes to read. + * @param[in] is_stderr If true, read from the stderr stream; otherwise read + * from stdout. + * + * @returns Number of bytes read (>= 0). A return of 0 may indicate no data. + * @returns `SSH_ERROR` on error (no-exception builds). + * + * @throws SshException on error (exception-enabled builds). + * @see ssh_channel_read_nonblocking + */ int readNonblocking(void *dest, size_t count, bool is_stderr=false){ int err; /* handle int overflow */ @@ -629,6 +784,18 @@ public: ssh_throw(err); return_throwable; } + /** @brief Request X11 forwarding for this channel. + * + * @param[in] single_connection If true, allow only a single X11 connection + * for this channel; further X11 connections are + * refused after the first is accepted. + * @param[in] protocol X11 authentication protocol. + * @param[in] cookie X11 authentication cookie. + * @param[in] screen_number X11 screen number. + * + * @returns `SSH_OK` on success. + * @returns `SSH_ERROR` on error (no-exception builds). + */ int requestX11(bool single_connection, const char *protocol, const char *cookie, int screen_number){ int err=ssh_channel_request_x11(channel,single_connection, @@ -641,11 +808,16 @@ public: ssh_throw(err); return_throwable; } - /** @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) + /** + * @brief Writes on a channel + * + * @param[in] data data to write. + * @param[in] len number of bytes to write. + * @param[in] is_stderr write should be done on the stderr channel (server + * only) + * * @returns number of bytes written + * * @throws SshException in case of error * @see ssh_channel_write * @see ssh_channel_write_stderr @@ -670,7 +842,13 @@ public: } protected: + /** @internal + * @brief Parent session owning this channel. + */ Session *session; + /** @internal + * @brief Underlying libssh channel handle. + */ ssh_channel channel; private: @@ -683,7 +861,6 @@ private: Channel &operator=(const Channel &); }; - inline Channel *Session::acceptForward(int timeout_ms){ ssh_channel forward = ssh_channel_open_forward_port(c_session, timeout_ms, NULL, NULL, NULL);