# HG changeset patch # User Matt Johnston # Date 1390485395 -28800 # Node ID 19ce21bd198a383098a98799d0373dd7e8fe28eb # Parent dd0bd9231fc2444d1bd0113ebeab1129a48045a8 Fix failing rekeying when we receive a still-in-flight packet diff -r dd0bd9231fc2 -r 19ce21bd198a cli-kex.c --- a/cli-kex.c Fri Jan 17 21:42:32 2014 +0800 +++ b/cli-kex.c Thu Jan 23 21:56:35 2014 +0800 @@ -86,8 +86,6 @@ 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 -r dd0bd9231fc2 -r 19ce21bd198a common-kex.c --- a/common-kex.c Fri Jan 17 21:42:32 2014 +0800 +++ b/common-kex.c Thu Jan 23 21:56:35 2014 +0800 @@ -483,9 +483,6 @@ * 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 @@ /* 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 -r dd0bd9231fc2 -r 19ce21bd198a process-packet.c --- a/process-packet.c Fri Jan 17 21:42:32 2014 +0800 +++ b/process-packet.c Thu Jan 23 21:56:35 2014 +0800 @@ -75,15 +75,34 @@ /* 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