diff options
-rw-r--r-- | cli-session.c | 2 | ||||
-rw-r--r-- | common-session.c | 29 | ||||
-rw-r--r-- | session.h | 7 | ||||
-rw-r--r-- | svr-session.c | 2 |
4 files changed, 26 insertions, 14 deletions
diff --git a/cli-session.c b/cli-session.c index 590bfcc..c5252b5 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)); @@ -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 a564525..6d76939 100644 --- a/svr-session.c +++ b/svr-session.c @@ -113,7 +113,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(); |