diff svr-auth.c @ 835:4095b6d7c9fc ecc

Merge in changes from the past couple of releases
author Matt Johnston <matt@ucc.asn.au>
date Fri, 18 Oct 2013 21:38:01 +0800
parents 7dcb46da72d9 8fe36617bf4e
children 7540c0822374
line wrap: on
line diff
--- a/svr-auth.c	Sat May 25 00:54:19 2013 +0800
+++ b/svr-auth.c	Fri Oct 18 21:38:01 2013 +0800
@@ -37,7 +37,6 @@
 
 static void authclear();
 static int checkusername(unsigned char *username, unsigned int userlen);
-static void send_msg_userauth_banner();
 
 /* initialise the first time for a session, resetting all parameters */
 void svr_authinitialise() {
@@ -82,23 +81,17 @@
 
 /* Send a banner message if specified to the client. The client might
  * ignore this, but possibly serves as a legal "no trespassing" sign */
-static void send_msg_userauth_banner() {
+void send_msg_userauth_banner(buffer *banner) {
 
 	TRACE(("enter send_msg_userauth_banner"))
-	if (svr_opts.banner == NULL) {
-		TRACE(("leave send_msg_userauth_banner: banner is NULL"))
-		return;
-	}
 
 	CHECKCLEARTOWRITE();
 
 	buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER);
-	buf_putbufstring(ses.writepayload, svr_opts.banner);
+	buf_putbufstring(ses.writepayload, banner);
 	buf_putstring(ses.writepayload, "en", 2);
 
 	encrypt_packet();
-	buf_free(svr_opts.banner);
-	svr_opts.banner = NULL;
 
 	TRACE(("leave send_msg_userauth_banner"))
 }
@@ -109,6 +102,7 @@
 
 	unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
 	unsigned int userlen, servicelen, methodlen;
+	int valid_user = 0;
 
 	TRACE(("enter recv_msg_userauth_request"))
 
@@ -120,10 +114,11 @@
 
 	/* send the banner if it exists, it will only exist once */
 	if (svr_opts.banner) {
-		send_msg_userauth_banner();
+		send_msg_userauth_banner(svr_opts.banner);
+		buf_free(svr_opts.banner);
+		svr_opts.banner = NULL;
 	}
 
-	
 	username = buf_getstring(ses.payload, &userlen);
 	servicename = buf_getstring(ses.payload, &servicelen);
 	methodname = buf_getstring(ses.payload, &methodlen);
@@ -140,12 +135,12 @@
 		dropbear_exit("unknown service in auth");
 	}
 
-	/* check username is good before continuing */
-	if (checkusername(username, userlen) == DROPBEAR_FAILURE) {
-		/* username is invalid/no shell/etc - send failure */
-		TRACE(("sending checkusername failure"))
-		send_msg_userauth_failure(0, 1);
-		goto out;
+	/* check username is good before continuing. 
+	 * the 'incrfail' varies depending on the auth method to
+	 * avoid giving away which users exist on the system through
+	 * the time delay. */
+	if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
+		valid_user = 1;
 	}
 
 	/* user wants to know what methods are supported */
@@ -153,7 +148,8 @@
 			strncmp(methodname, AUTH_METHOD_NONE,
 				AUTH_METHOD_NONE_LEN) == 0) {
 		TRACE(("recv_msg_userauth_request: 'none' request"))
-		if (svr_opts.allowblankpass
+		if (valid_user
+				&& svr_opts.allowblankpass
 				&& !svr_opts.noauthpass
 				&& !(svr_opts.norootpass && ses.authstate.pw_uid == 0) 
 				&& ses.authstate.pw_passwd[0] == '\0') 
@@ -167,6 +163,7 @@
 		}
 		else
 		{
+			/* 'none' has no failure delay */
 			send_msg_userauth_failure(0, 0);
 			goto out;
 		}
@@ -179,8 +176,10 @@
 		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
 				strncmp(methodname, AUTH_METHOD_PASSWORD,
 					AUTH_METHOD_PASSWORD_LEN) == 0) {
-			svr_auth_password();
-			goto out;
+			if (valid_user) {
+				svr_auth_password();
+				goto out;
+			}
 		}
 	}
 #endif
@@ -192,8 +191,10 @@
 		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
 				strncmp(methodname, AUTH_METHOD_PASSWORD,
 					AUTH_METHOD_PASSWORD_LEN) == 0) {
-			svr_auth_pam();
-			goto out;
+			if (valid_user) {
+				svr_auth_pam();
+				goto out;
+			}
 		}
 	}
 #endif
@@ -203,12 +204,17 @@
 	if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
 			strncmp(methodname, AUTH_METHOD_PUBKEY,
 				AUTH_METHOD_PUBKEY_LEN) == 0) {
-		svr_auth_pubkey();
+		if (valid_user) {
+			svr_auth_pubkey();
+		} else {
+			/* pubkey has no failure delay */
+			send_msg_userauth_failure(0, 0);
+		}
 		goto out;
 	}
 #endif
 
-	/* nothing matched, we just fail */
+	/* nothing matched, we just fail with a delay */
 	send_msg_userauth_failure(0, 1);
 
 out:
@@ -251,7 +257,6 @@
 		dropbear_log(LOG_WARNING,
 				"Login attempt for nonexistent user from %s",
 				svr_ses.addrstring);
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -263,7 +268,6 @@
 				"Login attempt with wrong user %s from %s",
 				ses.authstate.pw_name,
 				svr_ses.addrstring);
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -271,7 +275,6 @@
 	if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
 		TRACE(("leave checkusername: root login disabled"))
 		dropbear_log(LOG_WARNING, "root login rejected");
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -300,7 +303,6 @@
 	TRACE(("no matching shell"))
 	dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
 				ses.authstate.pw_name);
-	send_msg_userauth_failure(0, 1);
 	return DROPBEAR_FAILURE;
 	
 goodshell:
@@ -310,7 +312,6 @@
 	TRACE(("uid = %d", ses.authstate.pw_uid))
 	TRACE(("leave checkusername"))
 	return DROPBEAR_SUCCESS;
-
 }
 
 /* Send a failure message to the client, in responds to a userauth_request.
@@ -355,8 +356,8 @@
 	if (incrfail) {
 		unsigned int delay;
 		genrandom((unsigned char*)&delay, sizeof(delay));
-		/* We delay for 300ms +- 50ms, 0.1ms granularity */
-		delay = 250000 + (delay % 1000)*100;
+		/* We delay for 300ms +- 50ms */
+		delay = 250000 + (delay % 100000);
 		usleep(delay);
 		ses.authstate.failcount++;
 	}