diff options
-rw-r--r-- | libssh/auth.c | 136 | ||||
-rw-r--r-- | libssh/buffer.c | 76 | ||||
-rw-r--r-- | libssh/channels.c | 194 | ||||
-rw-r--r-- | libssh/error.c | 22 |
4 files changed, 417 insertions, 11 deletions
diff --git a/libssh/auth.c b/libssh/auth.c index 8c7fb2db..f4ea45e7 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -26,6 +26,12 @@ MA 02111-1307, USA. */ #include <string.h> #include <netdb.h> +/** defgroup ssh_auth + * \brief functions to authenticate + */ +/** \addtogroup ssh_auth + * @{ */ + static int ask_userauth(SSH_SESSION *session){ if(session->auth_service_asked) return 0; @@ -114,6 +120,16 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){ /* use the "none" authentication question */ +/** \brief Try to authenticate through the "none" method + * \param session ssh session + * \param username username to authenticate. You can specify NULL if + * ssh_option_set_username() has been used. You cannot try two different logins in a row. + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : Authentication failed : use another method\n + * SSH_AUTH_PARTIAL : You've been partially authenticated, you still have to use another method\n + * SSH_AUTH_SUCCESS : Authentication success + */ + int ssh_userauth_none(SSH_SESSION *session,char *username){ STRING *user; STRING *service; @@ -146,6 +162,20 @@ int ssh_userauth_none(SSH_SESSION *session,char *username){ return wait_auth_status(session,0); } +/** \brief Try to authenticate through public key + * \param session ssh session + * \param username 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 type type of public key. This value is given by publickey_from_file() + * \param publickey a public key returned by publickey_from_file() + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : The server doesn't accept that public key as an authentication token. Try another key or another method\n + * SSH_AUTH_SUCCESS : The public key is accepted, you want now to use ssh_userauth_pubkey() + * \see publickey_from_file() + * \see privatekey_from_file() + * \see ssh_userauth_pubkey() + */ + int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STRING *publickey){ STRING *user; STRING *service; @@ -187,6 +217,23 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STR return err; } + +/** \brief Try to authenticate through public key + * \param session ssh session + * \param username 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 publickey a public key returned by publickey_from_file() + * \param privatekey a private key returned by privatekey_from_file() + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : Authentication failed : use another method\n + * SSH_AUTH_PARTIAL : You've been partially authenticated, you still have to use another method\n + * SSH_AUTH_SUCCESS : Authentication success + * \see publickey_from_file() + * \see privatekey_from_file() + * \see private_key_free() + * \see ssh_userauth_offer_pubkey() + */ + int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey, PRIVATE_KEY *privatekey){ STRING *user; STRING *service; @@ -234,6 +281,19 @@ int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey, return err; } +/** \brief Try to authenticate by password + * \param session ssh session + * \param username 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 password password to use. Take care to clean it after authentication + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : Authentication failed : use another method\n + * SSH_AUTH_PARTIAL : You've been partially authenticated, you still have to use another method\n + * SSH_AUTH_SUCCESS : Authentication success + * \see ssh_userauth_kbdint() + */ + + int ssh_userauth_password(SSH_SESSION *session,char *username,char *password){ STRING *user; STRING *service; @@ -280,6 +340,20 @@ static char *pub_keys_path[]={NULL,"%s/.ssh/identity.pub","%s/.ssh/id_dsa.pub"," /* this function initialy was in the client */ /* but the fools are the ones who never change mind */ + +/** it may fail, for instance it doesn't ask for a password and uses a default + * asker for passphrases (in case the private key is encrypted) + * \brief Tries to automaticaly authenticate with public key and "none" + * \param session ssh session + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : Authentication failed : use another method\n + * SSH_AUTH_PARTIAL : You've been partially authenticated, you still have to use another method\n + * SSH_AUTH_SUCCESS : Authentication success + * \see ssh_userauth_kbdint() + * \see ssh_userauth_password() + * \see ssh_options_set_identity() + */ + int ssh_userauth_autopubkey(SSH_SESSION *session){ int count=1; /* bypass identity */ int type=0; @@ -540,6 +614,24 @@ static int kbdauth_send(SSH_SESSION *session) { return wait_auth_status(session,1); } +/** \brief Try to authenticate through the "keyboard-interactive" method + * \param session ssh session + * \param user 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 submethods undocumented. Set it to NULL + * \returns SSH_AUTH_ERROR : a serious error happened\n + * SSH_AUTH_DENIED : Authentication failed : use another method\n + * SSH_AUTH_PARTIAL : You've been partially authenticated, you still have to use another method\n + * SSH_AUTH_SUCCESS : Authentication success\n + * SSH_AUTH_INFO : The server asked some questions. Use ssh_userauth_kbdint_getnprompts() and such. + * \see ssh_userauth_kbdint_getnprompts() + * \see ssh_userauth_kbdint_getname() + * \see ssh_userauth_kbdint_getinstruction() + * \see ssh_userauth_kbdint_getprompt() + * \see ssh_userauth_kbdint_setanswer() + */ + + /* the heart of the whole keyboard interactive login */ int ssh_userauth_kbdint(SSH_SESSION *session,char *user,char *submethods){ int err; @@ -583,27 +675,66 @@ int ssh_userauth_kbdint(SSH_SESSION *session,char *user,char *submethods){ return err; } +/** You have called ssh_userauth_kbdint() and got SSH_AUTH_INFO. this + * function returns the questions from the server + * \brief get the number of prompts (questions) the server has given + * \param session ssh session + * \returns number of prompts + */ + int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session){ return session->kbdint->nprompts; } +/** You have called ssh_userauth_kbdint() and got SSH_AUTH_INFO. this + * function returns the questions from the server + * \brief get the "name" of the message block + * \param session ssh session + * \returns name of the message block. Do not free it + */ + char *ssh_userauth_kbdint_getname(SSH_SESSION *session){ return session->kbdint->name; } +/** You have called ssh_userauth_kbdint() and got SSH_AUTH_INFO. this + * function returns the questions from the server + * \brief get the "instruction" of the message block + * \param session ssh session + * \returns instruction of the message block + */ + char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session){ return session->kbdint->instruction; } +/** You have called ssh_userauth_kbdint() and got SSH_AUTH_INFO. this + * function returns the questions from the server + * \brief get a prompt from a message block + * \param session ssh session + * \param i index number of the ith prompt + * \param echo when different of NULL, it will obtain a boolean meaning that the + * resulting user input should be echoed or not (like passwords) + * \returns pointer to the prompt. Do not free it + */ + char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, int i, char *echo){ - if(i > session->kbdint->nprompts) + if(i > session->kbdint->nprompts || i<0) return NULL; if(echo) *echo=session->kbdint->echo[i]; return session->kbdint->prompts[i]; } +/** You have called ssh_userauth_kbdint() and got SSH_AUTH_INFO. this + * function returns the questions from the server + * \brief set the answer for a question from a message block. + * \param session ssh session + * \param i index number of the ith prompt + * \param answer answer to give to server + */ + void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *answer){ if (i>session->kbdint->nprompts) return; @@ -617,3 +748,6 @@ void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *a } session->kbdint->answers[i]=strdup(answer); } + +/** @} */ + diff --git a/libssh/buffer.c b/libssh/buffer.c index ade6f02f..673c6c55 100644 --- a/libssh/buffer.c +++ b/libssh/buffer.c @@ -24,12 +24,27 @@ MA 02111-1307, USA. */ #include <string.h> #include <netdb.h> #include "libssh/priv.h" + +/** defgroup ssh_buffer + * \brief buffer handling + */ + +/** \addtogroup ssh_buffer + * @{ + */ + +/** \brief creates a new buffer + * \return a new initialized buffer + */ BUFFER *buffer_new(){ BUFFER *buffer=malloc(sizeof(BUFFER)); memset(buffer,0,sizeof(BUFFER)); return buffer; } +/** \brief desallocate a buffer + * \param buffer buffer to free + */ void buffer_free(BUFFER *buffer){ // printf("buffer %p : free(%p);\n",buffer,buffer->data); if(buffer->data){ @@ -40,6 +55,10 @@ void buffer_free(BUFFER *buffer){ free(buffer); } +/* \internal + * \brief reinitialize a buffer + * \param buffer buffer + */ void buffer_reinit(BUFFER *buffer){ memset(buffer->data,0,buffer->used); buffer->used=0; @@ -53,7 +72,12 @@ static void realloc_buffer(BUFFER *buffer,int needed){ // printf("%p\n",buffer->data); buffer->allocated=needed; } - +/** \internal + * \brief add data at tail of the buffer + * \param buffer buffer + * \param data data pointer + * \param len length of data + */ void buffer_add_data(BUFFER *buffer,void *data,int len){ if(buffer->allocated < buffer->used+len) realloc_buffer(buffer,buffer->used+len); @@ -78,6 +102,12 @@ void buffer_add_u8(BUFFER *buffer,u8 data){ buffer_add_data(buffer,&data,sizeof(u8)); } +/** \internal + * \brief add data at head of a buffer + * \param buffer buffer + * \param data data to add + * \param len length of data + */ void buffer_add_data_begin(BUFFER *buffer, void *data, int len){ if(buffer->allocated < buffer->used + len) realloc_buffer(buffer,buffer->used+len); @@ -86,26 +116,63 @@ void buffer_add_data_begin(BUFFER *buffer, void *data, int len){ buffer->used+=len; } +/** \internal + * \brief append data from a buffer to tail of another + * \param buffer destination buffer + * \param source source buffer. Doesn't take position in buffer into account + */ void buffer_add_buffer(BUFFER *buffer, BUFFER *source){ buffer_add_data(buffer,buffer_get(source),buffer_get_len(source)); } +/** \brief get a pointer on the head of the buffer + * \param buffer buffer + * \return data pointer on the head. Doesn't take position into account. + * \warning don't expect data to be nul-terminated + * \see buffer_get_rest() + * \see buffer_get_len() + */ void *buffer_get(BUFFER *buffer){ return buffer->data; } +/** \internal + * \brief get a pointer to head of the buffer at current position + * \param buffer buffer + * \return pointer to the data from current position + * \see buffer_get_rest_len() + * \see buffer_get() + */ void *buffer_get_rest(BUFFER *buffer){ return buffer->data+buffer->pos; } +/** \brief get length of the buffer, not counting position + * \param buffer + * \return length of the buffer + * \see buffer_get() + */ int buffer_get_len(BUFFER *buffer){ return buffer->used; } +/** \internal + * \brief get length of the buffer from the current position + * \param buffer + * \return length of the buffer + * \see buffer_get_rest() + */ int buffer_get_rest_len(BUFFER *buffer){ return buffer->used - buffer->pos; } +/** \internal + * has effect to "eat" bytes at head of the buffer + * \brief advance the position in the buffer + * \param buffer buffer + * \param len number of bytes to eat + * \return new size of the buffer + */ int buffer_pass_bytes(BUFFER *buffer,int len){ if(buffer->used < buffer->pos+len) return 0; @@ -118,6 +185,12 @@ int buffer_pass_bytes(BUFFER *buffer,int len){ return len; } +/** \internal + * \brief cut the end of the buffer + * \param buffer buffer + * \param len number of bytes to remove from tail + * \return new size of the buffer + */ int buffer_pass_bytes_end(BUFFER *buffer,int len){ if(buffer->used < buffer->pos + len) return 0; @@ -182,4 +255,5 @@ STRING *buffer_get_mpint(BUFFER *buffer){ } return str; } +/** @} */ diff --git a/libssh/channels.c b/libssh/channels.c index 78b66cb5..45c6d6a4 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -32,6 +32,17 @@ MA 02111-1307, USA. */ #define WINDOWLIMIT 1024 #define WINDOWBASE 32000 +/** defgroup ssh_channel + * \brief functions that manage a channel + */ + +/** \addtogroup ssh_channel + * @{ */ + +/** \brief allocate a new channel + * \param session ssh session + * \return an allocated channel. As this function doesn't speak with server, it never fails + */ CHANNEL *channel_new(SSH_SESSION *session){ CHANNEL *channel=malloc(sizeof(CHANNEL)); memset(channel,0,sizeof(CHANNEL)); @@ -344,6 +355,16 @@ void channel_default_bufferize(CHANNEL *channel, void *data, int len, int is_std } } +/** \brief open a session channel (suited for a shell. Not tcp) + * \param channel an allocated channel (see channel_new()) + * \return SSH_OK on success\n + * SSH_ERROR on error + * \see channel_open_forward() + * \see channel_request_env() + * \see channel_request_shell() + * \see channel_request_exec() + * \warning API changed from 0.11 + */ int channel_open_session(CHANNEL *channel){ #ifdef HAVE_SSH1 if(channel->session->version==2) @@ -355,8 +376,16 @@ int channel_open_session(CHANNEL *channel){ #endif } -/* tcpip forwarding */ - +/** \brief open a TCP/IP forwarding channel. + * \param channel an allocated channel (see channel_new()) + * \param remotehost remote host to be connected (host name or IP) + * \param remoteport remote port + * \param sourcehost source host (your local computer). It's facultative and for logging purpose + * \param localport source port (your local computer). It's facultative and for logging purpose + * \return SSH_ERROR on error\n + * SSH_OK on success + * \warning API changed from 0.11 + */ int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char *sourcehost, int localport){ BUFFER *payload=buffer_new(); STRING *str=string_from_char(remotehost); @@ -373,7 +402,10 @@ int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char return ret; } - +/** \brief close and free a channel + * \param channel channel to free + * \warning any data unread on channel will be lost + */ void channel_free(CHANNEL *channel){ SSH_SESSION *session=channel->session; if(session->alive && channel->open) @@ -397,6 +429,14 @@ void channel_free(CHANNEL *channel){ free(channel); } +/** it doesn't close the channel. You may still read from it but not write. + * \brief send an end of file on the channel + * \param channel channel + * \return SSH_ERROR on error\n + * SSH_SUCCESS on success + * \see channel_close() + * \see channel_free() + */ int channel_send_eof(CHANNEL *channel){ SSH_SESSION *session=channel->session; int ret; @@ -410,6 +450,15 @@ int channel_send_eof(CHANNEL *channel){ return ret; } +/** It sends an end of file and then closes the channel. You won't be able + * to recover any data the server was going to send or was in buffers. + * \brief close a channel + * \param channel channel + * \return SSH_ERROR on error\n + * SSH_SUCCESS on success + * \see channel_free() + * \see channel_eof() + */ int channel_close(CHANNEL *channel){ SSH_SESSION *session=channel->session; int ret=0; @@ -428,8 +477,14 @@ int channel_close(CHANNEL *channel){ return ret; } -/* Blocking write */ -/* The exact len is written */ +/** \brief blocking write on channel + * \param channel channel + * \param data pointer to data to write + * \param len length of data + * \return number of bytes written on success\n + * SSH_ERROR on error + * \see channel_read() + */ int channel_write(CHANNEL *channel ,void *data,int len){ SSH_SESSION *session=channel->session; int effectivelen; @@ -474,14 +529,29 @@ int channel_write(CHANNEL *channel ,void *data,int len){ return origlen; } +/** \brief returns if the channel is open or not + * \param channel channel + * \return 0 if channel is closed, nonzero otherwise + * \see channel_is_closed() + */ int channel_is_open(CHANNEL *channel){ return (channel->open!=0 && channel->session->alive); } +/** \brief returns if the channel is closed or not + * \param channel channel + * \return 0 if channel is opened, nonzero otherwise + * \see channel_is_open() + */ + int channel_is_closed(CHANNEL *channel){ return (channel->open==0 || !channel->session->alive); } +/** \brief returns if the remote has sent an EOF + * \param channel channel + * \return 0 if there is no EOF, nonzero otherwise + */ int channel_is_eof(CHANNEL *channel){ if((channel->stdout_buffer && buffer_get_rest_len(channel->stdout_buffer) >0) || (channel->stderr_buffer && buffer_get_rest_len( @@ -490,6 +560,12 @@ int channel_is_eof(CHANNEL *channel){ return (channel->remote_eof!=0); } +/** \brief put the channel into nonblocking mode + * \param channel channel + * \param blocking boolean for blocking or nonblocking + * \bug This functionnality is still under development and + * doesn't work correctly + */ void channel_set_blocking(CHANNEL *channel, int blocking){ channel->blocking=blocking; } @@ -523,6 +599,14 @@ static int channel_request(CHANNEL *channel,char *request, BUFFER *buffer,int re return err; } +/** \brief requests a pty with a specific type and size + * \param channel channel + * \param terminal terminal type ("vt100, xterm,...") + * \param col number of cols + * \param row number of rows + * \return SSH_SUCCESS on success\n + * SSH_ERROR on error + */ int channel_request_pty_size(CHANNEL *channel, char *terminal, int col, int row){ STRING *term; BUFFER *buffer; @@ -547,10 +631,24 @@ int channel_request_pty_size(CHANNEL *channel, char *terminal, int col, int row) return err; } +/** \brief requests a pty + * \param channel channel + * \see channel_request_pty_size() + * \return SSH_SUCCESS on success\n + * SSH_ERROR on error + */ int channel_request_pty(CHANNEL *channel){ return channel_request_pty_size(channel,"xterm",80,24); } +/** \brief change the size of the terminal associated to a channel + * \param channel channel + * \param cols new number of cols + * \param rows new number of rows + * \warning Do not call it from a signal handler if you are not + * sure any other libssh function using the same channel/session + * is running at same time (not 100% threadsafe) + */ int channel_change_pty_size(CHANNEL *channel,int cols,int rows){ BUFFER *buffer; int err; @@ -568,7 +666,12 @@ int channel_change_pty_size(CHANNEL *channel,int cols,int rows){ buffer_free(buffer); return err; } - + +/** \brief requests a shell + * \param channel + * \returns SSH_SUCCESS on success\n + * SSH_ERROR on error + */ int channel_request_shell(CHANNEL *channel){ #ifdef HAVE_SSH1 if(channel->version==1) @@ -577,6 +680,14 @@ int channel_request_shell(CHANNEL *channel){ return channel_request(channel,"shell",NULL,1); } +/** \brief requests a subsystem (for example sftp) + * \param channel channel + * \param system subsystem to request (for example sftp) + * \return SSH_SUCCESS on success\n + * SSH_ERROR on error + * \warning you normally don't have to call it to have sftp + * \see sftp_new() + */ int channel_request_subsystem(CHANNEL *channel, char *system){ BUFFER* buffer=buffer_new(); int ret; @@ -592,7 +703,14 @@ int channel_request_sftp( CHANNEL *channel){ return channel_request_subsystem(channel, "sftp"); } - +/** \brief set the environement variables + * \param channel channel + * \param name name of the variable + * \param value value + * \return SSH_SUCCESS on success\n + * SSH_ERROR on error + * \warning some environement variables may be refused by security + * */ int channel_request_env(CHANNEL *channel,char *name, char *value){ BUFFER *buffer=buffer_new(); int ret; @@ -607,6 +725,14 @@ int channel_request_env(CHANNEL *channel,char *name, char *value){ return ret; } +/** it's similar to sh -c "command" + * \brief run a shell command without an interactive shell + * \param channel channel + * \param cmd command to execute (by ex. "ls ~/ -al | grep -i reports") + * \return SSH_SUCCESS on success\n + * SSH_ERROR on error + * \see channel_request_shell() + */ int channel_request_exec(CHANNEL *channel, char *cmd){ BUFFER *buffer; int ret; @@ -628,7 +754,17 @@ int channel_request_exec(CHANNEL *channel, char *cmd){ /* reads into a channel and put result into buffer */ /* returns number of bytes read, 0 if eof or such and -1 in case of error */ /* if bytes != 0, the exact number of bytes are going to be read */ - +/** \brief reads data from a channel + * \param channel channel + * \param buffer buffer which will get the data + * \param bytes number of bytes to be read. If it is bigger + * than 0, the exact size will be read, else (bytes=0) it will return + * once anything is available + * \param is_stderr boolean value to mark reading from the stderr flow. + * \return number of bytes read\n + * 0 on end of file\n + * SSH_ERROR on error + */ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){ BUFFER *stdbuf=NULL; int len; @@ -663,7 +799,16 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){ return buffer_get_len(buffer); } -/* returns the number of bytes available, 0 if nothing is currently available, -1 if error */ +/** \brief polls the channel for data to read + * \param channel channel + * \param is_stderr boolean to select the stderr stream + * \return number of bytes available for reading\n + * 0 if nothing is available\n + * SSH_ERROR on error + * \warning don't forget to check for EOF as it would + * return 0 here + * \see channel_is_eof() + */ int channel_poll(CHANNEL *channel, int is_stderr){ BUFFER *buffer; int r=0; @@ -684,6 +829,20 @@ int channel_poll(CHANNEL *channel, int is_stderr){ /* nonblocking read on the specified channel. it will return <=len bytes of data read atomicly. */ +/** This read will make a nonblocking read (unlike channel_read()) and won't force you + * to deal with BUFFER's + * \brief nonblocking read + * \param channel channel + * \param dest pointer to destination for data + * \param len maximum length of data to be read + * \param is_stderr boolean to select the stderr stream + * \return number of bytes read\n + * 0 if nothing is available\n + * SSH_ERROR on error + * \warning don't forget to check for EOF as it would + * return 0 here + * \see channel_is_eof() + */ int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stderr){ int to_read=channel_poll(channel,is_stderr); int lu; @@ -700,6 +859,10 @@ int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stder return lu; } +/** \brief recover the session in which belong a channel + * \param channel channel + * \return the session pointer + */ SSH_SESSION *channel_get_session(CHANNEL *channel){ return channel->session; } @@ -759,6 +922,16 @@ static int count_ptrs(CHANNEL **ptrs){ return c; } +/** the list of pointers are then actualized and will only contain pointers to + * channels that are respectively readable, writable or have an exception to trap + * \brief act as the standard select(2) for channels + * \param readchans a NULL pointer or an array of channel pointers, finished by a NULL + * \param writechans a NULL pointer or an array of channel pointers, finished by a NULL + * \param exceptchans a NULL pointer or an array of channel pointers, finished by a NULL + * \param timeout timeout as defined by select(2) + * \return SSH_SUCCESS operation successful\n + * SSH_EINTR select(2) syscall was interrupted, relaunch the function + */ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptchans, struct timeval * timeout){ fd_set rset; @@ -855,3 +1028,6 @@ int channel_select(CHANNEL **readchans, CHANNEL **writechans, CHANNEL **exceptch /* not reached */ return 0; } + +/** @} */ + diff --git a/libssh/error.c b/libssh/error.c index 78a7ea12..07169836 100644 --- a/libssh/error.c +++ b/libssh/error.c @@ -23,6 +23,13 @@ MA 02111-1307, USA. */ #include <stdio.h> #include <stdarg.h> #include "libssh/priv.h" +/** defgroup ssh_error + * \brief error handling + */ + +/** \addtogroup ssh_error + * @{ + */ static int verbosity; @@ -36,11 +43,24 @@ void ssh_set_error(void *error,int code,char *descr,...){ err->error_code=code; } +/** \brief retrieve an error text message + * \param error the ssh session pointer + * \return a static string describing the error + */ char *ssh_get_error(void *error){ struct error_struct *err=error; return err->error_buffer; } +/** \brief retrieve the error code from the last + * error + * \param error the ssh session pointer + * \return SSH_NO_ERROR no error occured\n + * SSH_REQUEST_DENIED The last request was denied but situation + * is recoverable\n + * SSH_FATAL A fatal error occured. this could be an unexpected disconnection\n + * Other error codes are internal but can be considered same than SSH_FATAL + */ int ssh_get_error_code(void *error){ struct error_struct *err=error; return err->error_code; @@ -57,3 +77,5 @@ void ssh_say(int priority, char *format,...){ void ssh_set_verbosity(int num){ verbosity=num; } + +/** @} */ |