From 9c7485331a581d1ff32f9caf005e7b13fa1c051e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sat, 30 Mar 2013 23:55:05 +0800 Subject: Get rid of client/server specific buf_match_algo, use single function with a couple of if statements instead --HG-- branch : kexguess --- svr-session.c | 1 - 1 file changed, 1 deletion(-) (limited to 'svr-session.c') diff --git a/svr-session.c b/svr-session.c index cf82289..a564525 100644 --- a/svr-session.c +++ b/svr-session.c @@ -106,7 +106,6 @@ void svr_session(int sock, int childpipe) { /* packet handlers */ ses.packettypes = svr_packettypes; - ses.buf_match_algo = svr_buf_match_algo; ses.isserver = 1; -- cgit v1.2.3 From a0e931005b6f9de407ba2ac5b5df9e34d4a7fb7e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 31 Mar 2013 00:40:00 +0800 Subject: send out our kexinit packet before blocking to read the SSH version string --- cli-session.c | 2 +- common-session.c | 29 +++++++++++++++++++---------- session.h | 7 +++++-- svr-session.c | 2 +- 4 files changed, 26 insertions(+), 14 deletions(-) (limited to 'svr-session.c') diff --git a/cli-session.c b/cli-session.c index e58fdbd..f862bc8 100644 --- a/cli-session.c +++ b/cli-session.c @@ -99,7 +99,7 @@ void cli_session(int sock_in, int sock_out) { sessinitdone = 1; /* Exchange identification */ - session_identification(); + send_session_identification(); send_msg_kexinit(); diff --git a/common-session.c b/common-session.c index f4fa579..ec5c9ed 100644 --- a/common-session.c +++ b/common-session.c @@ -39,6 +39,7 @@ static void checktimeouts(); static long select_timeout(); static int ident_readln(int fd, char* buf, int count); +static void read_session_identification(); struct sshsession ses; /* GLOBAL */ @@ -141,7 +142,10 @@ void session_loop(void(*loophandler)()) { FD_ZERO(&writefd); FD_ZERO(&readfd); dropbear_assert(ses.payload == NULL); - if (ses.sock_in != -1) { + + /* during initial setup we flush out the KEXINIT packet before + * attempting to read the remote version string, which might block */ + if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { FD_SET(ses.sock_in, &readfd); } if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { @@ -195,7 +199,12 @@ void session_loop(void(*loophandler)()) { if (ses.sock_in != -1) { if (FD_ISSET(ses.sock_in, &readfd)) { - read_packet(); + if (!ses.remoteident) { + /* blocking read of the version string */ + read_session_identification(); + } else { + read_packet(); + } } /* Process the decrypted packet. After this, the read buffer @@ -245,20 +254,20 @@ void common_session_cleanup() { } -void session_identification() { - - /* max length of 255 chars */ - char linebuf[256]; - int len = 0; - char done = 0; - int i; - +void send_session_identification() { /* write our version string, this blocks */ if (atomicio(write, ses.sock_out, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { ses.remoteclosed(); } +} +static void read_session_identification() { + /* max length of 255 chars */ + char linebuf[256]; + int len = 0; + char done = 0; + int i; /* If they send more than 50 lines, something is wrong */ for (i = 0; i < 50; i++) { len = ident_readln(ses.sock_in, linebuf, sizeof(linebuf)); diff --git a/session.h b/session.h index 0719e34..d524226 100644 --- a/session.h +++ b/session.h @@ -45,7 +45,7 @@ extern int exitflag; void common_session_init(int sock_in, int sock_out); void session_loop(void(*loophandler)()); void common_session_cleanup(); -void session_identification(); +void send_session_identification(); void send_msg_ignore(); const char* get_user_shell(); @@ -111,7 +111,10 @@ struct sshsession { int sock_in; int sock_out; - unsigned char *remoteident; + /* remotehost will be initially NULL as we delay + * reading the remote version string. it will be set + * by the time any recv_() packet methods are called */ + unsigned char *remoteident; int maxfd; /* the maximum file descriptor to check with select() */ diff --git a/svr-session.c b/svr-session.c index cf82289..7234f4a 100644 --- a/svr-session.c +++ b/svr-session.c @@ -114,7 +114,7 @@ void svr_session(int sock, int childpipe) { sessinitdone = 1; /* exchange identification, version etc */ - session_identification(); + send_session_identification(); /* start off with key exchange */ send_msg_kexinit(); -- cgit v1.2.3 From 90b5691183f12d348d2651e026e8438ad278c2be Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 1 Apr 2013 22:26:55 +0800 Subject: Run the cleanup handler also when we close due to TCP connection being closed --- cli-main.c | 3 +-- cli-session.c | 7 ++++--- common-session.c | 6 +++++- session.h | 4 ++-- svr-session.c | 13 +++++++++---- 5 files changed, 21 insertions(+), 12 deletions(-) (limited to 'svr-session.c') diff --git a/cli-main.c b/cli-main.c index 5f72969..1a8b02e 100644 --- a/cli-main.c +++ b/cli-main.c @@ -98,8 +98,7 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) { } /* Do the cleanup first, since then the terminal will be reset */ - cli_session_cleanup(); - common_session_cleanup(); + session_cleanup(); _dropbear_log(LOG_INFO, fmtbuf, param); diff --git a/cli-session.c b/cli-session.c index 3adec73..0c6635a 100644 --- a/cli-session.c +++ b/cli-session.c @@ -42,6 +42,7 @@ static void cli_sessionloop(); static void cli_session_init(); static void cli_finished(); static void recv_msg_service_accept(void); +static void cli_session_cleanup(void); struct clientsession cli_ses; /* GLOBAL */ @@ -143,6 +144,7 @@ static void cli_session_init() { /* For printing "remote host closed" for the user */ ses.remoteclosed = cli_remoteclosed; + ses.extra_session_cleanup = cli_session_cleanup; ses.buf_match_algo = cli_buf_match_algo; /* packet handlers */ @@ -290,7 +292,7 @@ static void cli_sessionloop() { } -void cli_session_cleanup() { +static void cli_session_cleanup(void) { if (!sessinitdone) { return; @@ -308,8 +310,7 @@ void cli_session_cleanup() { static void cli_finished() { - cli_session_cleanup(); - common_session_cleanup(); + session_cleanup(); fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport); exit(cli_ses.retval); diff --git a/common-session.c b/common-session.c index ec5c9ed..b514796 100644 --- a/common-session.c +++ b/common-session.c @@ -234,7 +234,7 @@ void session_loop(void(*loophandler)()) { } /* clean up a session on exit */ -void common_session_cleanup() { +void session_cleanup() { TRACE(("enter session_cleanup")) @@ -243,6 +243,10 @@ void common_session_cleanup() { TRACE(("leave session_cleanup: !sessinitdone")) return; } + + if (ses.extra_session_cleanup) { + ses.extra_session_cleanup(); + } m_free(ses.session_id); m_burn(ses.keys, sizeof(struct key_context)); diff --git a/session.h b/session.h index 39104a3..dd486f0 100644 --- a/session.h +++ b/session.h @@ -44,7 +44,7 @@ extern int exitflag; void common_session_init(int sock_in, int sock_out); void session_loop(void(*loophandler)()); -void common_session_cleanup(); +void session_cleanup(); void send_session_identification(); void send_msg_ignore(); @@ -58,7 +58,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param); /* Client */ void cli_session(int sock_in, int sock_out); -void cli_session_cleanup(); void cleantext(unsigned char* dirtytext); /* crypto parameters that are stored individually for transmit and receive */ @@ -181,6 +180,7 @@ struct sshsession { void(*remoteclosed)(); /* A callback to handle closure of the remote connection */ + void(*extra_session_cleanup)(); /* client or server specific cleanup */ struct AuthState authstate; /* Common amongst client and server, since most struct elements are common */ diff --git a/svr-session.c b/svr-session.c index 7234f4a..c235c8a 100644 --- a/svr-session.c +++ b/svr-session.c @@ -72,6 +72,13 @@ static const struct ChanType *svr_chantypes[] = { NULL /* Null termination is mandatory. */ }; +static void +svr_session_cleanup(void) +{ + /* free potential public key options */ + svr_pubkey_options_cleanup(); +} + void svr_session(int sock, int childpipe) { char *host, *port; size_t len; @@ -103,6 +110,7 @@ void svr_session(int sock, int childpipe) { /* set up messages etc */ ses.remoteclosed = svr_remoteclosed; + ses.extra_session_cleanup = svr_session_cleanup; /* packet handlers */ ses.packettypes = svr_packettypes; @@ -160,11 +168,8 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { if (svr_ses.server_pid == getpid()) #endif { - /* free potential public key options */ - svr_pubkey_options_cleanup(); - /* must be after we've done with username etc */ - common_session_cleanup(); + session_cleanup(); } exit(exitcode); -- cgit v1.2.3