diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2008-06-12 20:14:17 +0000 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2008-06-12 20:14:17 +0000 |
commit | fe51f9c7662b7391f80953bedc4fe61b89013913 (patch) | |
tree | 66e1390ec6f593ba32b7a881040a303fd2669653 | |
parent | b94422ef10bb083dde58e8c8349cc3e004888f9f (diff) | |
download | libssh-fe51f9c7662b7391f80953bedc4fe61b89013913.tar.gz libssh-fe51f9c7662b7391f80953bedc4fe61b89013913.tar.xz libssh-fe51f9c7662b7391f80953bedc4fe61b89013913.zip |
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
-rw-r--r-- | Doxyfile | 2 | ||||
-rw-r--r-- | include/libssh/libssh.h | 18 | ||||
-rw-r--r-- | include/libssh/priv.h | 25 | ||||
-rw-r--r-- | libssh/Makefile.am | 2 | ||||
-rw-r--r-- | libssh/auth.c | 171 | ||||
-rw-r--r-- | libssh/channels.c | 115 | ||||
-rw-r--r-- | libssh/client.c | 73 | ||||
-rw-r--r-- | libssh/connect.c | 20 | ||||
-rw-r--r-- | libssh/dh.c | 18 | ||||
-rw-r--r-- | libssh/kex.c | 28 | ||||
-rw-r--r-- | libssh/keyfiles.c | 1 | ||||
-rw-r--r-- | libssh/log.c | 61 | ||||
-rw-r--r-- | libssh/messages.c | 98 | ||||
-rw-r--r-- | libssh/options.c | 27 | ||||
-rw-r--r-- | libssh/packet.c | 109 | ||||
-rw-r--r-- | libssh/session.c | 19 | ||||
-rw-r--r-- | libssh/sftp.c | 40 |
17 files changed, 654 insertions, 173 deletions
@@ -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. diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index f0114f88..c7f0d5c0 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -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 */ diff --git a/include/libssh/priv.h b/include/libssh/priv.h index fa8ba3c2..d5aeda82 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -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); diff --git a/libssh/Makefile.am b/libssh/Makefile.am index 50367a4e..a98fb01b 100644 --- a/libssh/Makefile.am +++ b/libssh/Makefile.am @@ -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 diff --git a/libssh/auth.c b/libssh/auth.c index ff1e1ed3..a2fd722d 100644 --- a/libssh/auth.c +++ b/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; } diff --git a/libssh/channels.c b/libssh/channels.c index 41c71dae..be87ca3e 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -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; } diff --git a/libssh/client.c b/libssh/client.c index d8dffcc6..f06a7363 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -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); } diff --git a/libssh/connect.c b/libssh/connect.c index 504882db..dacb291f 100644 --- a/libssh/connect.c +++ b/libssh/connect.c @@ -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; sock_set_nonblocking(s); @@ -110,11 +111,13 @@ int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host, int port, str /* timeout */ ssh_set_error(session,SSH_FATAL,"Timeout while connecting to %s:%d",host,port); close(s); + leave_function(); return -1; } if(ret<0){ ssh_set_error(session,SSH_FATAL,"Select error : %s",strerror(errno)); close(s); + leave_function(); return -1; } ret = 0; @@ -123,11 +126,13 @@ int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host, int port, str if (ret!=0){ ssh_set_error(session,SSH_FATAL,"Connecting : %s",strerror(ret)); close(s); + leave_function(); return -1; } /* s is connected ? */ ssh_say(3,"socket connected with timeout\n"); sock_set_blocking(s); + leave_function(); return s; } @@ -140,10 +145,11 @@ socket_t ssh_connect_host(SSH_SESSION *session, const char *host, const char socket_t s=-1; int my_errno; struct addrinfo *ai, *ai2; - + enter_function(); my_errno=getai(host, port, &ai); if (my_errno){ ssh_set_error(session,SSH_FATAL,"Failed to resolve hostname %s (%s)",host,gai_strerror(my_errno)); + leave_function(); return -1; } @@ -162,6 +168,7 @@ socket_t ssh_connect_host(SSH_SESSION *session, const char *host, const char my_errno=getai(host,0,&bind_ai); if (my_errno){ ssh_set_error(session,SSH_FATAL,"Failed to resolve bind address %s (%s)",bind_addr,gai_strerror(my_errno)); + leave_function(); return -1; } @@ -182,12 +189,15 @@ socket_t ssh_connect_host(SSH_SESSION *session, const char *host, const char } } if(timeout||usec){ - return ssh_connect_ai_timeout(session,host,port,ai2,timeout,usec,s); + socket_t ret=ssh_connect_ai_timeout(session,host,port,ai2,timeout,usec,s); + leave_function(); + return ret; } if(connect(s,ai2->ai_addr,ai2->ai_addrlen)<0){ ssh_set_error(session,SSH_FATAL,"connect: %s",strerror(errno)); close(s); s=-1; + leave_function(); continue; } else{ /*we are connected*/ @@ -195,6 +205,7 @@ socket_t ssh_connect_host(SSH_SESSION *session, const char *host, const char } } freeaddrinfo(ai); + leave_function(); return s; } @@ -214,7 +225,7 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ fd_set wdes; // writing set fd_set edes; // exception set int fdmax=-1; - + enter_function(); FD_ZERO(&rdes); FD_ZERO(&wdes); FD_ZERO(&edes); @@ -223,6 +234,7 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ *except=1; *write=0; session->alive=0; + leave_function(); return 0; } if(!session->data_to_read) @@ -238,6 +250,7 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ /* Make the call, and listen for errors */ if (select(fdmax, &rdes,&wdes,&edes, &sometime) < 0) { ssh_set_error(session,SSH_FATAL, "select: %s", strerror(errno)); + leave_function(); return -1; } if(!session->data_to_read) @@ -246,6 +259,7 @@ int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){ session->data_to_write=ssh_socket_fd_isset(session->socket,&wdes); *except=ssh_socket_fd_isset(session->socket,&edes); *write=session->data_to_write; + leave_function(); return session->data_to_read; } diff --git a/libssh/dh.c b/libssh/dh.c index be660888..bfbab9cd 100644 --- a/libssh/dh.c +++ b/libssh/dh.c @@ -1,7 +1,7 @@ /* dh.c */ /* this file contains usefull stuff for Diffie helman algorithm against SSH 2 */ /* -Copyright 2003 Aris Adamantiadis +Copyright 2003-2008 Aris Adamantiadis This file is part of the SSH Library @@ -310,6 +310,7 @@ void make_sessionid(SSH_SESSION *session){ BUFFER *server_hash, *client_hash; BUFFER *buf=buffer_new(); u32 len; + enter_function(); ctx=sha1_init(); str=string_from_char(session->clientbanner); @@ -379,6 +380,7 @@ void make_sessionid(SSH_SESSION *session){ printf("Session hash : "); ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LEN); #endif + leave_function(); } void hashbufout_add_cookie(SSH_SESSION *session){ @@ -409,6 +411,7 @@ static void generate_one_key(STRING *k,unsigned char session_id[SHA_DIGEST_LEN], void generate_session_keys(SSH_SESSION *session){ STRING *k_string; SHACTX ctx; + enter_function(); k_string=make_bignum_string(session->next_crypto->k); /* IV */ @@ -460,6 +463,7 @@ void generate_session_keys(SSH_SESSION *session){ ssh_print_hexa("Decryption MAC",session->next_crypto->decryptMAC,20); #endif free(k_string); + leave_function(); } /** \addtogroup ssh_session @@ -587,18 +591,24 @@ int signature_verify(SSH_SESSION *session,STRING *signature){ PUBLIC_KEY *pubkey; SIGNATURE *sign; int err; + enter_function(); if(session->options->dont_verify_hostkey){ ssh_say(1,"Host key wasn't verified\n"); + leave_function(); return 0; } pubkey=publickey_from_string(session,session->next_crypto->server_pubkey); - if(!pubkey) - return -1; + if(!pubkey){ + leave_function(); + return -1; + } + if(session->options->wanted_methods[SSH_HOSTKEYS]){ if(match(session->options->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)){ ssh_set_error(session,SSH_FATAL,"Public key from server (%s) doesn't match user preference (%s)", pubkey->type_c,session->options->wanted_methods[SSH_HOSTKEYS]); publickey_free(pubkey); + leave_function(); return -1; } } @@ -606,6 +616,7 @@ int signature_verify(SSH_SESSION *session,STRING *signature){ if(!sign){ ssh_set_error(session,SSH_FATAL,"Invalid signature blob"); publickey_free(pubkey); + leave_function(); return -1; } ssh_say(1,"Going to verify a %s type signature\n",pubkey->type_c); @@ -613,6 +624,7 @@ int signature_verify(SSH_SESSION *session,STRING *signature){ signature_free(sign); session->next_crypto->server_pubkey_type=pubkey->type_c; publickey_free(pubkey); + leave_function(); return err; } diff --git a/libssh/kex.c b/libssh/kex.c index 9a2c30f7..0856fdfe 100644 --- a/libssh/kex.c +++ b/libssh/kex.c @@ -165,10 +165,14 @@ int ssh_get_kex(SSH_SESSION *session,int server_kex ){ STRING *str; char *strings[10]; int i; - if(packet_wait(session,SSH2_MSG_KEXINIT,1)) - return -1; + enter_function(); + if(packet_wait(session,SSH2_MSG_KEXINIT,1)){ + leave_function(); + return -1; + } if(buffer_get_data(session->in_buffer,session->server_kex.cookie,16)!=16){ ssh_set_error(session,SSH_FATAL,"get_kex(): no cookie in packet"); + leave_function(); return -1; } hashbufin_add_cookie(session,session->server_kex.cookie); @@ -194,6 +198,7 @@ int ssh_get_kex(SSH_SESSION *session,int server_kex ){ for(i=0;i<10;++i) session->server_kex.methods[i]=strings[i]; } + leave_function(); return 0; } @@ -217,6 +222,7 @@ int set_kex(SSH_SESSION *session){ SSH_OPTIONS *options=session->options; int i; char *wanted; + enter_function(); /* the client might ask for a specific cookie to be sent. useful for server debugging */ if(options->wanted_cookie) memcpy(client->cookie,options->wanted_cookie,16); @@ -231,12 +237,14 @@ int set_kex(SSH_SESSION *session){ if(!client->methods[i] && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s", wanted,server->methods[i],ssh_kex_nums[i]); + leave_function(); return -1; } else { if(i>=SSH_LANG_C_S && !client->methods[i]) client->methods[i]=strdup(""); // we can safely do that for languages } } + leave_function(); return 0; } @@ -245,6 +253,7 @@ void ssh_send_kex(SSH_SESSION *session, int server_kex){ STRING *str; int i=0; KEX *kex=(server_kex ? &session->server_kex : &session->client_kex); + enter_function(); packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_KEXINIT); buffer_add_data(session->out_buffer,kex->cookie,16); @@ -260,6 +269,7 @@ void ssh_send_kex(SSH_SESSION *session, int server_kex){ buffer_add_u8(session->out_buffer,0); buffer_add_u32(session->out_buffer,0); packet_send(session); + leave_function(); } /* returns 1 if at least one of the name algos is in the default algorithms table */ @@ -401,13 +411,16 @@ int ssh_get_kex1(SSH_SESSION *session){ PUBLIC_KEY *svr,*host; int ko; u16 bits; + enter_function(); ssh_say(3,"Waiting for a SSH_SMSG_PUBLIC_KEY\n"); if(packet_wait(session,SSH_SMSG_PUBLIC_KEY,1)){ + leave_function(); return -1; } ssh_say(3,"Got a SSH_SMSG_PUBLIC_KEY\n"); if(buffer_get_data(session->in_buffer,session->server_kex.cookie,8)!=8){ ssh_set_error(session,SSH_FATAL,"Can't get cookie in buffer"); + leave_function(); return -1; } buffer_get_u32(session->in_buffer,&server_bits); @@ -430,6 +443,7 @@ int ssh_get_kex1(SSH_SESSION *session){ free(server_mod); if(server_exp) free(server_exp); + leave_function(); return -1; } server_bits=ntohl(server_bits); @@ -457,6 +471,7 @@ int ssh_get_kex1(SSH_SESSION *session){ /* hardcode 3des */ if(!(supported_ciphers_mask & (1<<SSH_CIPHER_3DES))){ ssh_set_error(session,SSH_FATAL,"Remote server doesn't accept 3des"); + leave_function(); return -1; } packet_clear_out(session); @@ -477,18 +492,21 @@ int ssh_get_kex1(SSH_SESSION *session){ packet_send(session); /* we can set encryption */ - if(crypt_set_algorithms(session)) - return -1; + if(crypt_set_algorithms(session)){ + leave_function(); + return -1; + } session->current_crypto=session->next_crypto; session->next_crypto=NULL; if(packet_wait(session,SSH_SMSG_SUCCESS,1)){ char buffer[1024]; snprintf(buffer,sizeof(buffer),"Key exchange failed : %s",ssh_get_error(session)); ssh_set_error(session,SSH_FATAL,"%s",buffer); + leave_function(); return -1; } ssh_say(1,"received SSH_SMSG_SUCCESS\n"); + leave_function(); return 0; } - diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index 48fe16cd..63e182ed 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -850,6 +850,7 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){ * \see ssh_options_set_wanted_algo() * \see ssh_get_pubkey_hash() * \bug there is no current way to remove or modify an entry into the known host table + * \todo TODO this is a real mess. Clean this up someday */ int ssh_is_server_known(SSH_SESSION *session){ char *pubkey_64; diff --git a/libssh/log.c b/libssh/log.c new file mode 100644 index 00000000..fbea05d8 --- /dev/null +++ b/libssh/log.c @@ -0,0 +1,61 @@ +/* + * Copyright 2008 Aris Adamantiadis + * + * This file is part of the SSH Library + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ + + +/** \defgroup ssh_log SSH logging + * \brief Logging functions for debugging and problem resolving + */ +/** \addtogroup ssh_log + * @{ */ +#include "libssh/priv.h" +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +/** \brief logs an event + * \param session the SSH session + * \param verbosity verbosity of the event + * \param format format string of the log entry + */ +void ssh_log(SSH_SESSION *session, int verbosity, char *format, ...){ + char buffer[1024]; + char buf2[256]; + int min; + va_list va; + if(verbosity <= session->log_verbosity){ + va_start(va,format); + vsnprintf(buffer,sizeof(buffer),format,va); + va_end(va); + if(session->options->log_function) + session->options->log_function(buffer,session,verbosity); + else if(verbosity==SSH_LOG_FUNCTIONS){ + if(session->log_indent > 255) + min=255; + else + min=session->log_indent; + memset(buf2,' ',min); + buf2[min]=0; + fprintf(stderr,"[func] %s%s\n",buf2,buffer); + } else { + fprintf(stderr,"[%d] %s\n",verbosity,buffer); + } + } +} + +/** @} */ diff --git a/libssh/messages.c b/libssh/messages.c index 5743ab80..be785e4a 100644 --- a/libssh/messages.c +++ b/libssh/messages.c @@ -48,9 +48,11 @@ static SSH_MESSAGE *message_new(SSH_SESSION *session){ static int handle_service_request(SSH_SESSION *session){ STRING *service; char *service_c; + enter_function(); service=buffer_get_ssh_string(session->in_buffer); if(!service){ ssh_set_error(session,SSH_FATAL,"Invalid SSH_MSG_SERVICE_REQUEST packet"); + leave_function(); return -1; } service_c=string_to_char(service); @@ -61,6 +63,7 @@ static int handle_service_request(SSH_SESSION *session){ buffer_add_ssh_string(session->out_buffer,service); packet_send(session); free(service); + leave_function(); return 0; } @@ -76,6 +79,7 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){ STRING *method=buffer_get_ssh_string(session->in_buffer); SSH_MESSAGE *msg; char *service_c,*method_c; + enter_function(); msg=message_new(session); msg->type=SSH_AUTH_REQUEST; msg->auth_request.username=string_to_char(user); @@ -88,6 +92,7 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){ if(!strcmp(method_c,"none")){ msg->auth_request.method=SSH_AUTH_NONE; free(method_c); + leave_function(); return msg; } if(!strcmp(method_c,"password")){ @@ -99,10 +104,12 @@ static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){ pass=buffer_get_ssh_string(session->in_buffer); msg->auth_request.password=string_to_char(pass); free(pass); + leave_function(); return msg; } msg->auth_request.method=SSH_AUTH_UNKNOWN; free(method_c); + leave_function(); return msg; } @@ -121,18 +128,21 @@ void ssh_message_auth_set_methods(SSH_MESSAGE *msg,int methods){ static int ssh_message_auth_reply_default(SSH_MESSAGE *msg,int partial){ char methods_c[128]=""; STRING *methods; - packet_clear_out(msg->session); - buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_FAILURE); - if(msg->session->auth_methods==0){ - msg->session->auth_methods=SSH_AUTH_PUBLICKEY|SSH_AUTH_PASSWORD; + SSH_SESSION *session=msg->session; + int ret; + enter_function(); + packet_clear_out(session); + buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_FAILURE); + if(session->auth_methods==0){ + session->auth_methods=SSH_AUTH_PUBLICKEY|SSH_AUTH_PASSWORD; } - if(msg->session->auth_methods & SSH_AUTH_PUBLICKEY) + if(session->auth_methods & SSH_AUTH_PUBLICKEY) strcat(methods_c,"publickey,"); - if(msg->session->auth_methods & SSH_AUTH_KEYBINT) + if(session->auth_methods & SSH_AUTH_KEYBINT) strcat(methods_c,"keyboard-interactive,"); - if(msg->session->auth_methods & SSH_AUTH_PASSWORD) + if(session->auth_methods & SSH_AUTH_PASSWORD) strcat(methods_c,"password,"); - if(msg->session->auth_methods & SSH_AUTH_HOSTBASED) + if(session->auth_methods & SSH_AUTH_HOSTBASED) strcat(methods_c,"hostbased,"); methods_c[strlen(methods_c)-1]=0; // strip the comma. We are sure there is at // least one word into the list @@ -141,10 +151,12 @@ static int ssh_message_auth_reply_default(SSH_MESSAGE *msg,int partial){ buffer_add_ssh_string(msg->session->out_buffer,methods); free(methods); if(partial) - buffer_add_u8(msg->session->out_buffer,1); + buffer_add_u8(session->out_buffer,1); else - buffer_add_u8(msg->session->out_buffer,0); // no partial success - return packet_send(msg->session); + buffer_add_u8(session->out_buffer,0); // no partial success + ret = packet_send(msg->session); + leave_function(); + return ret; } int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial){ @@ -156,6 +168,7 @@ int ssh_message_auth_reply_success(SSH_MESSAGE *msg,int partial){ } static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session){ + enter_function(); SSH_MESSAGE *msg=message_new(session); STRING *type; char *type_c; @@ -173,32 +186,38 @@ static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session){ msg->channel_request_open.packet_size=ntohl(packet); if(!strcmp(type_c,"session")){ msg->channel_request_open.type=SSH_CHANNEL_SESSION; + leave_function(); return msg; } msg->channel_request_open.type=SSH_CHANNEL_UNKNOWN; + leave_function(); return msg; } CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg){ - CHANNEL *chan=channel_new(msg->session); - chan->local_channel=ssh_channel_new_id(msg->session); + SSH_SESSION *session=msg->session; + enter_function(); + CHANNEL *chan=channel_new(session); + chan->local_channel=ssh_channel_new_id(session); chan->local_maxpacket=35000; chan->local_window=32000; chan->remote_channel=msg->channel_request_open.sender; chan->remote_maxpacket=msg->channel_request_open.packet_size; chan->remote_window=msg->channel_request_open.window; chan->open=1; - packet_clear_out(msg->session); - buffer_add_u8(msg->session->out_buffer,SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - buffer_add_u32(msg->session->out_buffer,htonl(chan->remote_channel)); - buffer_add_u32(msg->session->out_buffer,htonl(chan->local_channel)); - buffer_add_u32(msg->session->out_buffer,htonl(chan->local_window)); - buffer_add_u32(msg->session->out_buffer,htonl(chan->local_maxpacket)); + packet_clear_out(session); + buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + buffer_add_u32(session->out_buffer,htonl(chan->remote_channel)); + buffer_add_u32(session->out_buffer,htonl(chan->local_channel)); + buffer_add_u32(session->out_buffer,htonl(chan->local_window)); + buffer_add_u32(session->out_buffer,htonl(chan->local_maxpacket)); ssh_say(2,"Accepting a channel request_open for chan %d\n",chan->remote_channel); - if(packet_send(msg->session)){ + if(packet_send(session)){ channel_free(chan); + leave_function(); return NULL; } + leave_function(); return chan; } @@ -219,6 +238,7 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){ char *type_c; u8 want_reply; SSH_MESSAGE *msg=message_new(session); + enter_function(); buffer_get_u32(session->in_buffer,&channel); channel=ntohl(channel); type=buffer_get_ssh_string(session->in_buffer); @@ -247,6 +267,7 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){ msg->channel_request.pxwidth=ntohl(msg->channel_request.pxwidth); msg->channel_request.pxheight=ntohl(msg->channel_request.pxheight); msg->channel_request.modes=buffer_get_ssh_string(session->in_buffer); + leave_function(); return msg; } if(!strcmp(type_c,"subsystem")){ @@ -257,10 +278,12 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){ free(subsys); msg->channel_request.type=SSH_CHANNEL_REQUEST_SUBSYSTEM; msg->channel_request.subsystem=subsys_c; + leave_function(); return msg; } if(!strcmp(type_c,"shell")){ msg->channel_request.type=SSH_CHANNEL_REQUEST_SHELL; + leave_function(); return msg; } if(!strcmp(type_c,"exec")){ @@ -268,10 +291,12 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session){ msg->channel_request.type=SSH_CHANNEL_REQUEST_EXEC; msg->channel_request.command=string_to_char(cmd); free(cmd); + leave_function(); return msg; } msg->channel_request.type=SSH_CHANNEL_UNKNOWN; + leave_function(); return msg; } @@ -310,34 +335,43 @@ static int ssh_message_channel_request_reply_default(SSH_MESSAGE *msg){ } SSH_MESSAGE *ssh_message_get(SSH_SESSION *session){ + SSH_MESSAGE *ret; + enter_function(); while(1){ - if(packet_read(session)) - return NULL; - if(packet_translate(session)) - return NULL; + if(packet_read(session) || packet_translate(session)){ + leave_function(); + return NULL; + } switch(session->in_packet.type){ case SSH2_MSG_SERVICE_REQUEST: - if(handle_service_request(session)) - return NULL; + if(handle_service_request(session)){ + leave_function(); + return NULL; + } break; case SSH2_MSG_IGNORE: case SSH2_MSG_DEBUG: break; case SSH2_MSG_USERAUTH_REQUEST: - return handle_userauth_request(session); - break; + ret = handle_userauth_request(session); + leave_function(); + return ret; case SSH2_MSG_CHANNEL_OPEN: - return handle_channel_request_open(session); - break; + ret = handle_channel_request_open(session); + leave_function(); + return ret; case SSH2_MSG_CHANNEL_REQUEST: - return handle_channel_request(session); - break; + ret = handle_channel_request(session); + leave_function(); + return ret; default: handle_unimplemented(session); ssh_set_error(session,SSH_FATAL,"Unhandled message %d\n",session->in_packet.type); + leave_function(); return NULL; } } + leave_function(); return NULL; } diff --git a/libssh/options.c b/libssh/options.c index cea7325e..570ef412 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -108,6 +108,8 @@ SSH_OPTIONS *ssh_options_copy(SSH_OPTIONS *opt){ ret->timeout_usec=opt->timeout_usec; ret->ssh2allowed=opt->ssh2allowed; ret->ssh1allowed=opt->ssh1allowed; + ret->log_function=opt->log_function; + ret->log_verbosity=opt->log_verbosity; return ret; } @@ -406,6 +408,29 @@ void ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow){ opt->ssh2allowed=0; } +/** Default is a write on stderr + * \brief Change the writer callback for logging + * \param opt options structure + * \param callback a callback function for the printing + * \warning the message string may contain format string characters. + */ +void ssh_options_set_log_function(SSH_OPTIONS *opt, + void (*callback)(const char *message, SSH_SESSION *session, int priority )){ + opt->log_function=callback; +} + +/** \brief set this session's logging priority + * \param opt options structure + * \param verbosity verbosity of the messages. Every log smaller or equal to verbosity will be shown\n + * SSH_LOG_NOLOG No logging \n + * SSH_LOG_RARE Rare conditions or warnings\n + * SSH_LOG_ENTRY Api-accessible entrypoints\n + * SSH_LOG_PACKET Packet id and size\n + * SSH_LOG_FUNCTIONS function entering and leaving\n + */ +void ssh_options_set_log_verbosity(SSH_OPTIONS *opt, int verbosity){ + opt->log_verbosity=verbosity; +} /** * This is a helper for your application to generate the appropriate * options from the command line arguments.\n @@ -502,7 +527,7 @@ int ssh_options_getopt(SSH_OPTIONS *options, int *argcptr, char **argv){ ssh_set_error(options,SSH_FATAL,"either RSA or DSS must be chosen"); cont=0; } - ssh_set_verbosity(debuglevel); + ssh_options_set_log_verbosity(options,debuglevel); optind=saveoptind; if(!cont){ free(save); diff --git a/libssh/packet.c b/libssh/packet.c index d0dcc716..a1b06cd0 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -33,13 +33,12 @@ MA 02111-1307, USA. */ /* XXX include selected mac size */ static int macsize=SHA_DIGEST_LEN; - - /* in nonblocking mode, socket_read will read as much as it can, and return */ /* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */ /* in blocking mode, it will read at least len bytes and will block until it's ok. */ static int socket_read(SSH_SESSION *session,int len){ + enter_function(); int except, can_write; int to_read; int r; @@ -48,8 +47,10 @@ static int socket_read(SSH_SESSION *session,int len){ if(!session->in_socket_buffer) session->in_socket_buffer=buffer_new(); to_read=len - buffer_get_rest_len(session->in_socket_buffer); - if(to_read <= 0) + if(to_read <= 0){ + leave_function(); return SSH_OK; + } if(session->blocking){ buf=malloc(to_read); r=ssh_socket_completeread(session->socket,buf,to_read); @@ -60,18 +61,22 @@ static int socket_read(SSH_SESSION *session,int len){ ssh_socket_close(session->socket); session->alive=0; session->data_except=1; + leave_function(); return SSH_ERROR; } buffer_add_data(session->in_socket_buffer,buf,to_read); free(buf); + leave_function(); return SSH_OK; } /* nonblocking read */ do { ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_read */ - if(!session->data_to_read) - return SSH_AGAIN; + if(!session->data_to_read){ + leave_function(); + return SSH_AGAIN; + } session->data_to_read=0; /* read as much as we can */ if(ssh_socket_is_open(session->socket)) @@ -84,10 +89,12 @@ static int socket_read(SSH_SESSION *session,int len){ ssh_socket_close(session->socket); session->data_except=1; session->alive=0; + leave_function(); return SSH_ERROR; } buffer_add_data(session->in_socket_buffer,buffer,r); } while(buffer_get_rest_len(session->in_socket_buffer)<len); + leave_function(); return SSH_OK; } @@ -104,8 +111,11 @@ static int packet_read2(SSH_SESSION *session){ u8 padding; unsigned int blocksize=(session->current_crypto?session->current_crypto->in_cipher->blocksize:8); int current_macsize=session->current_crypto?macsize:0; - if(!session->alive || session->data_except) + enter_function(); + if(!session->alive || session->data_except){ + leave_function(); return SSH_ERROR; // the error message was already set into this session + } switch(session->packet_state){ case PACKET_STATE_INIT: memset(&session->in_packet,0,sizeof(PACKET)); @@ -114,8 +124,10 @@ static int packet_read2(SSH_SESSION *session){ else session->in_buffer=buffer_new(); ret=socket_read(session,blocksize); - if(ret != SSH_OK) - return ret; // can be SSH_ERROR or SSH_AGAIN + if(ret != SSH_OK){ + leave_function(); + return ret; // can be SSH_ERROR or SSH_AGAIN + } // be_read=completeread(session->fd,buffer,blocksize); memcpy(buffer,buffer_get_rest(session->in_socket_buffer),blocksize); buffer_pass_bytes(session->in_socket_buffer,blocksize); // mark them as read @@ -123,12 +135,14 @@ static int packet_read2(SSH_SESSION *session){ buffer_add_data(session->in_buffer,buffer,blocksize); if(len> MAX_PACKET_LEN){ ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%uld %.8lx)",len,len); + leave_function(); return SSH_ERROR; } to_be_read=len-blocksize+sizeof(u32); if(to_be_read<0){ /* remote sshd sends invalid sizes?*/ ssh_set_error(session,SSH_FATAL,"given numbers of bytes left to be read <0 (%d)!",to_be_read); + leave_function(); return SSH_ERROR; } /* saves the status of the current operations */ @@ -140,8 +154,10 @@ static int packet_read2(SSH_SESSION *session){ /* if to_be_read is zero, the whole packet was blocksize bytes. */ if(to_be_read != 0){ ret=socket_read(session,to_be_read); - if(ret!=SSH_OK) - return ret; + if(ret!=SSH_OK){ + leave_function(); + return ret; + } packet=malloc(to_be_read); memcpy(packet,buffer_get_rest(session->in_socket_buffer),to_be_read-current_macsize); buffer_pass_bytes(session->in_socket_buffer,to_be_read-current_macsize); @@ -157,6 +173,7 @@ static int packet_read2(SSH_SESSION *session){ buffer_pass_bytes(session->in_socket_buffer,macsize); if(packet_hmac_verify(session,session->in_buffer,mac)){ ssh_set_error(session,SSH_FATAL,"HMAC error"); + leave_function(); return SSH_ERROR; } } @@ -164,6 +181,7 @@ static int packet_read2(SSH_SESSION *session){ /*pass the size which has been processed before*/ if(!buffer_get_u8(session->in_buffer,&padding)){ ssh_set_error(session,SSH_FATAL,"Packet too short to read padding"); + leave_function(); return SSH_ERROR; } ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n", @@ -175,6 +193,7 @@ static int packet_read2(SSH_SESSION *session){ ssh_print_hexa("incrimined packet", buffer_get(session->in_buffer),buffer_get_len(session->in_buffer)); #endif + leave_function(); return SSH_ERROR; } buffer_pass_bytes_end(session->in_buffer,padding); @@ -187,9 +206,11 @@ static int packet_read2(SSH_SESSION *session){ #endif session->recv_seq++; session->packet_state=PACKET_STATE_INIT; + leave_function(); return SSH_OK; } ssh_set_error(session,SSH_FATAL,"Invalid state into packet_read2() : %d",session->packet_state); + leave_function(); return SSH_ERROR; } @@ -306,16 +327,21 @@ int packet_read(SSH_SESSION *session){ } int packet_translate(SSH_SESSION *session){ + enter_function(); memset(&session->in_packet,0,sizeof(PACKET)); - if(!session->in_buffer) - return -1; + if(!session->in_buffer){ + leave_function(); + return -1; + } ssh_say(3,"Final size %d\n",buffer_get_rest_len(session->in_buffer)); if(!buffer_get_u8(session->in_buffer,&session->in_packet.type)){ ssh_set_error(session,SSH_FATAL,"Packet too short to read type"); + leave_function(); return -1; } ssh_say(3,"type %hhd\n",session->in_packet.type); session->in_packet.valid=1; + leave_function(); return 0; } @@ -339,11 +365,13 @@ static int atomic_write(struct socket *s, void *buffer, int len){ static int packet_nonblocking_flush(SSH_SESSION *session){ int except, can_write; int w; + enter_function(); ssh_fd_poll(session,&can_write,&except); /* internally sets data_to_write */ if(!ssh_socket_is_open(session->socket)){ session->alive=0; // FIXME use ssh_socket_get_errno ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s",strerror(errno)); + leave_function(); return SSH_ERROR; } while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){ @@ -361,27 +389,37 @@ static int packet_nonblocking_flush(SSH_SESSION *session){ // FIXME use ssh_socket_get_errno() ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", strerror(errno)); + leave_function(); return SSH_ERROR; } buffer_pass_bytes(session->out_socket_buffer,w); /* refresh the socket status */ ssh_fd_poll(session,&can_write,&except); } - if(buffer_get_rest_len(session->out_socket_buffer)>0) - return SSH_AGAIN; /* there is data pending */ + if(buffer_get_rest_len(session->out_socket_buffer)>0){ + leave_function(); + return SSH_AGAIN; /* there is data pending */ + } + leave_function(); return SSH_OK; // all data written } /* blocking packet flush */ static int packet_blocking_flush(SSH_SESSION *session){ + enter_function(); if(!ssh_socket_is_open(session->socket)) { session->alive=0; + leave_function(); return SSH_ERROR; } - if(session->data_except) - return SSH_ERROR; - if(buffer_get_rest(session->out_socket_buffer)==0) + if(session->data_except){ + leave_function(); + return SSH_ERROR; + } + if(buffer_get_rest(session->out_socket_buffer)==0){ + leave_function(); return SSH_OK; + } if(atomic_write(session->socket,buffer_get_rest(session->out_socket_buffer), buffer_get_rest_len(session->out_socket_buffer))){ session->data_to_write=0; @@ -391,10 +429,12 @@ static int packet_blocking_flush(SSH_SESSION *session){ // FIXME use the proper errno ssh_set_error(session,SSH_FATAL,"Writing packet : error on socket (or connection closed): %s", strerror(errno)); + leave_function(); return SSH_ERROR; } session->data_to_write=0; buffer_reinit(session->out_socket_buffer); + leave_function(); return SSH_OK; // no data pending } @@ -410,15 +450,19 @@ int packet_flush(SSH_SESSION *session, int enforce_blocking){ /* this function places the outgoing packet buffer into an outgoing socket buffer */ static int socket_write(SSH_SESSION *session){ + int ret; + enter_function(); if(!session->out_socket_buffer){ session->out_socket_buffer=buffer_new(); } buffer_add_data(session->out_socket_buffer, buffer_get(session->out_buffer),buffer_get_len(session->out_buffer)); - if(!session->blocking){ - return packet_nonblocking_flush(session); - } else - return packet_blocking_flush(session); + if(!session->blocking) + ret = packet_nonblocking_flush(session); + else + ret = packet_blocking_flush(session); + leave_function(); + return ret; } static int packet_send2(SSH_SESSION *session){ @@ -429,6 +473,7 @@ static int packet_send2(SSH_SESSION *session){ unsigned char *hmac; int ret=0; unsigned int blocksize=(session->current_crypto?session->current_crypto->out_cipher->blocksize:8); + enter_function(); ssh_say(3,"Writing on the wire a packet having %ld bytes before",currentlen); #ifdef HAVE_LIBZ if(session->current_crypto && session->current_crypto->do_compress_out){ @@ -455,6 +500,7 @@ static int packet_send2(SSH_SESSION *session){ ret=socket_write(session); session->send_seq++; buffer_reinit(session->out_buffer); + leave_function(); return ret; /* SSH_OK, AGAIN or ERROR */ } @@ -611,16 +657,22 @@ static int packet_wait1(SSH_SESSION *session,int type,int blocking){ #endif /* HAVE_SSH1 */ static int packet_wait2(SSH_SESSION *session,int type,int blocking){ int ret; + enter_function(); while(1){ ret=packet_read2(session); - if(ret != SSH_OK) - return ret; - if(packet_translate(session)) + if(ret != SSH_OK){ + leave_function(); + return ret; + } + if(packet_translate(session)){ + leave_function(); return SSH_ERROR; + } switch(session->in_packet.type){ case SSH2_MSG_DISCONNECT: packet_parse(session); ssh_say(2,"received disconnect packet\n"); + leave_function(); return SSH_ERROR; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_DATA: @@ -635,13 +687,18 @@ static int packet_wait2(SSH_SESSION *session,int type,int blocking){ default: if(type && (type != session->in_packet.type)){ ssh_set_error(session,SSH_FATAL,"waitpacket(): Received a %d type packet, was waiting for a %d\n",session->in_packet.type,type); + leave_function(); return SSH_ERROR; } + leave_function(); return SSH_OK; } - if(blocking==0) - return SSH_OK; //shouldn't it return SSH_AGAIN here ? + if(blocking==0){ + leave_function(); + return SSH_OK; //shouldn't it return SSH_AGAIN here ? + } } + leave_function(); return SSH_OK; } int packet_wait(SSH_SESSION *session, int type, int block){ diff --git a/libssh/session.c b/libssh/session.c index 28d89de6..f8344fa8 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -44,10 +44,12 @@ SSH_SESSION *ssh_new() { session->socket=ssh_socket_new(); session->alive=0; session->blocking=1; + session->log_indent=0; return session; } void ssh_cleanup(SSH_SESSION *session){ + enter_function(); int i; if(session->serverbanner) free(session->serverbanner); @@ -95,15 +97,19 @@ void ssh_cleanup(SSH_SESSION *session){ memset(session,'X',sizeof(SSH_SESSION)); /* burn connection, it could hangs sensitive datas */ free(session); + //leave_function(); } /** \brief disconnect impolitely from remote host * \param session current ssh session */ void ssh_silent_disconnect(SSH_SESSION *session){ + enter_function(); + ssh_log(session,SSH_LOG_ENTRY,"ssh_silent_disconnect()"); ssh_socket_close(session->socket); session->alive=0; ssh_disconnect(session); + //leave_function(); } /** \brief set the options for the current session @@ -114,6 +120,7 @@ void ssh_silent_disconnect(SSH_SESSION *session){ */ void ssh_set_options(SSH_SESSION *session, SSH_OPTIONS *options){ session->options=options; + session->log_verbosity=options->log_verbosity; } /** \brief set the session in blocking/nonblocking mode @@ -163,16 +170,22 @@ void ssh_set_fd_except(SSH_SESSION *session){ /* looks if there is data to read on the socket and parse it. */ int ssh_handle_packets(SSH_SESSION *session){ int w,err,r,i=0; + enter_function(); do { r=ssh_fd_poll(session,&w,&err); - if(r<=0) + if(r<=0){ + leave_function(); return r; // error or no data available + } /* if an exception happened, it will be trapped by packet_read() */ - if(packet_read(session)||packet_translate(session)) - return -1; + if(packet_read(session)||packet_translate(session)){ + leave_function(); + return -1; + } packet_parse(session); ++i; } while(r>0 && i<5); + leave_function(); return r; } diff --git a/libssh/sftp.c b/libssh/sftp.c index ff833e2f..c6fd56f2 100644 --- a/libssh/sftp.c +++ b/libssh/sftp.c @@ -42,6 +42,8 @@ MA 02111-1307, USA. */ /* can fetch it, while continuing to read for other messages (it is inspecified in which order messages may */ /* be sent back to the client */ +#define sftp_enter_function() _enter_function(sftp->channel->session) +#define sftp_leave_function() _leave_function(sftp->channel->session) /* functions */ void sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg); @@ -49,18 +51,22 @@ static void sftp_message_free(SFTP_MESSAGE *msg); SFTP_SESSION *sftp_new(SSH_SESSION *session){ SFTP_SESSION *sftp=malloc(sizeof(SFTP_SESSION)); + enter_function(); memset(sftp,0,sizeof(SFTP_SESSION)); sftp->session=session; sftp->channel=channel_new(session); if(channel_open_session(sftp->channel)){ channel_free(sftp->channel); free(sftp); + leave_function(); return NULL; } if(channel_request_sftp(sftp->channel)){ sftp_free(sftp); + leave_function(); return NULL; } + leave_function(); return sftp; } @@ -138,11 +144,13 @@ int sftp_packet_write(SFTP_SESSION *sftp,u8 type, BUFFER *payload){ SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp){ SFTP_PACKET *packet=malloc(sizeof(SFTP_PACKET)); u32 size; + sftp_enter_function(); packet->sftp=sftp; packet->payload=buffer_new(); if(channel_read(sftp->channel,packet->payload,4,0)<=0){ buffer_free(packet->payload); free(packet); + sftp_leave_function(); return NULL; } buffer_get_u32(packet->payload,&size); @@ -150,6 +158,7 @@ SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp){ if(channel_read(sftp->channel,packet->payload,1,0)<=0){ buffer_free(packet->payload); free(packet); + sftp_leave_function(); return NULL; } buffer_get_u8(packet->payload,&packet->type); @@ -157,8 +166,10 @@ SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp){ if(channel_read(sftp->channel,packet->payload,size-1,0)<=0){ buffer_free(packet->payload); free(packet); + sftp_leave_function(); return NULL; } + sftp_leave_function(); return packet; } @@ -196,17 +207,23 @@ SFTP_MESSAGE *sftp_get_message(SFTP_PACKET *packet){ return msg; } -int sftp_read_and_dispatch(SFTP_SESSION *session){ +int sftp_read_and_dispatch(SFTP_SESSION *sftp){ SFTP_PACKET *packet; SFTP_MESSAGE *message=NULL; - packet=sftp_packet_read(session); - if(!packet) - return -1; /* something nasty happened reading the packet */ + sftp_enter_function(); + packet=sftp_packet_read(sftp); + if(!packet){ + sftp_leave_function(); + return -1; /* something nasty happened reading the packet */ + } message=sftp_get_message(packet); sftp_packet_free(packet); - if(!message) - return -1; - sftp_enqueue(session,message); + if(!message){ + sftp_leave_function(); + return -1; + } + sftp_enqueue(sftp,message); + sftp_leave_function(); return 0; } @@ -222,15 +239,19 @@ int sftp_init(SFTP_SESSION *sftp){ STRING *ext_name_s=NULL, *ext_data_s=NULL; char *ext_name,*ext_data; u32 version=htonl(LIBSFTP_VERSION); + sftp_enter_function(); buffer_add_u32(buffer,version); sftp_packet_write(sftp,SSH_FXP_INIT,buffer); buffer_free(buffer); packet=sftp_packet_read(sftp); - if(!packet) - return -1; + if(!packet){ + sftp_leave_function(); + return -1; + } if(packet->type != SSH_FXP_VERSION){ ssh_set_error(sftp->session,SSH_FATAL,"Received a %d messages instead of SSH_FXP_VERSION",packet->type); sftp_packet_free(packet); + sftp_leave_function(); return -1; } buffer_get_u32(packet->payload,&version); @@ -250,6 +271,7 @@ int sftp_init(SFTP_SESSION *sftp){ free(ext_data_s); sftp_packet_free(packet); sftp->version=sftp->server_version=version; + sftp_leave_function(); return 0; } |