diff options
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 99 |
1 files changed, 2 insertions, 97 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.122 2017/06/24 06:34:38 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.123 2017/08/18 05:36:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -43,9 +43,6 @@ | |||
43 | #ifdef USE_SHADOW | 43 | #ifdef USE_SHADOW |
44 | #include <shadow.h> | 44 | #include <shadow.h> |
45 | #endif | 45 | #endif |
46 | #ifdef HAVE_LIBGEN_H | ||
47 | #include <libgen.h> | ||
48 | #endif | ||
49 | #include <stdarg.h> | 46 | #include <stdarg.h> |
50 | #include <stdio.h> | 47 | #include <stdio.h> |
51 | #include <string.h> | 48 | #include <string.h> |
@@ -498,98 +495,6 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, | |||
498 | return host_status; | 495 | return host_status; |
499 | } | 496 | } |
500 | 497 | ||
501 | /* | ||
502 | * Check a given path for security. This is defined as all components | ||
503 | * of the path to the file must be owned by either the owner of | ||
504 | * of the file or root and no directories must be group or world writable. | ||
505 | * | ||
506 | * XXX Should any specific check be done for sym links ? | ||
507 | * | ||
508 | * Takes a file name, its stat information (preferably from fstat() to | ||
509 | * avoid races), the uid of the expected owner, their home directory and an | ||
510 | * error buffer plus max size as arguments. | ||
511 | * | ||
512 | * Returns 0 on success and -1 on failure | ||
513 | */ | ||
514 | int | ||
515 | auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, | ||
516 | uid_t uid, char *err, size_t errlen) | ||
517 | { | ||
518 | char buf[PATH_MAX], homedir[PATH_MAX]; | ||
519 | char *cp; | ||
520 | int comparehome = 0; | ||
521 | struct stat st; | ||
522 | |||
523 | if (realpath(name, buf) == NULL) { | ||
524 | snprintf(err, errlen, "realpath %s failed: %s", name, | ||
525 | strerror(errno)); | ||
526 | return -1; | ||
527 | } | ||
528 | if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) | ||
529 | comparehome = 1; | ||
530 | |||
531 | if (!S_ISREG(stp->st_mode)) { | ||
532 | snprintf(err, errlen, "%s is not a regular file", buf); | ||
533 | return -1; | ||
534 | } | ||
535 | if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || | ||
536 | (stp->st_mode & 022) != 0) { | ||
537 | snprintf(err, errlen, "bad ownership or modes for file %s", | ||
538 | buf); | ||
539 | return -1; | ||
540 | } | ||
541 | |||
542 | /* for each component of the canonical path, walking upwards */ | ||
543 | for (;;) { | ||
544 | if ((cp = dirname(buf)) == NULL) { | ||
545 | snprintf(err, errlen, "dirname() failed"); | ||
546 | return -1; | ||
547 | } | ||
548 | strlcpy(buf, cp, sizeof(buf)); | ||
549 | |||
550 | if (stat(buf, &st) < 0 || | ||
551 | (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || | ||
552 | (st.st_mode & 022) != 0) { | ||
553 | snprintf(err, errlen, | ||
554 | "bad ownership or modes for directory %s", buf); | ||
555 | return -1; | ||
556 | } | ||
557 | |||
558 | /* If are past the homedir then we can stop */ | ||
559 | if (comparehome && strcmp(homedir, buf) == 0) | ||
560 | break; | ||
561 | |||
562 | /* | ||
563 | * dirname should always complete with a "/" path, | ||
564 | * but we can be paranoid and check for "." too | ||
565 | */ | ||
566 | if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) | ||
567 | break; | ||
568 | } | ||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * Version of secure_path() that accepts an open file descriptor to | ||
574 | * avoid races. | ||
575 | * | ||
576 | * Returns 0 on success and -1 on failure | ||
577 | */ | ||
578 | static int | ||
579 | secure_filename(FILE *f, const char *file, struct passwd *pw, | ||
580 | char *err, size_t errlen) | ||
581 | { | ||
582 | struct stat st; | ||
583 | |||
584 | /* check the open file to avoid races */ | ||
585 | if (fstat(fileno(f), &st) < 0) { | ||
586 | snprintf(err, errlen, "cannot stat file %s: %s", | ||
587 | file, strerror(errno)); | ||
588 | return -1; | ||
589 | } | ||
590 | return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); | ||
591 | } | ||
592 | |||
593 | static FILE * | 498 | static FILE * |
594 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, | 499 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, |
595 | int log_missing, char *file_type) | 500 | int log_missing, char *file_type) |
@@ -622,7 +527,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes, | |||
622 | return NULL; | 527 | return NULL; |
623 | } | 528 | } |
624 | if (strict_modes && | 529 | if (strict_modes && |
625 | secure_filename(f, file, pw, line, sizeof(line)) != 0) { | 530 | safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { |
626 | fclose(f); | 531 | fclose(f); |
627 | logit("Authentication refused: %s", line); | 532 | logit("Authentication refused: %s", line); |
628 | auth_debug_add("Ignored %s: %s", file_type, line); | 533 | auth_debug_add("Ignored %s: %s", file_type, line); |