diff options
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 77 |
1 files changed, 57 insertions, 20 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.101 2013/02/06 00:22:21 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -71,6 +71,7 @@ | |||
71 | #endif | 71 | #endif |
72 | #include "authfile.h" | 72 | #include "authfile.h" |
73 | #include "monitor_wrap.h" | 73 | #include "monitor_wrap.h" |
74 | #include "krl.h" | ||
74 | 75 | ||
75 | /* import */ | 76 | /* import */ |
76 | extern ServerOptions options; | 77 | extern ServerOptions options; |
@@ -251,7 +252,8 @@ allowed_user(struct passwd * pw) | |||
251 | } | 252 | } |
252 | 253 | ||
253 | void | 254 | void |
254 | auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | 255 | auth_log(Authctxt *authctxt, int authenticated, int partial, |
256 | const char *method, const char *submethod, const char *info) | ||
255 | { | 257 | { |
256 | void (*authlog) (const char *fmt,...) = verbose; | 258 | void (*authlog) (const char *fmt,...) = verbose; |
257 | char *authmsg; | 259 | char *authmsg; |
@@ -268,12 +270,15 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
268 | 270 | ||
269 | if (authctxt->postponed) | 271 | if (authctxt->postponed) |
270 | authmsg = "Postponed"; | 272 | authmsg = "Postponed"; |
273 | else if (partial) | ||
274 | authmsg = "Partial"; | ||
271 | else | 275 | else |
272 | authmsg = authenticated ? "Accepted" : "Failed"; | 276 | authmsg = authenticated ? "Accepted" : "Failed"; |
273 | 277 | ||
274 | authlog("%s %s for %s%.100s from %.200s port %d%s", | 278 | authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", |
275 | authmsg, | 279 | authmsg, |
276 | method, | 280 | method, |
281 | submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, | ||
277 | authctxt->valid ? "" : "invalid user ", | 282 | authctxt->valid ? "" : "invalid user ", |
278 | authctxt->user, | 283 | authctxt->user, |
279 | get_remote_ipaddr(), | 284 | get_remote_ipaddr(), |
@@ -303,7 +308,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
303 | * Check whether root logins are disallowed. | 308 | * Check whether root logins are disallowed. |
304 | */ | 309 | */ |
305 | int | 310 | int |
306 | auth_root_allowed(char *method) | 311 | auth_root_allowed(const char *method) |
307 | { | 312 | { |
308 | switch (options.permit_root_login) { | 313 | switch (options.permit_root_login) { |
309 | case PERMIT_YES: | 314 | case PERMIT_YES: |
@@ -409,41 +414,42 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, | |||
409 | return host_status; | 414 | return host_status; |
410 | } | 415 | } |
411 | 416 | ||
412 | |||
413 | /* | 417 | /* |
414 | * Check a given file for security. This is defined as all components | 418 | * Check a given path for security. This is defined as all components |
415 | * of the path to the file must be owned by either the owner of | 419 | * of the path to the file must be owned by either the owner of |
416 | * of the file or root and no directories must be group or world writable. | 420 | * of the file or root and no directories must be group or world writable. |
417 | * | 421 | * |
418 | * XXX Should any specific check be done for sym links ? | 422 | * XXX Should any specific check be done for sym links ? |
419 | * | 423 | * |
420 | * Takes an open file descriptor, the file name, a uid and and | 424 | * Takes a file name, its stat information (preferably from fstat() to |
425 | * avoid races), the uid of the expected owner, their home directory and an | ||
421 | * error buffer plus max size as arguments. | 426 | * error buffer plus max size as arguments. |
422 | * | 427 | * |
423 | * Returns 0 on success and -1 on failure | 428 | * Returns 0 on success and -1 on failure |
424 | */ | 429 | */ |
425 | static int | 430 | int |
426 | secure_filename(FILE *f, const char *file, struct passwd *pw, | 431 | auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, |
427 | char *err, size_t errlen) | 432 | uid_t uid, char *err, size_t errlen) |
428 | { | 433 | { |
429 | uid_t uid = pw->pw_uid; | ||
430 | char buf[MAXPATHLEN], homedir[MAXPATHLEN]; | 434 | char buf[MAXPATHLEN], homedir[MAXPATHLEN]; |
431 | char *cp; | 435 | char *cp; |
432 | int comparehome = 0; | 436 | int comparehome = 0; |
433 | struct stat st; | 437 | struct stat st; |
434 | 438 | ||
435 | if (realpath(file, buf) == NULL) { | 439 | if (realpath(name, buf) == NULL) { |
436 | snprintf(err, errlen, "realpath %s failed: %s", file, | 440 | snprintf(err, errlen, "realpath %s failed: %s", name, |
437 | strerror(errno)); | 441 | strerror(errno)); |
438 | return -1; | 442 | return -1; |
439 | } | 443 | } |
440 | if (realpath(pw->pw_dir, homedir) != NULL) | 444 | if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) |
441 | comparehome = 1; | 445 | comparehome = 1; |
442 | 446 | ||
443 | /* check the open file to avoid races */ | 447 | if (!S_ISREG(stp->st_mode)) { |
444 | if (fstat(fileno(f), &st) < 0 || | 448 | snprintf(err, errlen, "%s is not a regular file", buf); |
445 | (st.st_uid != 0 && st.st_uid != uid) || | 449 | return -1; |
446 | (st.st_mode & 022) != 0) { | 450 | } |
451 | if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || | ||
452 | (stp->st_mode & 022) != 0) { | ||
447 | snprintf(err, errlen, "bad ownership or modes for file %s", | 453 | snprintf(err, errlen, "bad ownership or modes for file %s", |
448 | buf); | 454 | buf); |
449 | return -1; | 455 | return -1; |
@@ -458,7 +464,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, | |||
458 | strlcpy(buf, cp, sizeof(buf)); | 464 | strlcpy(buf, cp, sizeof(buf)); |
459 | 465 | ||
460 | if (stat(buf, &st) < 0 || | 466 | if (stat(buf, &st) < 0 || |
461 | (st.st_uid != 0 && st.st_uid != uid) || | 467 | (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || |
462 | (st.st_mode & 022) != 0) { | 468 | (st.st_mode & 022) != 0) { |
463 | snprintf(err, errlen, | 469 | snprintf(err, errlen, |
464 | "bad ownership or modes for directory %s", buf); | 470 | "bad ownership or modes for directory %s", buf); |
@@ -479,6 +485,27 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, | |||
479 | return 0; | 485 | return 0; |
480 | } | 486 | } |
481 | 487 | ||
488 | /* | ||
489 | * Version of secure_path() that accepts an open file descriptor to | ||
490 | * avoid races. | ||
491 | * | ||
492 | * Returns 0 on success and -1 on failure | ||
493 | */ | ||
494 | static int | ||
495 | secure_filename(FILE *f, const char *file, struct passwd *pw, | ||
496 | char *err, size_t errlen) | ||
497 | { | ||
498 | struct stat st; | ||
499 | |||
500 | /* check the open file to avoid races */ | ||
501 | if (fstat(fileno(f), &st) < 0) { | ||
502 | snprintf(err, errlen, "cannot stat file %s: %s", | ||
503 | file, strerror(errno)); | ||
504 | return -1; | ||
505 | } | ||
506 | return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); | ||
507 | } | ||
508 | |||
482 | static FILE * | 509 | static FILE * |
483 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, | 510 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, |
484 | int log_missing, char *file_type) | 511 | int log_missing, char *file_type) |
@@ -614,7 +641,16 @@ auth_key_is_revoked(Key *key) | |||
614 | 641 | ||
615 | if (options.revoked_keys_file == NULL) | 642 | if (options.revoked_keys_file == NULL) |
616 | return 0; | 643 | return 0; |
617 | 644 | switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) { | |
645 | case 0: | ||
646 | return 0; /* Not revoked */ | ||
647 | case -2: | ||
648 | break; /* Not a KRL */ | ||
649 | default: | ||
650 | goto revoked; | ||
651 | } | ||
652 | debug3("%s: treating %s as a key list", __func__, | ||
653 | options.revoked_keys_file); | ||
618 | switch (key_in_file(key, options.revoked_keys_file, 0)) { | 654 | switch (key_in_file(key, options.revoked_keys_file, 0)) { |
619 | case 0: | 655 | case 0: |
620 | /* key not revoked */ | 656 | /* key not revoked */ |
@@ -625,6 +661,7 @@ auth_key_is_revoked(Key *key) | |||
625 | "authentication"); | 661 | "authentication"); |
626 | return 1; | 662 | return 1; |
627 | case 1: | 663 | case 1: |
664 | revoked: | ||
628 | /* Key revoked */ | 665 | /* Key revoked */ |
629 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); | 666 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); |
630 | error("WARNING: authentication attempt with a revoked " | 667 | error("WARNING: authentication attempt with a revoked " |