# HG changeset patch # User Matt Johnston # Date 1364661675 -28800 # Node ID cd201dc2da9a1c835dab0be0df79314c6619c6ce # Parent eafdf8b363f541b8b94854902cea18d977012783# Parent 78eda530c0005dbd656eeeaaeb21560c15e3b568 merge diff -r eafdf8b363f5 -r cd201dc2da9a cli-session.c --- a/cli-session.c Sat Mar 30 23:55:05 2013 +0800 +++ b/cli-session.c Sun Mar 31 00:41:15 2013 +0800 @@ -99,7 +99,7 @@ sessinitdone = 1; /* Exchange identification */ - session_identification(); + send_session_identification(); send_msg_kexinit(); diff -r eafdf8b363f5 -r cd201dc2da9a common-session.c --- a/common-session.c Sat Mar 30 23:55:05 2013 +0800 +++ b/common-session.c Sun Mar 31 00:41:15 2013 +0800 @@ -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 @@ 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 @@ 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 session_identification() { +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; - - /* 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(); - } - /* 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 -r eafdf8b363f5 -r cd201dc2da9a session.h --- a/session.h Sat Mar 30 23:55:05 2013 +0800 +++ b/session.h Sun Mar 31 00:41:15 2013 +0800 @@ -45,7 +45,7 @@ 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 @@ 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 -r eafdf8b363f5 -r cd201dc2da9a svr-session.c --- a/svr-session.c Sat Mar 30 23:55:05 2013 +0800 +++ b/svr-session.c Sun Mar 31 00:41:15 2013 +0800 @@ -113,7 +113,7 @@ sessinitdone = 1; /* exchange identification, version etc */ - session_identification(); + send_session_identification(); /* start off with key exchange */ send_msg_kexinit();