dropbear

changeset 808:d7784616409a

improve auth failure delays to avoid indicating which users exist
author Matt Johnston <matt@ucc.asn.au>
date Sun, 26 May 2013 18:39:24 +0800
parents e0084f136cb8
children 0e17269254b6
files svr-auth.c
diffstat 1 files changed, 27 insertions(+), 21 deletions(-) [+]
line diff
     1.1 --- a/svr-auth.c	Wed Apr 17 22:29:18 2013 +0800
     1.2 +++ b/svr-auth.c	Sun May 26 18:39:24 2013 +0800
     1.3 @@ -110,6 +110,7 @@
     1.4  
     1.5  	unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
     1.6  	unsigned int userlen, servicelen, methodlen;
     1.7 +	int valid_user = 0;
     1.8  
     1.9  	TRACE(("enter recv_msg_userauth_request"))
    1.10  
    1.11 @@ -124,7 +125,6 @@
    1.12  		send_msg_userauth_banner();
    1.13  	}
    1.14  
    1.15 -	
    1.16  	username = buf_getstring(ses.payload, &userlen);
    1.17  	servicename = buf_getstring(ses.payload, &servicelen);
    1.18  	methodname = buf_getstring(ses.payload, &methodlen);
    1.19 @@ -141,12 +141,12 @@
    1.20  		dropbear_exit("unknown service in auth");
    1.21  	}
    1.22  
    1.23 -	/* check username is good before continuing */
    1.24 -	if (checkusername(username, userlen) == DROPBEAR_FAILURE) {
    1.25 -		/* username is invalid/no shell/etc - send failure */
    1.26 -		TRACE(("sending checkusername failure"))
    1.27 -		send_msg_userauth_failure(0, 1);
    1.28 -		goto out;
    1.29 +	/* check username is good before continuing. 
    1.30 +	 * the 'incrfail' varies depending on the auth method to
    1.31 +	 * avoid giving away which users exist on the system through
    1.32 +	 * the time delay. */
    1.33 +	if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
    1.34 +		valid_user = 1;
    1.35  	}
    1.36  
    1.37  	/* user wants to know what methods are supported */
    1.38 @@ -154,7 +154,8 @@
    1.39  			strncmp(methodname, AUTH_METHOD_NONE,
    1.40  				AUTH_METHOD_NONE_LEN) == 0) {
    1.41  		TRACE(("recv_msg_userauth_request: 'none' request"))
    1.42 -		if (svr_opts.allowblankpass
    1.43 +		if (valid_user
    1.44 +				&& svr_opts.allowblankpass
    1.45  				&& !svr_opts.noauthpass
    1.46  				&& !(svr_opts.norootpass && ses.authstate.pw_uid == 0) 
    1.47  				&& ses.authstate.pw_passwd[0] == '\0') 
    1.48 @@ -168,6 +169,7 @@
    1.49  		}
    1.50  		else
    1.51  		{
    1.52 +			/* 'none' has no failure delay */
    1.53  			send_msg_userauth_failure(0, 0);
    1.54  			goto out;
    1.55  		}
    1.56 @@ -180,8 +182,10 @@
    1.57  		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
    1.58  				strncmp(methodname, AUTH_METHOD_PASSWORD,
    1.59  					AUTH_METHOD_PASSWORD_LEN) == 0) {
    1.60 -			svr_auth_password();
    1.61 -			goto out;
    1.62 +			if (valid_user) {
    1.63 +				svr_auth_password();
    1.64 +				goto out;
    1.65 +			}
    1.66  		}
    1.67  	}
    1.68  #endif
    1.69 @@ -193,8 +197,10 @@
    1.70  		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
    1.71  				strncmp(methodname, AUTH_METHOD_PASSWORD,
    1.72  					AUTH_METHOD_PASSWORD_LEN) == 0) {
    1.73 -			svr_auth_pam();
    1.74 -			goto out;
    1.75 +			if (valid_user) {
    1.76 +				svr_auth_pam();
    1.77 +				goto out;
    1.78 +			}
    1.79  		}
    1.80  	}
    1.81  #endif
    1.82 @@ -204,12 +210,17 @@
    1.83  	if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
    1.84  			strncmp(methodname, AUTH_METHOD_PUBKEY,
    1.85  				AUTH_METHOD_PUBKEY_LEN) == 0) {
    1.86 -		svr_auth_pubkey();
    1.87 +		if (valid_user) {
    1.88 +			svr_auth_pubkey();
    1.89 +		} else {
    1.90 +			/* pubkey has no failure delay */
    1.91 +			send_msg_userauth_failure(0, 0);
    1.92 +		}
    1.93  		goto out;
    1.94  	}
    1.95  #endif
    1.96  
    1.97 -	/* nothing matched, we just fail */
    1.98 +	/* nothing matched, we just fail with a delay */
    1.99  	send_msg_userauth_failure(0, 1);
   1.100  
   1.101  out:
   1.102 @@ -252,7 +263,6 @@
   1.103  		dropbear_log(LOG_WARNING,
   1.104  				"Login attempt for nonexistent user from %s",
   1.105  				svr_ses.addrstring);
   1.106 -		send_msg_userauth_failure(0, 1);
   1.107  		return DROPBEAR_FAILURE;
   1.108  	}
   1.109  
   1.110 @@ -264,7 +274,6 @@
   1.111  				"Login attempt with wrong user %s from %s",
   1.112  				ses.authstate.pw_name,
   1.113  				svr_ses.addrstring);
   1.114 -		send_msg_userauth_failure(0, 1);
   1.115  		return DROPBEAR_FAILURE;
   1.116  	}
   1.117  
   1.118 @@ -272,7 +281,6 @@
   1.119  	if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
   1.120  		TRACE(("leave checkusername: root login disabled"))
   1.121  		dropbear_log(LOG_WARNING, "root login rejected");
   1.122 -		send_msg_userauth_failure(0, 1);
   1.123  		return DROPBEAR_FAILURE;
   1.124  	}
   1.125  
   1.126 @@ -301,7 +309,6 @@
   1.127  	TRACE(("no matching shell"))
   1.128  	dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
   1.129  				ses.authstate.pw_name);
   1.130 -	send_msg_userauth_failure(0, 1);
   1.131  	return DROPBEAR_FAILURE;
   1.132  	
   1.133  goodshell:
   1.134 @@ -311,7 +318,6 @@
   1.135  	TRACE(("uid = %d", ses.authstate.pw_uid))
   1.136  	TRACE(("leave checkusername"))
   1.137  	return DROPBEAR_SUCCESS;
   1.138 -
   1.139  }
   1.140  
   1.141  /* Send a failure message to the client, in responds to a userauth_request.
   1.142 @@ -358,8 +364,8 @@
   1.143  	if (incrfail) {
   1.144  		unsigned int delay;
   1.145  		genrandom((unsigned char*)&delay, sizeof(delay));
   1.146 -		/* We delay for 300ms +- 50ms, 0.1ms granularity */
   1.147 -		delay = 250000 + (delay % 1000)*100;
   1.148 +		/* We delay for 300ms +- 50ms */
   1.149 +		delay = 250000 + (delay % 100000);
   1.150  		usleep(delay);
   1.151  		ses.authstate.failcount++;
   1.152  	}