diff svr-authpubkey.c @ 1733:d529a52b2f7c coverity coverity

merge coverity from main
author Matt Johnston <matt@ucc.asn.au>
date Fri, 26 Jun 2020 21:07:34 +0800
parents ae41624c2198
children 064f5be2fc45
line wrap: on
line diff
--- a/svr-authpubkey.c	Thu Mar 21 23:28:59 2019 +0800
+++ b/svr-authpubkey.c	Fri Jun 26 21:07:34 2020 +0800
@@ -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,15 +82,19 @@
 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;
+	enum signature_type sigtype;
+	enum signkey_type keytype;
+    int auth_failure = 1;
 
 	TRACE(("enter pubkeyauth"))
 
@@ -98,7 +102,7 @@
 	 * actual attempt*/
 	testkey = (buf_getbool(ses.payload) == 0);
 
-	algo = buf_getstring(ses.payload, &algolen);
+	sigalgo = buf_getstring(ses.payload, &sigalgolen);
 	keybloblen = buf_getint(ses.payload);
 	keyblob = buf_getptr(ses.payload, keybloblen);
 
@@ -111,15 +115,61 @@
 		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;
+            if (svr_ses.plugin_instance->checkpubkey(
+                        svr_ses.plugin_instance,
+                        &ses.plugin_session,
+                        keyalgo, 
+                        keyalgolen, 
+                        keyblob, 
+                        keybloblen,
+                        ses.authstate.username) == DROPBEAR_SUCCESS) {
+                /* Success */
+                auth_failure = 0;
+
+                /* Options provided? */
+                options_buf = ses.plugin_session->get_options(ses.plugin_session);
+                if (options_buf) {
+                    struct buf temp_buf = { 
+                        .data = (unsigned char *)options_buf,
+                        .len = strlen(options_buf),
+                        .pos = 0,
+                        .size = 0
+                    };
+                    int ret = svr_add_pubkey_options(&temp_buf, 0, "N/A");
+                    if (ret == DROPBEAR_FAILURE) {
+                        /* Fail immediately as the plugin provided wrong options */
+                        send_msg_userauth_failure(0, 0);
+                        goto out;
+                    }
+                }
+            }
+        }
+#endif
 	/* check if the key is valid */
-	if (checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE) {
+        if (auth_failure) {
+            auth_failure = checkpubkey(keyalgo, keyalgolen, keyblob, keybloblen) == DROPBEAR_FAILURE;
+        }
+
+        if (auth_failure) {
 		send_msg_userauth_failure(0, 0);
 		goto out;
 	}
 
 	/* 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;
 	}
 
@@ -127,8 +177,7 @@
 	
 	/* 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;
 	}
@@ -151,11 +200,18 @@
 
 	/* ... 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);
 		send_msg_userauth_success();
+#if DROPBEAR_PLUGIN
+                if ((ses.plugin_session != NULL) && (svr_ses.plugin_instance->auth_success != NULL)) {
+                    /* Was authenticated through the external plugin. tell plugin that signature verification was ok */
+                    svr_ses.plugin_instance->auth_success(ses.plugin_session);
+                }
+#endif
+                
 	} else {
 		dropbear_log(LOG_WARNING,
 				"Pubkey auth bad signature for '%s' with key %s from %s",
@@ -169,8 +225,8 @@
 	if (signbuf) {
 		buf_free(signbuf);
 	}
-	if (algo) {
-		m_free(algo);
+	if (sigalgo) {
+		m_free(sigalgo);
 	}
 	if (key) {
 		sign_key_free(key);
@@ -186,14 +242,14 @@
 /* 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();
@@ -310,7 +366,7 @@
 /* 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;
@@ -324,14 +380,6 @@
 
 	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"))
@@ -383,7 +431,7 @@
 		}
 		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;
 		}