diff cli-authpubkey.c @ 551:c3f2ec71e3d4 agent-client

New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList
author Matt Johnston <matt@ucc.asn.au>
date Mon, 06 Jul 2009 12:59:13 +0000
parents 61c3513825b0
children de3653483ac0
line wrap: on
line diff
--- a/cli-authpubkey.c	Wed Jul 01 06:27:27 2009 +0000
+++ b/cli-authpubkey.c	Mon Jul 06 12:59:13 2009 +0000
@@ -30,6 +30,7 @@
 #include "ssh.h"
 #include "runopts.h"
 #include "auth.h"
+#include "agentfwd.h"
 
 #ifdef ENABLE_CLI_PUBKEY_AUTH
 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
@@ -37,31 +38,23 @@
 /* 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 */
 void cli_pubkeyfail() {
-
-	struct SignKeyList *keyitem;
-	struct SignKeyList **previtem;
-
-	TRACE(("enter cli_pubkeyfail"))
-	previtem = &cli_opts.privkeys;
-
-	/* Find the key we failed with, and remove it */
-	for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
-		if (keyitem == cli_ses.lastprivkey) {
-			*previtem = keyitem->next;
+	m_list_elem *iter;
+	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
+		sign_key *iter_key = (sign_key*)iter->item;
+		
+		if (iter_key == cli_ses.lastprivkey)
+		{
+			/* found the failing key */
+			list_remove(iter);
+			sign_key_free(iter_key);
+			cli_ses.lastprivkey = NULL;
+			return;
 		}
-		previtem = &keyitem;
 	}
-
-	sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */
-	m_free(cli_ses.lastprivkey->filename);
-	m_free(cli_ses.lastprivkey);
-
-	TRACE(("leave cli_pubkeyfail"))
 }
 
 void recv_msg_userauth_pk_ok() {
-
-	struct SignKeyList *keyitem = NULL;
+	m_list_elem *iter;
 	buffer* keybuf = NULL;
 	char* algotype = NULL;
 	unsigned int algolen;
@@ -81,9 +74,9 @@
 
 	/* Iterate through our keys, find which one it was that matched, and
 	 * send a real request with that key */
-	for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
-
-		if (keyitem->type != keytype) {
+	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
+		sign_key *key = (sign_key*)iter->item;
+		if (key->type != keytype) {
 			/* Types differed */
 			TRACE(("types differed"))
 			continue;
@@ -91,7 +84,7 @@
 
 		/* Now we compare the contents of the key */
 		keybuf->pos = keybuf->len = 0;
-		buf_put_pub_key(keybuf, keyitem->key, keytype);
+		buf_put_pub_key(keybuf, key, keytype);
 		buf_setpos(keybuf, 0);
 		buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
 								   remotelen) which has already been taken from
@@ -115,11 +108,11 @@
 	}
 	buf_free(keybuf);
 
-	if (keyitem != NULL) {
+	if (iter != NULL) {
 		TRACE(("matching key"))
 		/* XXX TODO: if it's an encrypted key, here we ask for their
 		 * password */
-		send_msg_userauth_pubkey(keyitem->key, keytype, 1);
+		send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 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"))
 	}
@@ -127,6 +120,25 @@
 	TRACE(("leave recv_msg_userauth_pk_ok"))
 }
 
+void cli_buf_put_sign(buffer* buf, sign_key *key, int type, 
+			const unsigned char *data, unsigned int len)
+{
+	if (key->source == SIGNKEY_SOURCE_AGENT) {
+		/* Format the agent signature ourselves, as buf_put_sign would. */
+		buffer *sigblob;
+		sigblob = buf_new(MAX_PUBKEY_SIZE);
+		agent_buf_sign(sigblob, key, data, len);
+		buf_setpos(sigblob, 0);
+		buf_putstring(buf, buf_getptr(sigblob, sigblob->len),
+				sigblob->len);
+
+		buf_free(sigblob);
+	} else {
+		buf_put_sign(buf, key, type, data, len);
+	}
+	
+}
+
 /* TODO: make it take an agent reference to use as well */
 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
 
@@ -170,6 +182,7 @@
 	TRACE(("leave send_msg_userauth_pubkey"))
 }
 
+/* Returns 1 if a key was tried */
 int cli_auth_pubkey() {
 
 	TRACE(("enter cli_auth_pubkey"))
@@ -177,15 +190,15 @@
 	if (cli_opts.agent_fwd &&
 			!cli_opts.agent_keys_loaded) {
 		/* get the list of available keys from the agent */
-		load_agent_keys(&cli_opts.privkeys);
+		load_agent_keys(cli_opts.privkeys);
 		cli_opts.agent_keys_loaded = 1;
 	}
 
-	if (cli_opts.privkeys != NULL) {
+	if (cli_opts.privkeys->first) {
+		sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
 		/* Send a trial request */
-		send_msg_userauth_pubkey(cli_opts.privkeys->key,
-				cli_opts.privkeys->type, 0);
-		cli_ses.lastprivkey = cli_opts.privkeys;
+		send_msg_userauth_pubkey(key, key->type, 0);
+		cli_ses.lastprivkey = key;
 		TRACE(("leave cli_auth_pubkey-success"))
 		return 1;
 	} else {