send and handle SSH_MSG_EXT_INFO only at the correct point

- other fixes for rsa pubkey auth
- only include ext-info handling when rsa pubkey auth is compiled
This commit is contained in:
Matt Johnston 2020-05-24 14:16:58 +08:00
parent 79bedc90a1
commit 701d43b859
13 changed files with 46 additions and 22 deletions

View File

@ -200,7 +200,7 @@ int cli_auth_pubkey() {
while (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
if (cli_ses.server_sig_algs) {
#ifdef DROPBEAR_RSA
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA256
if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256)
@ -242,7 +242,7 @@ int cli_auth_pubkey() {
assume all except rsa-sha256 are OK. */
#if DROPBEAR_RSA
if (key->type == DROPBEAR_SIGNKEY_RSA) {
#ifdef DROPBEAR_RSA_SHA1
#if DROPBEAR_RSA_SHA1
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
TRACE(("no server-sig-algs, using rsa sha1"))
break;

View File

@ -418,6 +418,15 @@ void recv_msg_ext_info(void) {
unsigned int num_ext;
unsigned int i;
TRACE(("enter recv_msg_ext_info"))
/* Must be after the first SSH_MSG_NEWKEYS */
TRACE(("last %d, donefirst %d, donescond %d", ses.lastpacket, ses.kexstate.donefirstkex, ses.kexstate.donesecondkex))
if (!(ses.lastpacket == SSH_MSG_NEWKEYS && !ses.kexstate.donesecondkex)) {
TRACE(("leave recv_msg_ext_info: ignoring packet received at the wrong time"))
return;
}
num_ext = buf_getint(ses.payload);
TRACE(("received SSH_MSG_EXT_INFO with %d items", num_ext))
@ -435,4 +444,5 @@ void recv_msg_ext_info(void) {
}
m_free(ext_name);
}
TRACE(("leave recv_msg_ext_info"))
}

View File

@ -313,9 +313,11 @@ algo_type sshkex[] = {
#if DROPBEAR_KEXGUESS2
{KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
#endif
#if DROPBEAR_EXT_INFO
#if DROPBEAR_CLIENT
/* Set unusable by svr_algos_initialise() */
{SSH_EXT_INFO_C, 0, NULL, 1, NULL},
#endif
#endif
{NULL, 0, NULL, 0, NULL}
};

View File

@ -175,6 +175,9 @@ void send_msg_newkeys() {
/* set up our state */
ses.kexstate.sentnewkeys = 1;
if (ses.kexstate.donefirstkex) {
ses.kexstate.donesecondkex = 1;
}
ses.kexstate.donefirstkex = 1;
ses.dataallowed = 1; /* we can send other packets again now */
gen_new_keys();
@ -197,8 +200,6 @@ void recv_msg_newkeys() {
/* Set up the kex for the first time */
void kexfirstinitialise() {
ses.kexstate.donefirstkex = 0;
#ifdef DISABLE_ZLIB
ses.compress_algos = ssh_nocompress;
#else
@ -833,6 +834,7 @@ static void read_kex_algos() {
}
#endif
#if DROPBEAR_EXT_INFO
/* Determine if SSH_MSG_EXT_INFO messages should be sent.
Should be done for the first key exchange. Only required on server side
for server-sig-algs */
@ -843,6 +845,7 @@ static void read_kex_algos() {
}
}
}
#endif
algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
allgood &= goodguess;

View File

@ -133,7 +133,7 @@ static void check_signkey_bits(enum signkey_type type, int bits)
}
break;
#endif
#ifdef DROPEAR_DSS
#if DROPEAR_DSS
case DROPBEAR_SIGNKEY_DSS:
if (bits != 1024) {
dropbear_exit("DSS keys have a fixed size of 1024 bits\n");

4
kex.h
View File

@ -61,7 +61,6 @@ int is_compress_recv(void);
#endif
void recv_msg_kexdh_init(void); /* server */
void send_msg_ext_info(void); /* server */
void send_msg_kexdh_init(void); /* client */
void recv_msg_kexdh_reply(void); /* client */
@ -76,8 +75,9 @@ struct KEXState {
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,
unsigned int donefirstkex; /* Set to 1 after the first kex has completed,
ie the transport layer has been set up */
unsigned int donesecondkex; /* Set to 1 after the second kex has completed */
unsigned our_first_follows_matches : 1;

View File

@ -51,8 +51,6 @@ void process_packet() {
type = buf_getbyte(ses.payload);
TRACE(("process_packet: packet type = %d, len %d", type, ses.payload->len))
ses.lastpacket = type;
now = monotonic_now();
ses.last_packet_time_keepalive_recv = now;
@ -154,6 +152,7 @@ void process_packet() {
recv_unimplemented();
out:
ses.lastpacket = type;
buf_free(ses.payload);
ses.payload = NULL;

View File

@ -186,7 +186,7 @@ struct sshsession {
/* Enables/disables compression */
algo_type *compress_algos;
/* Other side allows SSH_MSG_EXT_INFO */
/* Other side allows SSH_MSG_EXT_INFO. Currently only set for server */
int allow_ext_info;
/* a list of queued replies that should be sent after a KEX has
@ -253,13 +253,12 @@ struct serversession {
#endif
#if DROPBEAR_PLUGIN
/* The shared library handle */
void *plugin_handle;
/* The shared library handle */
void *plugin_handle;
/* The instance created by the plugin_new function */
struct PluginInstance *plugin_instance;
/* The instance created by the plugin_new function */
struct PluginInstance *plugin_instance;
#endif
};
typedef enum {
@ -288,7 +287,6 @@ struct clientsession {
cli_kex_state kex_state; /* Used for progressing KEX */
cli_state state; /* Used to progress auth/channelsession etc */
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
int tty_raw_mode; /* Whether we're in raw mode (and have to clean up) */
struct termios saved_tio;

View File

@ -139,7 +139,7 @@ enum signature_type signature_type_from_name(const char* name, unsigned int name
return DROPBEAR_SIGNATURE_RSA_SHA256;
}
#endif
#if DROPBEAR_RSA_SHA256
#if DROPBEAR_RSA_SHA1
if (namelen == strlen(SSH_SIGNKEY_RSA)
&& memcmp(name, SSH_SIGNKEY_RSA, namelen) == 0) {
return DROPBEAR_SIGNATURE_RSA_SHA1;

View File

@ -38,13 +38,15 @@
#include "gensignkey.h"
static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs);
#if DROPBEAR_EXT_INFO
static void send_msg_ext_info(void);
#endif
/* Handle a diffie-hellman key exchange initialisation. This involves
* calculating a session key reply value, and corresponding hash. These
* are carried out by send_msg_kexdh_reply(). recv_msg_kexdh_init() calls
* that function, then brings the new keys into use */
void recv_msg_kexdh_init() {
DEF_MP_INT(dh_e);
buffer *ecdh_qs = NULL;
@ -87,9 +89,12 @@ void recv_msg_kexdh_init() {
send_msg_newkeys();
if (ses.allow_ext_info) {
#if DROPBEAR_EXT_INFO
/* Only send it following the first newkeys */
if (!ses.kexstate.donesecondkex && ses.allow_ext_info) {
send_msg_ext_info();
}
#endif
ses.requirenext = SSH_MSG_NEWKEYS;
TRACE(("leave recv_msg_kexdh_init"))
@ -247,8 +252,9 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
TRACE(("leave send_msg_kexdh_reply"))
}
#if DROPBEAR_EXT_INFO
/* Only used for server-sig-algs on the server side */
void send_msg_ext_info(void) {
static void send_msg_ext_info(void) {
TRACE(("enter send_msg_ext_info"))
buf_putbyte(ses.writepayload, SSH_MSG_EXT_INFO);
@ -261,5 +267,5 @@ void send_msg_ext_info(void) {
encrypt_packet();
TRACE(("leave send_msg_ext_info"))
}
#endif

View File

@ -567,7 +567,7 @@ static void addhostkey(const char *keyfile) {
void load_all_hostkeys() {
int i;
int any_keys = 0;
#ifdef DROPBEAR_ECDSA
#if DROPBEAR_ECDSA
int loaded_any_ecdsa = 0;
#endif

View File

@ -337,9 +337,11 @@ static void svr_algos_initialise(void) {
algo->usable = 0;
}
#endif
#if DROPBEAR_EXT_INFO
if (strcmp(algo->name, SSH_EXT_INFO_C) == 0) {
algo->usable = 0;
}
#endif
}
}

View File

@ -161,6 +161,10 @@ If you test it please contact the Dropbear author */
#define DROPBEAR_NORMAL_DH ((DROPBEAR_DH_GROUP1) || (DROPBEAR_DH_GROUP14) || (DROPBEAR_DH_GROUP16))
/* Dropbear only uses server-sig-algs, only needed if we have rsa-sha256 pubkey auth */
#define DROPBEAR_EXT_INFO ((DROPBEAR_RSA_SHA256) \
&& ((DROPBEAR_CLI_PUBKEY_AUTH) || (DROPBEAR_SVR_PUBKEY_AUTH)))
/* roughly 2x 521 bits */
#define MAX_ECC_SIZE 140