changeset 883:ff597bf2cfb0

DROPBEAR_CLI_AUTH_IMMEDIATE fixed, now enabled by default
author Matt Johnston <matt@ucc.asn.au>
date Fri, 17 Jan 2014 21:39:27 +0800
parents f05107560aa9
children dd0bd9231fc2
files cli-auth.c cli-session.c common-kex.c dbutil.c options.h session.h sysoptions.h
diffstat 7 files changed, 65 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/cli-auth.c	Wed Dec 11 21:50:33 2013 +0800
+++ b/cli-auth.c	Fri Jan 17 21:39:27 2014 +0800
@@ -41,16 +41,6 @@
 /* Send a "none" auth request to get available methods */
 void cli_auth_getmethods() {
 	TRACE(("enter cli_auth_getmethods"))
-#ifdef CLI_IMMEDIATE_AUTH
-	ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
-    if (getenv(DROPBEAR_PASSWORD_ENV)) {
-		ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
-	}
-	if (cli_auth_try() == DROPBEAR_SUCCESS) {
-		TRACE(("skipped initial none auth query"))
-		return;
-	}
-#endif
 	CHECKCLEARTOWRITE();
 	buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
 	buf_putstring(ses.writepayload, cli_opts.username, 
@@ -60,6 +50,18 @@
 	buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
 
 	encrypt_packet();
+
+#ifdef DROPBEAR_CLI_IMMEDIATE_AUTH
+	ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
+    if (getenv(DROPBEAR_PASSWORD_ENV)) {
+		ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
+	}
+	if (cli_auth_try() == DROPBEAR_SUCCESS) {
+		TRACE(("skipped initial none auth query"))
+		/* Note that there will be two auth responses in-flight */
+		cli_ses.ignore_next_auth_response = 1;
+	}
+#endif
 	TRACE(("leave cli_auth_getmethods"))
 }
 
@@ -150,31 +152,46 @@
 	TRACE(("<- MSG_USERAUTH_FAILURE"))
 	TRACE(("enter recv_msg_userauth_failure"))
 
+	if (ses.authstate.authdone) {
+		TRACE(("leave recv_msg_userauth_failure, already authdone."))
+		return;
+	}
+
 	if (cli_ses.state != USERAUTH_REQ_SENT) {
 		/* Perhaps we should be more fatal? */
 		dropbear_exit("Unexpected userauth failure");
 	}
 
+	/* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for 
+	the "none" auth request, and then a response to the immediate auth request. 
+	We need to be careful handling them. */
+	if (cli_ses.ignore_next_auth_response) {
+		TRACE(("ignore next response, state set to USERAUTH_REQ_SENT"))
+		cli_ses.state = USERAUTH_REQ_SENT;
+	} else  {
+		cli_ses.state = USERAUTH_FAIL_RCVD;
+		cli_ses.lastauthtype = AUTH_TYPE_NONE;
 #ifdef ENABLE_CLI_PUBKEY_AUTH
-	/* If it was a pubkey auth request, we should cross that key 
-	 * off the list. */
-	if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
-		cli_pubkeyfail();
-	}
+		/* If it was a pubkey auth request, we should cross that key 
+		 * off the list. */
+		if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) {
+			cli_pubkeyfail();
+		}
 #endif
 
 #ifdef ENABLE_CLI_INTERACT_AUTH
-	/* If we get a failure message for keyboard interactive without
-	 * receiving any request info packet, then we don't bother trying
-	 * keyboard interactive again */
-	if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
-			&& !cli_ses.interact_request_received) {
-		TRACE(("setting auth_interact_failed = 1"))
-		cli_ses.auth_interact_failed = 1;
+		/* If we get a failure message for keyboard interactive without
+		 * receiving any request info packet, then we don't bother trying
+		 * keyboard interactive again */
+		if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT
+				&& !cli_ses.interact_request_received) {
+			TRACE(("setting auth_interact_failed = 1"))
+			cli_ses.auth_interact_failed = 1;
+		}
+#endif
 	}
-#endif
 
-	cli_ses.lastauthtype = AUTH_TYPE_NONE;
+	cli_ses.ignore_next_auth_response = 0;
 
 	methods = buf_getstring(ses.payload, &methlen);
 
