Merge branch 'vendor/OPENSSH'
[dragonfly.git] / crypto / openssh / auth2-pubkey.c
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 #include "includes.h"
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/wait.h>
31
32 #include <errno.h>
33 #include <fcntl.h>
34 #ifdef HAVE_PATHS_H
35 # include <paths.h>
36 #endif
37 #include <pwd.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44
45 #include "xmalloc.h"
46 #include "ssh.h"
47 #include "ssh2.h"
48 #include "packet.h"
49 #include "buffer.h"
50 #include "log.h"
51 #include "misc.h"
52 #include "servconf.h"
53 #include "compat.h"
54 #include "key.h"
55 #include "hostfile.h"
56 #include "authfile.h"
57 #include "auth.h"
58 #include "pathnames.h"
59 #include "uidswap.h"
60 #include "auth-options.h"
61 #include "canohost.h"
62 #ifdef GSSAPI
63 #include "ssh-gss.h"
64 #endif
65 #include "monitor_wrap.h"
66 #include "authfile.h"
67 #include "match.h"
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;
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("userauth_pubkey: disabled because of invalid user");
87                 return 0;
88         }
89         have_sig = packet_get_char();
90         if (datafellows & SSH_BUG_PKAUTH) {
91                 debug2("userauth_pubkey: SSH_BUG_PKAUTH");
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("userauth_pubkey: unsupported public key algorithm: %s",
107                     pkalg);
108                 goto done;
109         }
110         key = key_from_blob(pkblob, blen);
111         if (key == NULL) {
112                 error("userauth_pubkey: cannot decode key: %s", pkalg);
113                 goto done;
114         }
115         if (key->type != pktype) {
116                 error("userauth_pubkey: type mismatch for decoded key "
117                     "(received %d, expected %d)", 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         if (have_sig) {
127                 sig = packet_get_string(&slen);
128                 packet_check_eom();
129                 buffer_init(&b);
130                 if (datafellows & SSH_OLD_SESSIONID) {
131                         buffer_append(&b, session_id2, session_id2_len);
132                 } else {
133                         buffer_put_string(&b, session_id2, session_id2_len);
134                 }
135                 /* reconstruct packet */
136                 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
137                 xasprintf(&userstyle, "%s%s%s", authctxt->user,
138                     authctxt->style ? ":" : "",
139                     authctxt->style ? authctxt->style : "");
140                 buffer_put_cstring(&b, userstyle);
141                 free(userstyle);
142                 buffer_put_cstring(&b,
143                     datafellows & SSH_BUG_PKSERVICE ?
144                     "ssh-userauth" :
145                     authctxt->service);
146                 if (datafellows & SSH_BUG_PKAUTH) {
147                         buffer_put_char(&b, have_sig);
148                 } else {
149                         buffer_put_cstring(&b, "publickey");
150                         buffer_put_char(&b, have_sig);
151                         buffer_put_cstring(&b, pkalg);
152                 }
153                 buffer_put_string(&b, pkblob, blen);
154 #ifdef DEBUG_PK
155                 buffer_dump(&b);
156 #endif
157                 pubkey_auth_info(authctxt, key, NULL);
158
159                 /* test for correct signature */
160                 authenticated = 0;
161                 if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
162                     PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
163                     buffer_len(&b))) == 1)
164                         authenticated = 1;
165                 buffer_free(&b);
166                 free(sig);
167         } else {
168                 debug("test whether pkalg/pkblob are acceptable");
169                 packet_check_eom();
170
171                 /* XXX fake reply and always send PK_OK ? */
172                 /*
173                  * XXX this allows testing whether a user is allowed
174                  * to login: if you happen to have a valid pubkey this
175                  * message is sent. the message is NEVER sent at all
176                  * if a user is not allowed to login. is this an
177                  * issue? -markus
178                  */
179                 if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
180                         packet_start(SSH2_MSG_USERAUTH_PK_OK);
181                         packet_put_string(pkalg, alen);
182                         packet_put_string(pkblob, blen);
183                         packet_send();
184                         packet_write_wait();
185                         authctxt->postponed = 1;
186                 }
187         }
188         if (authenticated != 1)
189                 auth_clear_options();
190 done:
191         debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
192         if (key != NULL)
193                 key_free(key);
194         free(pkalg);
195         free(pkblob);
196         return authenticated;
197 }
198
199 void
200 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
201 {
202         char *fp, *extra;
203         va_list ap;
204         int i;
205
206         extra = NULL;
207         if (fmt != NULL) {
208                 va_start(ap, fmt);
209                 i = vasprintf(&extra, fmt, ap);
210                 va_end(ap);
211                 if (i < 0 || extra == NULL)
212                         fatal("%s: vasprintf failed", __func__);        
213         }
214
215         if (key_is_cert(key)) {
216                 fp = key_fingerprint(key->cert->signature_key,
217                     SSH_FP_MD5, SSH_FP_HEX);
218                 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
219                     key_type(key), key->cert->key_id,
220                     (unsigned long long)key->cert->serial,
221                     key_type(key->cert->signature_key), fp,
222                     extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
223                 free(fp);
224         } else {
225                 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
226                 auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
227                     extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
228                 free(fp);
229         }
230         free(extra);
231 }
232
233 static int
234 match_principals_option(const char *principal_list, struct sshkey_cert *cert)
235 {
236         char *result;
237         u_int i;
238
239         /* XXX percent_expand() sequences for authorized_principals? */
240
241         for (i = 0; i < cert->nprincipals; i++) {
242                 if ((result = match_list(cert->principals[i],
243                     principal_list, NULL)) != NULL) {
244                         debug3("matched principal from key options \"%.100s\"",
245                             result);
246                         free(result);
247                         return 1;
248                 }
249         }
250         return 0;
251 }
252
253 static int
254 match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
255 {
256         FILE *f;
257         char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
258         u_long linenum = 0;
259         u_int i;
260
261         temporarily_use_uid(pw);
262         debug("trying authorized principals file %s", file);
263         if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
264                 restore_uid();
265                 return 0;
266         }
267         while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
268                 /* Skip leading whitespace. */
269                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
270                         ;
271                 /* Skip blank and comment lines. */
272                 if ((ep = strchr(cp, '#')) != NULL)
273                         *ep = '\0';
274                 if (!*cp || *cp == '\n')
275                         continue;
276                 /* Trim trailing whitespace. */
277                 ep = cp + strlen(cp) - 1;
278                 while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
279                         *ep-- = '\0';
280                 /*
281                  * If the line has internal whitespace then assume it has
282                  * key options.
283                  */
284                 line_opts = NULL;
285                 if ((ep = strrchr(cp, ' ')) != NULL ||
286                     (ep = strrchr(cp, '\t')) != NULL) {
287                         for (; *ep == ' ' || *ep == '\t'; ep++)
288                                 ;
289                         line_opts = cp;
290                         cp = ep;
291                 }
292                 for (i = 0; i < cert->nprincipals; i++) {
293                         if (strcmp(cp, cert->principals[i]) == 0) {
294                                 debug3("matched principal \"%.100s\" "
295                                     "from file \"%s\" on line %lu",
296                                     cert->principals[i], file, linenum);
297                                 if (auth_parse_options(pw, line_opts,
298                                     file, linenum) != 1)
299                                         continue;
300                                 fclose(f);
301                                 restore_uid();
302                                 return 1;
303                         }
304                 }
305         }
306         fclose(f);
307         restore_uid();
308         return 0;
309 }
310
311 /*
312  * Checks whether key is allowed in authorized_keys-format file,
313  * returns 1 if the key is allowed or 0 otherwise.
314  */
315 static int
316 check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
317 {
318         char line[SSH_MAX_PUBKEY_BYTES];
319         const char *reason;
320         int found_key = 0;
321         u_long linenum = 0;
322         Key *found;
323         char *fp;
324
325         found_key = 0;
326
327         found = NULL;
328         while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
329                 char *cp, *key_options = NULL;
330                 if (found != NULL)
331                         key_free(found);
332                 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
333                 auth_clear_options();
334
335                 /* Skip leading whitespace, empty and comment lines. */
336                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
337                         ;
338                 if (!*cp || *cp == '\n' || *cp == '#')
339                         continue;
340
341                 if (key_read(found, &cp) != 1) {
342                         /* no key?  check if there are options for this key */
343                         int quoted = 0;
344                         debug2("user_key_allowed: check options: '%s'", cp);
345                         key_options = cp;
346                         for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
347                                 if (*cp == '\\' && cp[1] == '"')
348                                         cp++;   /* Skip both */
349                                 else if (*cp == '"')
350                                         quoted = !quoted;
351                         }
352                         /* Skip remaining whitespace. */
353                         for (; *cp == ' ' || *cp == '\t'; cp++)
354                                 ;
355                         if (key_read(found, &cp) != 1) {
356                                 debug2("user_key_allowed: advance: '%s'", cp);
357                                 /* still no key?  advance to next line*/
358                                 continue;
359                         }
360                 }
361                 if (key_is_cert(key)) {
362                         if (!key_equal(found, key->cert->signature_key))
363                                 continue;
364                         if (auth_parse_options(pw, key_options, file,
365                             linenum) != 1)
366                                 continue;
367                         if (!key_is_cert_authority)
368                                 continue;
369                         fp = key_fingerprint(found, SSH_FP_MD5,
370                             SSH_FP_HEX);
371                         debug("matching CA found: file %s, line %lu, %s %s",
372                             file, linenum, key_type(found), fp);
373                         /*
374                          * If the user has specified a list of principals as
375                          * a key option, then prefer that list to matching
376                          * their username in the certificate principals list.
377                          */
378                         if (authorized_principals != NULL &&
379                             !match_principals_option(authorized_principals,
380                             key->cert)) {
381                                 reason = "Certificate does not contain an "
382                                     "authorized principal";
383  fail_reason:
384                                 free(fp);
385                                 error("%s", reason);
386                                 auth_debug_add("%s", reason);
387                                 continue;
388                         }
389                         if (key_cert_check_authority(key, 0, 0,
390                             authorized_principals == NULL ? pw->pw_name : NULL,
391                             &reason) != 0)
392                                 goto fail_reason;
393                         if (auth_cert_options(key, pw) != 0) {
394                                 free(fp);
395                                 continue;
396                         }
397                         verbose("Accepted certificate ID \"%s\" "
398                             "signed by %s CA %s via %s", key->cert->key_id,
399                             key_type(found), fp, file);
400                         free(fp);
401                         found_key = 1;
402                         break;
403                 } else if (key_equal(found, key)) {
404                         if (auth_parse_options(pw, key_options, file,
405                             linenum) != 1)
406                                 continue;
407                         if (key_is_cert_authority)
408                                 continue;
409                         found_key = 1;
410                         fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
411                         debug("matching key found: file %s, line %lu %s %s",
412                             file, linenum, key_type(found), fp);
413                         free(fp);
414                         break;
415                 }
416         }
417         if (found != NULL)
418                 key_free(found);
419         if (!found_key)
420                 debug2("key not found");
421         return found_key;
422 }
423
424 /* Authenticate a certificate key against TrustedUserCAKeys */
425 static int
426 user_cert_trusted_ca(struct passwd *pw, Key *key)
427 {
428         char *ca_fp, *principals_file = NULL;
429         const char *reason;
430         int ret = 0;
431
432         if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
433                 return 0;
434
435         ca_fp = key_fingerprint(key->cert->signature_key,
436             SSH_FP_MD5, SSH_FP_HEX);
437
438         if (key_in_file(key->cert->signature_key,
439             options.trusted_user_ca_keys, 1) != 1) {
440                 debug2("%s: CA %s %s is not listed in %s", __func__,
441                     key_type(key->cert->signature_key), ca_fp,
442                     options.trusted_user_ca_keys);
443                 goto out;
444         }
445         /*
446          * If AuthorizedPrincipals is in use, then compare the certificate
447          * principals against the names in that file rather than matching
448          * against the username.
449          */
450         if ((principals_file = authorized_principals_file(pw)) != NULL) {
451                 if (!match_principals_file(principals_file, pw, key->cert)) {
452                         reason = "Certificate does not contain an "
453                             "authorized principal";
454  fail_reason:
455                         error("%s", reason);
456                         auth_debug_add("%s", reason);
457                         goto out;
458                 }
459         }
460         if (key_cert_check_authority(key, 0, 1,
461             principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
462                 goto fail_reason;
463         if (auth_cert_options(key, pw) != 0)
464                 goto out;
465
466         verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
467             key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
468             options.trusted_user_ca_keys);
469         ret = 1;
470
471  out:
472         free(principals_file);
473         free(ca_fp);
474         return ret;
475 }
476
477 /*
478  * Checks whether key is allowed in file.
479  * returns 1 if the key is allowed or 0 otherwise.
480  */
481 static int
482 user_key_allowed2(struct passwd *pw, Key *key, char *file)
483 {
484         FILE *f;
485         int found_key = 0;
486
487         /* Temporarily use the user's uid. */
488         temporarily_use_uid(pw);
489
490         debug("trying public key file %s", file);
491         if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
492                 found_key = check_authkeys_file(f, file, key, pw);
493                 fclose(f);
494         }
495
496         restore_uid();
497         return found_key;
498 }
499
500 /*
501  * Checks whether key is allowed in output of command.
502  * returns 1 if the key is allowed or 0 otherwise.
503  */
504 static int
505 user_key_command_allowed2(struct passwd *user_pw, Key *key)
506 {
507         FILE *f;
508         int ok, found_key = 0;
509         struct passwd *pw;
510         struct stat st;
511         int status, devnull, p[2], i;
512         pid_t pid;
513         char *username, errmsg[512];
514
515         if (options.authorized_keys_command == NULL ||
516             options.authorized_keys_command[0] != '/')
517                 return 0;
518
519         if (options.authorized_keys_command_user == NULL) {
520                 error("No user for AuthorizedKeysCommand specified, skipping");
521                 return 0;
522         }
523
524         username = percent_expand(options.authorized_keys_command_user,
525             "u", user_pw->pw_name, (char *)NULL);
526         pw = getpwnam(username);
527         if (pw == NULL) {
528                 error("AuthorizedKeysCommandUser \"%s\" not found: %s",
529                     username, strerror(errno));
530                 free(username);
531                 return 0;
532         }
533         free(username);
534
535         temporarily_use_uid(pw);
536
537         if (stat(options.authorized_keys_command, &st) < 0) {
538                 error("Could not stat AuthorizedKeysCommand \"%s\": %s",
539                     options.authorized_keys_command, strerror(errno));
540                 goto out;
541         }
542         if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
543             errmsg, sizeof(errmsg)) != 0) {
544                 error("Unsafe AuthorizedKeysCommand: %s", errmsg);
545                 goto out;
546         }
547
548         if (pipe(p) != 0) {
549                 error("%s: pipe: %s", __func__, strerror(errno));
550                 goto out;
551         }
552
553         debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
554             options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
555
556         /*
557          * Don't want to call this in the child, where it can fatal() and
558          * run cleanup_exit() code.
559          */
560         restore_uid();
561
562         switch ((pid = fork())) {
563         case -1: /* error */
564                 error("%s: fork: %s", __func__, strerror(errno));
565                 close(p[0]);
566                 close(p[1]);
567                 return 0;
568         case 0: /* child */
569                 for (i = 0; i < NSIG; i++)
570                         signal(i, SIG_DFL);
571
572                 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
573                         error("%s: open %s: %s", __func__, _PATH_DEVNULL,
574                             strerror(errno));
575                         _exit(1);
576                 }
577                 /* Keep stderr around a while longer to catch errors */
578                 if (dup2(devnull, STDIN_FILENO) == -1 ||
579                     dup2(p[1], STDOUT_FILENO) == -1) {
580                         error("%s: dup2: %s", __func__, strerror(errno));
581                         _exit(1);
582                 }
583                 closefrom(STDERR_FILENO + 1);
584
585                 /* Don't use permanently_set_uid() here to avoid fatal() */
586                 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
587                         error("setresgid %u: %s", (u_int)pw->pw_gid,
588                             strerror(errno));
589                         _exit(1);
590                 }
591                 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
592                         error("setresuid %u: %s", (u_int)pw->pw_uid,
593                             strerror(errno));
594                         _exit(1);
595                 }
596                 /* stdin is pointed to /dev/null at this point */
597                 if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
598                         error("%s: dup2: %s", __func__, strerror(errno));
599                         _exit(1);
600                 }
601
602                 execl(options.authorized_keys_command,
603                     options.authorized_keys_command, user_pw->pw_name, NULL);
604
605                 error("AuthorizedKeysCommand %s exec failed: %s",
606                     options.authorized_keys_command, strerror(errno));
607                 _exit(127);
608         default: /* parent */
609                 break;
610         }
611
612         temporarily_use_uid(pw);
613
614         close(p[1]);
615         if ((f = fdopen(p[0], "r")) == NULL) {
616                 error("%s: fdopen: %s", __func__, strerror(errno));
617                 close(p[0]);
618                 /* Don't leave zombie child */
619                 kill(pid, SIGTERM);
620                 while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
621                         ;
622                 goto out;
623         }
624         ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
625         fclose(f);
626
627         while (waitpid(pid, &status, 0) == -1) {
628                 if (errno != EINTR) {
629                         error("%s: waitpid: %s", __func__, strerror(errno));
630                         goto out;
631                 }
632         }
633         if (WIFSIGNALED(status)) {
634                 error("AuthorizedKeysCommand %s exited on signal %d",
635                     options.authorized_keys_command, WTERMSIG(status));
636                 goto out;
637         } else if (WEXITSTATUS(status) != 0) {
638                 error("AuthorizedKeysCommand %s returned status %d",
639                     options.authorized_keys_command, WEXITSTATUS(status));
640                 goto out;
641         }
642         found_key = ok;
643  out:
644         restore_uid();
645         return found_key;
646 }
647
648 /*
649  * Check whether key authenticates and authorises the user.
650  */
651 int
652 user_key_allowed(struct passwd *pw, Key *key)
653 {
654         char *fp;
655         u_int success, i;
656         char *file;
657
658         if (blacklisted_key(key)) {
659                 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
660                 if (options.permit_blacklisted_keys)
661                         logit("Public key %s blacklisted (see "
662                             "ssh-vulnkey(1)); continuing anyway", fp);
663                 else
664                         logit("Public key %s blacklisted (see "
665                             "ssh-vulnkey(1))", fp);
666                 xfree(fp);
667                 if (!options.permit_blacklisted_keys)
668                         return 0;
669         }
670
671         if (auth_key_is_revoked(key))
672                 return 0;
673         if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
674                 return 0;
675
676         success = user_cert_trusted_ca(pw, key);
677         if (success)
678                 return success;
679
680         success = user_key_command_allowed2(pw, key);
681         if (success > 0)
682                 return success;
683
684         for (i = 0; !success && i < options.num_authkeys_files; i++) {
685
686                 if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
687                         continue;
688                 file = expand_authorized_keys(
689                     options.authorized_keys_files[i], pw);
690
691                 success = user_key_allowed2(pw, key, file);
692                 free(file);
693         }
694
695         return success;
696 }
697
698 Authmethod method_pubkey = {
699         "publickey",
700         userauth_pubkey,
701         &options.pubkey_authentication
702 };