changeset 739:d44325108d0e kexguess

first_kex_packet_follows working, needs tidying
author Matt Johnston <matt@ucc.asn.au>
date Fri, 29 Mar 2013 20:44:13 +0800
parents 49f68a7b7a55
children 3062da90dab8
files cli-kex.c cli-session.c common-kex.c kex.h session.h
diffstat 5 files changed, 48 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/cli-kex.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/cli-kex.c	Fri Mar 29 20:44:13 2013 +0800
@@ -42,7 +42,7 @@
 #define MAX_KNOWNHOSTS_LINE 4500
 
 void send_msg_kexdh_init() {
-
+	TRACE(("send_msg_kexdh_init()"))	
 	cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
 	cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
 	m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
@@ -53,7 +53,8 @@
 	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
 	buf_putmpint(ses.writepayload, cli_ses.dh_e);
 	encrypt_packet();
-	ses.requirenext = SSH_MSG_KEXDH_REPLY;
+	// XXX fixme
+	//ses.requirenext = SSH_MSG_KEXDH_REPLY;
 }
 
 /* Handle a diffie-hellman key exchange reply. */
--- a/cli-session.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/cli-session.c	Fri Mar 29 20:44:13 2013 +0800
@@ -109,6 +109,12 @@
 
 }
 
+static void cli_send_kex_first_guess() {
+	send_msg_kexdh_init();
+	dropbear_log(LOG_INFO, "kexdh_init guess sent");
+	//cli_ses.kex_state = KEXDH_INIT_SENT;			
+}
+
 static void cli_session_init() {
 
 	cli_ses.state = STATE_NOTHING;
@@ -148,6 +154,9 @@
 	ses.packettypes = cli_packettypes;
 
 	ses.isserver = 0;
+
+	ses.send_kex_first_guess = cli_send_kex_first_guess;
+
 }
 
 /* This function drives the progress of the session - it initiates KEX,
@@ -157,15 +166,13 @@
 	TRACE(("enter cli_sessionloop"))
 
 	if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
-		cli_ses.kex_state = KEXINIT_RCVD;
-	}
-
-	if (cli_ses.kex_state == KEXINIT_RCVD) {
-
 		/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
 		 * negotiation would have failed. */
-		send_msg_kexdh_init();
-		cli_ses.kex_state = KEXDH_INIT_SENT;
+		if (!ses.kexstate.our_first_follows_matches) {
+			dropbear_log(LOG_INFO, "kexdh_init after remote's kexinit");
+			send_msg_kexdh_init();
+		}
+		cli_ses.kex_state = KEXDH_INIT_SENT;			
 		TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"))
 		return;
 	}
--- a/common-kex.c	Sun Mar 24 00:02:20 2013 +0800
+++ b/common-kex.c	Fri Mar 29 20:44:13 2013 +0800
@@ -131,8 +131,8 @@
 	/* languages_server_to_client */
 	buf_putstring(ses.writepayload, "", 0);
 
-	/* first_kex_packet_follows - unimplemented for now */
-	buf_putbyte(ses.writepayload, 0x00);
+	/* first_kex_packet_follows */
+	buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
 
 	/* reserved unit32 */
 	buf_putint(ses.writepayload, 0);
@@ -144,9 +144,19 @@
 	encrypt_packet();
 	ses.dataallowed = 0; /* don't send other packets during kex */
 
+	ses.kexstate.sentkexinit = 1;
+
+	ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
+
+	if (ses.send_kex_first_guess) {
+		ses.newkeys->algo_kex = sshkex[0].val;
+		ses.newkeys->algo_hostkey = sshhostkey[0].val;
+		ses.send_kex_first_guess();
+	}
+
 	TRACE(("DATAALLOWED=0"))
 	TRACE(("-> KEXINIT"))
-	ses.kexstate.sentkexinit = 1;
+
 }
 
 /* *** NOTE regarding (send|recv)_msg_newkeys *** 
@@ -236,11 +246,13 @@
 	ses.kexstate.sentnewkeys = 0;
 
 	/* first_packet_follows */
-	ses.kexstate.firstfollows = 0;
+	ses.kexstate.them_firstfollows = 0;
 
 	ses.kexstate.datatrans = 0;
 	ses.kexstate.datarecv = 0;
 
+	ses.kexstate.our_first_follows_matches = 0;
+
 	ses.kexstate.lastkextime = time(NULL);
 
 }
@@ -555,7 +567,7 @@
 	DEF_MP_INT(dh_q);
 	DEF_MP_INT(dh_g);
 
-	TRACE(("enter send_msg_kexdh_reply"))
+	TRACE(("enter gen_kexdh_vals"))
 	
 	m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
 
@@ -678,7 +690,7 @@
 
 	buf_incrpos(ses.payload, 16); /* start after the cookie */
 
-	ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
+	memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
 
 	/* kex_algorithms */
 	algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
@@ -754,9 +766,10 @@
 	/* languages_server_to_client */
 	buf_eatstring(ses.payload);
 
-	/* first_kex_packet_follows */
+	/* their first_kex_packet_follows */
 	if (buf_getbool(ses.payload)) {
-		ses.kexstate.firstfollows = 1;
+		TRACE(("them kex firstfollows. allgood %d", allgood))
+		ses.kexstate.them_firstfollows = 1;
 		/* if the guess wasn't good, we ignore the packet sent */
 		if (!allgood) {
 			ses.ignorenext = 1;
@@ -799,6 +812,11 @@
 
 	/* reserved for future extensions */
 	buf_getint(ses.payload);
+
+	if (ses.send_kex_first_guess && allgood) {
+		TRACE(("our_first_follows_matches 1"))
+		ses.kexstate.our_first_follows_matches = 1;
+	}
 	return;
 
 error:
--- a/kex.h	Sun Mar 24 00:02:20 2013 +0800
+++ b/kex.h	Fri Mar 29 20:44:13 2013 +0800
@@ -51,13 +51,15 @@
 
 	unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
 	unsigned recvkexinit : 1;
-	unsigned firstfollows : 1; /* true when first_kex_packet_follows is set */
+	unsigned them_firstfollows : 1; /* true when first_kex_packet_follows is set */
 	unsigned sentnewkeys : 1; /* set once we've send MSG_NEWKEYS (will be cleared once we have also received */
 	unsigned recvnewkeys : 1; /* set once we've received MSG_NEWKEYS (cleared once we have also sent */
 
 	unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed,
 								  ie the transport layer has been set up */
 
+	unsigned our_first_follows_matches : 1;
+
 	time_t lastkextime; /* time of the last kex */
 	unsigned int datatrans; /* data transmitted since last kex */
 	unsigned int datarecv; /* data received since last kex */
--- a/session.h	Sun Mar 24 00:02:20 2013 +0800
+++ b/session.h	Fri Mar 29 20:44:13 2013 +0800
@@ -178,6 +178,8 @@
 	void(*remoteclosed)(); /* A callback to handle closure of the
 									  remote connection */
 
+	void(*send_kex_first_guess)();
+
 
 	struct AuthState authstate; /* Common amongst client and server, since most
 								   struct elements are common */