summaryrefslogtreecommitdiff
path: root/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth.c')
-rw-r--r--auth.c163
1 files changed, 49 insertions, 114 deletions
diff --git a/auth.c b/auth.c
index 90390724d..68a1e4a76 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 &&
@@ -429,7 +452,7 @@ authorized_principals_file(struct passwd *pw)
429 452
430/* return ok if key exists in sysfile or userfile */ 453/* return ok if key exists in sysfile or userfile */
431HostStatus 454HostStatus
432check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 455check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
433 const char *sysfile, const char *userfile) 456 const char *sysfile, const char *userfile)
434{ 457{
435 char *user_hostfile; 458 char *user_hostfile;
@@ -472,96 +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 (!secure_permissions(stp, uid)) {
510 snprintf(err, errlen, "bad ownership or modes for file %s",
511 buf);
512 return -1;
513 }
514
515 /* for each component of the canonical path, walking upwards */
516 for (;;) {
517 if ((cp = dirname(buf)) == NULL) {
518 snprintf(err, errlen, "dirname() failed");
519 return -1;
520 }
521 strlcpy(buf, cp, sizeof(buf));
522
523 if (stat(buf, &st) < 0 ||
524 !secure_permissions(&st, uid)) {
525 snprintf(err, errlen,
526 "bad ownership or modes for directory %s", buf);
527 return -1;
528 }
529
530 /* If are past the homedir then we can stop */
531 if (comparehome && strcmp(homedir, buf) == 0)
532 break;
533
534 /*
535 * dirname should always complete with a "/" path,
536 * but we can be paranoid and check for "." too
537 */
538 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
539 break;
540 }
541 return 0;
542}
543
544/*
545 * Version of secure_path() that accepts an open file descriptor to
546 * avoid races.
547 *
548 * Returns 0 on success and -1 on failure
549 */
550static int
551secure_filename(FILE *f, const char *file, struct passwd *pw,
552 char *err, size_t errlen)
553{
554 struct stat st;
555
556 /* check the open file to avoid races */
557 if (fstat(fileno(f), &st) < 0) {
558 snprintf(err, errlen, "cannot stat file %s: %s",
559 file, strerror(errno));
560 return -1;
561 }
562 return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
563}
564
565static FILE * 498static FILE *
566auth_openfile(const char *file, struct passwd *pw, int strict_modes, 499auth_openfile(const char *file, struct passwd *pw, int strict_modes,
567 int log_missing, char *file_type) 500 int log_missing, char *file_type)
@@ -594,7 +527,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
594 return NULL; 527 return NULL;
595 } 528 }
596 if (strict_modes && 529 if (strict_modes &&
597 secure_filename(f, file, pw, line, sizeof(line)) != 0) { 530 safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
598 fclose(f); 531 fclose(f);
599 logit("Authentication refused: %s", line); 532 logit("Authentication refused: %s", line);
600 auth_debug_add("Ignored %s: %s", file_type, line); 533 auth_debug_add("Ignored %s: %s", file_type, line);
@@ -633,6 +566,8 @@ getpwnamallow(const char *user)
633 566
634 ci->user = user; 567 ci->user = user;
635 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);
636 571
637#if defined(_AIX) && defined(HAVE_SETAUTHDB) 572#if defined(_AIX) && defined(HAVE_SETAUTHDB)
638 aix_setauthdb(user); 573 aix_setauthdb(user);
@@ -692,7 +627,7 @@ getpwnamallow(const char *user)
692 627
693/* 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 */
694int 629int
695auth_key_is_revoked(Key *key) 630auth_key_is_revoked(struct sshkey *key)
696{ 631{
697 char *fp = NULL; 632 char *fp = NULL;
698 int r; 633 int r;