summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli-kex.c1
-rw-r--r--cli-session.c4
-rw-r--r--common-kex.c86
-rw-r--r--dbutil.c24
-rw-r--r--packet.c2
-rw-r--r--session.h1
6 files changed, 64 insertions, 54 deletions
diff --git a/cli-kex.c b/cli-kex.c
index 1158aa6..fd2e48e 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -256,7 +256,6 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
/* Compare hostnames */
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
hostlen) != 0) {
- TRACE2(("hosts don't match"))
continue;
}
diff --git a/cli-session.c b/cli-session.c
index 7adea26..9639ffa 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -204,8 +204,7 @@ static void cli_sessionloop() {
}
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
- if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
- && ses.kexstate.sentkexinit == 0) {
+ if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
cli_ses.kex_state = KEX_NOTHING;
}
@@ -218,6 +217,7 @@ static void cli_sessionloop() {
if (ses.kexstate.donefirstkex == 0) {
/* We might reach here if we have partial packet reads or have
* received SSG_MSG_IGNORE etc. Just skip it */
+ TRACE2(("donefirstkex false\n"))
return;
}
diff --git a/common-kex.c b/common-kex.c
index 6c22600..88dcb89 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -80,7 +80,7 @@ static const unsigned char dh_p_14[DH_P_14_LEN] = {
static const int DH_G_VAL = 2;
static void kexinitialise();
-void gen_new_keys();
+static void gen_new_keys();
#ifndef DISABLE_ZLIB
static void gen_new_zstreams();
#endif
@@ -159,11 +159,39 @@ void send_msg_kexinit() {
}
-/* *** NOTE regarding (send|recv)_msg_newkeys ***
- * Changed by mihnea from the original kex.c to set dataallowed after a
- * completed key exchange, no matter the order in which it was performed.
- * This enables client mode without affecting server functionality.
- */
+void switch_keys() {
+ TRACE2(("enter switch_keys"))
+ if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
+ dropbear_exit("Unexpected newkeys message");
+ }
+
+ if (!ses.keys) {
+ ses.keys = m_malloc(sizeof(*ses.newkeys));
+ }
+ if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
+ TRACE(("switch_keys recv"))
+ ses.keys->recv = ses.newkeys->recv;
+ m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
+ ses.newkeys->recv.valid = 0;
+ }
+ if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
+ TRACE(("switch_keys trans"))
+ ses.keys->trans = ses.newkeys->trans;
+ m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
+ ses.newkeys->trans.valid = 0;
+ }
+ if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
+ {
+ TRACE(("switch_keys done"))
+ ses.keys->algo_kex = ses.newkeys->algo_kex;
+ ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
+ ses.keys->allow_compress = 0;
+ m_free(ses.newkeys);
+ ses.newkeys = NULL;
+ kexinitialise();
+ }
+ TRACE2(("leave switch_keys"))
+}
/* Bring new keys into use after a key exchange, and let the client know*/
void send_msg_newkeys() {
@@ -174,44 +202,25 @@ void send_msg_newkeys() {
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
encrypt_packet();
-
+
/* set up our state */
- if (ses.kexstate.recvnewkeys) {
- TRACE(("while RECVNEWKEYS=1"))
- gen_new_keys();
- kexinitialise(); /* we've finished with this kex */
- TRACE((" -> DATAALLOWED=1"))
- ses.dataallowed = 1; /* we can send other packets again now */
- ses.kexstate.donefirstkex = 1;
- } else {
- ses.kexstate.sentnewkeys = 1;
- TRACE(("SENTNEWKEYS=1"))
- }
+ ses.kexstate.sentnewkeys = 1;
+ ses.kexstate.donefirstkex = 1;
+ ses.dataallowed = 1; /* we can send other packets again now */
+ gen_new_keys();
+ switch_keys();
- TRACE(("-> MSG_NEWKEYS"))
TRACE(("leave send_msg_newkeys"))
}
/* Bring the new keys into use after a key exchange */
void recv_msg_newkeys() {
- TRACE(("<- MSG_NEWKEYS"))
TRACE(("enter recv_msg_newkeys"))
- /* simply check if we've sent SSH_MSG_NEWKEYS, and if so,
- * switch to the new keys */
- if (ses.kexstate.sentnewkeys) {
- TRACE(("while SENTNEWKEYS=1"))
- gen_new_keys();
- kexinitialise(); /* we've finished with this kex */
- TRACE((" -> DATAALLOWED=1"))
- ses.dataallowed = 1; /* we can send other packets again now */
- ses.kexstate.donefirstkex = 1;
- } else {
- TRACE(("RECVNEWKEYS=1"))
- ses.kexstate.recvnewkeys = 1;
- }
+ ses.kexstate.recvnewkeys = 1;
+ switch_keys();
TRACE(("leave recv_msg_newkeys"))
}
@@ -293,8 +302,7 @@ static void hashkeys(unsigned char *out, int outlen,
* ses.newkeys is the new set of keys which are generated, these are only
* taken into use after both sides have sent a newkeys message */
-/* Originally from kex.c, generalized for cli/svr mode --mihnea */
-void gen_new_keys() {
+static void gen_new_keys() {
unsigned char C2S_IV[MAX_IV_LEN];
unsigned char C2S_key[MAX_KEY_LEN];
@@ -382,11 +390,9 @@ void gen_new_keys() {
gen_new_zstreams();
#endif
- /* Switch over to the new keys */
- m_burn(ses.keys, sizeof(struct key_context));
- m_free(ses.keys);
- ses.keys = ses.newkeys;
- ses.newkeys = NULL;
+ /* Ready to switch over */
+ ses.newkeys->trans.valid = 1;
+ ses.newkeys->recv.valid = 1;
m_burn(C2S_IV, sizeof(C2S_IV));
m_burn(C2S_key, sizeof(C2S_key));
diff --git a/dbutil.c b/dbutil.c
index 8c48a24..8ee6050 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -138,29 +138,39 @@ void dropbear_log(int priority, const char* format, ...) {
#ifdef DEBUG_TRACE
void dropbear_trace(const char* format, ...) {
-
va_list param;
+ struct timeval tv;
if (!debug_trace) {
return;
}
+ gettimeofday(&tv, NULL);
+
va_start(param, format);
- fprintf(stderr, "TRACE (%d): ", getpid());
+ fprintf(stderr, "TRACE (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
}
-void dropbear_trace2(const char* format, ...) {
+void dropbear_trace2(const char* format, ...) {
+ static int trace_env = -1;
va_list param;
+ struct timeval tv;
- if (!(debug_trace && getenv("DROPBEAR_TRACE2"))) {
+ if (trace_env == -1) {
+ trace_env = getenv("DROPBEAR_TRACE2") ? 1 : 0;
+ }
+
+ if (!(debug_trace && trace_env)) {
return;
}
+ gettimeofday(&tv, NULL);
+
va_start(param, format);
- fprintf(stderr, "TRACE2 (%d): ", getpid());
+ fprintf(stderr, "TRACE2 (%d) %d.%d: ", getpid(), tv.tv_sec, tv.tv_usec);
vfprintf(stderr, format, param);
fprintf(stderr, "\n");
va_end(param);
@@ -739,8 +749,6 @@ int buf_getline(buffer * line, FILE * authfile) {
int c = EOF;
- TRACE2(("enter buf_getline"))
-
buf_setpos(line, 0);
buf_setlen(line, 0);
@@ -764,10 +772,8 @@ out:
/* if we didn't read anything before EOF or error, exit */
if (c == EOF && line->pos == 0) {
- TRACE2(("leave buf_getline: failure"))
return DROPBEAR_FAILURE;
} else {
- TRACE2(("leave buf_getline: success"))
buf_setpos(line, 0);
return DROPBEAR_SUCCESS;
}
diff --git a/packet.c b/packet.c
index 366c3d1..09f0600 100644
--- a/packet.c
+++ b/packet.c
@@ -505,8 +505,6 @@ void encrypt_packet() {
/* During key exchange only particular packets are allowed.
Since this packet_type isn't OK we just enqueue it to send
after the KEX, see maybe_flush_reply_queue */
- TRACE2(("Delay sending reply packet. dataallowed %d, type %d, sentnewkeys %d",
- ses.dataallowed, packet_type, ses.kexstate.sentnewkeys))
enqueue_reply_packet();
return;
}
diff --git a/session.h b/session.h
index a76fa99..4ba8ac8 100644
--- a/session.h
+++ b/session.h
@@ -78,6 +78,7 @@ struct key_context_directional {
#endif
} cipher_state;
unsigned char mackey[MAX_MAC_LEN];
+ int valid;
};
struct key_context {