xref: /netbsd-src/crypto/external/bsd/openssh/dist/auth2-pubkey.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: auth2-pubkey.c,v 1.9 2013/11/08 19:18:24 christos Exp $	*/
2 /* $OpenBSD: auth2-pubkey.c,v 1.38 2013/06/21 00:34:49 djm Exp $ */
3 /*
4  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "includes.h"
28 __RCSID("$NetBSD: auth2-pubkey.c,v 1.9 2013/11/08 19:18:24 christos Exp $");
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32 
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <paths.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 
44 #include "xmalloc.h"
45 #include "ssh.h"
46 #include "ssh2.h"
47 #include "packet.h"
48 #include "buffer.h"
49 #include "log.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 "misc.h"
64 #include "authfile.h"
65 #include "match.h"
66 
67 #ifdef WITH_LDAP_PUBKEY
68 #include "ldapauth.h"
69 #endif
70 
71 /* import */
72 extern ServerOptions options;
73 extern u_char *session_id2;
74 extern u_int session_id2_len;
75 
76 static int
77 userauth_pubkey(Authctxt *authctxt)
78 {
79 	Buffer b;
80 	Key *key = NULL;
81 	char *pkalg, *userstyle;
82 	u_char *pkblob, *sig;
83 	u_int alen, blen, slen;
84 	int have_sig, pktype;
85 	int authenticated = 0;
86 
87 	if (!authctxt->valid) {
88 		debug2("userauth_pubkey: disabled because of invalid user");
89 		return 0;
90 	}
91 	have_sig = packet_get_char();
92 	if (datafellows & SSH_BUG_PKAUTH) {
93 		debug2("userauth_pubkey: SSH_BUG_PKAUTH");
94 		/* no explicit pkalg given */
95 		pkblob = packet_get_string(&blen);
96 		buffer_init(&b);
97 		buffer_append(&b, pkblob, blen);
98 		/* so we have to extract the pkalg from the pkblob */
99 		pkalg = buffer_get_string(&b, &alen);
100 		buffer_free(&b);
101 	} else {
102 		pkalg = packet_get_string(&alen);
103 		pkblob = packet_get_string(&blen);
104 	}
105 	pktype = key_type_from_name(pkalg);
106 	if (pktype == KEY_UNSPEC) {
107 		/* this is perfectly legal */
108 		logit("userauth_pubkey: unsupported public key algorithm: %s",
109 		    pkalg);
110 		goto done;
111 	}
112 	key = key_from_blob(pkblob, blen);
113 	if (key == NULL) {
114 		error("userauth_pubkey: cannot decode key: %s", pkalg);
115 		goto done;
116 	}
117 	if (key->type != pktype) {
118 		error("userauth_pubkey: type mismatch for decoded key "
119 		    "(received %d, expected %d)", key->type, pktype);
120 		goto done;
121 	}
122 	if (have_sig) {
123 		sig = packet_get_string(&slen);
124 		packet_check_eom();
125 		buffer_init(&b);
126 		if (datafellows & SSH_OLD_SESSIONID) {
127 			buffer_append(&b, session_id2, session_id2_len);
128 		} else {
129 			buffer_put_string(&b, session_id2, session_id2_len);
130 		}
131 		/* reconstruct packet */
132 		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
133 		xasprintf(&userstyle, "%s%s%s", authctxt->user,
134 		    authctxt->style ? ":" : "",
135 		    authctxt->style ? authctxt->style : "");
136 		buffer_put_cstring(&b, userstyle);
137 		free(userstyle);
138 		buffer_put_cstring(&b,
139 		    datafellows & SSH_BUG_PKSERVICE ?
140 		    "ssh-userauth" :
141 		    authctxt->service);
142 		if (datafellows & SSH_BUG_PKAUTH) {
143 			buffer_put_char(&b, have_sig);
144 		} else {
145 			buffer_put_cstring(&b, "publickey");
146 			buffer_put_char(&b, have_sig);
147 			buffer_put_cstring(&b, pkalg);
148 		}
149 		buffer_put_string(&b, pkblob, blen);
150 #ifdef DEBUG_PK
151 		buffer_dump(&b);
152 #endif
153 		pubkey_auth_info(authctxt, key, NULL);
154 
155 		/* test for correct signature */
156 		authenticated = 0;
157 		if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
158 		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
159 		    buffer_len(&b))) == 1)
160 			authenticated = 1;
161 		buffer_free(&b);
162 		free(sig);
163 	} else {
164 		debug("test whether pkalg/pkblob are acceptable");
165 		packet_check_eom();
166 
167 		/* XXX fake reply and always send PK_OK ? */
168 		/*
169 		 * XXX this allows testing whether a user is allowed
170 		 * to login: if you happen to have a valid pubkey this
171 		 * message is sent. the message is NEVER sent at all
172 		 * if a user is not allowed to login. is this an
173 		 * issue? -markus
174 		 */
175 		if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
176 			packet_start(SSH2_MSG_USERAUTH_PK_OK);
177 			packet_put_string(pkalg, alen);
178 			packet_put_string(pkblob, blen);
179 			packet_send();
180 			packet_write_wait();
181 			authctxt->postponed = 1;
182 		}
183 	}
184 	if (authenticated != 1)
185 		auth_clear_options();
186 done:
187 	debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
188 	if (key != NULL)
189 		key_free(key);
190 	free(pkalg);
191 	free(pkblob);
192 	return authenticated;
193 }
194 
195 void
196 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
197 {
198 	char *fp, *extra;
199 	va_list ap;
200 	int i;
201 
202 	extra = NULL;
203 	if (fmt != NULL) {
204 		va_start(ap, fmt);
205 		i = vasprintf(&extra, fmt, ap);
206 		va_end(ap);
207 		if (i < 0 || extra == NULL)
208 			fatal("%s: vasprintf failed", __func__);
209 	}
210 
211 	if (key_is_cert(key)) {
212 		fp = key_fingerprint(key->cert->signature_key,
213 		    SSH_FP_MD5, SSH_FP_HEX);
214 		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
215 		    key_type(key), key->cert->key_id,
216 		    (unsigned long long)key->cert->serial,
217 		    key_type(key->cert->signature_key), fp,
218 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
219 		free(fp);
220 	} else {
221 		fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
222 		auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
223 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
224 		free(fp);
225 	}
226 	free(extra);
227 }
228 
229 static int
230 match_principals_option(const char *principal_list, struct KeyCert *cert)
231 {
232 	char *result;
233 	u_int i;
234 
235 	/* XXX percent_expand() sequences for authorized_principals? */
236 
237 	for (i = 0; i < cert->nprincipals; i++) {
238 		if ((result = match_list(cert->principals[i],
239 		    principal_list, NULL)) != NULL) {
240 			debug3("matched principal from key options \"%.100s\"",
241 			    result);
242 			free(result);
243 			return 1;
244 		}
245 	}
246 	return 0;
247 }
248 
249 static int
250 match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
251 {
252 	FILE *f;
253 	char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
254 	u_long linenum = 0;
255 	u_int i;
256 
257 	temporarily_use_uid(pw);
258 	debug("trying authorized principals file %s", file);
259 	if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
260 		restore_uid();
261 		return 0;
262 	}
263 	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
264 		/* Skip leading whitespace. */
265 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
266 			;
267 		/* Skip blank and comment lines. */
268 		if ((ep = strchr(cp, '#')) != NULL)
269 			*ep = '\0';
270 		if (!*cp || *cp == '\n')
271 			continue;
272 		/* Trim trailing whitespace. */
273 		ep = cp + strlen(cp) - 1;
274 		while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
275 			*ep-- = '\0';
276 		/*
277 		 * If the line has internal whitespace then assume it has
278 		 * key options.
279 		 */
280 		line_opts = NULL;
281 		if ((ep = strrchr(cp, ' ')) != NULL ||
282 		    (ep = strrchr(cp, '\t')) != NULL) {
283 			for (; *ep == ' ' || *ep == '\t'; ep++)
284 				;
285 			line_opts = cp;
286 			cp = ep;
287 		}
288 		for (i = 0; i < cert->nprincipals; i++) {
289 			if (strcmp(cp, cert->principals[i]) == 0) {
290 				debug3("matched principal \"%.100s\" "
291 				    "from file \"%s\" on line %lu",
292 				    cert->principals[i], file, linenum);
293 				if (auth_parse_options(pw, line_opts,
294 				    file, linenum) != 1)
295 					continue;
296 				fclose(f);
297 				restore_uid();
298 				return 1;
299 			}
300 		}
301 	}
302 	fclose(f);
303 	restore_uid();
304 	return 0;
305 }
306 
307 /*
308  * Checks whether key is allowed in authorized_keys-format file,
309  * returns 1 if the key is allowed or 0 otherwise.
310  */
311 static int
312 check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
313 {
314 	char line[SSH_MAX_PUBKEY_BYTES];
315 	const char *reason;
316 	int found_key = 0;
317 	u_long linenum = 0;
318 	Key *found;
319 	char *fp;
320 #ifdef WITH_LDAP_PUBKEY
321 	ldap_key_t * k;
322 	unsigned int i = 0;
323 #endif
324 
325 #ifdef WITH_LDAP_PUBKEY
326 	found_key = 0;
327 	/* allocate a new key type */
328 	found = key_new(key->type);
329 
330 	/* first check if the options is enabled, then try.. */
331 	if (options.lpk.on) {
332 	    debug("[LDAP] trying LDAP first uid=%s",pw->pw_name);
333 	    if (ldap_ismember(&options.lpk, pw->pw_name) > 0) {
334 		if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
335 		    /* Skip leading whitespace, empty and comment lines. */
336 		    for (i = 0 ; i < k->num ; i++) {
337 			/* dont forget if multiple keys to reset options */
338 			char *cp, *xoptions = NULL;
339 
340 			for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
341 			    ;
342 			if (!*cp || *cp == '\n' || *cp == '#')
343 			    continue;
344 
345 			if (key_read(found, &cp) != 1) {
346 			    /* no key?  check if there are options for this key */
347 			    int quoted = 0;
348 			    debug2("[LDAP] user_key_allowed: check options: '%s'", cp);
349 			    xoptions = cp;
350 			    for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
351 				if (*cp == '\\' && cp[1] == '"')
352 				    cp++;	/* Skip both */
353 				else if (*cp == '"')
354 				    quoted = !quoted;
355 			    }
356 			    /* Skip remaining whitespace. */
357 			    for (; *cp == ' ' || *cp == '\t'; cp++)
358 				;
359 			    if (key_read(found, &cp) != 1) {
360 				debug2("[LDAP] user_key_allowed: advance: '%s'", cp);
361 				/* still no key?  advance to next line*/
362 				continue;
363 			    }
364 			}
365 
366 			if (key_equal(found, key) &&
367 				auth_parse_options(pw, xoptions, file, linenum) == 1) {
368 			    found_key = 1;
369 			    debug("[LDAP] matching key found");
370 			    fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
371 			    verbose("[LDAP] Found matching %s key: %s", key_type(found), fp);
372 
373 			    /* restoring memory */
374 			    ldap_keys_free(k);
375 			    free(fp);
376 			    restore_uid();
377 			    key_free(found);
378 			    return found_key;
379 			    break;
380 			}
381 		    }/* end of LDAP for() */
382 		} else {
383 		    logit("[LDAP] no keys found for '%s'!", pw->pw_name);
384 		}
385 	    } else {
386 		logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
387 	    }
388 	}
389 #endif
390 	debug("trying public key file %s", file);
391 	f = auth_openkeyfile(file, pw, options.strict_modes);
392 
393 	if (!f) {
394 		restore_uid();
395 		return 0;
396 	}
397 
398 	found_key = 0;
399 
400 	found = NULL;
401 	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
402 		char *cp, *key_options = NULL;
403 		if (found != NULL)
404 			key_free(found);
405 		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
406 		auth_clear_options();
407 
408 		/* Skip leading whitespace, empty and comment lines. */
409 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
410 			;
411 		if (!*cp || *cp == '\n' || *cp == '#')
412 			continue;
413 
414 		if (key_read(found, &cp) != 1) {
415 			/* no key?  check if there are options for this key */
416 			int quoted = 0;
417 			debug2("user_key_allowed: check options: '%s'", cp);
418 			key_options = cp;
419 			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
420 				if (*cp == '\\' && cp[1] == '"')
421 					cp++;	/* Skip both */
422 				else if (*cp == '"')
423 					quoted = !quoted;
424 			}
425 			/* Skip remaining whitespace. */
426 			for (; *cp == ' ' || *cp == '\t'; cp++)
427 				;
428 			if (key_read(found, &cp) != 1) {
429 				debug2("user_key_allowed: advance: '%s'", cp);
430 				/* still no key?  advance to next line*/
431 				continue;
432 			}
433 		}
434 		if (key_is_cert(key)) {
435 			if (!key_equal(found, key->cert->signature_key))
436 				continue;
437 			if (auth_parse_options(pw, key_options, file,
438 			    linenum) != 1)
439 				continue;
440 			if (!key_is_cert_authority)
441 				continue;
442 			fp = key_fingerprint(found, SSH_FP_MD5,
443 			    SSH_FP_HEX);
444 			debug("matching CA found: file %s, line %lu, %s %s",
445 			    file, linenum, key_type(found), fp);
446 			/*
447 			 * If the user has specified a list of principals as
448 			 * a key option, then prefer that list to matching
449 			 * their username in the certificate principals list.
450 			 */
451 			if (authorized_principals != NULL &&
452 			    !match_principals_option(authorized_principals,
453 			    key->cert)) {
454 				reason = "Certificate does not contain an "
455 				    "authorized principal";
456  fail_reason:
457 				free(fp);
458 				error("%s", reason);
459 				auth_debug_add("%s", reason);
460 				continue;
461 			}
462 			if (key_cert_check_authority(key, 0, 0,
463 			    authorized_principals == NULL ? pw->pw_name : NULL,
464 			    &reason) != 0)
465 				goto fail_reason;
466 			if (auth_cert_options(key, pw) != 0) {
467 				free(fp);
468 				continue;
469 			}
470 			verbose("Accepted certificate ID \"%s\" "
471 			    "signed by %s CA %s via %s", key->cert->key_id,
472 			    key_type(found), fp, file);
473 			free(fp);
474 			found_key = 1;
475 			break;
476 		} else if (key_equal(found, key)) {
477 			if (auth_parse_options(pw, key_options, file,
478 			    linenum) != 1)
479 				continue;
480 			if (key_is_cert_authority)
481 				continue;
482 			found_key = 1;
483 			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
484 			debug("matching key found: file %s, line %lu %s %s",
485 			    file, linenum, key_type(found), fp);
486 			free(fp);
487 			break;
488 		}
489 	}
490 	if (found != NULL)
491 		key_free(found);
492 	if (!found_key)
493 		debug2("key not found");
494 	return found_key;
495 }
496 
497 /* Authenticate a certificate key against TrustedUserCAKeys */
498 static int
499 user_cert_trusted_ca(struct passwd *pw, Key *key)
500 {
501 	char *ca_fp, *principals_file = NULL;
502 	const char *reason;
503 	int ret = 0;
504 
505 	if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
506 		return 0;
507 
508 	ca_fp = key_fingerprint(key->cert->signature_key,
509 	    SSH_FP_MD5, SSH_FP_HEX);
510 
511 	if (key_in_file(key->cert->signature_key,
512 	    options.trusted_user_ca_keys, 1) != 1) {
513 		debug2("%s: CA %s %s is not listed in %s", __func__,
514 		    key_type(key->cert->signature_key), ca_fp,
515 		    options.trusted_user_ca_keys);
516 		goto out;
517 	}
518 	/*
519 	 * If AuthorizedPrincipals is in use, then compare the certificate
520 	 * principals against the names in that file rather than matching
521 	 * against the username.
522 	 */
523 	if ((principals_file = authorized_principals_file(pw)) != NULL) {
524 		if (!match_principals_file(principals_file, pw, key->cert)) {
525 			reason = "Certificate does not contain an "
526 			    "authorized principal";
527  fail_reason:
528 			error("%s", reason);
529 			auth_debug_add("%s", reason);
530 			goto out;
531 		}
532 	}
533 	if (key_cert_check_authority(key, 0, 1,
534 	    principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
535 		goto fail_reason;
536 	if (auth_cert_options(key, pw) != 0)
537 		goto out;
538 
539 	verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
540 	    key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
541 	    options.trusted_user_ca_keys);
542 	ret = 1;
543 
544  out:
545 	free(principals_file);
546 	free(ca_fp);
547 	return ret;
548 }
549 
550 /*
551  * Checks whether key is allowed in file.
552  * returns 1 if the key is allowed or 0 otherwise.
553  */
554 static int
555 user_key_allowed2(struct passwd *pw, Key *key, char *file)
556 {
557 	FILE *f;
558 	int found_key = 0;
559 
560 	/* Temporarily use the user's uid. */
561 	temporarily_use_uid(pw);
562 
563 	debug("trying public key file %s", file);
564 	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
565 		found_key = check_authkeys_file(f, file, key, pw);
566 		fclose(f);
567 	}
568 
569 	restore_uid();
570 	return found_key;
571 }
572 
573 /*
574  * Checks whether key is allowed in output of command.
575  * returns 1 if the key is allowed or 0 otherwise.
576  */
577 static int
578 user_key_command_allowed2(struct passwd *user_pw, Key *key)
579 {
580 	FILE *f;
581 	int ok, found_key = 0;
582 	struct passwd *pw;
583 	struct stat st;
584 	int status, devnull, p[2], i;
585 	pid_t pid;
586 	char *username, errmsg[512];
587 
588 	if (options.authorized_keys_command == NULL ||
589 	    options.authorized_keys_command[0] != '/')
590 		return 0;
591 
592 	if (options.authorized_keys_command_user == NULL) {
593 		error("No user for AuthorizedKeysCommand specified, skipping");
594 		return 0;
595 	}
596 
597 	username = percent_expand(options.authorized_keys_command_user,
598 	    "u", user_pw->pw_name, (char *)NULL);
599 	pw = getpwnam(username);
600 	if (pw == NULL) {
601 		error("AuthorizedKeysCommandUser \"%s\" not found: %s",
602 		    username, strerror(errno));
603 		free(username);
604 		return 0;
605 	}
606 	free(username);
607 
608 	temporarily_use_uid(pw);
609 
610 	if (stat(options.authorized_keys_command, &st) < 0) {
611 		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
612 		    options.authorized_keys_command, strerror(errno));
613 		goto out;
614 	}
615 	if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
616 	    errmsg, sizeof(errmsg)) != 0) {
617 		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
618 		goto out;
619 	}
620 
621 	if (pipe(p) != 0) {
622 		error("%s: pipe: %s", __func__, strerror(errno));
623 		goto out;
624 	}
625 
626 	debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
627 	    options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
628 
629 	/*
630 	 * Don't want to call this in the child, where it can fatal() and
631 	 * run cleanup_exit() code.
632 	 */
633 	restore_uid();
634 
635 	switch ((pid = fork())) {
636 	case -1: /* error */
637 		error("%s: fork: %s", __func__, strerror(errno));
638 		close(p[0]);
639 		close(p[1]);
640 		return 0;
641 	case 0: /* child */
642 		for (i = 0; i < NSIG; i++)
643 			signal(i, SIG_DFL);
644 
645 		if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
646 			error("%s: open %s: %s", __func__, _PATH_DEVNULL,
647 			    strerror(errno));
648 			_exit(1);
649 		}
650 		/* Keep stderr around a while longer to catch errors */
651 		if (dup2(devnull, STDIN_FILENO) == -1 ||
652 		    dup2(p[1], STDOUT_FILENO) == -1) {
653 			error("%s: dup2: %s", __func__, strerror(errno));
654 			_exit(1);
655 		}
656 		closefrom(STDERR_FILENO + 1);
657 
658 		/* Don't use permanently_set_uid() here to avoid fatal() */
659 		if (setgid(pw->pw_gid) != 0) {
660 			error("setgid %u: %s", (u_int)pw->pw_gid,
661 			    strerror(errno));
662 			_exit(1);
663 		}
664 		if (setuid(pw->pw_uid) != 0) {
665 			error("setuid %u: %s", (u_int)pw->pw_uid,
666 			    strerror(errno));
667 			_exit(1);
668 		}
669 		/* stdin is pointed to /dev/null at this point */
670 		if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
671 			error("%s: dup2: %s", __func__, strerror(errno));
672 			_exit(1);
673 		}
674 
675 		execl(options.authorized_keys_command,
676 		    options.authorized_keys_command, user_pw->pw_name, NULL);
677 
678 		error("AuthorizedKeysCommand %s exec failed: %s",
679 		    options.authorized_keys_command, strerror(errno));
680 		_exit(127);
681 	default: /* parent */
682 		break;
683 	}
684 
685 	temporarily_use_uid(pw);
686 
687 	close(p[1]);
688 	if ((f = fdopen(p[0], "r")) == NULL) {
689 		error("%s: fdopen: %s", __func__, strerror(errno));
690 		close(p[0]);
691 		/* Don't leave zombie child */
692 		kill(pid, SIGTERM);
693 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
694 			;
695 		goto out;
696 	}
697 	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
698 	fclose(f);
699 
700 	while (waitpid(pid, &status, 0) == -1) {
701 		if (errno != EINTR) {
702 			error("%s: waitpid: %s", __func__, strerror(errno));
703 			goto out;
704 		}
705 	}
706 	if (WIFSIGNALED(status)) {
707 		error("AuthorizedKeysCommand %s exited on signal %d",
708 		    options.authorized_keys_command, WTERMSIG(status));
709 		goto out;
710 	} else if (WEXITSTATUS(status) != 0) {
711 		error("AuthorizedKeysCommand %s returned status %d",
712 		    options.authorized_keys_command, WEXITSTATUS(status));
713 		goto out;
714 	}
715 	found_key = ok;
716  out:
717 	restore_uid();
718 	return found_key;
719 }
720 
721 /*
722  * Check whether key authenticates and authorises the user.
723  */
724 int
725 user_key_allowed(struct passwd *pw, Key *key)
726 {
727 	u_int success, i;
728 	char *file;
729 
730 	if (auth_key_is_revoked(key))
731 		return 0;
732 	if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
733 		return 0;
734 
735 	success = user_cert_trusted_ca(pw, key);
736 	if (success)
737 		return success;
738 
739 	success = user_key_command_allowed2(pw, key);
740 	if (success > 0)
741 		return success;
742 
743 	for (i = 0; !success && i < options.num_authkeys_files; i++) {
744 
745 		if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
746 			continue;
747 		file = expand_authorized_keys(
748 		    options.authorized_keys_files[i], pw);
749 
750 		success = user_key_allowed2(pw, key, file);
751 		free(file);
752 	}
753 
754 	return success;
755 }
756 
757 Authmethod method_pubkey = {
758 	"publickey",
759 	userauth_pubkey,
760 	&options.pubkey_authentication
761 };
762