Home | History | Annotate | Line # | Download | only in dist
      1 /*	$NetBSD: auth.c,v 1.40 2026/04/08 18:58:40 christos Exp $	*/
      2 /* $OpenBSD: auth.c,v 1.164 2026/02/11 22:57:16 djm Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "includes.h"
     29 __RCSID("$NetBSD: auth.c,v 1.40 2026/04/08 18:58:40 christos Exp $");
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 #include <sys/socket.h>
     33 #include <sys/wait.h>
     34 
     35 #include <stdlib.h>
     36 #include <errno.h>
     37 #include <fcntl.h>
     38 #include <login_cap.h>
     39 #include <paths.h>
     40 #include <pwd.h>
     41 #include <stdarg.h>
     42 #include <stdio.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 #include <limits.h>
     46 #include <netdb.h>
     47 #include <time.h>
     48 
     49 #include "xmalloc.h"
     50 #include "match.h"
     51 #include "groupaccess.h"
     52 #include "log.h"
     53 #include "sshbuf.h"
     54 #include "misc.h"
     55 #include "servconf.h"
     56 #include "sshkey.h"
     57 #include "hostfile.h"
     58 #include "auth.h"
     59 #include "auth-options.h"
     60 #include "canohost.h"
     61 #include "uidswap.h"
     62 #include "packet.h"
     63 #ifdef GSSAPI
     64 #include "ssh-gss.h"
     65 #endif
     66 #include "authfile.h"
     67 #include "monitor_wrap.h"
     68 #include "ssherr.h"
     69 #include "channels.h"
     70 #include "pfilter.h"
     71 
     72 #ifdef HAVE_LOGIN_CAP
     73 #include <login_cap.h>
     74 #endif
     75 
     76 /* import */
     77 extern ServerOptions options;
     78 extern struct include_list includes;
     79 extern struct sshauthopt *auth_opts;
     80 
     81 /* Debugging messages */
     82 static struct sshbuf *auth_debug;
     83 
     84 #ifndef HOST_ONLY
     85 /*
     86  * Check if the user is allowed to log in via ssh. If user is listed
     87  * in DenyUsers or one of user's groups is listed in DenyGroups, false
     88  * will be returned. If AllowUsers isn't empty and user isn't listed
     89  * there, or if AllowGroups isn't empty and one of user's groups isn't
     90  * listed there, false will be returned.
     91  * If the user's shell is not executable, false will be returned.
     92  * Otherwise true is returned.
     93  */
     94 int
     95 allowed_user(struct ssh *ssh, struct passwd * pw)
     96 {
     97 #ifdef HAVE_LOGIN_CAP
     98 	extern login_cap_t *lc;
     99 	int match_name, match_ip;
    100 	char *cap_hlist, *hp;
    101 #endif
    102 	struct stat st;
    103 	const char *hostname = NULL, *ipaddr = NULL;
    104 	int r;
    105 	u_int i;
    106 
    107 	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
    108 	if (!pw || !pw->pw_name)
    109 		return 0;
    110 
    111 #ifdef HAVE_LOGIN_CAP
    112 	hostname = auth_get_canonical_hostname(ssh, options.use_dns);
    113 	ipaddr = ssh_remote_ipaddr(ssh);
    114 
    115 	lc = login_getclass(pw->pw_class);
    116 
    117 	/*
    118 	 * Check the deny list.
    119 	 */
    120 	cap_hlist = login_getcapstr(lc, "host.deny", NULL, NULL);
    121 	if (cap_hlist != NULL) {
    122 		hp = strtok(cap_hlist, ",");
    123 		while (hp != NULL) {
    124 			match_name = match_hostname(hostname, hp);
    125 			match_ip = match_hostname(ipaddr, hp);
    126 			/*
    127 			 * Only a positive match here causes a "deny".
    128 			 */
    129 			if (match_name > 0 || match_ip > 0) {
    130 				free(cap_hlist);
    131 				login_close(lc);
    132 				return 0;
    133 			}
    134 			hp = strtok(NULL, ",");
    135 		}
    136 		free(cap_hlist);
    137 	}
    138 
    139 	/*
    140 	 * Check the allow list.  If the allow list exists, and the
    141 	 * remote host is not in it, the user is implicitly denied.
    142 	 */
    143 	cap_hlist = login_getcapstr(lc, "host.allow", NULL, NULL);
    144 	if (cap_hlist != NULL) {
    145 		hp = strtok(cap_hlist, ",");
    146 		if (hp == NULL) {
    147 			/* Just in case there's an empty string... */
    148 			free(cap_hlist);
    149 			login_close(lc);
    150 			return 0;
    151 		}
    152 		while (hp != NULL) {
    153 			match_name = match_hostname(hostname, hp);
    154 			match_ip = match_hostname(ipaddr, hp);
    155 			/*
    156 			 * Negative match causes an immediate "deny".
    157 			 * Positive match causes us to break out
    158 			 * of the loop (allowing a fallthrough).
    159 			 */
    160 			if (match_name < 0 || match_ip < 0) {
    161 				free(cap_hlist);
    162 				login_close(lc);
    163 				return 0;
    164 			}
    165 			if (match_name > 0 || match_ip > 0)
    166 				break;
    167 			hp = strtok(NULL, ",");
    168 		}
    169 		free(cap_hlist);
    170 		if (hp == NULL) {
    171 			login_close(lc);
    172 			return 0;
    173 		}
    174 	}
    175 
    176 	login_close(lc);
    177 #endif
    178 
    179 #ifdef USE_PAM
    180 	if (!options.use_pam) {
    181 #endif
    182 	/*
    183 	 * password/account expiration.
    184 	 */
    185 	if (pw->pw_change || pw->pw_expire) {
    186 		struct timeval tv;
    187 
    188 		(void)gettimeofday(&tv, (struct timezone *)NULL);
    189 		if (pw->pw_expire) {
    190 			if (tv.tv_sec >= pw->pw_expire) {
    191 				logit("User %.100s not allowed because account has expired",
    192 				    pw->pw_name);
    193 				return 0;	/* expired */
    194 			}
    195 		}
    196 #ifdef _PASSWORD_CHGNOW
    197 		if (pw->pw_change == _PASSWORD_CHGNOW) {
    198 			logit("User %.100s not allowed because password needs to be changed",
    199 			    pw->pw_name);
    200 
    201 			return 0;	/* can't force password change (yet) */
    202 		}
    203 #endif
    204 		if (pw->pw_change) {
    205 			if (tv.tv_sec >= pw->pw_change) {
    206 				logit("User %.100s not allowed because password has expired",
    207 				    pw->pw_name);
    208 				return 0;	/* expired */
    209 			}
    210 		}
    211 	}
    212 #ifdef USE_PAM
    213 	}
    214 #endif
    215 
    216 	/*
    217 	 * Deny if shell does not exist or is not executable unless we
    218 	 * are chrooting.
    219 	 */
    220 	/*
    221 	 * XXX Should check to see if it is executable by the
    222 	 * XXX requesting user.  --thorpej
    223 	 */
    224 	if (options.chroot_directory == NULL ||
    225 	    strcasecmp(options.chroot_directory, "none") == 0) {
    226 		char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
    227 		    _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
    228 
    229 		if (stat(shell, &st) == -1) {
    230 			logit("User %.100s not allowed because shell %.100s "
    231 			    "does not exist", pw->pw_name, shell);
    232 			free(shell);
    233 			return 0;
    234 		}
    235 		if (S_ISREG(st.st_mode) == 0 ||
    236 		    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
    237 			logit("User %.100s not allowed because shell %.100s "
    238 			    "is not executable", pw->pw_name, shell);
    239 			free(shell);
    240 			return 0;
    241 		}
    242 		free(shell);
    243 	}
    244 	/*
    245 	 * XXX Consider nuking {Allow,Deny}{Users,Groups}.  We have the
    246 	 * XXX login_cap(3) mechanism which covers all other types of
    247 	 * XXX logins, too.
    248 	 */
    249 
    250 	if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
    251 	    options.num_deny_groups > 0 || options.num_allow_groups > 0) {
    252 		hostname = auth_get_canonical_hostname(ssh, options.use_dns);
    253 		ipaddr = ssh_remote_ipaddr(ssh);
    254 	}
    255 
    256 	/* Return false if user is listed in DenyUsers */
    257 	if (options.num_deny_users > 0) {
    258 		for (i = 0; i < options.num_deny_users; i++) {
    259 			r = match_user(pw->pw_name, hostname, ipaddr,
    260 			    options.deny_users[i]);
    261 			if (r < 0) {
    262 				fatal("Invalid DenyUsers pattern \"%.100s\"",
    263 				    options.deny_users[i]);
    264 			} else if (r != 0) {
    265 				logit("User %.100s from %.100s not allowed "
    266 				    "because listed in DenyUsers",
    267 				    pw->pw_name, hostname);
    268 				return 0;
    269 			}
    270 		}
    271 	}
    272 	/* Return false if AllowUsers isn't empty and user isn't listed there */
    273 	if (options.num_allow_users > 0) {
    274 		for (i = 0; i < options.num_allow_users; i++) {
    275 			r = match_user(pw->pw_name, hostname, ipaddr,
    276 			    options.allow_users[i]);
    277 			if (r < 0) {
    278 				fatal("Invalid AllowUsers pattern \"%.100s\"",
    279 				    options.allow_users[i]);
    280 			} else if (r == 1)
    281 				break;
    282 		}
    283 		/* i < options.num_allow_users iff we break for loop */
    284 		if (i >= options.num_allow_users) {
    285 			logit("User %.100s from %.100s not allowed because "
    286 			    "not listed in AllowUsers", pw->pw_name, hostname);
    287 			return 0;
    288 		}
    289 	}
    290 	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
    291 		/* Get the user's group access list (primary and supplementary) */
    292 		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
    293 			logit("User %.100s from %.100s not allowed because "
    294 			    "not in any group", pw->pw_name, hostname);
    295 			return 0;
    296 		}
    297 
    298 		/* Return false if one of user's groups is listed in DenyGroups */
    299 		if (options.num_deny_groups > 0)
    300 			if (ga_match(options.deny_groups,
    301 			    options.num_deny_groups)) {
    302 				ga_free();
    303 				logit("User %.100s from %.100s not allowed "
    304 				    "because a group is listed in DenyGroups",
    305 				    pw->pw_name, hostname);
    306 				return 0;
    307 			}
    308 		/*
    309 		 * Return false if AllowGroups isn't empty and one of user's groups
    310 		 * isn't listed there
    311 		 */
    312 		if (options.num_allow_groups > 0)
    313 			if (!ga_match(options.allow_groups,
    314 			    options.num_allow_groups)) {
    315 				ga_free();
    316 				logit("User %.100s from %.100s not allowed "
    317 				    "because none of user's groups are listed "
    318 				    "in AllowGroups", pw->pw_name, hostname);
    319 				return 0;
    320 			}
    321 		ga_free();
    322 	}
    323 	/* We found no reason not to let this user try to log on... */
    324 	return 1;
    325 }
    326 
    327 /*
    328  * Formats any key left in authctxt->auth_method_key for inclusion in
    329  * auth_log()'s message. Also includes authxtct->auth_method_info if present.
    330  */
    331 static char *
    332 format_method_key(Authctxt *authctxt)
    333 {
    334 	const struct sshkey *key = authctxt->auth_method_key;
    335 	const char *methinfo = authctxt->auth_method_info;
    336 	char *fp, *cafp, *ret = NULL;
    337 
    338 	if (key == NULL)
    339 		return NULL;
    340 
    341 	if (sshkey_is_cert(key)) {
    342 		fp = sshkey_fingerprint(key,
    343 		    options.fingerprint_hash, SSH_FP_DEFAULT);
    344 		cafp = sshkey_fingerprint(key->cert->signature_key,
    345 		    options.fingerprint_hash, SSH_FP_DEFAULT);
    346 		xasprintf(&ret, "%s %s ID %s (serial %llu) CA %s %s%s%s",
    347 		    sshkey_type(key), fp == NULL ? "(null)" : fp,
    348 		    key->cert->key_id,
    349 		    (unsigned long long)key->cert->serial,
    350 		    sshkey_type(key->cert->signature_key),
    351 		    cafp == NULL ? "(null)" : cafp,
    352 		    methinfo == NULL ? "" : ", ",
    353 		    methinfo == NULL ? "" : methinfo);
    354 		free(fp);
    355 		free(cafp);
    356 	} else {
    357 		fp = sshkey_fingerprint(key, options.fingerprint_hash,
    358 		    SSH_FP_DEFAULT);
    359 		xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
    360 		    fp == NULL ? "(null)" : fp,
    361 		    methinfo == NULL ? "" : ", ",
    362 		    methinfo == NULL ? "" : methinfo);
    363 		free(fp);
    364 	}
    365 	return ret;
    366 }
    367 
    368 void
    369 auth_log(struct ssh *ssh, int authenticated, int partial,
    370     const char *method, const char *submethod)
    371 {
    372 	Authctxt *authctxt = (Authctxt *)ssh->authctxt;
    373 	int level = SYSLOG_LEVEL_VERBOSE;
    374 	const char *authmsg;
    375 	char *extra = NULL;
    376 
    377 	if (!mm_is_monitor() && !authctxt->postponed)
    378 		return;
    379 
    380 	/* Raise logging level */
    381 	if (authenticated == 1 ||
    382 	    !authctxt->valid ||
    383 	    authctxt->failures >= options.max_authtries / 2 ||
    384 	    strcmp(method, "password") == 0)
    385 		level = SYSLOG_LEVEL_INFO;
    386 
    387 	if (authctxt->postponed)
    388 		authmsg = "Postponed";
    389 	else if (partial)
    390 		authmsg = "Partial";
    391 	else {
    392 		authmsg = authenticated ? "Accepted" : "Failed";
    393 		if (authenticated)
    394 			pfilter_notify(0);
    395 	}
    396 
    397 	if ((extra = format_method_key(authctxt)) == NULL) {
    398 		if (authctxt->auth_method_info != NULL)
    399 			extra = xstrdup(authctxt->auth_method_info);
    400 	}
    401 
    402 	do_log2(level, "%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
    403 	    authmsg,
    404 	    method,
    405 	    submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
    406 	    authctxt->valid ? "" : "invalid user ",
    407 	    authctxt->user,
    408 	    ssh_remote_ipaddr(ssh),
    409 	    ssh_remote_port(ssh),
    410 	    extra != NULL ? ": " : "",
    411 	    extra != NULL ? extra : "");
    412 
    413 	free(extra);
    414 }
    415 
    416 void
    417 auth_maxtries_exceeded(struct ssh *ssh)
    418 {
    419 	Authctxt *authctxt = (Authctxt *)ssh->authctxt;
    420 
    421 	pfilter_notify(1);
    422 	error("maximum authentication attempts exceeded for "
    423 	    "%s%.100s from %.200s port %d ssh2",
    424 	    authctxt->valid ? "" : "invalid user ",
    425 	    authctxt->user,
    426 	    ssh_remote_ipaddr(ssh),
    427 	    ssh_remote_port(ssh));
    428 	ssh_packet_disconnect(ssh, "Too many authentication failures");
    429 	/* NOTREACHED */
    430 }
    431 
    432 /*
    433  * Check whether root logins are disallowed.
    434  */
    435 int
    436 auth_root_allowed(struct ssh *ssh, const char *method)
    437 {
    438 	switch (options.permit_root_login) {
    439 	case PERMIT_YES:
    440 		return 1;
    441 	case PERMIT_NO_PASSWD:
    442 		if (strcmp(method, "publickey") == 0 ||
    443 		    strcmp(method, "hostbased") == 0 ||
    444 		    strcmp(method, "gssapi-with-mic") == 0)
    445 			return 1;
    446 		break;
    447 	case PERMIT_FORCED_ONLY:
    448 		if (auth_opts->force_command != NULL) {
    449 			logit("Root login accepted for forced command.");
    450 			return 1;
    451 		}
    452 		break;
    453 	}
    454 	logit("ROOT LOGIN REFUSED FROM %.200s port %d",
    455 	    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
    456 	return 0;
    457 }
    458 
    459 
    460 /*
    461  * Given a template and a passwd structure, build a filename
    462  * by substituting % tokenised options. Currently, %% becomes '%',
    463  * %h becomes the home directory and %u the username.
    464  *
    465  * This returns a buffer allocated by xmalloc.
    466  */
    467 char *
    468 expand_authorized_keys(const char *filename, struct passwd *pw)
    469 {
    470 	char *file, uidstr[32], ret[PATH_MAX];
    471 	int i;
    472 
    473 	snprintf(uidstr, sizeof(uidstr), "%llu",
    474 	    (unsigned long long)pw->pw_uid);
    475 	file = percent_expand(filename, "h", pw->pw_dir,
    476 	    "u", pw->pw_name, "U", uidstr, (char *)NULL);
    477 
    478 	/*
    479 	 * Ensure that filename starts anchored. If not, be backward
    480 	 * compatible and prepend the '%h/'
    481 	 */
    482 	if (path_absolute(file))
    483 		return (file);
    484 
    485 	i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
    486 	if (i < 0 || (size_t)i >= sizeof(ret))
    487 		fatal("expand_authorized_keys: path too long");
    488 	free(file);
    489 	return (xstrdup(ret));
    490 }
    491 
    492 char *
    493 authorized_principals_file(struct passwd *pw)
    494 {
    495 	if (options.authorized_principals_file == NULL)
    496 		return NULL;
    497 	return expand_authorized_keys(options.authorized_principals_file, pw);
    498 }
    499 
    500 /* return ok if key exists in sysfile or userfile */
    501 HostStatus
    502 check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
    503     const char *sysfile, const char *userfile)
    504 {
    505 	char *user_hostfile;
    506 	struct stat st;
    507 	HostStatus host_status;
    508 	struct hostkeys *hostkeys;
    509 	const struct hostkey_entry *found;
    510 
    511 	hostkeys = init_hostkeys();
    512 	load_hostkeys(hostkeys, host, sysfile, 0);
    513 	if (userfile != NULL) {
    514 		user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
    515 		if (options.strict_modes &&
    516 		    (stat(user_hostfile, &st) == 0) &&
    517 		    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
    518 		    (st.st_mode & 022) != 0)) {
    519 			logit("Authentication refused for %.100s: "
    520 			    "bad owner or modes for %.200s",
    521 			    pw->pw_name, user_hostfile);
    522 			auth_debug_add("Ignored %.200s: bad ownership or modes",
    523 			    user_hostfile);
    524 		} else {
    525 			temporarily_use_uid(pw);
    526 			load_hostkeys(hostkeys, host, user_hostfile, 0);
    527 			restore_uid();
    528 		}
    529 		free(user_hostfile);
    530 	}
    531 	host_status = check_key_in_hostkeys(hostkeys, key, &found);
    532 	if (host_status == HOST_REVOKED)
    533 		error("WARNING: revoked key for %s attempted authentication",
    534 		    host);
    535 	else if (host_status == HOST_OK)
    536 		debug_f("key for %s found at %s:%ld",
    537 		    found->host, found->file, found->line);
    538 	else
    539 		debug_f("key for host %s not found", host);
    540 
    541 	free_hostkeys(hostkeys);
    542 
    543 	return host_status;
    544 }
    545 
    546 struct passwd *
    547 getpwnamallow(struct ssh *ssh, const char *user)
    548 {
    549 #ifdef HAVE_LOGIN_CAP
    550  	extern login_cap_t *lc;
    551 #ifdef BSD_AUTH
    552  	auth_session_t *as;
    553 #endif
    554 #endif
    555 	struct passwd *pw;
    556 	struct connection_info *ci;
    557 	u_int i;
    558 
    559 	ci = server_get_connection_info(ssh, 1, options.use_dns);
    560 	ci->user = user;
    561 	ci->user_invalid = getpwnam(user) == NULL;
    562 	parse_server_match_config(&options, &includes, ci);
    563 	log_change_level(options.log_level);
    564 	log_verbose_reset();
    565 	for (i = 0; i < options.num_log_verbose; i++)
    566 		log_verbose_add(options.log_verbose[i]);
    567 	server_process_permitopen(ssh);
    568 
    569 	pw = getpwnam(user);
    570 	if (pw == NULL) {
    571 		pfilter_notify(1);
    572 		logit("Invalid user %.100s from %.100s port %d",
    573 		    user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
    574 		return (NULL);
    575 	}
    576 	if (!allowed_user(ssh, pw))
    577 		return (NULL);
    578 #ifdef HAVE_LOGIN_CAP
    579 	if ((lc = login_getclass(pw->pw_class)) == NULL) {
    580 		debug("unable to get login class: %s", user);
    581 		return (NULL);
    582 	}
    583 #ifdef BSD_AUTH
    584 	if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
    585 	    auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
    586 		debug("Approval failure for %s", user);
    587 		pw = NULL;
    588 	}
    589 	if (as != NULL)
    590 		auth_close(as);
    591 #endif
    592 #endif
    593 	if (pw != NULL)
    594 		return (pwcopy(pw));
    595 	return (NULL);
    596 }
    597 
    598 /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
    599 int
    600 auth_key_is_revoked(struct sshkey *key)
    601 {
    602 	char *fp = NULL;
    603 	u_int i;
    604 	int r;
    605 
    606 	if (options.num_revoked_keys_files == 0)
    607 		return 0;
    608 	if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
    609 	    SSH_FP_DEFAULT)) == NULL) {
    610 		r = SSH_ERR_ALLOC_FAIL;
    611 		error_fr(r, "fingerprint key");
    612 		goto out;
    613 	}
    614 
    615 	for (i = 0; i < options.num_revoked_keys_files; i++) {
    616 		r = sshkey_check_revoked(key, options.revoked_keys_files[i]);
    617 		switch (r) {
    618 		case 0:
    619 			break; /* not revoked */
    620 		case SSH_ERR_KEY_REVOKED:
    621 			error("Authentication key %s %s revoked by file %s",
    622 			    sshkey_type(key), fp,
    623 			    options.revoked_keys_files[i]);
    624 			goto out;
    625 		default:
    626 			error_r(r, "Error checking authentication key %s %s in "
    627 			    "revoked keys file %s", sshkey_type(key), fp,
    628 			    options.revoked_keys_files[i]);
    629 			goto out;
    630 		}
    631 	}
    632 
    633 	/* Success */
    634 	r = 0;
    635 
    636  out:
    637 	free(fp);
    638 	return r == 0 ? 0 : 1;
    639 }
    640 #endif
    641 
    642 void
    643 auth_debug_add(const char *fmt,...)
    644 {
    645 	char buf[1024];
    646 	va_list args;
    647 	int r;
    648 
    649 	va_start(args, fmt);
    650 	vsnprintf(buf, sizeof(buf), fmt, args);
    651 	va_end(args);
    652 	debug3("%s", buf);
    653 	if (auth_debug != NULL)
    654 		if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0)
    655 			fatal_fr(r, "sshbuf_put_cstring");
    656 }
    657 
    658 void
    659 auth_debug_send(struct ssh *ssh)
    660 {
    661 	char *msg;
    662 	int r;
    663 
    664 	if (auth_debug == NULL)
    665 		return;
    666 	while (sshbuf_len(auth_debug) != 0) {
    667 		if ((r = sshbuf_get_cstring(auth_debug, &msg, NULL)) != 0)
    668 			fatal_fr(r, "sshbuf_get_cstring");
    669 		ssh_packet_send_debug(ssh, "%s", msg);
    670 		free(msg);
    671 	}
    672 }
    673 
    674 void
    675 auth_debug_reset(void)
    676 {
    677 	if (auth_debug != NULL)
    678 		sshbuf_reset(auth_debug);
    679 	else if ((auth_debug = sshbuf_new()) == NULL)
    680 		fatal_f("sshbuf_new failed");
    681 }
    682 
    683 struct passwd *
    684 fakepw(void)
    685 {
    686 	static int done = 0;
    687 	static struct passwd fake;
    688 	const char hashchars[] = "./ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    689 	    "abcdefghijklmnopqrstuvwxyz0123456789"; /* from bcrypt.c */
    690 	char *cp;
    691 
    692 	if (done)
    693 		return (&fake);
    694 
    695 	memset(&fake, 0, sizeof(fake));
    696 	fake.pw_name = __UNCONST("NOUSER");
    697 	fake.pw_passwd = xstrdup("$2a$10$"
    698 	    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    699 	for (cp = fake.pw_passwd + 7; *cp != '\0'; cp++)
    700 		*cp = hashchars[arc4random_uniform(sizeof(hashchars) - 1)];
    701 	fake.pw_gecos = __UNCONST("NOUSER");
    702 	fake.pw_uid = (uid_t)-1;
    703 	fake.pw_gid = (gid_t)-1;
    704 	fake.pw_class = __UNCONST("");
    705 	fake.pw_dir = __UNCONST("/nonexist");
    706 	fake.pw_shell = __UNCONST("/nonexist");
    707 	done = 1;
    708 
    709 	return (&fake);
    710 }
    711 
    712 /*
    713  * Return the canonical name of the host in the other side of the current
    714  * connection.  The host name is cached, so it is efficient to call this
    715  * several times.
    716  */
    717 
    718 const char *
    719 auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
    720 {
    721 	static char *dnsname;
    722 
    723 	if (!use_dns)
    724 		return ssh_remote_ipaddr(ssh);
    725 	if (dnsname != NULL)
    726 		return dnsname;
    727 	dnsname = ssh_remote_hostname(ssh);
    728 	return dnsname;
    729 }
    730 
    731 /* These functions link key/cert options to the auth framework */
    732 
    733 /* Log sshauthopt options locally and (optionally) for remote transmission */
    734 void
    735 auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
    736 {
    737 	int do_env = options.permit_user_env && opts->nenv > 0;
    738 	int do_permitopen = opts->npermitopen > 0 &&
    739 	    (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0;
    740 	int do_permitlisten = opts->npermitlisten > 0 &&
    741 	    (options.allow_tcp_forwarding & FORWARD_REMOTE) != 0;
    742 	size_t i;
    743 	char msg[1024], buf[64];
    744 
    745 	snprintf(buf, sizeof(buf), "%d", opts->force_tun_device);
    746 	/* Try to keep this alphabetically sorted */
    747 	snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
    748 	    opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
    749 	    opts->force_command == NULL ? "" : " command",
    750 	    do_env ?  " environment" : "",
    751 	    opts->valid_before == 0 ? "" : "expires",
    752 	    opts->no_require_user_presence ? " no-touch-required" : "",
    753 	    do_permitopen ?  " permitopen" : "",
    754 	    do_permitlisten ?  " permitlisten" : "",
    755 	    opts->permit_port_forwarding_flag ? " port-forwarding" : "",
    756 	    opts->cert_principals == NULL ? "" : " principals",
    757 	    opts->permit_pty_flag ? " pty" : "",
    758 	    opts->require_verify ? " uv" : "",
    759 	    opts->force_tun_device == -1 ? "" : " tun=",
    760 	    opts->force_tun_device == -1 ? "" : buf,
    761 	    opts->permit_user_rc ? " user-rc" : "",
    762 	    opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");
    763 
    764 	debug("%s: %s", loc, msg);
    765 	if (do_remote)
    766 		auth_debug_add("%s: %s", loc, msg);
    767 
    768 	if (options.permit_user_env) {
    769 		for (i = 0; i < opts->nenv; i++) {
    770 			debug("%s: environment: %s", loc, opts->env[i]);
    771 			if (do_remote) {
    772 				auth_debug_add("%s: environment: %s",
    773 				    loc, opts->env[i]);
    774 			}
    775 		}
    776 	}
    777 
    778 	/* Go into a little more details for the local logs. */
    779 	if (opts->valid_before != 0) {
    780 		format_absolute_time(opts->valid_before, buf, sizeof(buf));
    781 		debug("%s: expires at %s", loc, buf);
    782 	}
    783 	if (opts->cert_principals != NULL) {
    784 		debug("%s: authorized principals: \"%s\"",
    785 		    loc, opts->cert_principals);
    786 	}
    787 	if (opts->force_command != NULL)
    788 		debug("%s: forced command: \"%s\"", loc, opts->force_command);
    789 	if (do_permitopen) {
    790 		for (i = 0; i < opts->npermitopen; i++) {
    791 			debug("%s: permitted open: %s",
    792 			    loc, opts->permitopen[i]);
    793 		}
    794 	}
    795 	if (do_permitlisten) {
    796 		for (i = 0; i < opts->npermitlisten; i++) {
    797 			debug("%s: permitted listen: %s",
    798 			    loc, opts->permitlisten[i]);
    799 		}
    800 	}
    801 }
    802 
    803 /* Activate a new set of key/cert options; merging with what is there. */
    804 int
    805 auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
    806 {
    807 	struct sshauthopt *old = auth_opts;
    808 	const char *emsg = NULL;
    809 
    810 	debug_f("setting new authentication options");
    811 	if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
    812 		error("Inconsistent authentication options: %s", emsg);
    813 		return -1;
    814 	}
    815 	sshauthopt_free(old);
    816 	return 0;
    817 }
    818 
    819 /* Disable forwarding, etc for the session */
    820 void
    821 auth_restrict_session(struct ssh *ssh)
    822 {
    823 	struct sshauthopt *restricted;
    824 
    825 	debug_f("restricting session");
    826 
    827 	/* A blank sshauthopt defaults to permitting nothing */
    828 	if ((restricted = sshauthopt_new()) == NULL)
    829 		fatal_f("sshauthopt_new failed");
    830 	restricted->permit_pty_flag = 1;
    831 	restricted->restricted = 1;
    832 
    833 	if (auth_activate_options(ssh, restricted) != 0)
    834 		fatal_f("failed to restrict session");
    835 	sshauthopt_free(restricted);
    836 }
    837