# HG changeset patch # User Matt Johnston # Date 1364561053 -28800 # Node ID d44325108d0e1fca00995d399d9db30c6f9f70bd # Parent 49f68a7b7a55e9fc120336a8514864c3156c717d first_kex_packet_follows working, needs tidying diff -r 49f68a7b7a55 -r d44325108d0e cli-kex.c --- 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. */ diff -r 49f68a7b7a55 -r d44325108d0e cli-session.c --- 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; } diff -r 49f68a7b7a55 -r d44325108d0e common-kex.c --- 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: diff -r 49f68a7b7a55 -r d44325108d0e kex.h --- 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 */ diff -r 49f68a7b7a55 -r d44325108d0e session.h --- 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 */