From 7dc2f36c3e2d21455ae432da4d8f338e7dc0668c Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 6 Apr 2020 23:18:26 +0800 Subject: use sigtype where appropriate --- svr-authpubkey.c | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'svr-authpubkey.c') diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 5c234b9..a52667c 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -70,10 +70,10 @@ #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ -static int checkpubkey(const char* algo, unsigned int algolen, +static int checkpubkey(const char* keyalgo, unsigned int keyalgolen, const unsigned char* keyblob, unsigned int keybloblen); static int checkpubkeyperms(void); -static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, +static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen, const unsigned char* keyblob, unsigned int keybloblen); static int checkfileperm(char * filename); @@ -82,16 +82,18 @@ static int checkfileperm(char * filename); void svr_auth_pubkey(int valid_user) { unsigned char testkey; /* whether we're just checking if a key is usable */ - char* algo = NULL; /* pubkey algo */ - unsigned int algolen; + char* sigalgo = NULL; + unsigned int sigalgolen; + const char* keyalgo; + unsigned int keyalgolen; unsigned char* keyblob = NULL; unsigned int keybloblen; unsigned int sign_payload_length; buffer * signbuf = NULL; sign_key * key = NULL; char* fp = NULL; - enum signkey_type type = -1; - int auth_failure = 1; + enum signkey_type sigtype, keytype; + int auth_failure = 1; TRACE(("enter pubkeyauth")) @@ -99,7 +101,11 @@ void svr_auth_pubkey(int valid_user) { * actual attempt*/ testkey = (buf_getbool(ses.payload) == 0); - algo = buf_getstring(ses.payload, &algolen); + sigalgo = buf_getstring(ses.payload, &sigalgolen); + sigtype = signature_type_from_name(sigalgo, sigalgolen); + keytype = signkey_type_from_signature(sigtype); + keyalgo = signkey_name_from_type(keytype, &keyalgolen); + keybloblen = buf_getint(ses.payload); keyblob = buf_getptr(ses.payload, keybloblen); @@ -117,8 +123,8 @@ void svr_auth_pubkey(int valid_user) { if (svr_ses.plugin_instance->checkpubkey( svr_ses.plugin_instance, &ses.plugin_session, - algo, - algolen, + keyalgo, + keyalgolen, keyblob, keybloblen, ses.authstate.username) == DROPBEAR_SUCCESS) { @@ -146,7 +152,7 @@ void svr_auth_pubkey(int valid_user) { #endif /* check if the key is valid */ if (auth_failure) { - auth_failure = checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE; + auth_failure = checkpubkey(keyalgo, keyalgolen, keyblob, keybloblen) == DROPBEAR_FAILURE; } if (auth_failure) { @@ -156,7 +162,7 @@ void svr_auth_pubkey(int valid_user) { /* let them know that the key is ok to use */ if (testkey) { - send_msg_userauth_pk_ok(algo, algolen, keyblob, keybloblen); + send_msg_userauth_pk_ok(sigalgo, sigalgolen, keyblob, keybloblen); goto out; } @@ -164,8 +170,7 @@ void svr_auth_pubkey(int valid_user) { /* get the key */ key = new_sign_key(); - type = DROPBEAR_SIGNKEY_ANY; - if (buf_get_pub_key(ses.payload, key, &type) == DROPBEAR_FAILURE) { + if (buf_get_pub_key(ses.payload, key, &keytype) == DROPBEAR_FAILURE) { send_msg_userauth_failure(0, 1); goto out; } @@ -188,7 +193,7 @@ void svr_auth_pubkey(int valid_user) { /* ... and finally verify the signature */ fp = sign_key_fingerprint(keyblob, keybloblen); - if (buf_verify(ses.payload, key, signbuf) == DROPBEAR_SUCCESS) { + if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) { dropbear_log(LOG_NOTICE, "Pubkey auth succeeded for '%s' with key %s from %s", ses.authstate.pw_name, fp, svr_ses.addrstring); @@ -213,8 +218,8 @@ out: if (signbuf) { buf_free(signbuf); } - if (algo) { - m_free(algo); + if (sigalgo) { + m_free(sigalgo); } if (key) { sign_key_free(key); @@ -230,14 +235,14 @@ out: /* Reply that the key is valid for auth, this is sent when the user sends * a straight copy of their pubkey to test, to avoid having to perform * expensive signing operations with a worthless key */ -static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, +static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen, const unsigned char* keyblob, unsigned int keybloblen) { TRACE(("enter send_msg_userauth_pk_ok")) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK); - buf_putstring(ses.writepayload, algo, algolen); + buf_putstring(ses.writepayload, sigalgo, sigalgolen); buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen); encrypt_packet(); @@ -354,7 +359,7 @@ out: /* Checks whether a specified publickey (and associated algorithm) is an * acceptable key for authentication */ /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ -static int checkpubkey(const char* algo, unsigned int algolen, +static int checkpubkey(const char* keyalgo, unsigned int keyalgolen, const unsigned char* keyblob, unsigned int keybloblen) { FILE * authfile = NULL; @@ -368,14 +373,6 @@ static int checkpubkey(const char* algo, unsigned int algolen, TRACE(("enter checkpubkey")) - /* check that we can use the algo */ - if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) { - dropbear_log(LOG_WARNING, - "Pubkey auth attempt with unknown algo for '%s' from %s", - ses.authstate.pw_name, svr_ses.addrstring); - goto out; - } - /* check file permissions, also whether file exists */ if (checkpubkeyperms() == DROPBEAR_FAILURE) { TRACE(("bad authorized_keys permissions, or file doesn't exist")) @@ -427,7 +424,7 @@ static int checkpubkey(const char* algo, unsigned int algolen, } line_num++; - ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen); + ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, keyblob, keybloblen); if (ret == DROPBEAR_SUCCESS) { break; } -- cgit v1.2.3 From 972d723484d89c71e73ed63cc17bb2a6ce8cca5a Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 17 May 2020 23:58:31 +0800 Subject: split signkey_type and signature_type for RSA sha1 vs sha256 --- cli-authpubkey.c | 36 ++++++++++++++++++++------------ common-algo.c | 16 +++++++------- fuzzer-verify.c | 18 ++++++++++++---- rsa.c | 12 +++++------ rsa.h | 4 ++-- session.h | 12 +++++++++-- signkey.c | 63 ++++++++++++++++++++++++++++++++++++++++---------------- signkey.h | 36 +++++++++++++++++++++++++------- ssh.h | 2 +- svr-authpubkey.c | 17 ++++++++++----- 10 files changed, 148 insertions(+), 68 deletions(-) (limited to 'svr-authpubkey.c') diff --git a/cli-authpubkey.c b/cli-authpubkey.c index d1cc1f6..0ad80ea 100644 --- a/cli-authpubkey.c +++ b/cli-authpubkey.c @@ -33,7 +33,7 @@ #include "agentfwd.h" #if DROPBEAR_CLI_PUBKEY_AUTH -static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign); +static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign); /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. * We use it to remove the key we tried from the list */ @@ -58,7 +58,8 @@ void recv_msg_userauth_pk_ok() { buffer* keybuf = NULL; char* algotype = NULL; unsigned int algolen; - enum signkey_type sigtype, keytype; + enum signkey_type keytype; + enum signature_type sigtype; unsigned int remotelen; TRACE(("enter recv_msg_userauth_pk_ok")) @@ -113,7 +114,7 @@ void recv_msg_userauth_pk_ok() { TRACE(("matching key")) /* XXX TODO: if it's an encrypted key, here we ask for their * password */ - send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1); + send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1); } else { TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part")) } @@ -121,7 +122,7 @@ void recv_msg_userauth_pk_ok() { TRACE(("leave recv_msg_userauth_pk_ok")) } -static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, +static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf) { #if DROPBEAR_CLI_AGENTFWD // TODO: rsa-sha256 agent @@ -139,14 +140,14 @@ static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigty } } -static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign) { +static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) { const char *algoname = NULL; unsigned int algolen; buffer* sigbuf = NULL; enum signkey_type keytype = signkey_type_from_signature(sigtype); - TRACE(("enter send_msg_userauth_pubkey")) + TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype)) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); @@ -183,7 +184,6 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, i /* Returns 1 if a key was tried */ int cli_auth_pubkey() { - TRACE(("enter cli_auth_pubkey")) #if DROPBEAR_CLI_AGENTFWD @@ -194,16 +194,26 @@ int cli_auth_pubkey() { } #endif + /* TODO iterate through privkeys to skip ones not in server-sig-algs */ + + /* TODO: testing */ +#if DROPBEAR_RSA_SHA256 + cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; +#elif DROPBEAR_RSA_SHA1 + cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; +#endif + if (cli_opts.privkeys->first) { sign_key * key = (sign_key*)cli_opts.privkeys->first->item; - enum signkey_type sigtype = key->type; - /* Send a trial request */ -#if DROPBEAR_RSA && DROPBEAR_RSA_SHA256 - // TODO: use ext-info to choose rsa kind - if (sigtype == DROPBEAR_SIGNKEY_RSA) { - sigtype = DROPBEAR_SIGNKEY_RSA_SHA256; + /* Determine the signature type to use */ + enum signature_type sigtype = (enum signature_type)key->type; +#if DROPBEAR_RSA + if (key->type == DROPBEAR_SIGNKEY_RSA) { + sigtype = cli_ses.preferred_rsa_sigtype; } #endif + + /* Send a trial request */ send_msg_userauth_pubkey(key, sigtype, 0); cli_ses.lastprivkey = key; TRACE(("leave cli_auth_pubkey-success")) diff --git a/common-algo.c b/common-algo.c index 28f6744..2a1047e 100644 --- a/common-algo.c +++ b/common-algo.c @@ -223,29 +223,29 @@ algo_type ssh_nocompress[] = { algo_type sshhostkey[] = { #if DROPBEAR_ED25519 - {"ssh-ed25519", DROPBEAR_SIGNKEY_ED25519, NULL, 1, NULL}, + {"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL}, #endif #if DROPBEAR_ECDSA #if DROPBEAR_ECC_256 - {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL}, + {"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL}, #endif #if DROPBEAR_ECC_384 - {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL}, + {"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL}, #endif #if DROPBEAR_ECC_521 - {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL}, + {"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL}, #endif #endif #if DROPBEAR_RSA #if DROPBEAR_RSA_SHA256 - {"rsa-sha2-256", DROPBEAR_SIGNKEY_RSA_SHA256, NULL, 1, NULL}, + {"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL}, #endif #if DROPBEAR_RSA_SHA1 - {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL}, + {"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL}, #endif #endif #if DROPBEAR_DSS - {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL}, + {"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL}, #endif {NULL, 0, NULL, 0, NULL} }; @@ -263,8 +263,6 @@ static const struct dropbear_kex kex_dh_group14_sha256 = {DROPBEAR_KEX_NORMAL_DH static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc }; #endif -/* These can't be const since dropbear_ecc_fill_dp() fills out - ecc_curve at runtime */ #if DROPBEAR_ECDH #if DROPBEAR_ECC_256 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc }; diff --git a/fuzzer-verify.c b/fuzzer-verify.c index 8ecbcdb..cda7723 100644 --- a/fuzzer-verify.c +++ b/fuzzer-verify.c @@ -27,15 +27,25 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (setjmp(fuzz.jmp) == 0) { sign_key *key = new_sign_key(); - enum signkey_type type = DROPBEAR_SIGNKEY_ANY; - if (buf_get_pub_key(fuzz.input, key, &type) == DROPBEAR_SUCCESS) { - if (buf_verify(fuzz.input, key, verifydata) == DROPBEAR_SUCCESS) { + enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY; + if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) { + enum signature_type sigtype = (enum signature_type)keytype; + if (keytype == DROPBEAR_SIGNKEY_RSA) { + /* Flip a coin to decide rsa signature type */ + int flag = buf_getbyte(fuzz_input); + if (flag & 0x01) { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; + } else { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; + } + } + if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) { /* The fuzzer is capable of generating keys with a signature to match. We don't want false positives if the key is bogus, since a client/server wouldn't be trusting a bogus key anyway */ int boguskey = 0; - if (type == DROPBEAR_SIGNKEY_DSS) { + if (keytype == DROPBEAR_SIGNKEY_DSS) { /* So far have seen dss keys with bad p/q/g domain parameters */ int pprime, qprime, trials; trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p)); diff --git a/rsa.c b/rsa.c index ef737c8..39e2d46 100644 --- a/rsa.c +++ b/rsa.c @@ -44,7 +44,7 @@ #endif static void rsa_pad_em(const dropbear_rsa_key * key, - const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype); + const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype); /* Load a public rsa key from a buffer, initialising the values. * The key will have the same format as buf_put_rsa_key. @@ -197,7 +197,7 @@ void buf_put_rsa_priv_key(buffer* buf, const dropbear_rsa_key *key) { /* Verify a signature in buf, made on data by the key given. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf) { + enum signature_type sigtype, const buffer *data_buf) { unsigned int slen; DEF_MP_INT(rsa_s); DEF_MP_INT(rsa_mdash); @@ -253,7 +253,7 @@ out: /* Sign the data presented with key, writing the signature contents * to the buffer */ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf) { + enum signature_type sigtype, const buffer *data_buf) { const char *name = NULL; unsigned int nsize, ssize, namelen = 0; unsigned int i; @@ -352,7 +352,7 @@ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, /* Creates the message value as expected by PKCS, see rfc8017 section 9.2 */ static void rsa_pad_em(const dropbear_rsa_key * key, - const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype) { + const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype) { /* EM = 0x00 || 0x01 || PS || 0x00 || T PS is padding of 0xff to make EM the size of key->n @@ -380,14 +380,14 @@ static void rsa_pad_em(const dropbear_rsa_key * key, switch (sigtype) { #if DROPBEAR_RSA_SHA1 - case DROPBEAR_SIGNKEY_RSA: + case DROPBEAR_SIGNATURE_RSA_SHA1: Tlen = sizeof(T_sha1); T = T_sha1; hash_desc = &sha1_desc; break; #endif #if DROPBEAR_RSA_SHA256 - case DROPBEAR_SIGNKEY_RSA_SHA256: + case DROPBEAR_SIGNATURE_RSA_SHA256: Tlen = sizeof(T_sha256); T = T_sha256; hash_desc = &sha256_desc; diff --git a/rsa.h b/rsa.h index 39e6004..a8bbf41 100644 --- a/rsa.h +++ b/rsa.h @@ -43,10 +43,10 @@ typedef struct dropbear_RSA_Key { } dropbear_rsa_key; void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf); + enum signature_type sigtype, const buffer *data_buf); #if DROPBEAR_SIGNKEY_VERIFY int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf); + enum signature_type sigtype, const buffer *data_buf); #endif int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key); int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key); diff --git a/session.h b/session.h index ebfc915..cbe9cb5 100644 --- a/session.h +++ b/session.h @@ -92,8 +92,8 @@ struct key_context { struct key_context_directional trans; const struct dropbear_kex *algo_kex; - int algo_hostkey; /* server key type */ - int algo_signature; /* server signature type */ + enum signkey_type algo_hostkey; /* server key type */ + enum signature_type algo_signature; /* server signature type */ int allow_compress; /* whether compression has started (useful in zlib@openssh.com delayed compression case) */ @@ -313,6 +313,14 @@ struct clientsession { #endif sign_key *lastprivkey; + enum signature_type server_sig_algs[DROPBEAR_SIGNKEY_NUM_NAMED+1]; + int server_sig_algs_count; +#if DROPBEAR_RSA + /* Set to DROPBEAR_SIGNATURE_RSA_SHA256 or DROPBEAR_SIGNATURE_RSA_SHA1 + if depending which the server accepts */ + enum signature_type preferred_rsa_sigtype; +#endif + int retval; /* What the command exit status was - we emulate it */ #if 0 TODO diff --git a/signkey.c b/signkey.c index 27b09a3..47c8c8e 100644 --- a/signkey.c +++ b/signkey.c @@ -111,34 +111,52 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) /* Special case for rsa-sha2-256. This could be generalised if more signature names are added that aren't 1-1 with public key names */ -const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen) { +const char* signature_name_from_type(enum signature_type type, unsigned int *namelen) { #if DROPBEAR_RSA_SHA256 - if (type == DROPBEAR_SIGNKEY_RSA_SHA256) { - *namelen = strlen(SSH_SIGNKEY_RSA_SHA256); - return SSH_SIGNKEY_RSA_SHA256; + if (type == DROPBEAR_SIGNATURE_RSA_SHA256) { + *namelen = strlen(SSH_SIGNATURE_RSA_SHA256); + return SSH_SIGNATURE_RSA_SHA256; } #endif - return signkey_name_from_type(type, namelen); +#if DROPBEAR_RSA_SHA1 + if (type == DROPBEAR_SIGNATURE_RSA_SHA1) { + *namelen = strlen(SSH_SIGNKEY_RSA); + return SSH_SIGNKEY_RSA; + } +#endif + return signkey_name_from_type((enum signkey_type)type, namelen); } -enum signkey_type signature_type_from_name(const char* name, unsigned int namelen) { +/* Returns DROPBEAR_SIGNATURE_NONE if none match */ +enum signature_type signature_type_from_name(const char* name, unsigned int namelen) { #if DROPBEAR_RSA_SHA256 - if (namelen == strlen(SSH_SIGNKEY_RSA_SHA256) - && memcmp(name, SSH_SIGNKEY_RSA_SHA256, namelen) == 0) { - return DROPBEAR_SIGNKEY_RSA_SHA256; + if (namelen == strlen(SSH_SIGNATURE_RSA_SHA256) + && memcmp(name, SSH_SIGNATURE_RSA_SHA256, namelen) == 0) { + return DROPBEAR_SIGNATURE_RSA_SHA256; } #endif - return signkey_type_from_name(name, namelen); +#if DROPBEAR_RSA_SHA256 + if (namelen == strlen(SSH_SIGNKEY_RSA) + && memcmp(name, SSH_SIGNKEY_RSA, namelen) == 0) { + return DROPBEAR_SIGNATURE_RSA_SHA1; + } +#endif + return (enum signature_type)signkey_type_from_name(name, namelen); } -enum signkey_type signkey_type_from_signature(enum signkey_type sigtype) { +enum signkey_type signkey_type_from_signature(enum signature_type sigtype) { #if DROPBEAR_RSA_SHA256 - if (sigtype == DROPBEAR_SIGNKEY_RSA_SHA256) { + if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) { + return DROPBEAR_SIGNKEY_RSA; + } +#endif +#if DROPBEAR_RSA_SHA1 + if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA1) { return DROPBEAR_SIGNKEY_RSA; } #endif assert(sigtype < DROPBEAR_SIGNKEY_NUM_NAMED); - return sigtype; + return (enum signkey_type)sigtype; } /* Returns a pointer to the key part specific to "type". @@ -562,11 +580,20 @@ char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloble #endif } -void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, +void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf) { buffer *sigblob = buf_new(MAX_PUBKEY_SIZE); enum signkey_type keytype = signkey_type_from_signature(sigtype); +#if DEBUG_TRACE + { + int namelen; + const char* signame = signature_name_from_type(sigtype, &namelen); + TRACE(("buf_put_sign type %d %s", sigtype, signame)); + } +#endif + + #if DROPBEAR_DSS if (keytype == DROPBEAR_SIGNKEY_DSS) { buf_put_dss_sign(sigblob, key->dsskey, data_buf); @@ -603,11 +630,12 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, * If FAILURE is returned, the position of * buf is undefined. If SUCCESS is returned, buf will be positioned after the * signature blob */ -int buf_verify(buffer * buf, sign_key *key, enum signkey_type expect_sigtype, const buffer *data_buf) { +int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) { char *type_name = NULL; unsigned int type_name_len = 0; - enum signkey_type sigtype, keytype; + enum signature_type sigtype; + enum signkey_type keytype; TRACE(("enter buf_verify")) @@ -616,8 +644,7 @@ int buf_verify(buffer * buf, sign_key *key, enum signkey_type expect_sigtype, co sigtype = signature_type_from_name(type_name, type_name_len); m_free(type_name); - if (expect_sigtype != DROPBEAR_SIGNKEY_ANY - && expect_sigtype != sigtype) { + if (expect_sigtype != sigtype) { dropbear_exit("Non-matching signing type"); } diff --git a/signkey.h b/signkey.h index 78b237b..9468509 100644 --- a/signkey.h +++ b/signkey.h @@ -32,6 +32,7 @@ struct dropbear_DSS_Key; struct dropbear_RSA_Key; struct dropbear_ED25519_Key; +/* Must match with signature_type below */ enum signkey_type { #if DROPBEAR_RSA DROPBEAR_SIGNKEY_RSA, @@ -49,13 +50,32 @@ enum signkey_type { #endif DROPBEAR_SIGNKEY_NUM_NAMED, DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */ -#if DROPBEAR_RSA_SHA256 - DROPBEAR_SIGNKEY_RSA_SHA256, /* rsa-sha2-256 signature. has a ssh-rsa key */ -#endif DROPBEAR_SIGNKEY_ANY = 80, DROPBEAR_SIGNKEY_NONE = 90, }; +/* Must match with signkey_type above, apart from rsa */ +enum signature_type { +#if DROPBEAR_DSS + DROPBEAR_SIGNATURE_DSS = DROPBEAR_SIGNKEY_DSS, +#endif +#if DROPBEAR_ECDSA + DROPBEAR_SIGNATURE_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_ECDSA_NISTP256, + DROPBEAR_SIGNATURE_ECDSA_NISTP384 = DROPBEAR_SIGNKEY_ECDSA_NISTP384, + DROPBEAR_SIGNATURE_ECDSA_NISTP521 = DROPBEAR_SIGNKEY_ECDSA_NISTP521, +#endif /* DROPBEAR_ECDSA */ +#if DROPBEAR_ED25519 + DROPBEAR_SIGNATURE_ED25519 = DROPBEAR_SIGNKEY_ED25519, +#endif +#if DROPBEAR_RSA_SHA1 + DROPBEAR_SIGNATURE_RSA_SHA1 = 100, /* ssh-rsa signature (sha1) */ +#endif +#if DROPBEAR_RSA_SHA256 + DROPBEAR_SIGNATURE_RSA_SHA256 = 101, /* rsa-sha2-256 signature. has a ssh-rsa key */ +#endif + DROPBEAR_SIGNATURE_NONE = DROPBEAR_SIGNKEY_NONE, +}; + /* Sources for signing keys */ typedef enum { @@ -97,17 +117,17 @@ typedef struct SIGN_key sign_key; sign_key * new_sign_key(void); const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen); enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen); -const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen); -enum signkey_type signature_type_from_name(const char* name, unsigned int namelen); -enum signkey_type signkey_type_from_signature(enum signkey_type sigtype); +const char* signature_name_from_type(enum signature_type type, unsigned int *namelen); +enum signature_type signature_type_from_name(const char* name, unsigned int namelen); +enum signkey_type signkey_type_from_signature(enum signature_type sigtype); int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type); int buf_get_priv_key(buffer* buf, sign_key *key, enum signkey_type *type); void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type); void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type); void sign_key_free(sign_key *key); -void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, const buffer *data_buf); +void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf); #if DROPBEAR_SIGNKEY_VERIFY -int buf_verify(buffer * buf, sign_key *key, enum signkey_type type, const buffer *data_buf); +int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf); char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen); #endif int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen, diff --git a/ssh.h b/ssh.h index fb7f9f2..5030fe9 100644 --- a/ssh.h +++ b/ssh.h @@ -108,7 +108,7 @@ #define SSH_SIGNKEY_ED25519 "ssh-ed25519" #define SSH_SIGNKEY_ED25519_LEN 11 /* signature type */ -#define SSH_SIGNKEY_RSA_SHA256 "rsa-sha2-256" +#define SSH_SIGNATURE_RSA_SHA256 "rsa-sha2-256" /* Agent commands. These aren't part of the spec, and are defined * only on the openssh implementation. */ diff --git a/svr-authpubkey.c b/svr-authpubkey.c index a52667c..46237b7 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -92,7 +92,8 @@ void svr_auth_pubkey(int valid_user) { buffer * signbuf = NULL; sign_key * key = NULL; char* fp = NULL; - enum signkey_type sigtype, keytype; + enum signature_type sigtype; + enum signkey_type keytype; int auth_failure = 1; TRACE(("enter pubkeyauth")) @@ -102,10 +103,6 @@ void svr_auth_pubkey(int valid_user) { testkey = (buf_getbool(ses.payload) == 0); sigalgo = buf_getstring(ses.payload, &sigalgolen); - sigtype = signature_type_from_name(sigalgo, sigalgolen); - keytype = signkey_type_from_signature(sigtype); - keyalgo = signkey_name_from_type(keytype, &keyalgolen); - keybloblen = buf_getint(ses.payload); keyblob = buf_getptr(ses.payload, keybloblen); @@ -117,6 +114,16 @@ void svr_auth_pubkey(int valid_user) { send_msg_userauth_failure(0, 0); goto out; } + + sigtype = signature_type_from_name(sigalgo, sigalgolen); + if (sigtype == DROPBEAR_SIGNATURE_NONE) { + send_msg_userauth_failure(0, 0); + goto out; + } + + keytype = signkey_type_from_signature(sigtype); + keyalgo = signkey_name_from_type(keytype, &keyalgolen); + #if DROPBEAR_PLUGIN if (svr_ses.plugin_instance != NULL) { char *options_buf; -- cgit v1.2.3