@@ -227,13 +244,14 @@
 	}
 
 	m_free(methods);
-
-	cli_ses.state = USERAUTH_FAIL_RCVD;
 		
 	TRACE(("leave recv_msg_userauth_failure"))
 }
 
 void recv_msg_userauth_success() {
+	/* This function can validly get called multiple times
+	if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
+
 	TRACE(("received msg_userauth_success"))
 	/* Note: in delayed-zlib mode, setting authdone here 
 	 * will enable compression in the transport layer */
--- a/cli-session.c	Wed Dec 11 21:50:33 2013 +0800
+++ b/cli-session.c	Fri Jan 17 21:39:27 2014 +0800
@@ -228,6 +228,10 @@
 			cli_ses.state = USERAUTH_REQ_SENT;
 			TRACE(("leave cli_sessionloop: sent userauth methods req"))
 			return;
+
+		case USERAUTH_REQ_SENT:
+			TRACE(("leave cli_sessionloop: waiting, req_sent"))
+			return;
 			
 		case USERAUTH_FAIL_RCVD:
 			if (cli_auth_try() == DROPBEAR_FAILURE) {
--- a/common-kex.c	Wed Dec 11 21:50:33 2013 +0800
+++ b/common-kex.c	Fri Jan 17 21:39:27 2014 +0800
@@ -792,6 +792,11 @@
 	hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize));
 	buf_setlen(ses.hash, hash_desc->hashsize);
 
+#ifdef DEBUG_KEXHASH
+	printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len);
+	printhex("kexhash", ses.hash->data, ses.hash->len);
+#endif
+
 	buf_burn(ses.kexhashbuf);
 	buf_free(ses.kexhashbuf);
 	ses.kexhashbuf = NULL;
--- a/dbutil.c	Wed Dec 11 21:50:33 2013 +0800
+++ b/dbutil.c	Fri Jan 17 21:39:27 2014 +0800
@@ -812,6 +812,10 @@
 /* make sure that the socket closes */
 void m_close(int fd) {
 
+	if (fd == -1) {
+		return;
+	}
+
 	int val;
 	do {
 		val = close(fd);
--- a/options.h	Wed Dec 11 21:50:33 2013 +0800
+++ b/options.h	Fri Jan 17 21:39:27 2014 +0800
@@ -222,13 +222,6 @@
  * return the password on standard output */
 /*#define ENABLE_CLI_ASKPASS_HELPER*/
 
-/* Send a real auth request first rather than requesting a list of available methods.
- * It saves a network round trip at login but prevents immediate login to
- * accounts with no password, and might be rejected by some strict servers (none
- * encountered yet) - hence it isn't enabled by default. */
-/* #define CLI_IMMEDIATE_AUTH */
-
-
 /* Source for randomness. This must be able to provide hundreds of bytes per SSH
  * connection without blocking. In addition /dev/random is used for seeding
  * rsa/dss key generation */
--- a/session.h	Wed Dec 11 21:50:33 2013 +0800
+++ b/session.h	Fri Jan 17 21:39:27 2014 +0800
@@ -233,6 +233,7 @@
 
 typedef enum {
 	STATE_NOTHING,
+	USERAUTH_WAIT,
 	USERAUTH_REQ_SENT,
 	USERAUTH_FAIL_RCVD,
 	USERAUTH_SUCCESS_RCVD,
@@ -267,6 +268,7 @@
 
 	int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
 						 for the last type of auth we tried */
+	int ignore_next_auth_response;
 #ifdef ENABLE_CLI_INTERACT_AUTH
 	int auth_interact_failed; /* flag whether interactive auth can still
 								 be used */
--- a/sysoptions.h	Wed Dec 11 21:50:33 2013 +0800
+++ b/sysoptions.h	Fri Jan 17 21:39:27 2014 +0800
@@ -176,6 +176,12 @@
 												accept for keyb-interactive
 												auth */
 
+/* Send a real auth request immediately after sending a query for the available methods.
+ * It saves a network round trip at login.
+ * If problems are encountered it can be disabled here. */
+ #define CLI_IMMEDIATE_AUTH
+
+
 #if defined(DROPBEAR_AES256) || defined(DROPBEAR_AES128)
 #define DROPBEAR_AES
 #endif