changeset 726:78eda530c000

send out our kexinit packet before blocking to read the SSH version string
author Matt Johnston <matt@ucc.asn.au>
date Sun, 31 Mar 2013 00:40:00 +0800
parents 49f68a7b7a55
children 00bc3df3a9c3 cd201dc2da9a
files cli-session.c common-session.c session.h svr-session.c
diffstat 4 files changed, 26 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/cli-session.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/cli-session.c	Sun Mar 31 00:40:00 2013 +0800
@@ -99,7 +99,7 @@
 	sessinitdone = 1;
 
 	/* Exchange identification */
-	session_identification();
+	send_session_identification();
 
 	send_msg_kexinit();
 
--- a/common-session.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/common-session.c	Sun Mar 31 00:40:00 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));
--- a/session.h	Sun Mar 24 00:02:20 2013 +0800
+++ b/session.h	Sun Mar 31 00:40:00 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() */
 
--- a/svr-session.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/svr-session.c	Sun Mar 31 00:40:00 2013 +0800
@@ -114,7 +114,7 @@
 	sessinitdone = 1;
 
 	/* exchange identification, version etc */
-	session_identification();
+	send_session_identification();
 
 	/* start off with key exchange */
 	send_msg_kexinit();