1 /* 2 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: auth2.c,v 1.80 2001/12/28 15:06:00 markus Exp $"); 27 28 #include <openssl/evp.h> 29 30 #include "ssh2.h" 31 #include "xmalloc.h" 32 #include "rsa.h" 33 #include "sshpty.h" 34 #include "packet.h" 35 #include "buffer.h" 36 #include "log.h" 37 #include "servconf.h" 38 #include "compat.h" 39 #include "channels.h" 40 #include "bufaux.h" 41 #include "auth.h" 42 #include "session.h" 43 #include "dispatch.h" 44 #include "key.h" 45 #include "cipher.h" 46 #include "kex.h" 47 #include "pathnames.h" 48 #include "uidswap.h" 49 #include "auth-options.h" 50 #include "misc.h" 51 #include "hostfile.h" 52 #include "canohost.h" 53 #include "match.h" 54 55 /* import */ 56 extern ServerOptions options; 57 extern u_char *session_id2; 58 extern int session_id2_len; 59 60 static Authctxt *x_authctxt = NULL; 61 static int one = 1; 62 63 typedef struct Authmethod Authmethod; 64 struct Authmethod { 65 char *name; 66 int (*userauth)(Authctxt *authctxt); 67 int *enabled; 68 }; 69 70 /* protocol */ 71 72 static void input_service_request(int, u_int32_t, void *); 73 static void input_userauth_request(int, u_int32_t, void *); 74 static void protocol_error(int, u_int32_t, void *); 75 76 /* helper */ 77 static Authmethod *authmethod_lookup(const char *); 78 static char *authmethods_get(void); 79 static int user_key_allowed(struct passwd *, Key *); 80 static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); 81 82 /* auth */ 83 static void userauth_banner(void); 84 static int userauth_none(Authctxt *); 85 static int userauth_passwd(Authctxt *); 86 static int userauth_pubkey(Authctxt *); 87 static int userauth_hostbased(Authctxt *); 88 static int userauth_kbdint(Authctxt *); 89 90 Authmethod authmethods[] = { 91 {"none", 92 userauth_none, 93 &one}, 94 {"publickey", 95 userauth_pubkey, 96 &options.pubkey_authentication}, 97 {"password", 98 userauth_passwd, 99 &options.password_authentication}, 100 {"keyboard-interactive", 101 userauth_kbdint, 102 &options.kbd_interactive_authentication}, 103 {"hostbased", 104 userauth_hostbased, 105 &options.hostbased_authentication}, 106 {NULL, NULL, NULL} 107 }; 108 109 /* 110 * loop until authctxt->success == TRUE 111 */ 112 113 void 114 do_authentication2(void) 115 { 116 Authctxt *authctxt = authctxt_new(); 117 118 x_authctxt = authctxt; /*XXX*/ 119 120 /* challenge-response is implemented via keyboard interactive */ 121 if (options.challenge_response_authentication) 122 options.kbd_interactive_authentication = 1; 123 124 dispatch_init(&protocol_error); 125 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 126 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 127 do_authenticated(authctxt); 128 } 129 130 static void 131 protocol_error(int type, u_int32_t seq, void *ctxt) 132 { 133 log("auth: protocol error: type %d", type); 134 packet_start(SSH2_MSG_UNIMPLEMENTED); 135 packet_put_int(seq); 136 packet_send(); 137 packet_write_wait(); 138 } 139 140 static void 141 input_service_request(int type, u_int32_t seq, void *ctxt) 142 { 143 Authctxt *authctxt = ctxt; 144 u_int len; 145 int accept = 0; 146 char *service = packet_get_string(&len); 147 packet_check_eom(); 148 149 if (authctxt == NULL) 150 fatal("input_service_request: no authctxt"); 151 152 if (strcmp(service, "ssh-userauth") == 0) { 153 if (!authctxt->success) { 154 accept = 1; 155 /* now we can handle user-auth requests */ 156 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 157 } 158 } 159 /* XXX all other service requests are denied */ 160 161 if (accept) { 162 packet_start(SSH2_MSG_SERVICE_ACCEPT); 163 packet_put_cstring(service); 164 packet_send(); 165 packet_write_wait(); 166 } else { 167 debug("bad service request %s", service); 168 packet_disconnect("bad service request %s", service); 169 } 170 xfree(service); 171 } 172 173 static void 174 input_userauth_request(int type, u_int32_t seq, void *ctxt) 175 { 176 Authctxt *authctxt = ctxt; 177 Authmethod *m = NULL; 178 char *user, *service, *method, *style = NULL; 179 int authenticated = 0; 180 181 if (authctxt == NULL) 182 fatal("input_userauth_request: no authctxt"); 183 184 user = packet_get_string(NULL); 185 service = packet_get_string(NULL); 186 method = packet_get_string(NULL); 187 debug("userauth-request for user %s service %s method %s", user, service, method); 188 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 189 190 if ((style = strchr(user, ':')) != NULL) 191 *style++ = 0; 192 193 if (authctxt->attempt++ == 0) { 194 /* setup auth context */ 195 struct passwd *pw = NULL; 196 pw = getpwnam(user); 197 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { 198 authctxt->pw = pwcopy(pw); 199 authctxt->valid = 1; 200 debug2("input_userauth_request: setting up authctxt for %s", user); 201 } else { 202 log("input_userauth_request: illegal user %s", user); 203 } 204 setproctitle("%s", pw ? user : "unknown"); 205 authctxt->user = xstrdup(user); 206 authctxt->service = xstrdup(service); 207 authctxt->style = style ? xstrdup(style) : NULL; 208 } else if (strcmp(user, authctxt->user) != 0 || 209 strcmp(service, authctxt->service) != 0) { 210 packet_disconnect("Change of username or service not allowed: " 211 "(%s,%s) -> (%s,%s)", 212 authctxt->user, authctxt->service, user, service); 213 } 214 /* reset state */ 215 auth2_challenge_stop(authctxt); 216 authctxt->postponed = 0; 217 218 /* try to authenticate user */ 219 m = authmethod_lookup(method); 220 if (m != NULL) { 221 debug2("input_userauth_request: try method %s", method); 222 authenticated = m->userauth(authctxt); 223 } 224 userauth_finish(authctxt, authenticated, method); 225 226 xfree(service); 227 xfree(user); 228 xfree(method); 229 } 230 231 void 232 userauth_finish(Authctxt *authctxt, int authenticated, char *method) 233 { 234 char *methods; 235 236 if (!authctxt->valid && authenticated) 237 fatal("INTERNAL ERROR: authenticated invalid user %s", 238 authctxt->user); 239 240 /* Special handling for root */ 241 if (authenticated && authctxt->pw->pw_uid == 0 && 242 !auth_root_allowed(method)) 243 authenticated = 0; 244 245 /* Log before sending the reply */ 246 auth_log(authctxt, authenticated, method, " ssh2"); 247 248 if (authctxt->postponed) 249 return; 250 251 /* XXX todo: check if multiple auth methods are needed */ 252 if (authenticated == 1) { 253 /* turn off userauth */ 254 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); 255 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 256 packet_send(); 257 packet_write_wait(); 258 /* now we can break out */ 259 authctxt->success = 1; 260 } else { 261 if (authctxt->failures++ > AUTH_FAIL_MAX) 262 packet_disconnect(AUTH_FAIL_MSG, authctxt->user); 263 methods = authmethods_get(); 264 packet_start(SSH2_MSG_USERAUTH_FAILURE); 265 packet_put_cstring(methods); 266 packet_put_char(0); /* XXX partial success, unused */ 267 packet_send(); 268 packet_write_wait(); 269 xfree(methods); 270 } 271 } 272 273 static void 274 userauth_banner(void) 275 { 276 struct stat st; 277 char *banner = NULL; 278 off_t len, n; 279 int fd; 280 281 if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) 282 return; 283 if ((fd = open(options.banner, O_RDONLY)) < 0) 284 return; 285 if (fstat(fd, &st) < 0) 286 goto done; 287 len = st.st_size; 288 banner = xmalloc(len + 1); 289 if ((n = read(fd, banner, len)) < 0) 290 goto done; 291 banner[n] = '\0'; 292 packet_start(SSH2_MSG_USERAUTH_BANNER); 293 packet_put_cstring(banner); 294 packet_put_cstring(""); /* language, unused */ 295 packet_send(); 296 debug("userauth_banner: sent"); 297 done: 298 if (banner) 299 xfree(banner); 300 close(fd); 301 return; 302 } 303 304 static int 305 userauth_none(Authctxt *authctxt) 306 { 307 /* disable method "none", only allowed one time */ 308 Authmethod *m = authmethod_lookup("none"); 309 if (m != NULL) 310 m->enabled = NULL; 311 packet_check_eom(); 312 userauth_banner(); 313 return authctxt->valid ? auth_password(authctxt, "") : 0; 314 } 315 316 static int 317 userauth_passwd(Authctxt *authctxt) 318 { 319 char *password; 320 int authenticated = 0; 321 int change; 322 u_int len; 323 change = packet_get_char(); 324 if (change) 325 log("password change not supported"); 326 password = packet_get_string(&len); 327 packet_check_eom(); 328 if (authctxt->valid && 329 auth_password(authctxt, password) == 1) 330 authenticated = 1; 331 memset(password, 0, len); 332 xfree(password); 333 return authenticated; 334 } 335 336 static int 337 userauth_kbdint(Authctxt *authctxt) 338 { 339 int authenticated = 0; 340 char *lang, *devs; 341 342 lang = packet_get_string(NULL); 343 devs = packet_get_string(NULL); 344 packet_check_eom(); 345 346 debug("keyboard-interactive devs %s", devs); 347 348 if (options.challenge_response_authentication) 349 authenticated = auth2_challenge(authctxt, devs); 350 351 xfree(devs); 352 xfree(lang); 353 return authenticated; 354 } 355 356 static int 357 userauth_pubkey(Authctxt *authctxt) 358 { 359 Buffer b; 360 Key *key; 361 char *pkalg, *pkblob, *sig; 362 u_int alen, blen, slen; 363 int have_sig, pktype; 364 int authenticated = 0; 365 366 if (!authctxt->valid) { 367 debug2("userauth_pubkey: disabled because of invalid user"); 368 return 0; 369 } 370 have_sig = packet_get_char(); 371 if (datafellows & SSH_BUG_PKAUTH) { 372 debug2("userauth_pubkey: SSH_BUG_PKAUTH"); 373 /* no explicit pkalg given */ 374 pkblob = packet_get_string(&blen); 375 buffer_init(&b); 376 buffer_append(&b, pkblob, blen); 377 /* so we have to extract the pkalg from the pkblob */ 378 pkalg = buffer_get_string(&b, &alen); 379 buffer_free(&b); 380 } else { 381 pkalg = packet_get_string(&alen); 382 pkblob = packet_get_string(&blen); 383 } 384 pktype = key_type_from_name(pkalg); 385 if (pktype == KEY_UNSPEC) { 386 /* this is perfectly legal */ 387 log("userauth_pubkey: unsupported public key algorithm: %s", pkalg); 388 xfree(pkalg); 389 xfree(pkblob); 390 return 0; 391 } 392 key = key_from_blob(pkblob, blen); 393 if (key != NULL) { 394 if (have_sig) { 395 sig = packet_get_string(&slen); 396 packet_check_eom(); 397 buffer_init(&b); 398 if (datafellows & SSH_OLD_SESSIONID) { 399 buffer_append(&b, session_id2, session_id2_len); 400 } else { 401 buffer_put_string(&b, session_id2, session_id2_len); 402 } 403 /* reconstruct packet */ 404 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 405 buffer_put_cstring(&b, authctxt->user); 406 buffer_put_cstring(&b, 407 datafellows & SSH_BUG_PKSERVICE ? 408 "ssh-userauth" : 409 authctxt->service); 410 if (datafellows & SSH_BUG_PKAUTH) { 411 buffer_put_char(&b, have_sig); 412 } else { 413 buffer_put_cstring(&b, "publickey"); 414 buffer_put_char(&b, have_sig); 415 buffer_put_cstring(&b, pkalg); 416 } 417 buffer_put_string(&b, pkblob, blen); 418 #ifdef DEBUG_PK 419 buffer_dump(&b); 420 #endif 421 /* test for correct signature */ 422 if (user_key_allowed(authctxt->pw, key) && 423 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 424 authenticated = 1; 425 buffer_clear(&b); 426 xfree(sig); 427 } else { 428 debug("test whether pkalg/pkblob are acceptable"); 429 packet_check_eom(); 430 431 /* XXX fake reply and always send PK_OK ? */ 432 /* 433 * XXX this allows testing whether a user is allowed 434 * to login: if you happen to have a valid pubkey this 435 * message is sent. the message is NEVER sent at all 436 * if a user is not allowed to login. is this an 437 * issue? -markus 438 */ 439 if (user_key_allowed(authctxt->pw, key)) { 440 packet_start(SSH2_MSG_USERAUTH_PK_OK); 441 packet_put_string(pkalg, alen); 442 packet_put_string(pkblob, blen); 443 packet_send(); 444 packet_write_wait(); 445 authctxt->postponed = 1; 446 } 447 } 448 if (authenticated != 1) 449 auth_clear_options(); 450 key_free(key); 451 } 452 debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); 453 xfree(pkalg); 454 xfree(pkblob); 455 return authenticated; 456 } 457 458 static int 459 userauth_hostbased(Authctxt *authctxt) 460 { 461 Buffer b; 462 Key *key; 463 char *pkalg, *pkblob, *sig, *cuser, *chost, *service; 464 u_int alen, blen, slen; 465 int pktype; 466 int authenticated = 0; 467 468 if (!authctxt->valid) { 469 debug2("userauth_hostbased: disabled because of invalid user"); 470 return 0; 471 } 472 pkalg = packet_get_string(&alen); 473 pkblob = packet_get_string(&blen); 474 chost = packet_get_string(NULL); 475 cuser = packet_get_string(NULL); 476 sig = packet_get_string(&slen); 477 478 debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", 479 cuser, chost, pkalg, slen); 480 #ifdef DEBUG_PK 481 debug("signature:"); 482 buffer_init(&b); 483 buffer_append(&b, sig, slen); 484 buffer_dump(&b); 485 buffer_free(&b); 486 #endif 487 pktype = key_type_from_name(pkalg); 488 if (pktype == KEY_UNSPEC) { 489 /* this is perfectly legal */ 490 log("userauth_hostbased: unsupported " 491 "public key algorithm: %s", pkalg); 492 goto done; 493 } 494 key = key_from_blob(pkblob, blen); 495 if (key == NULL) { 496 debug("userauth_hostbased: cannot decode key: %s", pkalg); 497 goto done; 498 } 499 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : 500 authctxt->service; 501 buffer_init(&b); 502 buffer_put_string(&b, session_id2, session_id2_len); 503 /* reconstruct packet */ 504 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 505 buffer_put_cstring(&b, authctxt->user); 506 buffer_put_cstring(&b, service); 507 buffer_put_cstring(&b, "hostbased"); 508 buffer_put_string(&b, pkalg, alen); 509 buffer_put_string(&b, pkblob, blen); 510 buffer_put_cstring(&b, chost); 511 buffer_put_cstring(&b, cuser); 512 #ifdef DEBUG_PK 513 buffer_dump(&b); 514 #endif 515 /* test for allowed key and correct signature */ 516 if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && 517 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 518 authenticated = 1; 519 520 buffer_clear(&b); 521 key_free(key); 522 523 done: 524 debug2("userauth_hostbased: authenticated %d", authenticated); 525 xfree(pkalg); 526 xfree(pkblob); 527 xfree(cuser); 528 xfree(chost); 529 xfree(sig); 530 return authenticated; 531 } 532 533 /* get current user */ 534 535 struct passwd* 536 auth_get_user(void) 537 { 538 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; 539 } 540 541 #define DELIM "," 542 543 static char * 544 authmethods_get(void) 545 { 546 Authmethod *method = NULL; 547 u_int size = 0; 548 char *list; 549 550 for (method = authmethods; method->name != NULL; method++) { 551 if (strcmp(method->name, "none") == 0) 552 continue; 553 if (method->enabled != NULL && *(method->enabled) != 0) { 554 if (size != 0) 555 size += strlen(DELIM); 556 size += strlen(method->name); 557 } 558 } 559 size++; /* trailing '\0' */ 560 list = xmalloc(size); 561 list[0] = '\0'; 562 563 for (method = authmethods; method->name != NULL; method++) { 564 if (strcmp(method->name, "none") == 0) 565 continue; 566 if (method->enabled != NULL && *(method->enabled) != 0) { 567 if (list[0] != '\0') 568 strlcat(list, DELIM, size); 569 strlcat(list, method->name, size); 570 } 571 } 572 return list; 573 } 574 575 static Authmethod * 576 authmethod_lookup(const char *name) 577 { 578 Authmethod *method = NULL; 579 if (name != NULL) 580 for (method = authmethods; method->name != NULL; method++) 581 if (method->enabled != NULL && 582 *(method->enabled) != 0 && 583 strcmp(name, method->name) == 0) 584 return method; 585 debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); 586 return NULL; 587 } 588 589 /* return 1 if user allows given key */ 590 static int 591 user_key_allowed2(struct passwd *pw, Key *key, char *file) 592 { 593 char line[8192]; 594 int found_key = 0; 595 FILE *f; 596 u_long linenum = 0; 597 struct stat st; 598 Key *found; 599 char *fp; 600 601 if (pw == NULL) 602 return 0; 603 604 /* Temporarily use the user's uid. */ 605 temporarily_use_uid(pw); 606 607 debug("trying public key file %s", file); 608 609 /* Fail quietly if file does not exist */ 610 if (stat(file, &st) < 0) { 611 /* Restore the privileged uid. */ 612 restore_uid(); 613 return 0; 614 } 615 /* Open the file containing the authorized keys. */ 616 f = fopen(file, "r"); 617 if (!f) { 618 /* Restore the privileged uid. */ 619 restore_uid(); 620 return 0; 621 } 622 if (options.strict_modes && 623 secure_filename(f, file, pw, line, sizeof(line)) != 0) { 624 fclose(f); 625 log("Authentication refused: %s", line); 626 restore_uid(); 627 return 0; 628 } 629 630 found_key = 0; 631 found = key_new(key->type); 632 633 while (fgets(line, sizeof(line), f)) { 634 char *cp, *options = NULL; 635 linenum++; 636 /* Skip leading whitespace, empty and comment lines. */ 637 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 638 ; 639 if (!*cp || *cp == '\n' || *cp == '#') 640 continue; 641 642 if (key_read(found, &cp) != 1) { 643 /* no key? check if there are options for this key */ 644 int quoted = 0; 645 debug2("user_key_allowed: check options: '%s'", cp); 646 options = cp; 647 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 648 if (*cp == '\\' && cp[1] == '"') 649 cp++; /* Skip both */ 650 else if (*cp == '"') 651 quoted = !quoted; 652 } 653 /* Skip remaining whitespace. */ 654 for (; *cp == ' ' || *cp == '\t'; cp++) 655 ; 656 if (key_read(found, &cp) != 1) { 657 debug2("user_key_allowed: advance: '%s'", cp); 658 /* still no key? advance to next line*/ 659 continue; 660 } 661 } 662 if (key_equal(found, key) && 663 auth_parse_options(pw, options, file, linenum) == 1) { 664 found_key = 1; 665 debug("matching key found: file %s, line %lu", 666 file, linenum); 667 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); 668 verbose("Found matching %s key: %s", 669 key_type(found), fp); 670 xfree(fp); 671 break; 672 } 673 } 674 restore_uid(); 675 fclose(f); 676 key_free(found); 677 if (!found_key) 678 debug2("key not found"); 679 return found_key; 680 } 681 682 /* check whether given key is in .ssh/authorized_keys* */ 683 static int 684 user_key_allowed(struct passwd *pw, Key *key) 685 { 686 int success; 687 char *file; 688 689 file = authorized_keys_file(pw); 690 success = user_key_allowed2(pw, key, file); 691 xfree(file); 692 if (success) 693 return success; 694 695 /* try suffix "2" for backward compat, too */ 696 file = authorized_keys_file2(pw); 697 success = user_key_allowed2(pw, key, file); 698 xfree(file); 699 return success; 700 } 701 702 /* return 1 if given hostkey is allowed */ 703 static int 704 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 705 Key *key) 706 { 707 const char *resolvedname, *ipaddr, *lookup; 708 HostStatus host_status; 709 int len; 710 711 resolvedname = get_canonical_hostname(options.reverse_mapping_check); 712 ipaddr = get_remote_ipaddr(); 713 714 debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", 715 chost, resolvedname, ipaddr); 716 717 if (options.hostbased_uses_name_from_packet_only) { 718 if (auth_rhosts2(pw, cuser, chost, chost) == 0) 719 return 0; 720 lookup = chost; 721 } else { 722 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { 723 debug2("stripping trailing dot from chost %s", chost); 724 chost[len - 1] = '\0'; 725 } 726 if (strcasecmp(resolvedname, chost) != 0) 727 log("userauth_hostbased mismatch: " 728 "client sends %s, but we resolve %s to %s", 729 chost, ipaddr, resolvedname); 730 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) 731 return 0; 732 lookup = resolvedname; 733 } 734 debug2("userauth_hostbased: access allowed by auth_rhosts2"); 735 736 host_status = check_key_in_hostfiles(pw, key, lookup, 737 _PATH_SSH_SYSTEM_HOSTFILE, 738 options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); 739 740 /* backward compat if no key has been found. */ 741 if (host_status == HOST_NEW) 742 host_status = check_key_in_hostfiles(pw, key, lookup, 743 _PATH_SSH_SYSTEM_HOSTFILE2, 744 options.ignore_user_known_hosts ? NULL : 745 _PATH_SSH_USER_HOSTFILE2); 746 747 return (host_status == HOST_OK); 748 } 749 750