diff options
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 53 |
1 files changed, 38 insertions, 15 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.97 2012/10/30 21:29:54 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -409,41 +409,42 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, | |||
409 | return host_status; | 409 | return host_status; |
410 | } | 410 | } |
411 | 411 | ||
412 | |||
413 | /* | 412 | /* |
414 | * Check a given file for security. This is defined as all components | 413 | * 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 | 414 | * 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. | 415 | * of the file or root and no directories must be group or world writable. |
417 | * | 416 | * |
418 | * XXX Should any specific check be done for sym links ? | 417 | * XXX Should any specific check be done for sym links ? |
419 | * | 418 | * |
420 | * Takes an open file descriptor, the file name, a uid and and | 419 | * Takes an the file name, its stat information (preferably from fstat() to |
420 | * avoid races), the uid of the expected owner, their home directory and an | ||
421 | * error buffer plus max size as arguments. | 421 | * error buffer plus max size as arguments. |
422 | * | 422 | * |
423 | * Returns 0 on success and -1 on failure | 423 | * Returns 0 on success and -1 on failure |
424 | */ | 424 | */ |
425 | static int | 425 | int |
426 | secure_filename(FILE *f, const char *file, struct passwd *pw, | 426 | auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, |
427 | char *err, size_t errlen) | 427 | uid_t uid, char *err, size_t errlen) |
428 | { | 428 | { |
429 | uid_t uid = pw->pw_uid; | ||
430 | char buf[MAXPATHLEN], homedir[MAXPATHLEN]; | 429 | char buf[MAXPATHLEN], homedir[MAXPATHLEN]; |
431 | char *cp; | 430 | char *cp; |
432 | int comparehome = 0; | 431 | int comparehome = 0; |
433 | struct stat st; | 432 | struct stat st; |
434 | 433 | ||
435 | if (realpath(file, buf) == NULL) { | 434 | if (realpath(name, buf) == NULL) { |
436 | snprintf(err, errlen, "realpath %s failed: %s", file, | 435 | snprintf(err, errlen, "realpath %s failed: %s", name, |
437 | strerror(errno)); | 436 | strerror(errno)); |
438 | return -1; | 437 | return -1; |
439 | } | 438 | } |
440 | if (realpath(pw->pw_dir, homedir) != NULL) | 439 | if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) |
441 | comparehome = 1; | 440 | comparehome = 1; |
442 | 441 | ||
443 | /* check the open file to avoid races */ | 442 | if (!S_ISREG(stp->st_mode)) { |
444 | if (fstat(fileno(f), &st) < 0 || | 443 | snprintf(err, errlen, "%s is not a regular file", buf); |
445 | (st.st_uid != 0 && st.st_uid != uid) || | 444 | return -1; |
446 | (st.st_mode & 022) != 0) { | 445 | } |
446 | if ((stp->st_uid != 0 && stp->st_uid != uid) || | ||
447 | (stp->st_mode & 022) != 0) { | ||
447 | snprintf(err, errlen, "bad ownership or modes for file %s", | 448 | snprintf(err, errlen, "bad ownership or modes for file %s", |
448 | buf); | 449 | buf); |
449 | return -1; | 450 | return -1; |
@@ -479,6 +480,28 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, | |||
479 | return 0; | 480 | return 0; |
480 | } | 481 | } |
481 | 482 | ||
483 | /* | ||
484 | * Version of secure_path() that accepts an open file descriptor to | ||
485 | * avoid races. | ||
486 | * | ||
487 | * Returns 0 on success and -1 on failure | ||
488 | */ | ||
489 | static int | ||
490 | secure_filename(FILE *f, const char *file, struct passwd *pw, | ||
491 | char *err, size_t errlen) | ||
492 | { | ||
493 | char buf[MAXPATHLEN]; | ||
494 | struct stat st; | ||
495 | |||
496 | /* check the open file to avoid races */ | ||
497 | if (fstat(fileno(f), &st) < 0) { | ||
498 | snprintf(err, errlen, "cannot stat file %s: %s", | ||
499 | buf, strerror(errno)); | ||
500 | return -1; | ||
501 | } | ||
502 | return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); | ||
503 | } | ||
504 | |||
482 | static FILE * | 505 | static FILE * |
483 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, | 506 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, |
484 | int log_missing, char *file_type) | 507 | int log_missing, char *file_type) |