diff options
-rw-r--r-- | options.h | 1 | ||||
-rw-r--r-- | signkey.c | 124 | ||||
-rw-r--r-- | signkey.h | 2 | ||||
-rw-r--r-- | svr-authpubkey.c | 10 |
4 files changed, 90 insertions, 47 deletions
@@ -227,6 +227,7 @@ #define DROPBEAR_SIGNKEY_ANY 0 #define DROPBEAR_SIGNKEY_RSA 1 #define DROPBEAR_SIGNKEY_DSS 2 +#define DROPBEAR_SIGNKEY_NONE 3 #define DROPBEAR_COMP_NONE 0 #define DROPBEAR_COMP_ZLIB 1 @@ -44,6 +44,46 @@ sign_key * new_sign_key() { } +/* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally + * if the type is invalid */ +const char* signkey_name_from_type(int type, int *namelen) { + +#ifdef DROPBEAR_RSA + if (type == DROPBEAR_SIGNKEY_RSA) { + *namelen = SSH_SIGNKEY_RSA_LEN; + return SSH_SIGNKEY_RSA; + } +#endif +#ifdef DROPBEAR_DSS + if (type == DROPBEAR_SIGNKEY_DSS) { + *namelen = SSH_SIGNKEY_DSS_LEN; + return SSH_SIGNKEY_DSS; + } +#endif + dropbear_exit("bad key type %d", type); + return NULL; /* notreached */ +} + +/* Returns DROPBEAR_SIGNKEY_RSA, DROPBEAR_SIGNKEY_DSS, + * or DROPBEAR_SIGNKEY_NONE */ +int signkey_type_from_name(const char* name, int namelen) { + +#ifdef DROPBEAR_RSA + if (namelen == SSH_SIGNKEY_RSA_LEN + && memcmp(name, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN) == 0) { + return DROPBEAR_SIGNKEY_RSA; + } +#endif +#ifdef DROPBEAR_DSS + if (namelen == SSH_SIGNKEY_DSS_LEN + && memcmp(name, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN) == 0) { + return DROPBEAR_SIGNKEY_DSS; + } +#endif + + return DROPBEAR_SIGNKEY_NONE; +} + /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail. * type should be set by the caller to specify the type to read, and * on return is set to the type read (useful when type = _ANY) */ @@ -51,94 +91,100 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { unsigned char* ident; unsigned int len; + int keytype; + int ret = DROPBEAR_FAILURE; TRACE(("enter buf_get_pub_key")); ident = buf_getstring(buf, &len); + keytype = signkey_type_from_name(ident, len); + m_free(ident); + + if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) { + return DROPBEAR_FAILURE; + } + + *type = keytype; + /* Rewind the buffer back before "ssh-rsa" etc */ + buf_incrpos(buf, -len - 4); #ifdef DROPBEAR_DSS - if (memcmp(ident, SSH_SIGNKEY_DSS, len) == 0 - && (*type == DROPBEAR_SIGNKEY_ANY - || *type == DROPBEAR_SIGNKEY_DSS)) { - m_free(ident); - buf_setpos(buf, buf->pos - len - 4); + if (keytype == DROPBEAR_SIGNKEY_DSS) { dss_key_free(key->dsskey); key->dsskey = (dss_key*)m_malloc(sizeof(dss_key)); - *type = DROPBEAR_SIGNKEY_DSS; - return buf_get_dss_pub_key(buf, key->dsskey); + ret = buf_get_dss_pub_key(buf, key->dsskey); + if (ret == DROPBEAR_FAILURE) { + m_free(key->dsskey); + } } #endif #ifdef DROPBEAR_RSA - if (memcmp(ident, SSH_SIGNKEY_RSA, len) == 0 - && (*type == DROPBEAR_SIGNKEY_ANY - || *type == DROPBEAR_SIGNKEY_RSA)) { - m_free(ident); - buf_setpos(buf, buf->pos - len - 4); + if (keytype == DROPBEAR_SIGNKEY_RSA) { rsa_key_free(key->rsakey); key->rsakey = (rsa_key*)m_malloc(sizeof(rsa_key)); - *type = DROPBEAR_SIGNKEY_RSA; - return buf_get_rsa_pub_key(buf, key->rsakey); + ret = buf_get_rsa_pub_key(buf, key->rsakey); + if (ret == DROPBEAR_FAILURE) { + m_free(key->rsakey); + } } #endif - TRACE(("leave buf_get_pub_key: didn't match the type we want (%d versus '%s'len %d)", *type, ident, len)); - m_free(ident); + TRACE(("leave buf_get_pub_key")); - return DROPBEAR_FAILURE; + return ret; } -/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ -/* type is set to hold the type returned */ +/* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail. + * type should be set by the caller to specify the type to read, and + * on return is set to the type read (useful when type = _ANY) */ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) { unsigned char* ident; unsigned int len; - int ret; + int keytype; + int ret = DROPBEAR_FAILURE; TRACE(("enter buf_get_priv_key")); + ident = buf_getstring(buf, &len); + keytype = signkey_type_from_name(ident, len); + m_free(ident); + + if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) { + return DROPBEAR_FAILURE; + } + + *type = keytype; + + /* Rewind the buffer back before "ssh-rsa" etc */ + buf_incrpos(buf, -len - 4); #ifdef DROPBEAR_DSS - if (memcmp(ident, SSH_SIGNKEY_DSS, len) == 0 - && (*type == DROPBEAR_SIGNKEY_ANY - || *type == DROPBEAR_SIGNKEY_DSS)) { - m_free(ident); - buf_setpos(buf, buf->pos - len - 4); + if (keytype == DROPBEAR_SIGNKEY_DSS) { dss_key_free(key->dsskey); key->dsskey = (dss_key*)m_malloc(sizeof(dss_key)); ret = buf_get_dss_priv_key(buf, key->dsskey); - *type = DROPBEAR_SIGNKEY_DSS; if (ret == DROPBEAR_FAILURE) { m_free(key->dsskey); } - TRACE(("leave buf_get_priv_key: done get dss")); - return ret; } #endif #ifdef DROPBEAR_RSA - if (memcmp(ident, SSH_SIGNKEY_RSA, len) == 0 - && (*type == DROPBEAR_SIGNKEY_ANY - || *type == DROPBEAR_SIGNKEY_RSA)) { - m_free(ident); - buf_setpos(buf, buf->pos - len - 4); + if (keytype == DROPBEAR_SIGNKEY_RSA) { rsa_key_free(key->rsakey); key->rsakey = (rsa_key*)m_malloc(sizeof(rsa_key)); ret = buf_get_rsa_priv_key(buf, key->rsakey); - *type = DROPBEAR_SIGNKEY_RSA; if (ret == DROPBEAR_FAILURE) { m_free(key->rsakey); } - TRACE(("leave buf_get_priv_key: done get rsa")); - return ret; } #endif - m_free(ident); - TRACE(("leave buf_get_priv_key")); - return DROPBEAR_FAILURE; + + return ret; } @@ -42,6 +42,8 @@ struct SIGN_key { typedef struct SIGN_key sign_key; sign_key * new_sign_key(); +const char* signkey_name_from_type(int type, int *namelen); +int signkey_type_from_name(const char* name, int namelen); int buf_get_pub_key(buffer *buf, sign_key *key, int *type); int buf_get_priv_key(buffer* buf, sign_key *key, int *type); void buf_put_pub_key(buffer* buf, sign_key *key, int type); diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 9c58a8d..e6cc606 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -58,7 +58,6 @@ void svr_auth_pubkey() { unsigned char* keyblob; unsigned int keybloblen; buffer * signbuf = NULL; - unsigned int sigoffset; sign_key * key = NULL; char* fp = NULL; int type = -1; @@ -99,14 +98,9 @@ void svr_auth_pubkey() { * session_id, concatenated with the payload packet up to the signature */ signbuf = buf_new(ses.payload->pos + 4 + SHA1_HASH_SIZE); buf_putstring(signbuf, ses.session_id, SHA1_HASH_SIZE); - sigoffset = ses.payload->pos; - buf_setpos(ses.payload, 0); - memcpy(buf_getwriteptr(signbuf, sigoffset), - buf_getptr(ses.payload, sigoffset), sigoffset); - buf_incrwritepos(signbuf, sigoffset); - buf_setpos(ses.payload, sigoffset); - + buf_putbytes(signbuf, ses.payload->data, ses.payload->pos); buf_setpos(signbuf, 0); + /* ... and finally verify the signature */ fp = sign_key_fingerprint(key, type); if (buf_verify(ses.payload, key, buf_getptr(signbuf, signbuf->len), |