summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--options.h1
-rw-r--r--signkey.c124
-rw-r--r--signkey.h2
-rw-r--r--svr-authpubkey.c10
4 files changed, 90 insertions, 47 deletions
diff --git a/options.h b/options.h
index 8ed21ab..02f36bc 100644
--- a/options.h
+++ b/options.h
@@ -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
diff --git a/signkey.c b/signkey.c
index 2fd301f..ec6ea74 100644
--- a/signkey.c
+++ b/signkey.c
@@ -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;
}
diff --git a/signkey.h b/signkey.h
index 396db7f..3bd5c58 100644
--- a/signkey.h
+++ b/signkey.h
@@ -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),