mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-04 12:20:42 +09:00
good work tonight. Made documentation for authentication, channels, buffers, errors
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@80 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
136
libssh/auth.c
136
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);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
Reference in New Issue
Block a user