mirror of
https://github.com/clearml/dropbear
synced 2025-04-07 14:14:19 +00:00
Take transmit and receive keys into use separately
This commit is contained in:
parent
e2c813df4d
commit
7f42096d0f
@ -256,7 +256,6 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
|||||||
/* Compare hostnames */
|
/* Compare hostnames */
|
||||||
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
|
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
|
||||||
hostlen) != 0) {
|
hostlen) != 0) {
|
||||||
TRACE2(("hosts don't match"))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +204,7 @@ static void cli_sessionloop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
|
/* 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
|
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.sentnewkeys) {
|
||||||
&& ses.kexstate.sentkexinit == 0) {
|
|
||||||
cli_ses.kex_state = KEX_NOTHING;
|
cli_ses.kex_state = KEX_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +217,7 @@ static void cli_sessionloop() {
|
|||||||
if (ses.kexstate.donefirstkex == 0) {
|
if (ses.kexstate.donefirstkex == 0) {
|
||||||
/* We might reach here if we have partial packet reads or have
|
/* We might reach here if we have partial packet reads or have
|
||||||
* received SSG_MSG_IGNORE etc. Just skip it */
|
* received SSG_MSG_IGNORE etc. Just skip it */
|
||||||
|
TRACE2(("donefirstkex false\n"))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
80
common-kex.c
80
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 const int DH_G_VAL = 2;
|
||||||
|
|
||||||
static void kexinitialise();
|
static void kexinitialise();
|
||||||
void gen_new_keys();
|
static void gen_new_keys();
|
||||||
#ifndef DISABLE_ZLIB
|
#ifndef DISABLE_ZLIB
|
||||||
static void gen_new_zstreams();
|
static void gen_new_zstreams();
|
||||||
#endif
|
#endif
|
||||||
@ -159,11 +159,39 @@ void send_msg_kexinit() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *** NOTE regarding (send|recv)_msg_newkeys ***
|
void switch_keys() {
|
||||||
* Changed by mihnea from the original kex.c to set dataallowed after a
|
TRACE2(("enter switch_keys"))
|
||||||
* completed key exchange, no matter the order in which it was performed.
|
if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
|
||||||
* This enables client mode without affecting server functionality.
|
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*/
|
/* Bring new keys into use after a key exchange, and let the client know*/
|
||||||
void send_msg_newkeys() {
|
void send_msg_newkeys() {
|
||||||
@ -177,41 +205,22 @@ void send_msg_newkeys() {
|
|||||||
|
|
||||||
|
|
||||||
/* set up our state */
|
/* 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;
|
ses.kexstate.sentnewkeys = 1;
|
||||||
TRACE(("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"))
|
TRACE(("leave send_msg_newkeys"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bring the new keys into use after a key exchange */
|
/* Bring the new keys into use after a key exchange */
|
||||||
void recv_msg_newkeys() {
|
void recv_msg_newkeys() {
|
||||||
|
|
||||||
TRACE(("<- MSG_NEWKEYS"))
|
|
||||||
TRACE(("enter recv_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"))
|
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
|
* 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 */
|
* taken into use after both sides have sent a newkeys message */
|
||||||
|
|
||||||
/* Originally from kex.c, generalized for cli/svr mode --mihnea */
|
static void gen_new_keys() {
|
||||||
void gen_new_keys() {
|
|
||||||
|
|
||||||
unsigned char C2S_IV[MAX_IV_LEN];
|
unsigned char C2S_IV[MAX_IV_LEN];
|
||||||
unsigned char C2S_key[MAX_KEY_LEN];
|
unsigned char C2S_key[MAX_KEY_LEN];
|
||||||
@ -382,11 +390,9 @@ void gen_new_keys() {
|
|||||||
gen_new_zstreams();
|
gen_new_zstreams();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Switch over to the new keys */
|
/* Ready to switch over */
|
||||||
m_burn(ses.keys, sizeof(struct key_context));
|
ses.newkeys->trans.valid = 1;
|
||||||
m_free(ses.keys);
|
ses.newkeys->recv.valid = 1;
|
||||||
ses.keys = ses.newkeys;
|
|
||||||
ses.newkeys = NULL;
|
|
||||||
|
|
||||||
m_burn(C2S_IV, sizeof(C2S_IV));
|
m_burn(C2S_IV, sizeof(C2S_IV));
|
||||||
m_burn(C2S_key, sizeof(C2S_key));
|
m_burn(C2S_key, sizeof(C2S_key));
|
||||||
|
24
dbutil.c
24
dbutil.c
@ -138,29 +138,39 @@ void dropbear_log(int priority, const char* format, ...) {
|
|||||||
|
|
||||||
#ifdef DEBUG_TRACE
|
#ifdef DEBUG_TRACE
|
||||||
void dropbear_trace(const char* format, ...) {
|
void dropbear_trace(const char* format, ...) {
|
||||||
|
|
||||||
va_list param;
|
va_list param;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
if (!debug_trace) {
|
if (!debug_trace) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
va_start(param, format);
|
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);
|
vfprintf(stderr, format, param);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
va_end(param);
|
va_end(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropbear_trace2(const char* format, ...) {
|
void dropbear_trace2(const char* format, ...) {
|
||||||
|
static int trace_env = -1;
|
||||||
va_list param;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
va_start(param, format);
|
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);
|
vfprintf(stderr, format, param);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
va_end(param);
|
va_end(param);
|
||||||
@ -739,8 +749,6 @@ int buf_getline(buffer * line, FILE * authfile) {
|
|||||||
|
|
||||||
int c = EOF;
|
int c = EOF;
|
||||||
|
|
||||||
TRACE2(("enter buf_getline"))
|
|
||||||
|
|
||||||
buf_setpos(line, 0);
|
buf_setpos(line, 0);
|
||||||
buf_setlen(line, 0);
|
buf_setlen(line, 0);
|
||||||
|
|
||||||
@ -764,10 +772,8 @@ out:
|
|||||||
|
|
||||||
/* if we didn't read anything before EOF or error, exit */
|
/* if we didn't read anything before EOF or error, exit */
|
||||||
if (c == EOF && line->pos == 0) {
|
if (c == EOF && line->pos == 0) {
|
||||||
TRACE2(("leave buf_getline: failure"))
|
|
||||||
return DROPBEAR_FAILURE;
|
return DROPBEAR_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
TRACE2(("leave buf_getline: success"))
|
|
||||||
buf_setpos(line, 0);
|
buf_setpos(line, 0);
|
||||||
return DROPBEAR_SUCCESS;
|
return DROPBEAR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
2
packet.c
2
packet.c
@ -505,8 +505,6 @@ void encrypt_packet() {
|
|||||||
/* During key exchange only particular packets are allowed.
|
/* During key exchange only particular packets are allowed.
|
||||||
Since this packet_type isn't OK we just enqueue it to send
|
Since this packet_type isn't OK we just enqueue it to send
|
||||||
after the KEX, see maybe_flush_reply_queue */
|
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();
|
enqueue_reply_packet();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user