OSDN Git Service

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