xref: /openbsd-src/usr.bin/ssh/auth2-pubkey.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /* $OpenBSD: auth2-pubkey.c,v 1.55 2016/01/27 00:53:12 djm Exp $ */
2 /*
3  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/wait.h>
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <paths.h>
34 #include <pwd.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <time.h>
40 #include <unistd.h>
41 #include <limits.h>
42 
43 #include "xmalloc.h"
44 #include "ssh.h"
45 #include "ssh2.h"
46 #include "packet.h"
47 #include "buffer.h"
48 #include "log.h"
49 #include "misc.h"
50 #include "servconf.h"
51 #include "compat.h"
52 #include "key.h"
53 #include "hostfile.h"
54 #include "auth.h"
55 #include "pathnames.h"
56 #include "uidswap.h"
57 #include "auth-options.h"
58 #include "canohost.h"
59 #ifdef GSSAPI
60 #include "ssh-gss.h"
61 #endif
62 #include "monitor_wrap.h"
63 #include "authfile.h"
64 #include "match.h"
65 #include "ssherr.h"
66 #include "channels.h" /* XXX for session.h */
67 #include "session.h" /* XXX for child_set_env(); refactor? */
68 
69 /* import */
70 extern ServerOptions options;
71 extern u_char *session_id2;
72 extern u_int session_id2_len;
73 
74 static int
75 userauth_pubkey(Authctxt *authctxt)
76 {
77 	Buffer b;
78 	Key *key = NULL;
79 	char *pkalg, *userstyle, *fp = NULL;
80 	u_char *pkblob, *sig;
81 	u_int alen, blen, slen;
82 	int have_sig, pktype;
83 	int authenticated = 0;
84 
85 	if (!authctxt->valid) {
86 		debug2("%s: disabled because of invalid user", __func__);
87 		return 0;
88 	}
89 	have_sig = packet_get_char();
90 	if (datafellows & SSH_BUG_PKAUTH) {
91 		debug2("%s: SSH_BUG_PKAUTH", __func__);
92 		/* no explicit pkalg given */
93 		pkblob = packet_get_string(&blen);
94 		buffer_init(&b);
95 		buffer_append(&b, pkblob, blen);
96 		/* so we have to extract the pkalg from the pkblob */
97 		pkalg = buffer_get_string(&b, &alen);
98 		buffer_free(&b);
99 	} else {
100 		pkalg = packet_get_string(&alen);
101 		pkblob = packet_get_string(&blen);
102 	}
103 	pktype = key_type_from_name(pkalg);
104 	if (pktype == KEY_UNSPEC) {
105 		/* this is perfectly legal */
106 		logit("%s: unsupported public key algorithm: %s",
107 		    __func__, pkalg);
108 		goto done;
109 	}
110 	key = key_from_blob(pkblob, blen);
111 	if (key == NULL) {
112 		error("%s: cannot decode key: %s", __func__, pkalg);
113 		goto done;
114 	}
115 	if (key->type != pktype) {
116 		error("%s: type mismatch for decoded key "
117 		    "(received %d, expected %d)", __func__, key->type, pktype);
118 		goto done;
119 	}
120 	if (key_type_plain(key->type) == KEY_RSA &&
121 	    (datafellows & SSH_BUG_RSASIGMD5) != 0) {
122 		logit("Refusing RSA key because client uses unsafe "
123 		    "signature scheme");
124 		goto done;
125 	}
126 	fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
127 	if (auth2_userkey_already_used(authctxt, key)) {
128 		logit("refusing previously-used %s key", key_type(key));
129 		goto done;
130 	}
131 	if (match_pattern_list(sshkey_ssh_name(key),
132 	    options.pubkey_key_types, 0) != 1) {
133 		logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
134 		    __func__, sshkey_ssh_name(key));
135 		goto done;
136 	}
137 
138 	if (have_sig) {
139 		debug3("%s: have signature for %s %s",
140 		    __func__, sshkey_type(key), fp);
141 		sig = packet_get_string(&slen);
142 		packet_check_eom();
143 		buffer_init(&b);
144 		if (datafellows & SSH_OLD_SESSIONID) {
145 			buffer_append(&b, session_id2, session_id2_len);
146 		} else {
147 			buffer_put_string(&b, session_id2, session_id2_len);
148 		}
149 		/* reconstruct packet */
150 		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
151 		xasprintf(&userstyle, "%s%s%s", authctxt->user,
152 		    authctxt->style ? ":" : "",
153 		    authctxt->style ? authctxt->style : "");
154 		buffer_put_cstring(&b, userstyle);
155 		free(userstyle);
156 		buffer_put_cstring(&b,
157 		    datafellows & SSH_BUG_PKSERVICE ?
158 		    "ssh-userauth" :
159 		    authctxt->service);
160 		if (datafellows & SSH_BUG_PKAUTH) {
161 			buffer_put_char(&b, have_sig);
162 		} else {
163 			buffer_put_cstring(&b, "publickey");
164 			buffer_put_char(&b, have_sig);
165 			buffer_put_cstring(&b, pkalg);
166 		}
167 		buffer_put_string(&b, pkblob, blen);
168 #ifdef DEBUG_PK
169 		buffer_dump(&b);
170 #endif
171 		pubkey_auth_info(authctxt, key, NULL);
172 
173 		/* test for correct signature */
174 		authenticated = 0;
175 		if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
176 		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
177 		    buffer_len(&b))) == 1) {
178 			authenticated = 1;
179 			/* Record the successful key to prevent reuse */
180 			auth2_record_userkey(authctxt, key);
181 			key = NULL; /* Don't free below */
182 		}
183 		buffer_free(&b);
184 		free(sig);
185 	} else {
186 		debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
187 		    __func__, sshkey_type(key), fp);
188 		packet_check_eom();
189 
190 		/* XXX fake reply and always send PK_OK ? */
191 		/*
192 		 * XXX this allows testing whether a user is allowed
193 		 * to login: if you happen to have a valid pubkey this
194 		 * message is sent. the message is NEVER sent at all
195 		 * if a user is not allowed to login. is this an
196 		 * issue? -markus
197 		 */
198 		if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
199 			packet_start(SSH2_MSG_USERAUTH_PK_OK);
200 			packet_put_string(pkalg, alen);
201 			packet_put_string(pkblob, blen);
202 			packet_send();
203 			packet_write_wait();
204 			authctxt->postponed = 1;
205 		}
206 	}
207 	if (authenticated != 1)
208 		auth_clear_options();
209 done:
210 	debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
211 	if (key != NULL)
212 		key_free(key);
213 	free(pkalg);
214 	free(pkblob);
215 	free(fp);
216 	return authenticated;
217 }
218 
219 void
220 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
221 {
222 	char *fp, *extra;
223 	va_list ap;
224 	int i;
225 
226 	extra = NULL;
227 	if (fmt != NULL) {
228 		va_start(ap, fmt);
229 		i = vasprintf(&extra, fmt, ap);
230 		va_end(ap);
231 		if (i < 0 || extra == NULL)
232 			fatal("%s: vasprintf failed", __func__);
233 	}
234 
235 	if (key_is_cert(key)) {
236 		fp = sshkey_fingerprint(key->cert->signature_key,
237 		    options.fingerprint_hash, SSH_FP_DEFAULT);
238 		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
239 		    key_type(key), key->cert->key_id,
240 		    (unsigned long long)key->cert->serial,
241 		    key_type(key->cert->signature_key),
242 		    fp == NULL ? "(null)" : fp,
243 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
244 		free(fp);
245 	} else {
246 		fp = sshkey_fingerprint(key, options.fingerprint_hash,
247 		    SSH_FP_DEFAULT);
248 		auth_info(authctxt, "%s %s%s%s", key_type(key),
249 		    fp == NULL ? "(null)" : fp,
250 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
251 		free(fp);
252 	}
253 	free(extra);
254 }
255 
256 /*
257  * Splits 's' into an argument vector. Handles quoted string and basic
258  * escape characters (\\, \", \'). Caller must free the argument vector
259  * and its members.
260  */
261 static int
262 split_argv(const char *s, int *argcp, char ***argvp)
263 {
264 	int r = SSH_ERR_INTERNAL_ERROR;
265 	int argc = 0, quote, i, j;
266 	char *arg, **argv = xcalloc(1, sizeof(*argv));
267 
268 	*argvp = NULL;
269 	*argcp = 0;
270 
271 	for (i = 0; s[i] != '\0'; i++) {
272 		/* Skip leading whitespace */
273 		if (s[i] == ' ' || s[i] == '\t')
274 			continue;
275 
276 		/* Start of a token */
277 		quote = 0;
278 		if (s[i] == '\\' &&
279 		    (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
280 			i++;
281 		else if (s[i] == '\'' || s[i] == '"')
282 			quote = s[i++];
283 
284 		argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
285 		arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
286 		argv[argc] = NULL;
287 
288 		/* Copy the token in, removing escapes */
289 		for (j = 0; s[i] != '\0'; i++) {
290 			if (s[i] == '\\') {
291 				if (s[i + 1] == '\'' ||
292 				    s[i + 1] == '\"' ||
293 				    s[i + 1] == '\\') {
294 					i++; /* Skip '\' */
295 					arg[j++] = s[i];
296 				} else {
297 					/* Unrecognised escape */
298 					arg[j++] = s[i];
299 				}
300 			} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
301 				break; /* done */
302 			else if (quote != 0 && s[i] == quote)
303 				break; /* done */
304 			else
305 				arg[j++] = s[i];
306 		}
307 		if (s[i] == '\0') {
308 			if (quote != 0) {
309 				/* Ran out of string looking for close quote */
310 				r = SSH_ERR_INVALID_FORMAT;
311 				goto out;
312 			}
313 			break;
314 		}
315 	}
316 	/* Success */
317 	*argcp = argc;
318 	*argvp = argv;
319 	argc = 0;
320 	argv = NULL;
321 	r = 0;
322  out:
323 	if (argc != 0 && argv != NULL) {
324 		for (i = 0; i < argc; i++)
325 			free(argv[i]);
326 		free(argv);
327 	}
328 	return r;
329 }
330 
331 /*
332  * Reassemble an argument vector into a string, quoting and escaping as
333  * necessary. Caller must free returned string.
334  */
335 static char *
336 assemble_argv(int argc, char **argv)
337 {
338 	int i, j, ws, r;
339 	char c, *ret;
340 	struct sshbuf *buf, *arg;
341 
342 	if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
343 		fatal("%s: sshbuf_new failed", __func__);
344 
345 	for (i = 0; i < argc; i++) {
346 		ws = 0;
347 		sshbuf_reset(arg);
348 		for (j = 0; argv[i][j] != '\0'; j++) {
349 			r = 0;
350 			c = argv[i][j];
351 			switch (c) {
352 			case ' ':
353 			case '\t':
354 				ws = 1;
355 				r = sshbuf_put_u8(arg, c);
356 				break;
357 			case '\\':
358 			case '\'':
359 			case '"':
360 				if ((r = sshbuf_put_u8(arg, '\\')) != 0)
361 					break;
362 				/* FALLTHROUGH */
363 			default:
364 				r = sshbuf_put_u8(arg, c);
365 				break;
366 			}
367 			if (r != 0)
368 				fatal("%s: sshbuf_put_u8: %s",
369 				    __func__, ssh_err(r));
370 		}
371 		if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
372 		    (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
373 		    (r = sshbuf_putb(buf, arg)) != 0 ||
374 		    (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
375 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
376 	}
377 	if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
378 		fatal("%s: malloc failed", __func__);
379 	memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
380 	ret[sshbuf_len(buf)] = '\0';
381 	sshbuf_free(buf);
382 	sshbuf_free(arg);
383 	return ret;
384 }
385 
386 /*
387  * Runs command in a subprocess. Returns pid on success and a FILE* to the
388  * subprocess' stdout or 0 on failure.
389  * NB. "command" is only used for logging.
390  */
391 static pid_t
392 subprocess(const char *tag, struct passwd *pw, const char *command,
393     int ac, char **av, FILE **child)
394 {
395 	FILE *f;
396 	struct stat st;
397 	int devnull, p[2], i;
398 	pid_t pid;
399 	char *cp, errmsg[512];
400 	u_int envsize;
401 	char **child_env;
402 
403 	*child = NULL;
404 
405 	debug3("%s: %s command \"%s\" running as %s", __func__,
406 	    tag, command, pw->pw_name);
407 
408 	/* Verify the path exists and is safe-ish to execute */
409 	if (*av[0] != '/') {
410 		error("%s path is not absolute", tag);
411 		return 0;
412 	}
413 	temporarily_use_uid(pw);
414 	if (stat(av[0], &st) < 0) {
415 		error("Could not stat %s \"%s\": %s", tag,
416 		    av[0], strerror(errno));
417 		restore_uid();
418 		return 0;
419 	}
420 	if (auth_secure_path(av[0], &st, NULL, 0,
421 	    errmsg, sizeof(errmsg)) != 0) {
422 		error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
423 		restore_uid();
424 		return 0;
425 	}
426 
427 	/*
428 	 * Run the command; stderr is left in place, stdout is the
429 	 * authorized_keys output.
430 	 */
431 	if (pipe(p) != 0) {
432 		error("%s: pipe: %s", tag, strerror(errno));
433 		restore_uid();
434 		return 0;
435 	}
436 
437 	/*
438 	 * Don't want to call this in the child, where it can fatal() and
439 	 * run cleanup_exit() code.
440 	 */
441 	restore_uid();
442 
443 	switch ((pid = fork())) {
444 	case -1: /* error */
445 		error("%s: fork: %s", tag, strerror(errno));
446 		close(p[0]);
447 		close(p[1]);
448 		return 0;
449 	case 0: /* child */
450 		/* Prepare a minimal environment for the child. */
451 		envsize = 5;
452 		child_env = xcalloc(sizeof(*child_env), envsize);
453 		child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
454 		child_set_env(&child_env, &envsize, "USER", pw->pw_name);
455 		child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
456 		child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
457 		if ((cp = getenv("LANG")) != NULL)
458 			child_set_env(&child_env, &envsize, "LANG", cp);
459 
460 		for (i = 0; i < NSIG; i++)
461 			signal(i, SIG_DFL);
462 
463 		if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
464 			error("%s: open %s: %s", tag, _PATH_DEVNULL,
465 			    strerror(errno));
466 			_exit(1);
467 		}
468 		/* Keep stderr around a while longer to catch errors */
469 		if (dup2(devnull, STDIN_FILENO) == -1 ||
470 		    dup2(p[1], STDOUT_FILENO) == -1) {
471 			error("%s: dup2: %s", tag, strerror(errno));
472 			_exit(1);
473 		}
474 		closefrom(STDERR_FILENO + 1);
475 
476 		/* Don't use permanently_set_uid() here to avoid fatal() */
477 		if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
478 			error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
479 			    strerror(errno));
480 			_exit(1);
481 		}
482 		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
483 			error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
484 			    strerror(errno));
485 			_exit(1);
486 		}
487 		/* stdin is pointed to /dev/null at this point */
488 		if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
489 			error("%s: dup2: %s", tag, strerror(errno));
490 			_exit(1);
491 		}
492 
493 		execve(av[0], av, child_env);
494 		error("%s exec \"%s\": %s", tag, command, strerror(errno));
495 		_exit(127);
496 	default: /* parent */
497 		break;
498 	}
499 
500 	close(p[1]);
501 	if ((f = fdopen(p[0], "r")) == NULL) {
502 		error("%s: fdopen: %s", tag, strerror(errno));
503 		close(p[0]);
504 		/* Don't leave zombie child */
505 		kill(pid, SIGTERM);
506 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
507 			;
508 		return 0;
509 	}
510 	/* Success */
511 	debug3("%s: %s pid %ld", __func__, tag, (long)pid);
512 	*child = f;
513 	return pid;
514 }
515 
516 /* Returns 0 if pid exited cleanly, non-zero otherwise */
517 static int
518 exited_cleanly(pid_t pid, const char *tag, const char *cmd)
519 {
520 	int status;
521 
522 	while (waitpid(pid, &status, 0) == -1) {
523 		if (errno != EINTR) {
524 			error("%s: waitpid: %s", tag, strerror(errno));
525 			return -1;
526 		}
527 	}
528 	if (WIFSIGNALED(status)) {
529 		error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
530 		return -1;
531 	} else if (WEXITSTATUS(status) != 0) {
532 		error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
533 		return -1;
534 	}
535 	return 0;
536 }
537 
538 static int
539 match_principals_option(const char *principal_list, struct sshkey_cert *cert)
540 {
541 	char *result;
542 	u_int i;
543 
544 	/* XXX percent_expand() sequences for authorized_principals? */
545 
546 	for (i = 0; i < cert->nprincipals; i++) {
547 		if ((result = match_list(cert->principals[i],
548 		    principal_list, NULL)) != NULL) {
549 			debug3("matched principal from key options \"%.100s\"",
550 			    result);
551 			free(result);
552 			return 1;
553 		}
554 	}
555 	return 0;
556 }
557 
558 static int
559 process_principals(FILE *f, char *file, struct passwd *pw,
560     struct sshkey_cert *cert)
561 {
562 	char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
563 	u_long linenum = 0;
564 	u_int i;
565 
566 	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
567 		/* Skip leading whitespace. */
568 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
569 			;
570 		/* Skip blank and comment lines. */
571 		if ((ep = strchr(cp, '#')) != NULL)
572 			*ep = '\0';
573 		if (!*cp || *cp == '\n')
574 			continue;
575 		/* Trim trailing whitespace. */
576 		ep = cp + strlen(cp) - 1;
577 		while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
578 			*ep-- = '\0';
579 		/*
580 		 * If the line has internal whitespace then assume it has
581 		 * key options.
582 		 */
583 		line_opts = NULL;
584 		if ((ep = strrchr(cp, ' ')) != NULL ||
585 		    (ep = strrchr(cp, '\t')) != NULL) {
586 			for (; *ep == ' ' || *ep == '\t'; ep++)
587 				;
588 			line_opts = cp;
589 			cp = ep;
590 		}
591 		for (i = 0; i < cert->nprincipals; i++) {
592 			if (strcmp(cp, cert->principals[i]) == 0) {
593 				debug3("%s:%lu: matched principal \"%.100s\"",
594 				    file == NULL ? "(command)" : file,
595 				    linenum, cert->principals[i]);
596 				if (auth_parse_options(pw, line_opts,
597 				    file, linenum) != 1)
598 					continue;
599 				return 1;
600 			}
601 		}
602 	}
603 	return 0;
604 }
605 
606 static int
607 match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
608 {
609 	FILE *f;
610 	int success;
611 
612 	temporarily_use_uid(pw);
613 	debug("trying authorized principals file %s", file);
614 	if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
615 		restore_uid();
616 		return 0;
617 	}
618 	success = process_principals(f, file, pw, cert);
619 	fclose(f);
620 	restore_uid();
621 	return success;
622 }
623 
624 /*
625  * Checks whether principal is allowed in output of command.
626  * returns 1 if the principal is allowed or 0 otherwise.
627  */
628 static int
629 match_principals_command(struct passwd *user_pw, struct sshkey_cert *cert)
630 {
631 	FILE *f = NULL;
632 	int ok, found_principal = 0;
633 	struct passwd *pw;
634 	int i, ac = 0, uid_swapped = 0;
635 	pid_t pid;
636 	char *tmp, *username = NULL, *command = NULL, **av = NULL;
637 	void (*osigchld)(int);
638 
639 	if (options.authorized_principals_command == NULL)
640 		return 0;
641 	if (options.authorized_principals_command_user == NULL) {
642 		error("No user for AuthorizedPrincipalsCommand specified, "
643 		    "skipping");
644 		return 0;
645 	}
646 
647 	/*
648 	 * NB. all returns later this function should go via "out" to
649 	 * ensure the original SIGCHLD handler is restored properly.
650 	 */
651 	osigchld = signal(SIGCHLD, SIG_DFL);
652 
653 	/* Prepare and verify the user for the command */
654 	username = percent_expand(options.authorized_principals_command_user,
655 	    "u", user_pw->pw_name, (char *)NULL);
656 	pw = getpwnam(username);
657 	if (pw == NULL) {
658 		error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
659 		    username, strerror(errno));
660 		goto out;
661 	}
662 
663 	/* Turn the command into an argument vector */
664 	if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
665 		error("AuthorizedPrincipalsCommand \"%s\" contains "
666 		    "invalid quotes", command);
667 		goto out;
668 	}
669 	if (ac == 0) {
670 		error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
671 		    command);
672 		goto out;
673 	}
674 	for (i = 1; i < ac; i++) {
675 		tmp = percent_expand(av[i],
676 		    "u", user_pw->pw_name,
677 		    "h", user_pw->pw_dir,
678 		    (char *)NULL);
679 		if (tmp == NULL)
680 			fatal("%s: percent_expand failed", __func__);
681 		free(av[i]);
682 		av[i] = tmp;
683 	}
684 	/* Prepare a printable command for logs, etc. */
685 	command = assemble_argv(ac, av);
686 
687 	if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
688 	    ac, av, &f)) == 0)
689 		goto out;
690 
691 	uid_swapped = 1;
692 	temporarily_use_uid(pw);
693 
694 	ok = process_principals(f, NULL, pw, cert);
695 
696 	if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
697 		goto out;
698 
699 	/* Read completed successfully */
700 	found_principal = ok;
701  out:
702 	if (f != NULL)
703 		fclose(f);
704 	signal(SIGCHLD, osigchld);
705 	for (i = 0; i < ac; i++)
706 		free(av[i]);
707 	free(av);
708 	if (uid_swapped)
709 		restore_uid();
710 	free(command);
711 	free(username);
712 	return found_principal;
713 }
714 /*
715  * Checks whether key is allowed in authorized_keys-format file,
716  * returns 1 if the key is allowed or 0 otherwise.
717  */
718 static int
719 check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
720 {
721 	char line[SSH_MAX_PUBKEY_BYTES];
722 	const char *reason;
723 	int found_key = 0;
724 	u_long linenum = 0;
725 	Key *found;
726 	char *fp;
727 
728 	found_key = 0;
729 
730 	found = NULL;
731 	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
732 		char *cp, *key_options = NULL;
733 		if (found != NULL)
734 			key_free(found);
735 		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
736 		auth_clear_options();
737 
738 		/* Skip leading whitespace, empty and comment lines. */
739 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
740 			;
741 		if (!*cp || *cp == '\n' || *cp == '#')
742 			continue;
743 
744 		if (key_read(found, &cp) != 1) {
745 			/* no key?  check if there are options for this key */
746 			int quoted = 0;
747 			debug2("user_key_allowed: check options: '%s'", cp);
748 			key_options = cp;
749 			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
750 				if (*cp == '\\' && cp[1] == '"')
751 					cp++;	/* Skip both */
752 				else if (*cp == '"')
753 					quoted = !quoted;
754 			}
755 			/* Skip remaining whitespace. */
756 			for (; *cp == ' ' || *cp == '\t'; cp++)
757 				;
758 			if (key_read(found, &cp) != 1) {
759 				debug2("user_key_allowed: advance: '%s'", cp);
760 				/* still no key?  advance to next line*/
761 				continue;
762 			}
763 		}
764 		if (key_is_cert(key)) {
765 			if (!key_equal(found, key->cert->signature_key))
766 				continue;
767 			if (auth_parse_options(pw, key_options, file,
768 			    linenum) != 1)
769 				continue;
770 			if (!key_is_cert_authority)
771 				continue;
772 			if ((fp = sshkey_fingerprint(found,
773 			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
774 				continue;
775 			debug("matching CA found: file %s, line %lu, %s %s",
776 			    file, linenum, key_type(found), fp);
777 			/*
778 			 * If the user has specified a list of principals as
779 			 * a key option, then prefer that list to matching
780 			 * their username in the certificate principals list.
781 			 */
782 			if (authorized_principals != NULL &&
783 			    !match_principals_option(authorized_principals,
784 			    key->cert)) {
785 				reason = "Certificate does not contain an "
786 				    "authorized principal";
787  fail_reason:
788 				free(fp);
789 				error("%s", reason);
790 				auth_debug_add("%s", reason);
791 				continue;
792 			}
793 			if (key_cert_check_authority(key, 0, 0,
794 			    authorized_principals == NULL ? pw->pw_name : NULL,
795 			    &reason) != 0)
796 				goto fail_reason;
797 			if (auth_cert_options(key, pw) != 0) {
798 				free(fp);
799 				continue;
800 			}
801 			verbose("Accepted certificate ID \"%s\" (serial %llu) "
802 			    "signed by %s CA %s via %s", key->cert->key_id,
803 			    (unsigned long long)key->cert->serial,
804 			    key_type(found), fp, file);
805 			free(fp);
806 			found_key = 1;
807 			break;
808 		} else if (key_equal(found, key)) {
809 			if (auth_parse_options(pw, key_options, file,
810 			    linenum) != 1)
811 				continue;
812 			if (key_is_cert_authority)
813 				continue;
814 			if ((fp = sshkey_fingerprint(found,
815 			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
816 				continue;
817 			debug("matching key found: file %s, line %lu %s %s",
818 			    file, linenum, key_type(found), fp);
819 			free(fp);
820 			found_key = 1;
821 			break;
822 		}
823 	}
824 	if (found != NULL)
825 		key_free(found);
826 	if (!found_key)
827 		debug2("key not found");
828 	return found_key;
829 }
830 
831 /* Authenticate a certificate key against TrustedUserCAKeys */
832 static int
833 user_cert_trusted_ca(struct passwd *pw, Key *key)
834 {
835 	char *ca_fp, *principals_file = NULL;
836 	const char *reason;
837 	int ret = 0, found_principal = 0, use_authorized_principals;
838 
839 	if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
840 		return 0;
841 
842 	if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
843 	    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
844 		return 0;
845 
846 	if (sshkey_in_file(key->cert->signature_key,
847 	    options.trusted_user_ca_keys, 1, 0) != 0) {
848 		debug2("%s: CA %s %s is not listed in %s", __func__,
849 		    key_type(key->cert->signature_key), ca_fp,
850 		    options.trusted_user_ca_keys);
851 		goto out;
852 	}
853 	/*
854 	 * If AuthorizedPrincipals is in use, then compare the certificate
855 	 * principals against the names in that file rather than matching
856 	 * against the username.
857 	 */
858 	if ((principals_file = authorized_principals_file(pw)) != NULL) {
859 		if (match_principals_file(principals_file, pw, key->cert))
860 			found_principal = 1;
861 	}
862 	/* Try querying command if specified */
863 	if (!found_principal && match_principals_command(pw, key->cert))
864 		found_principal = 1;
865 	/* If principals file or command is specified, then require a match */
866 	use_authorized_principals = principals_file != NULL ||
867             options.authorized_principals_command != NULL;
868 	if (!found_principal && use_authorized_principals) {
869 		reason = "Certificate does not contain an authorized principal";
870  fail_reason:
871 		error("%s", reason);
872 		auth_debug_add("%s", reason);
873 		goto out;
874 	}
875 	if (key_cert_check_authority(key, 0, 1,
876 	    use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
877 		goto fail_reason;
878 	if (auth_cert_options(key, pw) != 0)
879 		goto out;
880 
881 	verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
882 	    "%s CA %s via %s", key->cert->key_id,
883 	    (unsigned long long)key->cert->serial,
884 	    key_type(key->cert->signature_key), ca_fp,
885 	    options.trusted_user_ca_keys);
886 	ret = 1;
887 
888  out:
889 	free(principals_file);
890 	free(ca_fp);
891 	return ret;
892 }
893 
894 /*
895  * Checks whether key is allowed in file.
896  * returns 1 if the key is allowed or 0 otherwise.
897  */
898 static int
899 user_key_allowed2(struct passwd *pw, Key *key, char *file)
900 {
901 	FILE *f;
902 	int found_key = 0;
903 
904 	/* Temporarily use the user's uid. */
905 	temporarily_use_uid(pw);
906 
907 	debug("trying public key file %s", file);
908 	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
909 		found_key = check_authkeys_file(f, file, key, pw);
910 		fclose(f);
911 	}
912 
913 	restore_uid();
914 	return found_key;
915 }
916 
917 /*
918  * Checks whether key is allowed in output of command.
919  * returns 1 if the key is allowed or 0 otherwise.
920  */
921 static int
922 user_key_command_allowed2(struct passwd *user_pw, Key *key)
923 {
924 	FILE *f = NULL;
925 	int r, ok, found_key = 0;
926 	struct passwd *pw;
927 	int i, uid_swapped = 0, ac = 0;
928 	pid_t pid;
929 	char *username = NULL, *key_fp = NULL, *keytext = NULL;
930 	char *tmp, *command = NULL, **av = NULL;
931 	void (*osigchld)(int);
932 
933 	if (options.authorized_keys_command == NULL)
934 		return 0;
935 	if (options.authorized_keys_command_user == NULL) {
936 		error("No user for AuthorizedKeysCommand specified, skipping");
937 		return 0;
938 	}
939 
940 	/*
941 	 * NB. all returns later this function should go via "out" to
942 	 * ensure the original SIGCHLD handler is restored properly.
943 	 */
944 	osigchld = signal(SIGCHLD, SIG_DFL);
945 
946 	/* Prepare and verify the user for the command */
947 	username = percent_expand(options.authorized_keys_command_user,
948 	    "u", user_pw->pw_name, (char *)NULL);
949 	pw = getpwnam(username);
950 	if (pw == NULL) {
951 		error("AuthorizedKeysCommandUser \"%s\" not found: %s",
952 		    username, strerror(errno));
953 		goto out;
954 	}
955 
956 	/* Prepare AuthorizedKeysCommand */
957 	if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash,
958 	    SSH_FP_DEFAULT)) == NULL) {
959 		error("%s: sshkey_fingerprint failed", __func__);
960 		goto out;
961 	}
962 	if ((r = sshkey_to_base64(key, &keytext)) != 0) {
963 		error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
964 		goto out;
965 	}
966 
967 	/* Turn the command into an argument vector */
968 	if (split_argv(options.authorized_keys_command, &ac, &av) != 0) {
969 		error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
970 		    command);
971 		goto out;
972 	}
973 	if (ac == 0) {
974 		error("AuthorizedKeysCommand \"%s\" yielded no arguments",
975 		    command);
976 		goto out;
977 	}
978 	for (i = 1; i < ac; i++) {
979 		tmp = percent_expand(av[i],
980 		    "u", user_pw->pw_name,
981 		    "h", user_pw->pw_dir,
982 		    "t", sshkey_ssh_name(key),
983 		    "f", key_fp,
984 		    "k", keytext,
985 		    (char *)NULL);
986 		if (tmp == NULL)
987 			fatal("%s: percent_expand failed", __func__);
988 		free(av[i]);
989 		av[i] = tmp;
990 	}
991 	/* Prepare a printable command for logs, etc. */
992 	command = assemble_argv(ac, av);
993 
994 	/*
995 	 * If AuthorizedKeysCommand was run without arguments
996 	 * then fall back to the old behaviour of passing the
997 	 * target username as a single argument.
998 	 */
999 	if (ac == 1) {
1000 		av = xreallocarray(av, ac + 2, sizeof(*av));
1001 		av[1] = xstrdup(user_pw->pw_name);
1002 		av[2] = NULL;
1003 		/* Fix up command too, since it is used in log messages */
1004 		free(command);
1005 		xasprintf(&command, "%s %s", av[0], av[1]);
1006 	}
1007 
1008 	if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
1009 	    ac, av, &f)) == 0)
1010 		goto out;
1011 
1012 	uid_swapped = 1;
1013 	temporarily_use_uid(pw);
1014 
1015 	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
1016 
1017 	if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
1018 		goto out;
1019 
1020 	/* Read completed successfully */
1021 	found_key = ok;
1022  out:
1023 	if (f != NULL)
1024 		fclose(f);
1025 	signal(SIGCHLD, osigchld);
1026 	for (i = 0; i < ac; i++)
1027 		free(av[i]);
1028 	free(av);
1029 	if (uid_swapped)
1030 		restore_uid();
1031 	free(command);
1032 	free(username);
1033 	free(key_fp);
1034 	free(keytext);
1035 	return found_key;
1036 }
1037 
1038 /*
1039  * Check whether key authenticates and authorises the user.
1040  */
1041 int
1042 user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
1043 {
1044 	u_int success, i;
1045 	char *file;
1046 
1047 	if (auth_key_is_revoked(key))
1048 		return 0;
1049 	if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
1050 		return 0;
1051 
1052 	success = user_cert_trusted_ca(pw, key);
1053 	if (success)
1054 		return success;
1055 
1056 	success = user_key_command_allowed2(pw, key);
1057 	if (success > 0)
1058 		return success;
1059 
1060 	for (i = 0; !success && i < options.num_authkeys_files; i++) {
1061 
1062 		if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
1063 			continue;
1064 		file = expand_authorized_keys(
1065 		    options.authorized_keys_files[i], pw);
1066 
1067 		success = user_key_allowed2(pw, key, file);
1068 		free(file);
1069 	}
1070 
1071 	return success;
1072 }
1073 
1074 /* Records a public key in the list of previously-successful keys */
1075 void
1076 auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
1077 {
1078 	struct sshkey **tmp;
1079 
1080 	if (authctxt->nprev_userkeys >= INT_MAX ||
1081 	    (tmp = reallocarray(authctxt->prev_userkeys,
1082 	    authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL)
1083 		fatal("%s: reallocarray failed", __func__);
1084 	authctxt->prev_userkeys = tmp;
1085 	authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
1086 	authctxt->nprev_userkeys++;
1087 }
1088 
1089 /* Checks whether a key has already been used successfully for authentication */
1090 int
1091 auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
1092 {
1093 	u_int i;
1094 
1095 	for (i = 0; i < authctxt->nprev_userkeys; i++) {
1096 		if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
1097 			return 1;
1098 		}
1099 	}
1100 	return 0;
1101 }
1102 
1103 Authmethod method_pubkey = {
1104 	"publickey",
1105 	userauth_pubkey,
1106 	&options.pubkey_authentication
1107 };
1108