From 8128b15e4157abc382f360eaf95c0fabefe5bc61 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Thu, 23 Jan 2014 21:56:35 +0800
Subject: [PATCH] Fix failing rekeying when we receive a still-in-flight packet

---
 cli-kex.c        |  2 --
 common-kex.c     |  5 +----
 process-packet.c | 29 ++++++++++++++++++++++++-----
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/cli-kex.c b/cli-kex.c
index 55b00415..a4fa39ab 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -86,8 +86,6 @@ void send_msg_kexdh_init() {
 
 	cli_ses.param_kex_algo = ses.newkeys->algo_kex;
 	encrypt_packet();
-	ses.requirenext[0] = SSH_MSG_KEXDH_REPLY;
-	ses.requirenext[1] = SSH_MSG_KEXINIT;
 }
 
 /* Handle a diffie-hellman key exchange reply. */
diff --git a/common-kex.c b/common-kex.c
index b3185158..3c1e6044 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -483,9 +483,6 @@ static void gen_new_zstream_trans() {
  * and we calculate the first portion of the key-exchange-hash for used
  * later in the key exchange. No response is sent, as the client should
  * initiate the diffie-hellman key exchange */
-
-/* Originally from kex.c, generalized for cli/svr mode --mihnea  */
-/* Belongs in common_kex.c where it should be moved after review */
 void recv_msg_kexinit() {
 	
 	unsigned int kexhashbuf_len = 0;
@@ -528,7 +525,7 @@ void recv_msg_kexinit() {
 		/* I_S, the payload of the server's SSH_MSG_KEXINIT */
 	    buf_setpos(ses.payload, 0);
 	    buf_putstring(ses.kexhashbuf, ses.payload->data, ses.payload->len);
-
+		ses.requirenext[0] = SSH_MSG_KEXDH_REPLY;
 	} else {
 		/* SERVER */
 
diff --git a/process-packet.c b/process-packet.c
index 0b925106..97de2034 100644
--- a/process-packet.c
+++ b/process-packet.c
@@ -75,15 +75,34 @@ void process_packet() {
 	/* This applies for KEX, where the spec says the next packet MUST be
 	 * NEWKEYS */
 	if (ses.requirenext[0] != 0) {
-		if (ses.requirenext[0] != type
-				&& (ses.requirenext[1] == 0 || ses.requirenext[1] != type)) {
-			dropbear_exit("Unexpected packet type %d, expected [%d,%d]", type,
-					ses.requirenext[0], ses.requirenext[1]);
-		} else {
+		if (ses.requirenext[0] == type || ses.requirenext[1] == type)
+		{
 			/* Got what we expected */
+			TRACE(("got expeced packet %d during kexinit", type))
 			ses.requirenext[0] = 0;
 			ses.requirenext[1] = 0;
 		}
+		else
+		{
+			/* RFC4253 7.1 - various messages are allowed at this point.
+			The only ones we know about have already been handled though,
+			so just return "unimplemented" */
+			if (type >= 1 && type <= 49
+				&& type != SSH_MSG_SERVICE_REQUEST
+				&& type != SSH_MSG_SERVICE_ACCEPT
+				&& type != SSH_MSG_KEXINIT)
+			{
+				TRACE(("unknown allowed packet during kexinit"))
+				recv_unimplemented();
+				goto out;
+			}
+			else
+			{
+				TRACE(("disallowed packet during kexinit"))
+				dropbear_exit("Unexpected packet type %d, expected [%d,%d]", type,
+						ses.requirenext[0], ses.requirenext[1]);
+			}
+		}
 	}
 
 	/* Check if we should ignore this packet. Used currently only for
-- 
GitLab