comparison svr-auth.c @ 1539:51df3d53b050

- Don't try to handle changed usernames - Avoid logging repeated failed username messages
author Matt Johnston <matt@ucc.asn.au>
date Mon, 26 Feb 2018 22:07:18 +0800
parents f20038b513a5
children bb8eaa26bc93 1acbdf64088e
comparison
equal deleted inserted replaced
1538:f20038b513a5 1539:51df3d53b050
35 #include "packet.h" 35 #include "packet.h"
36 #include "auth.h" 36 #include "auth.h"
37 #include "runopts.h" 37 #include "runopts.h"
38 #include "dbrandom.h" 38 #include "dbrandom.h"
39 39
40 static void authclear(void);
41 static int checkusername(const char *username, unsigned int userlen); 40 static int checkusername(const char *username, unsigned int userlen);
42 41
43 /* initialise the first time for a session, resetting all parameters */ 42 /* initialise the first time for a session, resetting all parameters */
44 void svr_authinitialise() { 43 void svr_authinitialise() {
45
46 ses.authstate.failcount = 0;
47 ses.authstate.pw_name = NULL;
48 ses.authstate.pw_dir = NULL;
49 ses.authstate.pw_shell = NULL;
50 ses.authstate.pw_passwd = NULL;
51 authclear();
52
53 }
54
55 /* Reset the auth state, but don't reset the failcount. This is for if the
56 * user decides to try with a different username etc, and is also invoked
57 * on initialisation */
58 static void authclear() {
59
60 memset(&ses.authstate, 0, sizeof(ses.authstate)); 44 memset(&ses.authstate, 0, sizeof(ses.authstate));
61 #if DROPBEAR_SVR_PUBKEY_AUTH 45 #if DROPBEAR_SVR_PUBKEY_AUTH
62 ses.authstate.authtypes |= AUTH_TYPE_PUBKEY; 46 ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
63 #endif 47 #endif
64 #if DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH 48 #if DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH
65 if (!svr_opts.noauthpass) { 49 if (!svr_opts.noauthpass) {
66 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; 50 ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
67 } 51 }
68 #endif 52 #endif
69 if (ses.authstate.pw_name) {
70 m_free(ses.authstate.pw_name);
71 }
72 if (ses.authstate.pw_shell) {
73 m_free(ses.authstate.pw_shell);
74 }
75 if (ses.authstate.pw_dir) {
76 m_free(ses.authstate.pw_dir);
77 }
78 if (ses.authstate.pw_passwd) {
79 m_free(ses.authstate.pw_passwd);
80 }
81
82 } 53 }
83 54
84 /* Send a banner message if specified to the client. The client might 55 /* Send a banner message if specified to the client. The client might
85 * ignore this, but possibly serves as a legal "no trespassing" sign */ 56 * ignore this, but possibly serves as a legal "no trespassing" sign */
86 void send_msg_userauth_banner(const buffer *banner) { 57 void send_msg_userauth_banner(const buffer *banner) {
272 TRACE(("enter checkusername")) 243 TRACE(("enter checkusername"))
273 if (userlen > MAX_USERNAME_LEN) { 244 if (userlen > MAX_USERNAME_LEN) {
274 return DROPBEAR_FAILURE; 245 return DROPBEAR_FAILURE;
275 } 246 }
276 247
277 /* new user or username has changed */ 248 if (strlen(username) != userlen) {
278 if (ses.authstate.username == NULL || 249 dropbear_exit("Attempted username with a null byte from %s",
279 strcmp(username, ses.authstate.username) != 0) { 250 svr_ses.addrstring);
280 /* the username needs resetting */ 251 }
281 if (ses.authstate.username != NULL) { 252
282 dropbear_log(LOG_WARNING, "Client trying multiple usernames from %s", 253 if (ses.authstate.username == NULL) {
283 svr_ses.addrstring); 254 /* first request */
284 m_free(ses.authstate.username); 255 fill_passwd(username);
285 } 256 ses.authstate.username = m_strdup(username);
286 authclear(); 257 } else {
287 fill_passwd(username); 258 /* check username hasn't changed */
288 ses.authstate.username = m_strdup(username); 259 if (strcmp(username, ses.authstate.username) != 0) {
260 dropbear_exit("Client trying multiple usernames from %s",
261 svr_ses.addrstring);
262 }
263 }
264
265 /* avoids cluttering logs with repeated failure messages from
266 consecutive authentication requests in a sesssion */
267 if (ses.authstate.checkusername_failed) {
268 TRACE(("checkusername: returning cached failure"))
269 return DROPBEAR_FAILURE;
289 } 270 }
290 271
291 /* check that user exists */ 272 /* check that user exists */
292 if (!ses.authstate.pw_name) { 273 if (!ses.authstate.pw_name) {
293 TRACE(("leave checkusername: user '%s' doesn't exist", username)) 274 TRACE(("leave checkusername: user '%s' doesn't exist", username))
294 dropbear_log(LOG_WARNING, 275 dropbear_log(LOG_WARNING,
295 "Login attempt for nonexistent user from %s", 276 "Login attempt for nonexistent user from %s",
296 svr_ses.addrstring); 277 svr_ses.addrstring);
278 ses.authstate.checkusername_failed = 1;
297 return DROPBEAR_FAILURE; 279 return DROPBEAR_FAILURE;
298 } 280 }
299 281
300 /* check if we are running as non-root, and login user is different from the server */ 282 /* check if we are running as non-root, and login user is different from the server */
301 uid = geteuid(); 283 uid = geteuid();
303 TRACE(("running as nonroot, only server uid is allowed")) 285 TRACE(("running as nonroot, only server uid is allowed"))
304 dropbear_log(LOG_WARNING, 286 dropbear_log(LOG_WARNING,
305 "Login attempt with wrong user %s from %s", 287 "Login attempt with wrong user %s from %s",
306 ses.authstate.pw_name, 288 ses.authstate.pw_name,
307 svr_ses.addrstring); 289 svr_ses.addrstring);
290 ses.authstate.checkusername_failed = 1;
308 return DROPBEAR_FAILURE; 291 return DROPBEAR_FAILURE;
309 } 292 }
310 293
311 /* check for non-root if desired */ 294 /* check for non-root if desired */
312 if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) { 295 if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
313 TRACE(("leave checkusername: root login disabled")) 296 TRACE(("leave checkusername: root login disabled"))
314 dropbear_log(LOG_WARNING, "root login rejected"); 297 dropbear_log(LOG_WARNING, "root login rejected");
298 ses.authstate.checkusername_failed = 1;
315 return DROPBEAR_FAILURE; 299 return DROPBEAR_FAILURE;
316 } 300 }
317 301
318 /* check for login restricted to certain group if desired */ 302 /* check for login restricted to certain group if desired */
319 if (svr_opts.restrict_group) { 303 if (svr_opts.restrict_group) {
320 if (check_group_membership(svr_opts.restrict_group_gid, 304 if (check_group_membership(svr_opts.restrict_group_gid,
321 ses.authstate.pw_name, ses.authstate.pw_gid) == DROPBEAR_FAILURE) { 305 ses.authstate.pw_name, ses.authstate.pw_gid) == DROPBEAR_FAILURE) {
322 dropbear_log(LOG_WARNING, 306 dropbear_log(LOG_WARNING,
323 "Logins are restricted to the group %s but user '%s' is not a member", 307 "Logins are restricted to the group %s but user '%s' is not a member",
324 svr_opts.restrict_group, ses.authstate.pw_name); 308 svr_opts.restrict_group, ses.authstate.pw_name);
309 ses.authstate.checkusername_failed = 1;
325 return DROPBEAR_FAILURE; 310 return DROPBEAR_FAILURE;
326 } 311 }
327 } 312 }
328 313
329 TRACE(("shell is %s", ses.authstate.pw_shell)) 314 TRACE(("shell is %s", ses.authstate.pw_shell))
347 } 332 }
348 } 333 }
349 /* no matching shell */ 334 /* no matching shell */
350 endusershell(); 335 endusershell();
351 TRACE(("no matching shell")) 336 TRACE(("no matching shell"))
337 ses.authstate.checkusername_failed = 1;
352 dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected", 338 dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
353 ses.authstate.pw_name); 339 ses.authstate.pw_name);
354 return DROPBEAR_FAILURE; 340 return DROPBEAR_FAILURE;
355 341
356 goodshell: 342 goodshell: