summaryrefslogtreecommitdiffhomepage
path: root/svr-auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'svr-auth.c')
-rw-r--r--svr-auth.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/svr-auth.c b/svr-auth.c
index acac6f8..8666108 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -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 @@ static void authclear() {
/* 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 @@ void recv_msg_userauth_request() {
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 @@ void recv_msg_userauth_request() {
/* 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 @@ void recv_msg_userauth_request() {
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 @@ void recv_msg_userauth_request() {
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 @@ void recv_msg_userauth_request() {
}
else
{
+ /* 'none' has no failure delay */
send_msg_userauth_failure(0, 0);
goto out;
}
@@ -179,8 +176,10 @@ void recv_msg_userauth_request() {
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 @@ void recv_msg_userauth_request() {
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 @@ void recv_msg_userauth_request() {
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 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
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 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
"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 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
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 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
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 @@ goodshell:
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 @@ void send_msg_userauth_failure(int partial, int incrfail) {
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++;
}