1 /* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */
3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include <sys/types.h>
57 #include "pathnames.h"
59 #include "auth-options.h"
64 #include "monitor_wrap.h"
68 #include "channels.h" /* XXX for session.h */
69 #include "session.h" /* XXX for child_set_env(); refactor? */
72 extern ServerOptions options
;
73 extern u_char
*session_id2
;
74 extern u_int session_id2_len
;
77 userauth_pubkey(struct ssh
*ssh
)
79 Authctxt
*authctxt
= ssh
->authctxt
;
81 struct sshkey
*key
= NULL
;
82 char *pkalg
, *userstyle
= NULL
, *fp
= NULL
;
83 u_char
*pkblob
, *sig
, have_sig
;
86 int authenticated
= 0;
88 if (!authctxt
->valid
) {
89 debug2("%s: disabled because of invalid user", __func__
);
92 if ((r
= sshpkt_get_u8(ssh
, &have_sig
)) != 0)
93 fatal("%s: sshpkt_get_u8 failed: %s", __func__
, ssh_err(r
));
94 if (ssh
->compat
& SSH_BUG_PKAUTH
) {
95 debug2("%s: SSH_BUG_PKAUTH", __func__
);
96 if ((b
= sshbuf_new()) == NULL
)
97 fatal("%s: sshbuf_new failed", __func__
);
98 /* no explicit pkalg given */
99 /* so we have to extract the pkalg from the pkblob */
100 /* XXX use sshbuf_from() */
101 if ((r
= sshpkt_get_string(ssh
, &pkblob
, &blen
)) != 0 ||
102 (r
= sshbuf_put(b
, pkblob
, blen
)) != 0 ||
103 (r
= sshbuf_get_cstring(b
, &pkalg
, NULL
)) != 0)
104 fatal("%s: failed: %s", __func__
, ssh_err(r
));
107 if ((r
= sshpkt_get_cstring(ssh
, &pkalg
, NULL
)) != 0 ||
108 (r
= sshpkt_get_string(ssh
, &pkblob
, &blen
)) != 0)
109 fatal("%s: sshpkt_get_cstring failed: %s",
110 __func__
, ssh_err(r
));
112 pktype
= sshkey_type_from_name(pkalg
);
113 if (pktype
== KEY_UNSPEC
) {
114 /* this is perfectly legal */
115 logit("%s: unsupported public key algorithm: %s",
119 if ((r
= sshkey_from_blob(pkblob
, blen
, &key
)) != 0) {
120 error("%s: could not parse key: %s", __func__
, ssh_err(r
));
124 error("%s: cannot decode key: %s", __func__
, pkalg
);
127 if (key
->type
!= pktype
) {
128 error("%s: type mismatch for decoded key "
129 "(received %d, expected %d)", __func__
, key
->type
, pktype
);
132 if (sshkey_type_plain(key
->type
) == KEY_RSA
&&
133 (ssh
->compat
& SSH_BUG_RSASIGMD5
) != 0) {
134 logit("Refusing RSA key because client uses unsafe "
138 fp
= sshkey_fingerprint(key
, options
.fingerprint_hash
, SSH_FP_DEFAULT
);
139 if (auth2_key_already_used(authctxt
, key
)) {
140 logit("refusing previously-used %s key", sshkey_type(key
));
143 if (match_pattern_list(sshkey_ssh_name(key
),
144 options
.pubkey_key_types
, 0) != 1) {
145 logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
146 __func__
, sshkey_ssh_name(key
));
151 debug3("%s: have signature for %s %s",
152 __func__
, sshkey_type(key
), fp
);
153 if ((r
= sshpkt_get_string(ssh
, &sig
, &slen
)) != 0 ||
154 (r
= sshpkt_get_end(ssh
)) != 0)
155 fatal("%s: %s", __func__
, ssh_err(r
));
156 if ((b
= sshbuf_new()) == NULL
)
157 fatal("%s: sshbuf_new failed", __func__
);
158 if (ssh
->compat
& SSH_OLD_SESSIONID
) {
159 if ((r
= sshbuf_put(b
, session_id2
,
160 session_id2_len
)) != 0)
161 fatal("%s: sshbuf_put session id: %s",
162 __func__
, ssh_err(r
));
164 if ((r
= sshbuf_put_string(b
, session_id2
,
165 session_id2_len
)) != 0)
166 fatal("%s: sshbuf_put_string session id: %s",
167 __func__
, ssh_err(r
));
169 /* reconstruct packet */
170 xasprintf(&userstyle
, "%s%s%s", authctxt
->user
,
171 authctxt
->style
? ":" : "",
172 authctxt
->style
? authctxt
->style
: "");
173 if ((r
= sshbuf_put_u8(b
, SSH2_MSG_USERAUTH_REQUEST
)) != 0 ||
174 (r
= sshbuf_put_cstring(b
, userstyle
)) != 0 ||
175 (r
= sshbuf_put_cstring(b
, ssh
->compat
& SSH_BUG_PKSERVICE
?
176 "ssh-userauth" : authctxt
->service
)) != 0)
177 fatal("%s: build packet failed: %s",
178 __func__
, ssh_err(r
));
179 if (ssh
->compat
& SSH_BUG_PKAUTH
) {
180 if ((r
= sshbuf_put_u8(b
, have_sig
)) != 0)
181 fatal("%s: build packet failed: %s",
182 __func__
, ssh_err(r
));
184 if ((r
= sshbuf_put_cstring(b
, "publickey")) != 0 ||
185 (r
= sshbuf_put_u8(b
, have_sig
)) != 0 ||
186 (r
= sshbuf_put_cstring(b
, pkalg
) != 0))
187 fatal("%s: build packet failed: %s",
188 __func__
, ssh_err(r
));
190 if ((r
= sshbuf_put_string(b
, pkblob
, blen
)) != 0)
191 fatal("%s: build packet failed: %s",
192 __func__
, ssh_err(r
));
194 sshbuf_dump(b
, stderr
);
197 /* test for correct signature */
199 if (PRIVSEP(user_key_allowed(authctxt
->pw
, key
, 1)) &&
200 PRIVSEP(sshkey_verify(key
, sig
, slen
, sshbuf_ptr(b
),
201 sshbuf_len(b
), ssh
->compat
)) == 0) {
206 auth2_record_key(authctxt
, authenticated
, key
);
208 debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
209 __func__
, sshkey_type(key
), fp
);
210 if ((r
= sshpkt_get_end(ssh
)) != 0)
211 fatal("%s: %s", __func__
, ssh_err(r
));
213 /* XXX fake reply and always send PK_OK ? */
215 * XXX this allows testing whether a user is allowed
216 * to login: if you happen to have a valid pubkey this
217 * message is sent. the message is NEVER sent at all
218 * if a user is not allowed to login. is this an
221 if (PRIVSEP(user_key_allowed(authctxt
->pw
, key
, 0))) {
222 if ((r
= sshpkt_start(ssh
, SSH2_MSG_USERAUTH_PK_OK
))
224 (r
= sshpkt_put_cstring(ssh
, pkalg
)) != 0 ||
225 (r
= sshpkt_put_string(ssh
, pkblob
, blen
)) != 0 ||
226 (r
= sshpkt_send(ssh
)) != 0)
227 fatal("%s: %s", __func__
, ssh_err(r
));
228 ssh_packet_write_wait(ssh
);
229 authctxt
->postponed
= 1;
232 if (authenticated
!= 1)
233 auth_clear_options();
235 debug2("%s: authenticated %d pkalg %s", __func__
, authenticated
, pkalg
);
241 return authenticated
;
245 match_principals_option(const char *principal_list
, struct sshkey_cert
*cert
)
250 /* XXX percent_expand() sequences for authorized_principals? */
252 for (i
= 0; i
< cert
->nprincipals
; i
++) {
253 if ((result
= match_list(cert
->principals
[i
],
254 principal_list
, NULL
)) != NULL
) {
255 debug3("matched principal from key options \"%.100s\"",
265 process_principals(FILE *f
, const char *file
, struct passwd
*pw
,
266 const struct sshkey_cert
*cert
)
268 char line
[SSH_MAX_PUBKEY_BYTES
], *cp
, *ep
, *line_opts
;
270 u_int i
, found_principal
= 0;
272 while (read_keyfile_line(f
, file
, line
, sizeof(line
), &linenum
) != -1) {
273 /* Always consume entire input */
276 /* Skip leading whitespace. */
277 for (cp
= line
; *cp
== ' ' || *cp
== '\t'; cp
++)
279 /* Skip blank and comment lines. */
280 if ((ep
= strchr(cp
, '#')) != NULL
)
282 if (!*cp
|| *cp
== '\n')
284 /* Trim trailing whitespace. */
285 ep
= cp
+ strlen(cp
) - 1;
286 while (ep
> cp
&& (*ep
== '\n' || *ep
== ' ' || *ep
== '\t'))
289 * If the line has internal whitespace then assume it has
293 if ((ep
= strrchr(cp
, ' ')) != NULL
||
294 (ep
= strrchr(cp
, '\t')) != NULL
) {
295 for (; *ep
== ' ' || *ep
== '\t'; ep
++)
300 for (i
= 0; i
< cert
->nprincipals
; i
++) {
301 if (strcmp(cp
, cert
->principals
[i
]) == 0) {
302 debug3("%s:%lu: matched principal \"%.100s\"",
303 file
, linenum
, cert
->principals
[i
]);
304 if (auth_parse_options(pw
, line_opts
,
312 return found_principal
;
316 match_principals_file(char *file
, struct passwd
*pw
, struct sshkey_cert
*cert
)
321 temporarily_use_uid(pw
);
322 debug("trying authorized principals file %s", file
);
323 if ((f
= auth_openprincipals(file
, pw
, options
.strict_modes
)) == NULL
) {
327 success
= process_principals(f
, file
, pw
, cert
);
334 * Checks whether principal is allowed in output of command.
335 * returns 1 if the principal is allowed or 0 otherwise.
338 match_principals_command(struct passwd
*user_pw
, const struct sshkey
*key
)
340 const struct sshkey_cert
*cert
= key
->cert
;
342 int r
, ok
, found_principal
= 0;
344 int i
, ac
= 0, uid_swapped
= 0;
346 char *tmp
, *username
= NULL
, *command
= NULL
, **av
= NULL
;
347 char *ca_fp
= NULL
, *key_fp
= NULL
, *catext
= NULL
, *keytext
= NULL
;
349 void (*osigchld
)(int);
351 if (options
.authorized_principals_command
== NULL
)
353 if (options
.authorized_principals_command_user
== NULL
) {
354 error("No user for AuthorizedPrincipalsCommand specified, "
360 * NB. all returns later this function should go via "out" to
361 * ensure the original SIGCHLD handler is restored properly.
363 osigchld
= signal(SIGCHLD
, SIG_DFL
);
365 /* Prepare and verify the user for the command */
366 username
= percent_expand(options
.authorized_principals_command_user
,
367 "u", user_pw
->pw_name
, (char *)NULL
);
368 pw
= getpwnam(username
);
370 error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
371 username
, strerror(errno
));
375 /* Turn the command into an argument vector */
376 if (argv_split(options
.authorized_principals_command
, &ac
, &av
) != 0) {
377 error("AuthorizedPrincipalsCommand \"%s\" contains "
378 "invalid quotes", command
);
382 error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
386 if ((ca_fp
= sshkey_fingerprint(cert
->signature_key
,
387 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
) {
388 error("%s: sshkey_fingerprint failed", __func__
);
391 if ((key_fp
= sshkey_fingerprint(key
,
392 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
) {
393 error("%s: sshkey_fingerprint failed", __func__
);
396 if ((r
= sshkey_to_base64(cert
->signature_key
, &catext
)) != 0) {
397 error("%s: sshkey_to_base64 failed: %s", __func__
, ssh_err(r
));
400 if ((r
= sshkey_to_base64(key
, &keytext
)) != 0) {
401 error("%s: sshkey_to_base64 failed: %s", __func__
, ssh_err(r
));
404 snprintf(serial_s
, sizeof(serial_s
), "%llu",
405 (unsigned long long)cert
->serial
);
406 for (i
= 1; i
< ac
; i
++) {
407 tmp
= percent_expand(av
[i
],
408 "u", user_pw
->pw_name
,
409 "h", user_pw
->pw_dir
,
410 "t", sshkey_ssh_name(key
),
411 "T", sshkey_ssh_name(cert
->signature_key
),
420 fatal("%s: percent_expand failed", __func__
);
424 /* Prepare a printable command for logs, etc. */
425 command
= argv_assemble(ac
, av
);
427 if ((pid
= subprocess("AuthorizedPrincipalsCommand", pw
, command
,
429 SSH_SUBPROCESS_STDOUT_CAPTURE
|SSH_SUBPROCESS_STDERR_DISCARD
)) == 0)
433 temporarily_use_uid(pw
);
435 ok
= process_principals(f
, "(command)", pw
, cert
);
440 if (exited_cleanly(pid
, "AuthorizedPrincipalsCommand", command
, 0) != 0)
443 /* Read completed successfully */
444 found_principal
= ok
;
448 signal(SIGCHLD
, osigchld
);
449 for (i
= 0; i
< ac
; i
++)
460 return found_principal
;
463 * Checks whether key is allowed in authorized_keys-format file,
464 * returns 1 if the key is allowed or 0 otherwise.
467 check_authkeys_file(FILE *f
, char *file
, struct sshkey
*key
, struct passwd
*pw
)
469 char line
[SSH_MAX_PUBKEY_BYTES
];
472 struct sshkey
*found
= NULL
;
474 while (read_keyfile_line(f
, file
, line
, sizeof(line
), &linenum
) != -1) {
475 char *cp
, *key_options
= NULL
, *fp
= NULL
;
476 const char *reason
= NULL
;
478 /* Always consume entire file */
483 found
= sshkey_new(sshkey_is_cert(key
) ? KEY_UNSPEC
: key
->type
);
486 auth_clear_options();
488 /* Skip leading whitespace, empty and comment lines. */
489 for (cp
= line
; *cp
== ' ' || *cp
== '\t'; cp
++)
491 if (!*cp
|| *cp
== '\n' || *cp
== '#')
494 if (sshkey_read(found
, &cp
) != 0) {
495 /* no key? check if there are options for this key */
497 debug2("user_key_allowed: check options: '%s'", cp
);
499 for (; *cp
&& (quoted
|| (*cp
!= ' ' && *cp
!= '\t')); cp
++) {
500 if (*cp
== '\\' && cp
[1] == '"')
501 cp
++; /* Skip both */
505 /* Skip remaining whitespace. */
506 for (; *cp
== ' ' || *cp
== '\t'; cp
++)
508 if (sshkey_read(found
, &cp
) != 0) {
509 debug2("user_key_allowed: advance: '%s'", cp
);
510 /* still no key? advance to next line*/
514 if (sshkey_is_cert(key
)) {
515 if (!sshkey_equal(found
, key
->cert
->signature_key
))
517 if (auth_parse_options(pw
, key_options
, file
,
520 if (!key_is_cert_authority
)
522 if ((fp
= sshkey_fingerprint(found
,
523 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
525 debug("matching CA found: file %s, line %lu, %s %s",
526 file
, linenum
, sshkey_type(found
), fp
);
528 * If the user has specified a list of principals as
529 * a key option, then prefer that list to matching
530 * their username in the certificate principals list.
532 if (authorized_principals
!= NULL
&&
533 !match_principals_option(authorized_principals
,
535 reason
= "Certificate does not contain an "
536 "authorized principal";
540 auth_debug_add("%s", reason
);
543 if (sshkey_cert_check_authority(key
, 0, 0,
544 authorized_principals
== NULL
? pw
->pw_name
: NULL
,
547 if (auth_cert_options(key
, pw
, &reason
) != 0)
549 verbose("Accepted certificate ID \"%s\" (serial %llu) "
550 "signed by %s CA %s via %s", key
->cert
->key_id
,
551 (unsigned long long)key
->cert
->serial
,
552 sshkey_type(found
), fp
, file
);
556 } else if (sshkey_equal(found
, key
)) {
557 if (auth_parse_options(pw
, key_options
, file
,
560 if (key_is_cert_authority
)
562 if ((fp
= sshkey_fingerprint(found
,
563 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
565 debug("matching key found: file %s, line %lu %s %s",
566 file
, linenum
, sshkey_type(found
), fp
);
576 debug2("key not found");
580 /* Authenticate a certificate key against TrustedUserCAKeys */
582 user_cert_trusted_ca(struct passwd
*pw
, struct sshkey
*key
)
584 char *ca_fp
, *principals_file
= NULL
;
586 int r
, ret
= 0, found_principal
= 0, use_authorized_principals
;
588 if (!sshkey_is_cert(key
) || options
.trusted_user_ca_keys
== NULL
)
591 if ((ca_fp
= sshkey_fingerprint(key
->cert
->signature_key
,
592 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
595 if ((r
= sshkey_in_file(key
->cert
->signature_key
,
596 options
.trusted_user_ca_keys
, 1, 0)) != 0) {
597 debug2("%s: CA %s %s is not listed in %s: %s", __func__
,
598 sshkey_type(key
->cert
->signature_key
), ca_fp
,
599 options
.trusted_user_ca_keys
, ssh_err(r
));
603 * If AuthorizedPrincipals is in use, then compare the certificate
604 * principals against the names in that file rather than matching
605 * against the username.
607 if ((principals_file
= authorized_principals_file(pw
)) != NULL
) {
608 if (match_principals_file(principals_file
, pw
, key
->cert
))
611 /* Try querying command if specified */
612 if (!found_principal
&& match_principals_command(pw
, key
))
614 /* If principals file or command is specified, then require a match */
615 use_authorized_principals
= principals_file
!= NULL
||
616 options
.authorized_principals_command
!= NULL
;
617 if (!found_principal
&& use_authorized_principals
) {
618 reason
= "Certificate does not contain an authorized principal";
621 auth_debug_add("%s", reason
);
624 if (sshkey_cert_check_authority(key
, 0, 1,
625 use_authorized_principals
? NULL
: pw
->pw_name
, &reason
) != 0)
627 if (auth_cert_options(key
, pw
, &reason
) != 0)
630 verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
631 "%s CA %s via %s", key
->cert
->key_id
,
632 (unsigned long long)key
->cert
->serial
,
633 sshkey_type(key
->cert
->signature_key
), ca_fp
,
634 options
.trusted_user_ca_keys
);
638 free(principals_file
);
644 * Checks whether key is allowed in file.
645 * returns 1 if the key is allowed or 0 otherwise.
648 user_key_allowed2(struct passwd
*pw
, struct sshkey
*key
, char *file
)
653 /* Temporarily use the user's uid. */
654 temporarily_use_uid(pw
);
656 debug("trying public key file %s", file
);
657 if ((f
= auth_openkeyfile(file
, pw
, options
.strict_modes
)) != NULL
) {
658 found_key
= check_authkeys_file(f
, file
, key
, pw
);
667 * Checks whether key is allowed in output of command.
668 * returns 1 if the key is allowed or 0 otherwise.
671 user_key_command_allowed2(struct passwd
*user_pw
, struct sshkey
*key
)
674 int r
, ok
, found_key
= 0;
676 int i
, uid_swapped
= 0, ac
= 0;
678 char *username
= NULL
, *key_fp
= NULL
, *keytext
= NULL
;
679 char *tmp
, *command
= NULL
, **av
= NULL
;
680 void (*osigchld
)(int);
682 if (options
.authorized_keys_command
== NULL
)
684 if (options
.authorized_keys_command_user
== NULL
) {
685 error("No user for AuthorizedKeysCommand specified, skipping");
690 * NB. all returns later this function should go via "out" to
691 * ensure the original SIGCHLD handler is restored properly.
693 osigchld
= signal(SIGCHLD
, SIG_DFL
);
695 /* Prepare and verify the user for the command */
696 username
= percent_expand(options
.authorized_keys_command_user
,
697 "u", user_pw
->pw_name
, (char *)NULL
);
698 pw
= getpwnam(username
);
700 error("AuthorizedKeysCommandUser \"%s\" not found: %s",
701 username
, strerror(errno
));
705 /* Prepare AuthorizedKeysCommand */
706 if ((key_fp
= sshkey_fingerprint(key
, options
.fingerprint_hash
,
707 SSH_FP_DEFAULT
)) == NULL
) {
708 error("%s: sshkey_fingerprint failed", __func__
);
711 if ((r
= sshkey_to_base64(key
, &keytext
)) != 0) {
712 error("%s: sshkey_to_base64 failed: %s", __func__
, ssh_err(r
));
716 /* Turn the command into an argument vector */
717 if (argv_split(options
.authorized_keys_command
, &ac
, &av
) != 0) {
718 error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
723 error("AuthorizedKeysCommand \"%s\" yielded no arguments",
727 for (i
= 1; i
< ac
; i
++) {
728 tmp
= percent_expand(av
[i
],
729 "u", user_pw
->pw_name
,
730 "h", user_pw
->pw_dir
,
731 "t", sshkey_ssh_name(key
),
736 fatal("%s: percent_expand failed", __func__
);
740 /* Prepare a printable command for logs, etc. */
741 command
= argv_assemble(ac
, av
);
744 * If AuthorizedKeysCommand was run without arguments
745 * then fall back to the old behaviour of passing the
746 * target username as a single argument.
749 av
= xreallocarray(av
, ac
+ 2, sizeof(*av
));
750 av
[1] = xstrdup(user_pw
->pw_name
);
752 /* Fix up command too, since it is used in log messages */
754 xasprintf(&command
, "%s %s", av
[0], av
[1]);
757 if ((pid
= subprocess("AuthorizedKeysCommand", pw
, command
,
759 SSH_SUBPROCESS_STDOUT_CAPTURE
|SSH_SUBPROCESS_STDERR_DISCARD
)) == 0)
763 temporarily_use_uid(pw
);
765 ok
= check_authkeys_file(f
, options
.authorized_keys_command
, key
, pw
);
770 if (exited_cleanly(pid
, "AuthorizedKeysCommand", command
, 0) != 0)
773 /* Read completed successfully */
778 signal(SIGCHLD
, osigchld
);
779 for (i
= 0; i
< ac
; i
++)
792 * Check whether key authenticates and authorises the user.
795 user_key_allowed(struct passwd
*pw
, struct sshkey
*key
, int auth_attempt
)
800 if (auth_key_is_revoked(key
))
802 if (sshkey_is_cert(key
) &&
803 auth_key_is_revoked(key
->cert
->signature_key
))
806 success
= user_cert_trusted_ca(pw
, key
);
810 success
= user_key_command_allowed2(pw
, key
);
814 for (i
= 0; !success
&& i
< options
.num_authkeys_files
; i
++) {
816 if (strcasecmp(options
.authorized_keys_files
[i
], "none") == 0)
818 file
= expand_authorized_keys(
819 options
.authorized_keys_files
[i
], pw
);
821 success
= user_key_allowed2(pw
, key
, file
);
828 Authmethod method_pubkey
= {
831 &options
.pubkey_authentication