Mercurial > dropbear
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: |