diff options
author | Colin Watson <cjwatson@debian.org> | 2013-05-07 11:47:26 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2013-05-07 11:47:26 +0100 |
commit | 2ea3f720daeb1ca9f765365fce3a9546961fe624 (patch) | |
tree | c4fb7d1f51fa51e7677232de806aae150e29e2ac /auth.c | |
parent | f5efcd3450bbf8261915e0c4a6f851229dddaa79 (diff) | |
parent | ecebda56da46a03dafff923d91c382f31faa9eec (diff) |
* New upstream release (http://www.openssh.com/txt/release-6.2).
- Add support for multiple required authentication in SSH protocol 2 via
an AuthenticationMethods option (closes: #195716).
- Fix Sophie Germain formula in moduli(5) (closes: #698612).
- Update ssh-copy-id to Phil Hands' greatly revised version (closes:
#99785, #322228, #620428; LP: #518883, #835901, #1074798).
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 73 |
1 files changed, 55 insertions, 18 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 | * |
@@ -72,6 +72,7 @@ | |||
72 | #endif | 72 | #endif |
73 | #include "authfile.h" | 73 | #include "authfile.h" |
74 | #include "monitor_wrap.h" | 74 | #include "monitor_wrap.h" |
75 | #include "krl.h" | ||
75 | 76 | ||
76 | /* import */ | 77 | /* import */ |
77 | extern ServerOptions options; | 78 | extern ServerOptions options; |
@@ -252,7 +253,8 @@ allowed_user(struct passwd * pw) | |||
252 | } | 253 | } |
253 | 254 | ||
254 | void | 255 | void |
255 | auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | 256 | auth_log(Authctxt *authctxt, int authenticated, int partial, |
257 | const char *method, const char *submethod, const char *info) | ||
256 | { | 258 | { |
257 | void (*authlog) (const char *fmt,...) = verbose; | 259 | void (*authlog) (const char *fmt,...) = verbose; |
258 | char *authmsg; | 260 | char *authmsg; |
@@ -269,12 +271,15 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
269 | 271 | ||
270 | if (authctxt->postponed) | 272 | if (authctxt->postponed) |
271 | authmsg = "Postponed"; | 273 | authmsg = "Postponed"; |
274 | else if (partial) | ||
275 | authmsg = "Partial"; | ||
272 | else | 276 | else |
273 | authmsg = authenticated ? "Accepted" : "Failed"; | 277 | authmsg = authenticated ? "Accepted" : "Failed"; |
274 | 278 | ||
275 | authlog("%s %s for %s%.100s from %.200s port %d%s", | 279 | authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", |
276 | authmsg, | 280 | authmsg, |
277 | method, | 281 | method, |
282 | submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, | ||
278 | authctxt->valid ? "" : "invalid user ", | 283 | authctxt->valid ? "" : "invalid user ", |
279 | authctxt->user, | 284 | authctxt->user, |
280 | get_remote_ipaddr(), | 285 | get_remote_ipaddr(), |
@@ -304,7 +309,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) | |||
304 | * Check whether root logins are disallowed. | 309 | * Check whether root logins are disallowed. |
305 | */ | 310 | */ |
306 | int | 311 | int |
307 | auth_root_allowed(char *method) | 312 | auth_root_allowed(const char *method) |
308 | { | 313 | { |
309 | switch (options.permit_root_login) { | 314 | switch (options.permit_root_login) { |
310 | case PERMIT_YES: | 315 | case PERMIT_YES: |
@@ -409,40 +414,41 @@ 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 | !secure_permissions(&st, uid)) { | 449 | return -1; |
450 | } | ||
451 | if (!secure_permissions(stp, uid)) { | ||
446 | snprintf(err, errlen, "bad ownership or modes for file %s", | 452 | snprintf(err, errlen, "bad ownership or modes for file %s", |
447 | buf); | 453 | buf); |
448 | return -1; | 454 | return -1; |
@@ -477,6 +483,27 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, | |||
477 | return 0; | 483 | return 0; |
478 | } | 484 | } |
479 | 485 | ||
486 | /* | ||
487 | * Version of secure_path() that accepts an open file descriptor to | ||
488 | * avoid races. | ||
489 | * | ||
490 | * Returns 0 on success and -1 on failure | ||
491 | */ | ||
492 | static int | ||
493 | secure_filename(FILE *f, const char *file, struct passwd *pw, | ||
494 | char *err, size_t errlen) | ||
495 | { | ||
496 | struct stat st; | ||
497 | |||
498 | /* check the open file to avoid races */ | ||
499 | if (fstat(fileno(f), &st) < 0) { | ||
500 | snprintf(err, errlen, "cannot stat file %s: %s", | ||
501 | file, strerror(errno)); | ||
502 | return -1; | ||
503 | } | ||
504 | return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); | ||
505 | } | ||
506 | |||
480 | static FILE * | 507 | static FILE * |
481 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, | 508 | auth_openfile(const char *file, struct passwd *pw, int strict_modes, |
482 | int log_missing, char *file_type) | 509 | int log_missing, char *file_type) |
@@ -636,7 +663,16 @@ auth_key_is_revoked(Key *key, int hostkey) | |||
636 | 663 | ||
637 | if (options.revoked_keys_file == NULL) | 664 | if (options.revoked_keys_file == NULL) |
638 | return 0; | 665 | return 0; |
639 | 666 | switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) { | |
667 | case 0: | ||
668 | return 0; /* Not revoked */ | ||
669 | case -2: | ||
670 | break; /* Not a KRL */ | ||
671 | default: | ||
672 | goto revoked; | ||
673 | } | ||
674 | debug3("%s: treating %s as a key list", __func__, | ||
675 | options.revoked_keys_file); | ||
640 | switch (key_in_file(key, options.revoked_keys_file, 0)) { | 676 | switch (key_in_file(key, options.revoked_keys_file, 0)) { |
641 | case 0: | 677 | case 0: |
642 | /* key not revoked */ | 678 | /* key not revoked */ |
@@ -647,6 +683,7 @@ auth_key_is_revoked(Key *key, int hostkey) | |||
647 | "authentication"); | 683 | "authentication"); |
648 | return 1; | 684 | return 1; |
649 | case 1: | 685 | case 1: |
686 | revoked: | ||
650 | /* Key revoked */ | 687 | /* Key revoked */ |
651 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); | 688 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); |
652 | error("WARNING: authentication attempt with a revoked " | 689 | error("WARNING: authentication attempt with a revoked " |