xref: /openbsd-src/usr.bin/ssh/auth2-pubkey.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert 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 
42 #include "xmalloc.h"
43 #include "ssh.h"
44 #include "ssh2.h"
45 #include "packet.h"
46 #include "buffer.h"
47 #include "log.h"
48 #include "misc.h"
49 #include "servconf.h"
50 #include "compat.h"
51 #include "key.h"
52 #include "hostfile.h"
53 #include "auth.h"
54 #include "pathnames.h"
55 #include "uidswap.h"
56 #include "auth-options.h"
57 #include "canohost.h"
58 #ifdef GSSAPI
59 #include "ssh-gss.h"
60 #endif
61 #include "monitor_wrap.h"
62 #include "authfile.h"
63 #include "match.h"
64 
65 /* import */
66 extern ServerOptions options;
67 extern u_char *session_id2;
68 extern u_int session_id2_len;
69 
70 static int
71 userauth_pubkey(Authctxt *authctxt)
72 {
73 	Buffer b;
74 	Key *key = NULL;
75 	char *pkalg, *userstyle;
76 	u_char *pkblob, *sig;
77 	u_int alen, blen, slen;
78 	int have_sig, pktype;
79 	int authenticated = 0;
80 
81 	if (!authctxt->valid) {
82 		debug2("userauth_pubkey: disabled because of invalid user");
83 		return 0;
84 	}
85 	have_sig = packet_get_char();
86 	if (datafellows & SSH_BUG_PKAUTH) {
87 		debug2("userauth_pubkey: SSH_BUG_PKAUTH");
88 		/* no explicit pkalg given */
89 		pkblob = packet_get_string(&blen);
90 		buffer_init(&b);
91 		buffer_append(&b, pkblob, blen);
92 		/* so we have to extract the pkalg from the pkblob */
93 		pkalg = buffer_get_string(&b, &alen);
94 		buffer_free(&b);
95 	} else {
96 		pkalg = packet_get_string(&alen);
97 		pkblob = packet_get_string(&blen);
98 	}
99 	pktype = key_type_from_name(pkalg);
100 	if (pktype == KEY_UNSPEC) {
101 		/* this is perfectly legal */
102 		logit("userauth_pubkey: unsupported public key algorithm: %s",
103 		    pkalg);
104 		goto done;
105 	}
106 	key = key_from_blob(pkblob, blen);
107 	if (key == NULL) {
108 		error("userauth_pubkey: cannot decode key: %s", pkalg);
109 		goto done;
110 	}
111 	if (key->type != pktype) {
112 		error("userauth_pubkey: type mismatch for decoded key "
113 		    "(received %d, expected %d)", key->type, pktype);
114 		goto done;
115 	}
116 	if (key_type_plain(key->type) == KEY_RSA &&
117 	    (datafellows & SSH_BUG_RSASIGMD5) != 0) {
118 		logit("Refusing RSA key because client uses unsafe "
119 		    "signature scheme");
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 sshkey_cert *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 sshkey_cert *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 
321 	found_key = 0;
322 
323 	found = NULL;
324 	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
325 		char *cp, *key_options = NULL;
326 		if (found != NULL)
327 			key_free(found);
328 		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
329 		auth_clear_options();
330 
331 		/* Skip leading whitespace, empty and comment lines. */
332 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
333 			;
334 		if (!*cp || *cp == '\n' || *cp == '#')
335 			continue;
336 
337 		if (key_read(found, &cp) != 1) {
338 			/* no key?  check if there are options for this key */
339 			int quoted = 0;
340 			debug2("user_key_allowed: check options: '%s'", cp);
341 			key_options = cp;
342 			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
343 				if (*cp == '\\' && cp[1] == '"')
344 					cp++;	/* Skip both */
345 				else if (*cp == '"')
346 					quoted = !quoted;
347 			}
348 			/* Skip remaining whitespace. */
349 			for (; *cp == ' ' || *cp == '\t'; cp++)
350 				;
351 			if (key_read(found, &cp) != 1) {
352 				debug2("user_key_allowed: advance: '%s'", cp);
353 				/* still no key?  advance to next line*/
354 				continue;
355 			}
356 		}
357 		if (key_is_cert(key)) {
358 			if (!key_equal(found, key->cert->signature_key))
359 				continue;
360 			if (auth_parse_options(pw, key_options, file,
361 			    linenum) != 1)
362 				continue;
363 			if (!key_is_cert_authority)
364 				continue;
365 			fp = key_fingerprint(found, SSH_FP_MD5,
366 			    SSH_FP_HEX);
367 			debug("matching CA found: file %s, line %lu, %s %s",
368 			    file, linenum, key_type(found), fp);
369 			/*
370 			 * If the user has specified a list of principals as
371 			 * a key option, then prefer that list to matching
372 			 * their username in the certificate principals list.
373 			 */
374 			if (authorized_principals != NULL &&
375 			    !match_principals_option(authorized_principals,
376 			    key->cert)) {
377 				reason = "Certificate does not contain an "
378 				    "authorized principal";
379  fail_reason:
380 				free(fp);
381 				error("%s", reason);
382 				auth_debug_add("%s", reason);
383 				continue;
384 			}
385 			if (key_cert_check_authority(key, 0, 0,
386 			    authorized_principals == NULL ? pw->pw_name : NULL,
387 			    &reason) != 0)
388 				goto fail_reason;
389 			if (auth_cert_options(key, pw) != 0) {
390 				free(fp);
391 				continue;
392 			}
393 			verbose("Accepted certificate ID \"%s\" "
394 			    "signed by %s CA %s via %s", key->cert->key_id,
395 			    key_type(found), fp, file);
396 			free(fp);
397 			found_key = 1;
398 			break;
399 		} else if (key_equal(found, key)) {
400 			if (auth_parse_options(pw, key_options, file,
401 			    linenum) != 1)
402 				continue;
403 			if (key_is_cert_authority)
404 				continue;
405 			found_key = 1;
406 			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
407 			debug("matching key found: file %s, line %lu %s %s",
408 			    file, linenum, key_type(found), fp);
409 			free(fp);
410 			break;
411 		}
412 	}
413 	if (found != NULL)
414 		key_free(found);
415 	if (!found_key)
416 		debug2("key not found");
417 	return found_key;
418 }
419 
420 /* Authenticate a certificate key against TrustedUserCAKeys */
421 static int
422 user_cert_trusted_ca(struct passwd *pw, Key *key)
423 {
424 	char *ca_fp, *principals_file = NULL;
425 	const char *reason;
426 	int ret = 0;
427 
428 	if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
429 		return 0;
430 
431 	ca_fp = key_fingerprint(key->cert->signature_key,
432 	    SSH_FP_MD5, SSH_FP_HEX);
433 
434 	if (key_in_file(key->cert->signature_key,
435 	    options.trusted_user_ca_keys, 1) != 1) {
436 		debug2("%s: CA %s %s is not listed in %s", __func__,
437 		    key_type(key->cert->signature_key), ca_fp,
438 		    options.trusted_user_ca_keys);
439 		goto out;
440 	}
441 	/*
442 	 * If AuthorizedPrincipals is in use, then compare the certificate
443 	 * principals against the names in that file rather than matching
444 	 * against the username.
445 	 */
446 	if ((principals_file = authorized_principals_file(pw)) != NULL) {
447 		if (!match_principals_file(principals_file, pw, key->cert)) {
448 			reason = "Certificate does not contain an "
449 			    "authorized principal";
450  fail_reason:
451 			error("%s", reason);
452 			auth_debug_add("%s", reason);
453 			goto out;
454 		}
455 	}
456 	if (key_cert_check_authority(key, 0, 1,
457 	    principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
458 		goto fail_reason;
459 	if (auth_cert_options(key, pw) != 0)
460 		goto out;
461 
462 	verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
463 	    key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
464 	    options.trusted_user_ca_keys);
465 	ret = 1;
466 
467  out:
468 	free(principals_file);
469 	free(ca_fp);
470 	return ret;
471 }
472 
473 /*
474  * Checks whether key is allowed in file.
475  * returns 1 if the key is allowed or 0 otherwise.
476  */
477 static int
478 user_key_allowed2(struct passwd *pw, Key *key, char *file)
479 {
480 	FILE *f;
481 	int found_key = 0;
482 
483 	/* Temporarily use the user's uid. */
484 	temporarily_use_uid(pw);
485 
486 	debug("trying public key file %s", file);
487 	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
488 		found_key = check_authkeys_file(f, file, key, pw);
489 		fclose(f);
490 	}
491 
492 	restore_uid();
493 	return found_key;
494 }
495 
496 /*
497  * Checks whether key is allowed in output of command.
498  * returns 1 if the key is allowed or 0 otherwise.
499  */
500 static int
501 user_key_command_allowed2(struct passwd *user_pw, Key *key)
502 {
503 	FILE *f;
504 	int ok, found_key = 0;
505 	struct passwd *pw;
506 	struct stat st;
507 	int status, devnull, p[2], i;
508 	pid_t pid;
509 	char *username, errmsg[512];
510 
511 	if (options.authorized_keys_command == NULL ||
512 	    options.authorized_keys_command[0] != '/')
513 		return 0;
514 
515 	if (options.authorized_keys_command_user == NULL) {
516 		error("No user for AuthorizedKeysCommand specified, skipping");
517 		return 0;
518 	}
519 
520 	username = percent_expand(options.authorized_keys_command_user,
521 	    "u", user_pw->pw_name, (char *)NULL);
522 	pw = getpwnam(username);
523 	if (pw == NULL) {
524 		error("AuthorizedKeysCommandUser \"%s\" not found: %s",
525 		    username, strerror(errno));
526 		free(username);
527 		return 0;
528 	}
529 	free(username);
530 
531 	temporarily_use_uid(pw);
532 
533 	if (stat(options.authorized_keys_command, &st) < 0) {
534 		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
535 		    options.authorized_keys_command, strerror(errno));
536 		goto out;
537 	}
538 	if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
539 	    errmsg, sizeof(errmsg)) != 0) {
540 		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
541 		goto out;
542 	}
543 
544 	if (pipe(p) != 0) {
545 		error("%s: pipe: %s", __func__, strerror(errno));
546 		goto out;
547 	}
548 
549 	debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
550 	    options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
551 
552 	/*
553 	 * Don't want to call this in the child, where it can fatal() and
554 	 * run cleanup_exit() code.
555 	 */
556 	restore_uid();
557 
558 	switch ((pid = fork())) {
559 	case -1: /* error */
560 		error("%s: fork: %s", __func__, strerror(errno));
561 		close(p[0]);
562 		close(p[1]);
563 		return 0;
564 	case 0: /* child */
565 		for (i = 0; i < NSIG; i++)
566 			signal(i, SIG_DFL);
567 
568 		if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
569 			error("%s: open %s: %s", __func__, _PATH_DEVNULL,
570 			    strerror(errno));
571 			_exit(1);
572 		}
573 		/* Keep stderr around a while longer to catch errors */
574 		if (dup2(devnull, STDIN_FILENO) == -1 ||
575 		    dup2(p[1], STDOUT_FILENO) == -1) {
576 			error("%s: dup2: %s", __func__, strerror(errno));
577 			_exit(1);
578 		}
579 		closefrom(STDERR_FILENO + 1);
580 
581 		/* Don't use permanently_set_uid() here to avoid fatal() */
582 		if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
583 			error("setresgid %u: %s", (u_int)pw->pw_gid,
584 			    strerror(errno));
585 			_exit(1);
586 		}
587 		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
588 			error("setresuid %u: %s", (u_int)pw->pw_uid,
589 			    strerror(errno));
590 			_exit(1);
591 		}
592 		/* stdin is pointed to /dev/null at this point */
593 		if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
594 			error("%s: dup2: %s", __func__, strerror(errno));
595 			_exit(1);
596 		}
597 
598 		execl(options.authorized_keys_command,
599 		    options.authorized_keys_command, user_pw->pw_name, NULL);
600 
601 		error("AuthorizedKeysCommand %s exec failed: %s",
602 		    options.authorized_keys_command, strerror(errno));
603 		_exit(127);
604 	default: /* parent */
605 		break;
606 	}
607 
608 	temporarily_use_uid(pw);
609 
610 	close(p[1]);
611 	if ((f = fdopen(p[0], "r")) == NULL) {
612 		error("%s: fdopen: %s", __func__, strerror(errno));
613 		close(p[0]);
614 		/* Don't leave zombie child */
615 		kill(pid, SIGTERM);
616 		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
617 			;
618 		goto out;
619 	}
620 	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
621 	fclose(f);
622 
623 	while (waitpid(pid, &status, 0) == -1) {
624 		if (errno != EINTR) {
625 			error("%s: waitpid: %s", __func__, strerror(errno));
626 			goto out;
627 		}
628 	}
629 	if (WIFSIGNALED(status)) {
630 		error("AuthorizedKeysCommand %s exited on signal %d",
631 		    options.authorized_keys_command, WTERMSIG(status));
632 		goto out;
633 	} else if (WEXITSTATUS(status) != 0) {
634 		error("AuthorizedKeysCommand %s returned status %d",
635 		    options.authorized_keys_command, WEXITSTATUS(status));
636 		goto out;
637 	}
638 	found_key = ok;
639  out:
640 	restore_uid();
641 	return found_key;
642 }
643 
644 /*
645  * Check whether key authenticates and authorises the user.
646  */
647 int
648 user_key_allowed(struct passwd *pw, Key *key)
649 {
650 	u_int success, i;
651 	char *file;
652 
653 	if (auth_key_is_revoked(key))
654 		return 0;
655 	if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
656 		return 0;
657 
658 	success = user_cert_trusted_ca(pw, key);
659 	if (success)
660 		return success;
661 
662 	success = user_key_command_allowed2(pw, key);
663 	if (success > 0)
664 		return success;
665 
666 	for (i = 0; !success && i < options.num_authkeys_files; i++) {
667 
668 		if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
669 			continue;
670 		file = expand_authorized_keys(
671 		    options.authorized_keys_files[i], pw);
672 
673 		success = user_key_allowed2(pw, key, file);
674 		free(file);
675 	}
676 
677 	return success;
678 }
679 
680 Authmethod method_pubkey = {
681 	"publickey",
682 	userauth_pubkey,
683 	&options.pubkey_authentication
684 };
685