diff options
-rw-r--r-- | auth.h | 6 | ||||
-rw-r--r-- | svr-auth.c | 68 |
2 files changed, 31 insertions, 43 deletions
@@ -105,12 +105,14 @@ struct AuthState { unsigned char authtypes; /* Flags indicating which auth types are still valid */ unsigned int failcount; /* Number of (failed) authentication attempts.*/ - unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for + unsigned int authdone; /* 0 if we haven't authed, 1 if we have. Applies for client and server (though has differing meanings). */ - unsigned perm_warn : 1; /* Server only, set if bad permissions on + unsigned int perm_warn; /* Server only, set if bad permissions on ~/.ssh/authorized_keys have already been logged. */ + unsigned int checkusername_failed; /* Server only, set if checkusername + has already failed */ /* These are only used for the server */ uid_t pw_uid; @@ -37,26 +37,10 @@ #include "runopts.h" #include "dbrandom.h" -static void authclear(void); static int checkusername(const char *username, unsigned int userlen); /* initialise the first time for a session, resetting all parameters */ void svr_authinitialise() { - - ses.authstate.failcount = 0; - ses.authstate.pw_name = NULL; - ses.authstate.pw_dir = NULL; - ses.authstate.pw_shell = NULL; - ses.authstate.pw_passwd = NULL; - authclear(); - -} - -/* Reset the auth state, but don't reset the failcount. This is for if the - * user decides to try with a different username etc, and is also invoked - * on initialisation */ -static void authclear() { - memset(&ses.authstate, 0, sizeof(ses.authstate)); #if DROPBEAR_SVR_PUBKEY_AUTH ses.authstate.authtypes |= AUTH_TYPE_PUBKEY; @@ -66,19 +50,6 @@ static void authclear() { ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; } #endif - if (ses.authstate.pw_name) { - m_free(ses.authstate.pw_name); - } - if (ses.authstate.pw_shell) { - m_free(ses.authstate.pw_shell); - } - if (ses.authstate.pw_dir) { - m_free(ses.authstate.pw_dir); - } - if (ses.authstate.pw_passwd) { - m_free(ses.authstate.pw_passwd); - } - } /* Send a banner message if specified to the client. The client might @@ -274,18 +245,28 @@ static int checkusername(const char *username, unsigned int userlen) { return DROPBEAR_FAILURE; } - /* new user or username has changed */ - if (ses.authstate.username == NULL || - strcmp(username, ses.authstate.username) != 0) { - /* the username needs resetting */ - if (ses.authstate.username != NULL) { - dropbear_log(LOG_WARNING, "Client trying multiple usernames from %s", - svr_ses.addrstring); - m_free(ses.authstate.username); - } - authclear(); - fill_passwd(username); - ses.authstate.username = m_strdup(username); + if (strlen(username) != userlen) { + dropbear_exit("Attempted username with a null byte from %s", + svr_ses.addrstring); + } + + if (ses.authstate.username == NULL) { + /* first request */ + fill_passwd(username); + ses.authstate.username = m_strdup(username); + } else { + /* check username hasn't changed */ + if (strcmp(username, ses.authstate.username) != 0) { + dropbear_exit("Client trying multiple usernames from %s", + svr_ses.addrstring); + } + } + + /* avoids cluttering logs with repeated failure messages from + consecutive authentication requests in a sesssion */ + if (ses.authstate.checkusername_failed) { + TRACE(("checkusername: returning cached failure")) + return DROPBEAR_FAILURE; } /* check that user exists */ @@ -294,6 +275,7 @@ static int checkusername(const char *username, unsigned int userlen) { dropbear_log(LOG_WARNING, "Login attempt for nonexistent user from %s", svr_ses.addrstring); + ses.authstate.checkusername_failed = 1; return DROPBEAR_FAILURE; } @@ -305,6 +287,7 @@ static int checkusername(const char *username, unsigned int userlen) { "Login attempt with wrong user %s from %s", ses.authstate.pw_name, svr_ses.addrstring); + ses.authstate.checkusername_failed = 1; return DROPBEAR_FAILURE; } @@ -312,6 +295,7 @@ static int checkusername(const 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"); + ses.authstate.checkusername_failed = 1; return DROPBEAR_FAILURE; } @@ -322,6 +306,7 @@ static int checkusername(const char *username, unsigned int userlen) { dropbear_log(LOG_WARNING, "Logins are restricted to the group %s but user '%s' is not a member", svr_opts.restrict_group, ses.authstate.pw_name); + ses.authstate.checkusername_failed = 1; return DROPBEAR_FAILURE; } } @@ -349,6 +334,7 @@ static int checkusername(const char *username, unsigned int userlen) { /* no matching shell */ endusershell(); TRACE(("no matching shell")) + ses.authstate.checkusername_failed = 1; dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected", ses.authstate.pw_name); return DROPBEAR_FAILURE; |