big changes :
Some documentation, and a new logging system. some work must be done to get rid of the infamous ssh_say() git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@166 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
parent
b94422ef10
commit
fe51f9c766
2
Doxyfile
2
Doxyfile
@ -31,7 +31,7 @@ PROJECT_NAME = libssh
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.2
|
||||
PROJECT_NUMBER = 0.2-svn
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
@ -33,6 +33,7 @@ typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h> /* for fd_set * */
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
@ -123,11 +124,15 @@ void ssh_say(int priority,char *format,...);
|
||||
void ssh_set_verbosity(int num);
|
||||
|
||||
/* There is a verbosity level */
|
||||
/* 3 : packet level */
|
||||
/* 2 : protocol level */
|
||||
/* 1 : functions level */
|
||||
/* 0 : important messages only */
|
||||
/* -1 : no messages */
|
||||
|
||||
#define SSH_LOG_NOLOG 0 // no log
|
||||
#define SSH_LOG_RARE 1 // rare conditions
|
||||
#define SSH_LOG_ENTRY 2 // user-accessible entrypoints
|
||||
#define SSH_LOG_PACKET 3 // packet id and size
|
||||
#define SSH_LOG_FUNCTIONS 4 // every function in and return
|
||||
|
||||
/* log.c */
|
||||
void ssh_log(SSH_SESSION *session, int prioriry, char *format, ...);
|
||||
|
||||
/* session.c */
|
||||
SSH_SESSION *ssh_new();
|
||||
@ -240,6 +245,9 @@ void ssh_options_allow_ssh1(SSH_OPTIONS *opt, int allow);
|
||||
void ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow);
|
||||
void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, char *dsakey);
|
||||
void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, char *rsakey);
|
||||
void ssh_options_set_log_function(SSH_OPTIONS *opt,
|
||||
void (*callback)(const char *message, SSH_SESSION *session, int verbosity ));
|
||||
void ssh_options_set_log_verbosity(SSH_OPTIONS *opt, int verbosity);
|
||||
|
||||
|
||||
/* buffer.c */
|
||||
|
@ -237,6 +237,8 @@ struct ssh_options_struct {
|
||||
int ssh1allowed;
|
||||
char *dsakey;
|
||||
char *rsakey; /* host key for server implementation */
|
||||
int log_verbosity;
|
||||
void (*log_function)(const char *message, SSH_SESSION *session, int verbosity); //log callback
|
||||
};
|
||||
|
||||
typedef struct ssh_crypto_struct {
|
||||
@ -355,6 +357,8 @@ struct ssh_session {
|
||||
int auth_methods;
|
||||
int hostkeys; /* contains type of host key wanted by client, in server impl */
|
||||
struct ssh_message *ssh_message; /* ssh message */
|
||||
int log_verbosity; /*cached copy of the option structure */
|
||||
int log_indent; /* indentation level in enter_function logs */
|
||||
};
|
||||
|
||||
struct ssh_kbdint {
|
||||
@ -612,6 +616,27 @@ int channel_write1(CHANNEL *channel, void *data, int len);
|
||||
|
||||
int ssh_handle_packets(SSH_SESSION *session);
|
||||
|
||||
/* log.c */
|
||||
|
||||
#define _enter_function(sess) \
|
||||
do {\
|
||||
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
||||
ssh_log((sess),SSH_LOG_FUNCTIONS,"entering function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
||||
(sess)->log_indent++; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define _leave_function(sess) \
|
||||
do { \
|
||||
if((sess)->log_verbosity >= SSH_LOG_FUNCTIONS){ \
|
||||
(sess)->log_indent--; \
|
||||
ssh_log((sess),SSH_LOG_FUNCTIONS,"leaving function %s line %d in " __FILE__ , __FUNCTION__,__LINE__);\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define enter_function() _enter_function(session)
|
||||
#define leave_function() _leave_function(session)
|
||||
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
/* gcrypt_missing.c */
|
||||
int my_gcry_dec2bn(bignum *bn, const char *data);
|
||||
|
@ -7,7 +7,7 @@ libssh_la_SOURCES = auth1.c auth.c base64.c buffer.c \
|
||||
keys.c messages.c misc.c options.c \
|
||||
packet.c server.c session.c sftp.c \
|
||||
sftpserver.c string.c wrapper.c \
|
||||
socket.c
|
||||
socket.c log.c
|
||||
|
||||
libssh_la_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
|
171
libssh/auth.c
171
libssh/auth.c
@ -32,16 +32,16 @@ MA 02111-1307, USA. */
|
||||
* @{ */
|
||||
|
||||
static int ask_userauth(SSH_SESSION *session){
|
||||
int ret=0;
|
||||
enter_function();
|
||||
if(session->auth_service_asked)
|
||||
return 0;
|
||||
else {
|
||||
if(ssh_service_request(session,"ssh-userauth"))
|
||||
return -1;
|
||||
else
|
||||
session->auth_service_asked++;
|
||||
}
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
else if(ssh_service_request(session,"ssh-userauth"))
|
||||
ret = -1;
|
||||
else
|
||||
session->auth_service_asked++;
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void burn(char *ptr){
|
||||
@ -55,6 +55,7 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
|
||||
STRING *can_continue;
|
||||
u8 partial=0;
|
||||
char *c_cont;
|
||||
enter_function();
|
||||
while(cont){
|
||||
if(packet_read(session))
|
||||
break;
|
||||
@ -66,6 +67,7 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
|
||||
if(!can_continue || buffer_get_u8(session->in_buffer,&partial)!=1 ){
|
||||
ssh_set_error(session,SSH_FATAL,
|
||||
"invalid SSH_MSG_USERAUTH_FAILURE message");
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
c_cont=string_to_char(can_continue);
|
||||
@ -114,6 +116,7 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
|
||||
break;
|
||||
}
|
||||
}
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -133,19 +136,27 @@ int ssh_userauth_none(SSH_SESSION *session,char *username){
|
||||
STRING *user;
|
||||
STRING *service;
|
||||
STRING *method;
|
||||
int ret;
|
||||
enter_function();
|
||||
#ifdef HAVE_SSH1
|
||||
if(session->version==1)
|
||||
return ssh_userauth1_none(session,username);
|
||||
if(session->version==1){
|
||||
ret = ssh_userauth1_none(session,username);
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(ssh_options_default_username(session->options))
|
||||
return SSH_AUTH_ERROR;
|
||||
else
|
||||
if(ssh_options_default_username(session->options)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
} else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
if(ask_userauth(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
user=string_from_char(username);
|
||||
method=string_from_char("none");
|
||||
service=string_from_char("ssh-connection");
|
||||
@ -158,7 +169,9 @@ int ssh_userauth_none(SSH_SESSION *session,char *username){
|
||||
free(method);
|
||||
free(user);
|
||||
packet_send(session);
|
||||
return wait_auth_status(session,0);
|
||||
ret = wait_auth_status(session,0);
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** \brief Try to authenticate through public key
|
||||
@ -182,19 +195,26 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STR
|
||||
STRING *method;
|
||||
STRING *algo;
|
||||
int err=SSH_AUTH_ERROR;
|
||||
enter_function();
|
||||
#ifdef HAVE_SSH1
|
||||
if(session->version==1)
|
||||
return ssh_userauth1_offer_pubkey(session,username,type,publickey);
|
||||
if(session->version==1){
|
||||
err= ssh_userauth1_offer_pubkey(session,username,type,publickey);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(ssh_options_default_username(session->options))
|
||||
return SSH_AUTH_ERROR;
|
||||
else
|
||||
if(ssh_options_default_username(session->options)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
} else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
if(ask_userauth(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
user=string_from_char(username);
|
||||
service=string_from_char("ssh-connection");
|
||||
method=string_from_char("publickey");
|
||||
@ -214,6 +234,7 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STR
|
||||
free(method);
|
||||
free(service);
|
||||
free(algo);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -241,17 +262,21 @@ int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey,
|
||||
STRING *algo;
|
||||
STRING *sign;
|
||||
int err=SSH_AUTH_ERROR;
|
||||
enter_function();
|
||||
// if(session->version==1)
|
||||
// return ssh_userauth1_pubkey(session,username,publickey,privatekey);
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(ssh_options_default_username(session->options))
|
||||
return err;
|
||||
else
|
||||
if(ssh_options_default_username(session->options)){
|
||||
leave_function();
|
||||
return err;
|
||||
} else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return err;
|
||||
if(ask_userauth(session)){
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
user=string_from_char(username);
|
||||
service=string_from_char("ssh-connection");
|
||||
method=string_from_char("publickey");
|
||||
@ -278,6 +303,7 @@ int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey,
|
||||
free(service);
|
||||
free(method);
|
||||
free(algo);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -300,19 +326,27 @@ int ssh_userauth_password(SSH_SESSION *session,char *username,char *password){
|
||||
STRING *method;
|
||||
STRING *password_s;
|
||||
int err;
|
||||
enter_function();
|
||||
#ifdef HAVE_SSH1
|
||||
if(session->version==1)
|
||||
return ssh_userauth1_password(session,username,password);
|
||||
if(session->version==1){
|
||||
err = ssh_userauth1_password(session,username,password);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
if(!username)
|
||||
if(!(username=session->options->username)){
|
||||
if(ssh_options_default_username(session->options))
|
||||
return SSH_AUTH_ERROR;
|
||||
else
|
||||
if(ssh_options_default_username(session->options)){
|
||||
err = SSH_AUTH_ERROR;
|
||||
leave_function();
|
||||
return err;
|
||||
} else
|
||||
username=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
if(ask_userauth(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
user=string_from_char(username);
|
||||
service=string_from_char("ssh-connection");
|
||||
method=string_from_char("password");
|
||||
@ -332,6 +366,7 @@ int ssh_userauth_password(SSH_SESSION *session,char *username,char *password){
|
||||
free(password_s);
|
||||
packet_send(session);
|
||||
err=wait_auth_status(session,0);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -362,9 +397,11 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){
|
||||
char *privkeyfile=NULL;
|
||||
PRIVATE_KEY *privkey;
|
||||
char *id=NULL;
|
||||
enter_function();
|
||||
// always testing none
|
||||
err=ssh_userauth_none(session,NULL);
|
||||
if(err==SSH_AUTH_ERROR || err==SSH_AUTH_SUCCESS){
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
if(session->options->identity){
|
||||
@ -386,6 +423,7 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){
|
||||
}
|
||||
free(pubkey);
|
||||
free(privkeyfile);
|
||||
leave_function();
|
||||
return err;
|
||||
} else
|
||||
if(err != SSH_AUTH_SUCCESS){
|
||||
@ -416,6 +454,7 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){
|
||||
free(pubkey);
|
||||
free(privkeyfile);
|
||||
private_key_free(privkey);
|
||||
leave_function();
|
||||
return err;
|
||||
} else
|
||||
if(err != SSH_AUTH_SUCCESS){
|
||||
@ -437,6 +476,7 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){
|
||||
keys_path[0]=NULL;
|
||||
free(id);
|
||||
}
|
||||
leave_function();
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
/* at this point, pubkey is NULL and so is privkeyfile */
|
||||
@ -447,7 +487,7 @@ int ssh_userauth_autopubkey(SSH_SESSION *session){
|
||||
keys_path[0]=NULL;
|
||||
free(id);
|
||||
}
|
||||
|
||||
leave_function();
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
@ -525,6 +565,8 @@ static int kbdauth_init(SSH_SESSION *session,
|
||||
STRING *submethods_s=(submethods ? string_from_char(submethods): string_from_char(""));
|
||||
STRING *service=string_from_char("ssh-connection");
|
||||
STRING *method=string_from_char("keyboard-interactive");
|
||||
int err;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_REQUEST);
|
||||
buffer_add_ssh_string(session->out_buffer,user_s);
|
||||
@ -536,9 +578,13 @@ static int kbdauth_init(SSH_SESSION *session,
|
||||
free(service);
|
||||
free(method);
|
||||
free(submethods_s);
|
||||
if(packet_send(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
return wait_auth_status(session,1);
|
||||
if(packet_send(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
err=wait_auth_status(session,1);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int kbdauth_info_get(SSH_SESSION *session){
|
||||
@ -547,6 +593,7 @@ static int kbdauth_info_get(SSH_SESSION *session){
|
||||
STRING *tmp;
|
||||
u32 nprompts;
|
||||
int i;
|
||||
enter_function();
|
||||
name=buffer_get_ssh_string(session->in_buffer);
|
||||
instruction=buffer_get_ssh_string(session->in_buffer);
|
||||
tmp=buffer_get_ssh_string(session->in_buffer);
|
||||
@ -558,6 +605,7 @@ static int kbdauth_info_get(SSH_SESSION *session){
|
||||
free(instruction);
|
||||
// tmp must be empty if we got here
|
||||
ssh_set_error(session,SSH_FATAL,"Invalid USERAUTH_INFO_REQUEST msg");
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
if(tmp)
|
||||
@ -573,6 +621,7 @@ static int kbdauth_info_get(SSH_SESSION *session){
|
||||
nprompts=ntohl(nprompts);
|
||||
if(nprompts>KBDINT_MAX_PROMPT){
|
||||
ssh_set_error(session,SSH_FATAL,"Too much prompt asked from server: %lu(0x%.8lx)",nprompts,nprompts);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
session->kbdint->nprompts=nprompts;
|
||||
@ -585,11 +634,13 @@ static int kbdauth_info_get(SSH_SESSION *session){
|
||||
buffer_get_u8(session->in_buffer,&session->kbdint->echo[i]);
|
||||
if(!tmp){
|
||||
ssh_set_error(session,SSH_FATAL,"Short INFO_REQUEST packet");
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
session->kbdint->prompts[i]=string_to_char(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
leave_function();
|
||||
return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */
|
||||
}
|
||||
|
||||
@ -597,6 +648,8 @@ static int kbdauth_info_get(SSH_SESSION *session){
|
||||
static int kbdauth_send(SSH_SESSION *session) {
|
||||
STRING *answer;
|
||||
int i;
|
||||
int err;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_INFO_RESPONSE);
|
||||
buffer_add_u32(session->out_buffer,htonl(session->kbdint->nprompts));
|
||||
@ -609,9 +662,13 @@ static int kbdauth_send(SSH_SESSION *session) {
|
||||
string_burn(answer);
|
||||
free(answer);
|
||||
}
|
||||
if(packet_send(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
return wait_auth_status(session,1);
|
||||
if(packet_send(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
err = wait_auth_status(session,1);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
/** \brief Try to authenticate through the "keyboard-interactive" method
|
||||
@ -637,25 +694,32 @@ int ssh_userauth_kbdint(SSH_SESSION *session,char *user,char *submethods){
|
||||
int err;
|
||||
if(session->version==1)
|
||||
return SSH_AUTH_DENIED; // no keyb-interactive for ssh1
|
||||
enter_function();
|
||||
if( !session->kbdint){
|
||||
/* first time we call. we must ask for a challenge */
|
||||
if(!user)
|
||||
if(!(user=session->options->username)){
|
||||
if(ssh_options_default_username(session->options))
|
||||
return SSH_AUTH_ERROR;
|
||||
else
|
||||
if(ssh_options_default_username(session->options)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
} else
|
||||
user=session->options->username;
|
||||
}
|
||||
if(ask_userauth(session))
|
||||
return SSH_AUTH_ERROR;
|
||||
if(ask_userauth(session)){
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
err=kbdauth_init(session,user,submethods);
|
||||
if(err!=SSH_AUTH_INFO)
|
||||
return err; /* error or first try success */
|
||||
if(err!=SSH_AUTH_INFO){
|
||||
leave_function();
|
||||
return err; /* error or first try success */
|
||||
}
|
||||
err=kbdauth_info_get(session);
|
||||
if(err==SSH_AUTH_ERROR){
|
||||
kbdint_free(session->kbdint);
|
||||
session->kbdint=NULL;
|
||||
}
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
/* if we are at this point, it's because session->kbdint exists */
|
||||
@ -665,13 +729,16 @@ int ssh_userauth_kbdint(SSH_SESSION *session,char *user,char *submethods){
|
||||
err=kbdauth_send(session);
|
||||
kbdint_free(session->kbdint);
|
||||
session->kbdint=NULL;
|
||||
if(err!=SSH_AUTH_INFO)
|
||||
return err;
|
||||
if(err!=SSH_AUTH_INFO){
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
err=kbdauth_info_get(session);
|
||||
if(err==SSH_AUTH_ERROR){
|
||||
kbdint_free(session->kbdint);
|
||||
session->kbdint=NULL;
|
||||
}
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ static int channel_open(CHANNEL *channel,char *type_c,int window,
|
||||
STRING *type=string_from_char(type_c);
|
||||
u32 foo;
|
||||
int err;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_OPEN);
|
||||
channel->local_channel=ssh_channel_new_id(session);
|
||||
@ -94,6 +95,7 @@ static int channel_open(CHANNEL *channel,char *type_c,int window,
|
||||
if(channel->local_channel!=ntohl(foo)){
|
||||
ssh_set_error(session,SSH_FATAL,"server answered with sender chan num %d instead of given %d",
|
||||
ntohl(foo),channel->local_channel);
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
buffer_get_u32(session->in_buffer,&foo);
|
||||
@ -107,6 +109,7 @@ static int channel_open(CHANNEL *channel,char *type_c,int window,
|
||||
ssh_say(3,"Remote window : %ld, maxpacket : %ld\n",
|
||||
channel->remote_window, channel->remote_maxpacket);
|
||||
channel->open=1;
|
||||
leave_function();
|
||||
return 0;
|
||||
case SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
||||
{
|
||||
@ -121,12 +124,15 @@ static int channel_open(CHANNEL *channel,char *type_c,int window,
|
||||
channel->local_channel,ntohl(code),error);
|
||||
free(error);
|
||||
free(error_s);
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Received unknown packet %d\n",session->in_packet.type);
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -145,6 +151,7 @@ CHANNEL *ssh_channel_from_local(SSH_SESSION *session,u32 num){
|
||||
|
||||
static void grow_window(SSH_SESSION *session, CHANNEL *channel){
|
||||
u32 new_window=WINDOWBASE;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_WINDOW_ADJUST);
|
||||
buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
|
||||
@ -154,6 +161,7 @@ static void grow_window(SSH_SESSION *session, CHANNEL *channel){
|
||||
channel->local_channel,channel->remote_channel,
|
||||
channel->local_window + new_window);
|
||||
channel->local_window+=new_window;
|
||||
leave_function();
|
||||
}
|
||||
|
||||
static CHANNEL *channel_from_msg(SSH_SESSION *session){
|
||||
@ -173,27 +181,32 @@ static void channel_rcv_change_window(SSH_SESSION *session){
|
||||
u32 bytes;
|
||||
CHANNEL *channel;
|
||||
int err;
|
||||
enter_function();
|
||||
channel=channel_from_msg(session);
|
||||
if(!channel)
|
||||
ssh_say(0,"%s\n",ssh_get_error(session));
|
||||
err = buffer_get_u32(session->in_buffer,&bytes);
|
||||
if(!channel || err!= sizeof(u32)){
|
||||
ssh_say(1,"Error getting a window adjust message : invalid packet\n");
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
bytes=ntohl(bytes);
|
||||
ssh_say(3,"Adding %d bytes to channel (%d:%d) (from %d bytes)\n",bytes,
|
||||
channel->local_channel,channel->remote_channel,channel->remote_window);
|
||||
channel->remote_window+=bytes;
|
||||
leave_function();
|
||||
}
|
||||
|
||||
/* is_stderr is set to 1 if the data are extended, ie stderr */
|
||||
static void channel_rcv_data(SSH_SESSION *session,int is_stderr){
|
||||
STRING *str;
|
||||
CHANNEL *channel;
|
||||
enter_function();
|
||||
channel=channel_from_msg(session);
|
||||
if(!channel){
|
||||
ssh_say(0,"%s",ssh_get_error(session));
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
if(is_stderr){
|
||||
@ -205,6 +218,7 @@ static void channel_rcv_data(SSH_SESSION *session,int is_stderr){
|
||||
|
||||
if(!str){
|
||||
ssh_say(0,"Invalid data packet !\n");
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
ssh_say(3,"adding %d bytes data in %d\n",string_len(str),is_stderr);
|
||||
@ -219,26 +233,32 @@ static void channel_rcv_data(SSH_SESSION *session,int is_stderr){
|
||||
if(channel->local_window < WINDOWLIMIT)
|
||||
grow_window(session,channel); /* i wonder if this is the correct place to do that */
|
||||
free(str);
|
||||
leave_function();
|
||||
}
|
||||
|
||||
static void channel_rcv_eof(SSH_SESSION *session){
|
||||
CHANNEL *channel;
|
||||
enter_function();
|
||||
channel=channel_from_msg(session);
|
||||
if(!channel){
|
||||
ssh_say(0,"%s\n",ssh_get_error(session));
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
ssh_say(2,"Received eof on channel (%d:%d)\n",channel->local_channel,
|
||||
channel->remote_channel);
|
||||
// channel->remote_window=0;
|
||||
channel->remote_eof=1;
|
||||
leave_function();
|
||||
}
|
||||
|
||||
static void channel_rcv_close(SSH_SESSION *session){
|
||||
CHANNEL *channel;
|
||||
enter_function();
|
||||
channel=channel_from_msg(session);
|
||||
if(!channel){
|
||||
ssh_say(0,"%s\n",ssh_get_error(session));
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
ssh_say(2,"Received close on channel (%d:%d)\n",channel->local_channel,
|
||||
@ -253,6 +273,7 @@ static void channel_rcv_close(SSH_SESSION *session){
|
||||
channel->remote_eof=1;
|
||||
/* the remote eof doesn't break things if there was still data into read
|
||||
* buffer because the eof is ignored until the buffer is empty. */
|
||||
leave_function();
|
||||
}
|
||||
|
||||
static void channel_rcv_request(SSH_SESSION *session){
|
||||
@ -260,13 +281,16 @@ static void channel_rcv_request(SSH_SESSION *session){
|
||||
char *request;
|
||||
u32 status;
|
||||
CHANNEL *channel=channel_from_msg(session);
|
||||
enter_function();
|
||||
if(!channel){
|
||||
ssh_say(1,"%s\n",ssh_get_error(session));
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
request_s=buffer_get_ssh_string(session->in_buffer);
|
||||
if(!request_s){
|
||||
ssh_say(0,"Invalid MSG_CHANNEL_REQUEST\n");
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
buffer_get_u8(session->in_buffer,(u8 *)&status);
|
||||
@ -274,9 +298,10 @@ static void channel_rcv_request(SSH_SESSION *session){
|
||||
if(!strcmp(request,"exit-status")){
|
||||
buffer_get_u32(session->in_buffer,&status);
|
||||
status=ntohl(status);
|
||||
/* XXX do something with status, we might need it */
|
||||
/* TODO do something with status, we might need it */
|
||||
free(request_s);
|
||||
free(request);
|
||||
leave_function();
|
||||
return ;
|
||||
}
|
||||
if(!strcmp(request,"exit-signal")){
|
||||
@ -289,6 +314,7 @@ static void channel_rcv_request(SSH_SESSION *session){
|
||||
ssh_say(0,"Invalid MSG_CHANNEL_REQUEST\n");
|
||||
free(request_s);
|
||||
free(request);
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
signal=string_to_char(signal_s);
|
||||
@ -300,15 +326,18 @@ static void channel_rcv_request(SSH_SESSION *session){
|
||||
free(signal);
|
||||
free(request_s);
|
||||
free(request);
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
ssh_say(0,"Unknown request %s\n",request);
|
||||
free(request_s);
|
||||
free(request);
|
||||
leave_function();
|
||||
}
|
||||
|
||||
/* channel_handle is called by wait_packet, ie, when there is channel informations to handle . */
|
||||
void channel_handle(SSH_SESSION *session, int type){
|
||||
enter_function();
|
||||
ssh_say(3,"Channel_handle(%d)\n",type);
|
||||
switch(type){
|
||||
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
|
||||
@ -332,6 +361,7 @@ void channel_handle(SSH_SESSION *session, int type){
|
||||
default:
|
||||
ssh_say(0,"Unexpected message %d\n",type);
|
||||
}
|
||||
leave_function();
|
||||
}
|
||||
|
||||
/* when data has been received from the ssh server, it can be applied to the known
|
||||
@ -386,7 +416,9 @@ int channel_open_session(CHANNEL *channel){
|
||||
int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char *sourcehost, int localport){
|
||||
BUFFER *payload=buffer_new();
|
||||
STRING *str=string_from_char(remotehost);
|
||||
SSH_SESSION *session=channel->session;
|
||||
int ret;
|
||||
enter_function();
|
||||
buffer_add_ssh_string(payload,str);
|
||||
free(str);
|
||||
str=string_from_char(sourcehost);
|
||||
@ -396,6 +428,7 @@ int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char
|
||||
buffer_add_u32(payload,htonl(localport));
|
||||
ret=channel_open(channel,"direct-tcpip",64000,32000,payload);
|
||||
buffer_free(payload);
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -405,6 +438,7 @@ int channel_open_forward(CHANNEL *channel,char *remotehost, int remoteport, char
|
||||
*/
|
||||
void channel_free(CHANNEL *channel){
|
||||
SSH_SESSION *session=channel->session;
|
||||
enter_function();
|
||||
if(session->alive && channel->open)
|
||||
channel_close(channel);
|
||||
/* handle the "my channel is first on session list" case */
|
||||
@ -424,6 +458,7 @@ void channel_free(CHANNEL *channel){
|
||||
/* debug trick to catch use after frees */
|
||||
memset(channel,'X',sizeof(CHANNEL));
|
||||
free(channel);
|
||||
leave_function();
|
||||
}
|
||||
|
||||
/** it doesn't close the channel. You may still read from it but not write.
|
||||
@ -437,6 +472,7 @@ void channel_free(CHANNEL *channel){
|
||||
int channel_send_eof(CHANNEL *channel){
|
||||
SSH_SESSION *session=channel->session;
|
||||
int ret;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_EOF);
|
||||
buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
|
||||
@ -444,6 +480,7 @@ int channel_send_eof(CHANNEL *channel){
|
||||
ssh_say(1,"Sent a EOF on client channel (%d:%d)\n",channel->local_channel,
|
||||
channel->remote_channel);
|
||||
channel->local_eof=1;
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -459,10 +496,13 @@ int channel_send_eof(CHANNEL *channel){
|
||||
int channel_close(CHANNEL *channel){
|
||||
SSH_SESSION *session=channel->session;
|
||||
int ret=0;
|
||||
enter_function();
|
||||
if(!channel->local_eof)
|
||||
ret=channel_send_eof(channel);
|
||||
if(ret)
|
||||
return ret;
|
||||
if(ret){
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_CLOSE);
|
||||
buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
|
||||
@ -471,6 +511,7 @@ int channel_close(CHANNEL *channel){
|
||||
channel->remote_channel);
|
||||
if(!ret)
|
||||
channel->open =0;
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -486,18 +527,23 @@ int channel_write(CHANNEL *channel ,void *data,int len){
|
||||
SSH_SESSION *session=channel->session;
|
||||
int effectivelen;
|
||||
int origlen=len;
|
||||
enter_function();
|
||||
if(channel->local_eof){
|
||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Can't write to channel %d:%d"
|
||||
" after EOF was sent",channel->local_channel,channel->remote_channel);
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
if(!channel->open || channel->delayed_close){
|
||||
ssh_set_error(session,SSH_REQUEST_DENIED,"Remote channel is closed");
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_SSH1
|
||||
if(channel->version==1)
|
||||
return channel_write1(channel,data,len);
|
||||
if(channel->version==1){
|
||||
err = channel_write1(channel,data,len);
|
||||
leave_function();
|
||||
return err;
|
||||
#endif
|
||||
while(len >0){
|
||||
if(channel->remote_window<len){
|
||||
@ -523,6 +569,7 @@ int channel_write(CHANNEL *channel ,void *data,int len){
|
||||
len -= effectivelen;
|
||||
data+=effectivelen;
|
||||
}
|
||||
leave_function();
|
||||
return origlen;
|
||||
}
|
||||
|
||||
@ -571,6 +618,7 @@ static int channel_request(CHANNEL *channel,char *request, BUFFER *buffer,int re
|
||||
STRING *request_s=string_from_char(request);
|
||||
SSH_SESSION *session=channel->session;
|
||||
int err;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_REQUEST);
|
||||
buffer_add_u32(session->out_buffer,htonl(channel->remote_channel));
|
||||
@ -581,8 +629,10 @@ static int channel_request(CHANNEL *channel,char *request, BUFFER *buffer,int re
|
||||
packet_send(session);
|
||||
ssh_say(3,"Sent a SSH_MSG_CHANNEL_REQUEST %s\n",request);
|
||||
free(request_s);
|
||||
if(!reply)
|
||||
return 0;
|
||||
if(!reply){
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
err=packet_wait(session,SSH2_MSG_CHANNEL_SUCCESS,1);
|
||||
if(err)
|
||||
if(session->in_packet.type==SSH2_MSG_CHANNEL_FAILURE){
|
||||
@ -593,6 +643,7 @@ static int channel_request(CHANNEL *channel,char *request, BUFFER *buffer,int re
|
||||
ssh_say(3,"Received an unexpected %d message\n",session->in_packet.type);
|
||||
else
|
||||
ssh_say(3,"Received a SUCCESS\n");
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -607,10 +658,15 @@ static int channel_request(CHANNEL *channel,char *request, BUFFER *buffer,int re
|
||||
int channel_request_pty_size(CHANNEL *channel, char *terminal, int col, int row){
|
||||
STRING *term;
|
||||
BUFFER *buffer;
|
||||
SSH_SESSION *session=channel->session;
|
||||
int err;
|
||||
enter_function();
|
||||
#ifdef HAVE_SSH1
|
||||
if(channel->version==1)
|
||||
return channel_request_pty_size1(channel,terminal, col, row);
|
||||
if(channel->version==1){
|
||||
err = channel_request_pty_size1(channel,terminal, col, row);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
term=string_from_char(terminal);
|
||||
buffer=buffer_new();
|
||||
@ -625,6 +681,7 @@ int channel_request_pty_size(CHANNEL *channel, char *terminal, int col, int row)
|
||||
free(term);
|
||||
err=channel_request(channel,"pty-req",buffer,1);
|
||||
buffer_free(buffer);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -649,9 +706,14 @@ int channel_request_pty(CHANNEL *channel){
|
||||
int channel_change_pty_size(CHANNEL *channel,int cols,int rows){
|
||||
BUFFER *buffer;
|
||||
int err;
|
||||
SSH_SESSION *session=channel->session;
|
||||
enter_function();
|
||||
#ifdef HAVE_SSH1
|
||||
if(channel->version==1)
|
||||
return channel_change_pty_size1(channel,cols,rows);
|
||||
if(channel->version==1){
|
||||
err = channel_change_pty_size1(channel,cols,rows);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
buffer=buffer_new();
|
||||
//buffer_add_u8(buffer,0);
|
||||
@ -661,6 +723,7 @@ int channel_change_pty_size(CHANNEL *channel,int cols,int rows){
|
||||
buffer_add_u32(buffer,0);
|
||||
err=channel_request(channel,"window-change",buffer,0);
|
||||
buffer_free(buffer);
|
||||
leave_function();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -764,9 +827,11 @@ int channel_request_exec(CHANNEL *channel, char *cmd){
|
||||
*/
|
||||
int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
|
||||
BUFFER *stdbuf=NULL;
|
||||
SSH_SESSION *session=channel->session;
|
||||
int len;
|
||||
buffer_reinit(buffer);
|
||||
int maxread=bytes;
|
||||
enter_function();
|
||||
if(bytes==0)
|
||||
maxread=MAX_PACKET_LEN;
|
||||
/* maybe i should always set a buffer to avoid races between channel_default_bufferize and channel_read */
|
||||
@ -777,15 +842,19 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
|
||||
|
||||
/* block reading if asked bytes=0 */
|
||||
while((buffer_get_rest_len(stdbuf)==0) || (buffer_get_rest_len(stdbuf) < bytes)){
|
||||
if(channel->remote_eof && buffer_get_rest_len(stdbuf)==0)
|
||||
return 0;
|
||||
if(channel->remote_eof && buffer_get_rest_len(stdbuf)==0){
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
if(channel->remote_eof)
|
||||
break; /* return the resting bytes in buffer */
|
||||
if(buffer_get_rest_len(stdbuf)>=maxread) // stop reading when buffer is full enough
|
||||
break;
|
||||
if(packet_read(channel->session)||packet_translate(channel->session))
|
||||
return -1;
|
||||
packet_parse(channel->session);
|
||||
if(packet_read(session)||packet_translate(session)){
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
packet_parse(session);
|
||||
}
|
||||
|
||||
if(bytes==0){
|
||||
@ -798,6 +867,7 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
|
||||
buffer_add_data(buffer,buffer_get_rest(stdbuf),len);
|
||||
buffer_pass_bytes(stdbuf,len);
|
||||
}
|
||||
leave_function();
|
||||
return buffer_get_len(buffer);
|
||||
}
|
||||
|
||||
@ -812,7 +882,9 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
|
||||
*/
|
||||
int channel_poll(CHANNEL *channel, int is_stderr){
|
||||
BUFFER *buffer;
|
||||
SSH_SESSION *session=channel->session;
|
||||
int r=0;
|
||||
enter_function();
|
||||
if(is_stderr)
|
||||
buffer=channel->stderr_buffer;
|
||||
else
|
||||
@ -823,8 +895,11 @@ int channel_poll(CHANNEL *channel, int is_stderr){
|
||||
if(r<=0)
|
||||
break;
|
||||
}
|
||||
if(channel->remote_eof)
|
||||
return 1;
|
||||
if(channel->remote_eof){
|
||||
leave_function();
|
||||
return 1;
|
||||
}
|
||||
leave_function();
|
||||
return buffer_get_rest_len(buffer);
|
||||
}
|
||||
|
||||
@ -845,11 +920,14 @@ int channel_poll(CHANNEL *channel, int is_stderr){
|
||||
* \see channel_is_eof()
|
||||
*/
|
||||
int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stderr){
|
||||
SSH_SESSION *session=channel->session;
|
||||
enter_function();
|
||||
int to_read=channel_poll(channel,is_stderr);
|
||||
int lu;
|
||||
BUFFER *buffer=buffer_new();
|
||||
if(to_read<=0){
|
||||
buffer_free(buffer);
|
||||
leave_function();
|
||||
return to_read; /* may be an error code */
|
||||
}
|
||||
if(to_read>len)
|
||||
@ -857,6 +935,7 @@ int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stder
|
||||
lu=channel_read(channel,buffer,to_read,is_stderr);
|
||||
memcpy(dest,buffer_get(buffer),lu>=0?lu:0);
|
||||
buffer_free(buffer);
|
||||
leave_function();
|
||||
return lu;
|
||||
}
|
||||
|
||||
|
@ -34,20 +34,26 @@ MA 02111-1307, USA. */
|
||||
char *ssh_get_banner(SSH_SESSION *session){
|
||||
char buffer[128];
|
||||
int i = 0;
|
||||
char *ret;
|
||||
enter_function();
|
||||
while (i < 127) {
|
||||
if(!ssh_socket_is_open(session->socket) || ssh_socket_read(session->socket, &buffer[i], 1)<=0){
|
||||
ssh_set_error(session,SSH_FATAL,"Remote host closed connection");
|
||||
leave_function();
|
||||
return NULL;
|
||||
}
|
||||
if (buffer[i] == '\r')
|
||||
buffer[i] = 0;
|
||||
if (buffer[i] == '\n') {
|
||||
buffer[i] = 0;
|
||||
return strdup(buffer);
|
||||
ret= strdup(buffer);
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ssh_set_error(session,SSH_FATAL,"Too large banner");
|
||||
leave_function();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -89,6 +95,7 @@ int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2){
|
||||
int ssh_send_banner(SSH_SESSION *session,int server){
|
||||
char *banner;
|
||||
char buffer[128];
|
||||
enter_function();
|
||||
banner=session->version==1?CLIENTBANNER1:CLIENTBANNER2;
|
||||
if(session->options->banner)
|
||||
banner=session->options->banner;
|
||||
@ -98,6 +105,7 @@ int ssh_send_banner(SSH_SESSION *session,int server){
|
||||
session->clientbanner=strdup(banner);
|
||||
snprintf(buffer,128,"%s\r\n",banner);
|
||||
ssh_socket_write(session->socket,buffer,strlen(buffer));
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -110,6 +118,7 @@ int ssh_send_banner(SSH_SESSION *session,int server){
|
||||
static int dh_handshake(SSH_SESSION *session){
|
||||
STRING *e,*f,*pubkey,*signature;
|
||||
int ret;
|
||||
enter_function();
|
||||
switch(session->dh_handshake_state){
|
||||
case DH_STATE_INIT:
|
||||
packet_clear_out(session);
|
||||
@ -121,32 +130,41 @@ static int dh_handshake(SSH_SESSION *session){
|
||||
ret=packet_send(session);
|
||||
free(e);
|
||||
session->dh_handshake_state=DH_STATE_INIT_TO_SEND;
|
||||
if(ret==SSH_ERROR)
|
||||
if(ret==SSH_ERROR){
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
case DH_STATE_INIT_TO_SEND:
|
||||
ret=packet_flush(session,0);
|
||||
if(ret!=SSH_OK)
|
||||
return ret; // SSH_ERROR or SSH_AGAIN
|
||||
if(ret!=SSH_OK){
|
||||
leave_function();
|
||||
return ret; // SSH_ERROR or SSH_AGAIN
|
||||
}
|
||||
session->dh_handshake_state=DH_STATE_INIT_SENT;
|
||||
case DH_STATE_INIT_SENT:
|
||||
ret=packet_wait(session,SSH2_MSG_KEXDH_REPLY,1);
|
||||
if(ret != SSH_OK)
|
||||
return ret;
|
||||
if(ret != SSH_OK){
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
pubkey=buffer_get_ssh_string(session->in_buffer);
|
||||
if(!pubkey){
|
||||
ssh_set_error(session,SSH_FATAL,"No public key in packet");
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
dh_import_pubkey(session,pubkey);
|
||||
f=buffer_get_ssh_string(session->in_buffer);
|
||||
if(!f){
|
||||
ssh_set_error(session,SSH_FATAL,"No F number in packet");
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
dh_import_f(session,f);
|
||||
free(f);
|
||||
if(!(signature=buffer_get_ssh_string(session->in_buffer))){
|
||||
ssh_set_error(session,SSH_FATAL,"No signature in packet");
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->dh_server_signature=signature;
|
||||
@ -158,26 +176,33 @@ static int dh_handshake(SSH_SESSION *session){
|
||||
session->dh_handshake_state=DH_STATE_NEWKEYS_TO_SEND;
|
||||
case DH_STATE_NEWKEYS_TO_SEND:
|
||||
ret=packet_flush(session,0);
|
||||
if(ret != SSH_OK)
|
||||
return ret;
|
||||
if(ret != SSH_OK){
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
|
||||
session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
|
||||
case DH_STATE_NEWKEYS_SENT:
|
||||
ret=packet_wait(session,SSH2_MSG_NEWKEYS,1);
|
||||
if(ret != SSH_OK)
|
||||
return ret;
|
||||
if(ret != SSH_OK){
|
||||
leave_function();
|
||||
return ret;
|
||||
}
|
||||
ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
|
||||
make_sessionid(session);
|
||||
/* set the cryptographic functions for the next crypto */
|
||||
/* (it is needed for generate_session_keys for key lenghts) */
|
||||
if(crypt_set_algorithms(session))
|
||||
return SSH_ERROR;
|
||||
if(crypt_set_algorithms(session)){
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
generate_session_keys(session);
|
||||
/* verify the host's signature. XXX do it sooner */
|
||||
signature=session->dh_server_signature;
|
||||
session->dh_server_signature=NULL;
|
||||
if(signature_verify(session,signature)){
|
||||
free(signature);
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
free(signature); /* forget it for now ... */
|
||||
@ -188,17 +213,21 @@ static int dh_handshake(SSH_SESSION *session){
|
||||
session->current_crypto=session->next_crypto;
|
||||
session->next_crypto=crypto_new();
|
||||
session->dh_handshake_state=DH_STATE_FINISHED;
|
||||
leave_function();
|
||||
return SSH_OK;
|
||||
default:
|
||||
ssh_set_error(session,SSH_FATAL,"Invalid state in dh_handshake():%d",session->dh_handshake_state);
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* not reached */
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int ssh_service_request(SSH_SESSION *session,char *service){
|
||||
STRING *service_s;
|
||||
enter_function();
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_REQUEST);
|
||||
service_s=string_from_char(service);
|
||||
@ -208,9 +237,11 @@ int ssh_service_request(SSH_SESSION *session,char *service){
|
||||
ssh_say(3,"Sent SSH_MSG_SERVICE_REQUEST (service %s)\n",service);
|
||||
if(packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1)){
|
||||
ssh_set_error(session,SSH_FATAL,"did not receive SERVICE_ACCEPT");
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
ssh_say(3,"Received SSH_MSG_SERVICE_ACCEPT (service %s)\n",service);
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -231,12 +262,14 @@ int ssh_connect(SSH_SESSION *session){
|
||||
ssh_set_error(session,SSH_FATAL,"Must set options before connect");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
enter_function();
|
||||
session->alive=0;
|
||||
session->client=1;
|
||||
ssh_crypto_init();
|
||||
ssh_socket_init();
|
||||
if(options->fd==-1 && !options->host){
|
||||
ssh_set_error(session,SSH_FATAL,"Hostname required");
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if(options->fd != -1)
|
||||
@ -244,14 +277,17 @@ int ssh_connect(SSH_SESSION *session){
|
||||
else
|
||||
fd=ssh_connect_host(session,options->host,options->bindaddr,options->port,
|
||||
options->timeout,options->timeout_usec);
|
||||
if(fd<0)
|
||||
return -1;
|
||||
if(fd<0){
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
set_status(options,0.2);
|
||||
ssh_socket_set_fd(session->socket,fd);
|
||||
session->alive=1;
|
||||
if(!(session->serverbanner=ssh_get_banner(session))){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
set_status(options,0.4);
|
||||
@ -260,6 +296,7 @@ int ssh_connect(SSH_SESSION *session){
|
||||
if(ssh_analyze_banner(session,&ssh1,&ssh2)){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
/* here we decide which version of the protocol to use */
|
||||
@ -273,6 +310,7 @@ int ssh_connect(SSH_SESSION *session){
|
||||
session->serverbanner);
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
ssh_send_banner(session,0);
|
||||
@ -282,6 +320,7 @@ int ssh_connect(SSH_SESSION *session){
|
||||
if(ssh_get_kex(session,0)){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
set_status(options,0.6);
|
||||
@ -289,6 +328,7 @@ int ssh_connect(SSH_SESSION *session){
|
||||
if(set_kex(session)){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
ssh_send_kex(session,0);
|
||||
@ -296,6 +336,7 @@ int ssh_connect(SSH_SESSION *session){
|
||||
if(dh_handshake(session)){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
set_status(options,1.0);
|
||||
@ -305,12 +346,14 @@ int ssh_connect(SSH_SESSION *session){
|
||||
if(ssh_get_kex1(session)){
|
||||
ssh_socket_close(session->socket);
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
set_status(options,0.6);
|
||||
session->connected=1;
|
||||
break;
|
||||
}
|
||||
leave_function();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -331,6 +374,7 @@ char *ssh_get_issue_banner(SSH_SESSION *session){
|
||||
*/
|
||||
void ssh_disconnect(SSH_SESSION *session){
|
||||
STRING *str;
|
||||
enter_function();
|
||||
if(ssh_socket_is_open(session->socket)) {
|
||||
packet_clear_out(session);
|
||||
buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT);
|
||||
@ -342,6 +386,7 @@ void ssh_disconnect(SSH_SESSION *session){
|
||||
ssh_socket_close(session->socket);
|
||||
}
|
||||
session->alive=0;
|
||||
leave_function();
|
||||
ssh_cleanup(session);
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,7 @@ int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host, int port, str
|
||||
fd_set set;
|
||||
int ret=0;
|
||||
unsigned int len=sizeof(ret);
|
||||
enter_function();
|
||||
to.tv_sec=timeout;
|
||||
to.tv_usec=usec;
|
||||