diff signkey.c @ 44:45edf30ea0a6

Improved signkey code
author Matt Johnston <matt@ucc.asn.au>
date Tue, 03 Aug 2004 15:51:55 +0000
parents b4874d772210
children 095d689fed16
line wrap: on
line diff
--- a/signkey.c	Mon Aug 02 04:25:05 2004 +0000
+++ b/signkey.c	Tue Aug 03 15:51:55 2004 +0000
@@ -44,6 +44,46 @@
 
 }
 
+/* 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 @@
 
 	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;
 	
 }