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