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