summaryrefslogtreecommitdiff
path: root/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth.c')
-rw-r--r--auth.c165
1 files changed, 49 insertions, 116 deletions
diff --git a/auth.c b/auth.c
index 6ee6116df..a44906174 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.119 2016/12/15 21:29:05 dtucker Exp $ */ 1/* $OpenBSD: auth.c,v 1.124 2017/09/12 06:32:07 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>
@@ -267,21 +264,41 @@ allowed_user(struct passwd * pw)
267 return 1; 264 return 1;
268} 265}
269 266
270void 267/*
271auth_info(Authctxt *authctxt, const char *fmt, ...) 268 * Formats any key left in authctxt->auth_method_key for inclusion in
269 * auth_log()'s message. Also includes authxtct->auth_method_info if present.
270 */
271static char *
272format_method_key(Authctxt *authctxt)
272{ 273{
273 va_list ap; 274 const struct sshkey *key = authctxt->auth_method_key;
274 int i; 275 const char *methinfo = authctxt->auth_method_info;
275 276 char *fp, *ret = NULL;
276 free(authctxt->info);
277 authctxt->info = NULL;
278 277
279 va_start(ap, fmt); 278 if (key == NULL)
280 i = vasprintf(&authctxt->info, fmt, ap); 279 return NULL;
281 va_end(ap);
282 280
283 if (i < 0 || authctxt->info == NULL) 281 if (key_is_cert(key)) {
284 fatal("vasprintf failed"); 282 fp = sshkey_fingerprint(key->cert->signature_key,
283 options.fingerprint_hash, SSH_FP_DEFAULT);
284 xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s",
285 sshkey_type(key), key->cert->key_id,
286 (unsigned long long)key->cert->serial,
287 sshkey_type(key->cert->signature_key),
288 fp == NULL ? "(null)" : fp,
289 methinfo == NULL ? "" : ", ",
290 methinfo == NULL ? "" : methinfo);
291 free(fp);
292 } else {
293 fp = sshkey_fingerprint(key, options.fingerprint_hash,
294 SSH_FP_DEFAULT);
295 xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
296 fp == NULL ? "(null)" : fp,
297 methinfo == NULL ? "" : ", ",
298 methinfo == NULL ? "" : methinfo);
299 free(fp);
300 }
301 return ret;
285} 302}
286 303
287void 304void
@@ -290,7 +307,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
290{ 307{
291 struct ssh *ssh = active_state; /* XXX */ 308 struct ssh *ssh = active_state; /* XXX */
292 void (*authlog) (const char *fmt,...) = verbose; 309 void (*authlog) (const char *fmt,...) = verbose;
293 char *authmsg; 310 const char *authmsg;
311 char *extra = NULL;
294 312
295 if (use_privsep && !mm_is_monitor() && !authctxt->postponed) 313 if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
296 return; 314 return;
@@ -309,6 +327,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
309 else 327 else
310 authmsg = authenticated ? "Accepted" : "Failed"; 328 authmsg = authenticated ? "Accepted" : "Failed";
311 329
330 if ((extra = format_method_key(authctxt)) == NULL) {
331 if (authctxt->auth_method_info != NULL)
332 extra = xstrdup(authctxt->auth_method_info);
333 }
334
312 authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s", 335 authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
313 authmsg, 336 authmsg,
314 method, 337 method,
@@ -317,10 +340,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
317 authctxt->user, 340 authctxt->user,
318 ssh_remote_ipaddr(ssh), 341 ssh_remote_ipaddr(ssh),
319 ssh_remote_port(ssh), 342 ssh_remote_port(ssh),
320 authctxt->info != NULL ? ": " : "", 343 extra != NULL ? ": " : "",
321 authctxt->info != NULL ? authctxt->info : ""); 344 extra != NULL ? extra : "");
322 free(authctxt->info); 345
323 authctxt->info = NULL; 346 free(extra);
324 347
325#ifdef CUSTOM_FAILED_LOGIN 348#ifdef CUSTOM_FAILED_LOGIN
326 if (authenticated == 0 && !authctxt->postponed && 349 if (authenticated == 0 && !authctxt->postponed &&
@@ -428,7 +451,7 @@ authorized_principals_file(struct passwd *pw)
428 451
429/* return ok if key exists in sysfile or userfile */ 452/* return ok if key exists in sysfile or userfile */
430HostStatus 453HostStatus
431check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 454check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
432 const char *sysfile, const char *userfile) 455 const char *sysfile, const char *userfile)
433{ 456{
434 char *user_hostfile; 457 char *user_hostfile;
@@ -472,98 +495,6 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
472 return host_status; 495 return host_status;
473} 496}
474 497
475/*
476 * Check a given path for security. This is defined as all components
477 * of the path to the file must be owned by either the owner of
478 * of the file or root and no directories must be group or world writable.
479 *
480 * XXX Should any specific check be done for sym links ?
481 *
482 * Takes a file name, its stat information (preferably from fstat() to
483 * avoid races), the uid of the expected owner, their home directory and an
484 * error buffer plus max size as arguments.
485 *
486 * Returns 0 on success and -1 on failure
487 */
488int
489auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
490 uid_t uid, char *err, size_t errlen)
491{
492 char buf[PATH_MAX], homedir[PATH_MAX];
493 char *cp;
494 int comparehome = 0;
495 struct stat st;
496
497 if (realpath(name, buf) == NULL) {
498 snprintf(err, errlen, "realpath %s failed: %s", name,
499 strerror(errno));
500 return -1;
501 }
502 if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
503 comparehome = 1;
504
505 if (!S_ISREG(stp->st_mode)) {
506 snprintf(err, errlen, "%s is not a regular file", buf);
507 return -1;
508 }
509 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
510 (stp->st_mode & 022) != 0) {
511 snprintf(err, errlen, "bad ownership or modes for file %s",
512 buf);
513 return -1;
514 }
515
516 /* for each component of the canonical path, walking upwards */
517 for (;;) {
518 if ((cp = dirname(buf)) == NULL) {
519 snprintf(err, errlen, "dirname() failed");
520 return -1;
521 }
522 strlcpy(buf, cp, sizeof(buf));
523
524 if (stat(buf, &st) < 0 ||
525 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
526 (st.st_mode & 022) != 0) {
527 snprintf(err, errlen,
528 "bad ownership or modes for directory %s", buf);
529 return -1;
530 }
531
532 /* If are past the homedir then we can stop */
533 if (comparehome && strcmp(homedir, buf) == 0)
534 break;
535
536 /*
537 * dirname should always complete with a "/" path,
538 * but we can be paranoid and check for "." too
539 */
540 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
541 break;
542 }
543 return 0;
544}
545
546/*
547 * Version of secure_path() that accepts an open file descriptor to
548 * avoid races.
549 *
550 * Returns 0 on success and -1 on failure
551 */
552static int
553secure_filename(FILE *f, const char *file, struct passwd *pw,
554 char *err, size_t errlen)
555{
556 struct stat st;
557
558 /* check the open file to avoid races */
559 if (fstat(fileno(f), &st) < 0) {
560 snprintf(err, errlen, "cannot stat file %s: %s",
561 file, strerror(errno));
562 return -1;
563 }
564 return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
565}
566
567static FILE * 498static FILE *
568auth_openfile(const char *file, struct passwd *pw, int strict_modes, 499auth_openfile(const char *file, struct passwd *pw, int strict_modes,
569 int log_missing, char *file_type) 500 int log_missing, char *file_type)
@@ -596,7 +527,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
596 return NULL; 527 return NULL;
597 } 528 }
598 if (strict_modes && 529 if (strict_modes &&
599 secure_filename(f, file, pw, line, sizeof(line)) != 0) { 530 safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
600 fclose(f); 531 fclose(f);
601 logit("Authentication refused: %s", line); 532 logit("Authentication refused: %s", line);
602 auth_debug_add("Ignored %s: %s", file_type, line); 533 auth_debug_add("Ignored %s: %s", file_type, line);
@@ -635,6 +566,8 @@ getpwnamallow(const char *user)
635 566
636 ci->user = user; 567 ci->user = user;
637 parse_server_match_config(&options, ci); 568 parse_server_match_config(&options, ci);
569 log_change_level(options.log_level);
570 process_permitopen(ssh, &options);
638 571
639#if defined(_AIX) && defined(HAVE_SETAUTHDB) 572#if defined(_AIX) && defined(HAVE_SETAUTHDB)
640 aix_setauthdb(user); 573 aix_setauthdb(user);
@@ -694,7 +627,7 @@ getpwnamallow(const char *user)
694 627
695/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */ 628/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
696int 629int
697auth_key_is_revoked(Key *key) 630auth_key_is_revoked(struct sshkey *key)
698{ 631{
699 char *fp = NULL; 632 char *fp = NULL;
700 int r; 633 int r;