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.56 2001/04/19 00:05:11 markus Exp $"); 27 RCSID("$FreeBSD$"); 28 29 #include <openssl/evp.h> 30 31 #include "ssh2.h" 32 #include "xmalloc.h" 33 #include "rsa.h" 34 #include "sshpty.h" 35 #include "packet.h" 36 #include "buffer.h" 37 #include "log.h" 38 #include "servconf.h" 39 #include "compat.h" 40 #include "channels.h" 41 #include "bufaux.h" 42 #include "auth.h" 43 #include "session.h" 44 #include "dispatch.h" 45 #include "key.h" 46 #include "cipher.h" 47 #include "kex.h" 48 #include "pathnames.h" 49 #include "uidswap.h" 50 #include "auth-options.h" 51 #include "misc.h" 52 #include "hostfile.h" 53 #include "canohost.h" 54 #include "tildexpand.h" 55 56 #ifdef HAVE_LOGIN_CAP 57 #include <login_cap.h> 58 #endif /* HAVE_LOGIN_CAP */ 59 60 /* import */ 61 extern ServerOptions options; 62 extern u_char *session_id2; 63 extern int session_id2_len; 64 65 static Authctxt *x_authctxt = NULL; 66 static int one = 1; 67 68 typedef struct Authmethod Authmethod; 69 struct Authmethod { 70 char *name; 71 int (*userauth)(Authctxt *authctxt); 72 int *enabled; 73 }; 74 75 /* protocol */ 76 77 void input_service_request(int type, int plen, void *ctxt); 78 void input_userauth_request(int type, int plen, void *ctxt); 79 void protocol_error(int type, int plen, void *ctxt); 80 81 /* helper */ 82 Authmethod *authmethod_lookup(const char *name); 83 char *authmethods_get(void); 84 int user_key_allowed(struct passwd *pw, Key *key); 85 int 86 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 87 Key *key); 88 89 /* auth */ 90 void userauth_banner(void); 91 void userauth_reply(Authctxt *authctxt, int authenticated); 92 int userauth_none(Authctxt *authctxt); 93 int userauth_passwd(Authctxt *authctxt); 94 int userauth_pubkey(Authctxt *authctxt); 95 int userauth_hostbased(Authctxt *authctxt); 96 int userauth_kbdint(Authctxt *authctxt); 97 98 Authmethod authmethods[] = { 99 {"none", 100 userauth_none, 101 &one}, 102 {"publickey", 103 userauth_pubkey, 104 &options.pubkey_authentication}, 105 {"password", 106 userauth_passwd, 107 &options.password_authentication}, 108 {"keyboard-interactive", 109 userauth_kbdint, 110 &options.kbd_interactive_authentication}, 111 {"hostbased", 112 userauth_hostbased, 113 &options.hostbased_authentication}, 114 {NULL, NULL, NULL} 115 }; 116 117 /* 118 * loop until authctxt->success == TRUE 119 */ 120 121 void 122 do_authentication2() 123 { 124 Authctxt *authctxt = authctxt_new(); 125 126 x_authctxt = authctxt; /*XXX*/ 127 128 #if defined(KRB4) || defined(KRB5) 129 /* turn off kerberos, not supported by SSH2 */ 130 options.kerberos_authentication = 0; 131 #endif 132 /* challenge-reponse is implemented via keyboard interactive */ 133 if (options.challenge_reponse_authentication) 134 options.kbd_interactive_authentication = 1; 135 136 dispatch_init(&protocol_error); 137 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 138 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 139 do_authenticated(authctxt); 140 } 141 142 void 143 protocol_error(int type, int plen, void *ctxt) 144 { 145 log("auth: protocol error: type %d plen %d", type, plen); 146 packet_start(SSH2_MSG_UNIMPLEMENTED); 147 packet_put_int(0); 148 packet_send(); 149 packet_write_wait(); 150 } 151 152 void 153 input_service_request(int type, int plen, void *ctxt) 154 { 155 Authctxt *authctxt = ctxt; 156 u_int len; 157 int accept = 0; 158 char *service = packet_get_string(&len); 159 packet_done(); 160 161 if (authctxt == NULL) 162 fatal("input_service_request: no authctxt"); 163 164 if (strcmp(service, "ssh-userauth") == 0) { 165 if (!authctxt->success) { 166 accept = 1; 167 /* now we can handle user-auth requests */ 168 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 169 } 170 } 171 /* XXX all other service requests are denied */ 172 173 if (accept) { 174 packet_start(SSH2_MSG_SERVICE_ACCEPT); 175 packet_put_cstring(service); 176 packet_send(); 177 packet_write_wait(); 178 } else { 179 debug("bad service request %s", service); 180 packet_disconnect("bad service request %s", service); 181 } 182 xfree(service); 183 } 184 185 void 186 input_userauth_request(int type, int plen, void *ctxt) 187 { 188 Authctxt *authctxt = ctxt; 189 Authmethod *m = NULL; 190 char *user, *service, *method, *style = NULL; 191 int authenticated = 0; 192 #ifdef HAVE_LOGIN_CAP 193 login_cap_t *lc; 194 #endif /* HAVE_LOGIN_CAP */ 195 #if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) 196 const char *from_host, *from_ip; 197 198 from_host = get_canonical_hostname(options.reverse_mapping_check); 199 from_ip = get_remote_ipaddr(); 200 #endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ 201 202 if (authctxt == NULL) 203 fatal("input_userauth_request: no authctxt"); 204 205 user = packet_get_string(NULL); 206 service = packet_get_string(NULL); 207 method = packet_get_string(NULL); 208 debug("userauth-request for user %s service %s method %s", user, service, method); 209 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 210 211 if ((style = strchr(user, ':')) != NULL) 212 *style++ = 0; 213 214 if (authctxt->attempt++ == 0) { 215 /* setup auth context */ 216 struct passwd *pw = NULL; 217 pw = getpwnam(user); 218 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { 219 authctxt->pw = pwcopy(pw); 220 authctxt->valid = 1; 221 debug2("input_userauth_request: setting up authctxt for %s", user); 222 #ifdef USE_PAM 223 start_pam(pw); 224 #endif 225 } else { 226 log("input_userauth_request: illegal user %s", user); 227 authctxt->pw = NULL; 228 } 229 setproctitle("%s", pw ? user : "unknown"); 230 authctxt->user = xstrdup(user); 231 authctxt->service = xstrdup(service); 232 authctxt->style = style ? xstrdup(style) : NULL; /* currently unused */ 233 } else if (authctxt->valid) { 234 if (strcmp(user, authctxt->user) != 0 || 235 strcmp(service, authctxt->service) != 0) { 236 log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)", 237 user, service, authctxt->user, authctxt->service); 238 authctxt->valid = 0; 239 } 240 } 241 242 #ifdef HAVE_LOGIN_CAP 243 if (authctxt->pw != NULL) { 244 lc = login_getpwclass(authctxt->pw); 245 if (lc == NULL) 246 lc = login_getclassbyname(NULL, authctxt->pw); 247 if (!auth_hostok(lc, from_host, from_ip)) { 248 log("Denied connection for %.200s from %.200s [%.200s].", 249 authctxt->pw->pw_name, from_host, from_ip); 250 packet_disconnect("Sorry, you are not allowed to connect."); 251 } 252 if (!auth_timeok(lc, time(NULL))) { 253 log("LOGIN %.200s REFUSED (TIME) FROM %.200s", 254 authctxt->pw->pw_name, from_host); 255 packet_disconnect("Logins not available right now."); 256 } 257 login_close(lc); 258 lc = NULL; 259 } 260 #endif /* HAVE_LOGIN_CAP */ 261 #ifdef LOGIN_ACCESS 262 if (authctxt->pw != NULL && 263 !login_access(authctxt->pw->pw_name, from_host)) { 264 log("Denied connection for %.200s from %.200s [%.200s].", 265 authctxt->pw->pw_name, from_host, from_ip); 266 packet_disconnect("Sorry, you are not allowed to connect."); 267 } 268 #endif /* LOGIN_ACCESS */ 269 /* reset state */ 270 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error); 271 authctxt->postponed = 0; 272 #ifdef BSD_AUTH 273 if (authctxt->as) { 274 auth_close(authctxt->as); 275 authctxt->as = NULL; 276 } 277 #endif 278 279 /* try to authenticate user */ 280 m = authmethod_lookup(method); 281 if (m != NULL) { 282 debug2("input_userauth_request: try method %s", method); 283 authenticated = m->userauth(authctxt); 284 } 285 #ifdef USE_PAM 286 if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL)) 287 authenticated = 0; 288 #endif /* USE_PAM */ 289 userauth_finish(authctxt, authenticated, method); 290 291 xfree(service); 292 xfree(user); 293 xfree(method); 294 } 295 296 void 297 userauth_finish(Authctxt *authctxt, int authenticated, char *method) 298 { 299 if (!authctxt->valid && authenticated) 300 fatal("INTERNAL ERROR: authenticated invalid user %s", 301 authctxt->user); 302 303 /* Special handling for root */ 304 if (authenticated && authctxt->pw->pw_uid == 0 && 305 !auth_root_allowed(method)) 306 authenticated = 0; 307 308 /* Log before sending the reply */ 309 auth_log(authctxt, authenticated, method, " ssh2"); 310 311 if (!authctxt->postponed) 312 userauth_reply(authctxt, authenticated); 313 } 314 315 void 316 userauth_banner(void) 317 { 318 struct stat st; 319 char *banner = NULL; 320 off_t len, n; 321 int fd; 322 323 if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) 324 return; 325 if ((fd = open(options.banner, O_RDONLY)) < 0) 326 return; 327 if (fstat(fd, &st) < 0) 328 goto done; 329 len = st.st_size; 330 banner = xmalloc(len + 1); 331 if ((n = read(fd, banner, len)) < 0) 332 goto done; 333 banner[n] = '\0'; 334 packet_start(SSH2_MSG_USERAUTH_BANNER); 335 packet_put_cstring(banner); 336 packet_put_cstring(""); /* language, unused */ 337 packet_send(); 338 debug("userauth_banner: sent"); 339 done: 340 if (banner) 341 xfree(banner); 342 close(fd); 343 return; 344 } 345 346 void 347 userauth_reply(Authctxt *authctxt, int authenticated) 348 { 349 char *methods; 350 351 /* XXX todo: check if multiple auth methods are needed */ 352 if (authenticated == 1) { 353 /* turn off userauth */ 354 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); 355 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 356 packet_send(); 357 packet_write_wait(); 358 /* now we can break out */ 359 authctxt->success = 1; 360 } else { 361 if (authctxt->failures++ > AUTH_FAIL_MAX) 362 packet_disconnect(AUTH_FAIL_MSG, authctxt->user); 363 methods = authmethods_get(); 364 packet_start(SSH2_MSG_USERAUTH_FAILURE); 365 packet_put_cstring(methods); 366 packet_put_char(0); /* XXX partial success, unused */ 367 packet_send(); 368 packet_write_wait(); 369 xfree(methods); 370 } 371 } 372 373 int 374 userauth_none(Authctxt *authctxt) 375 { 376 /* disable method "none", only allowed one time */ 377 Authmethod *m = authmethod_lookup("none"); 378 if (m != NULL) 379 m->enabled = NULL; 380 packet_done(); 381 userauth_banner(); 382 #ifdef USE_PAM 383 return authctxt->valid ? auth_pam_password(authctxt, "") : 0; 384 #else /* !USE_PAM */ 385 return authctxt->valid ? auth_password(authctxt, "") : 0; 386 #endif /* USE_PAM */ 387 } 388 389 int 390 userauth_passwd(Authctxt *authctxt) 391 { 392 char *password; 393 int authenticated = 0; 394 int change; 395 u_int len; 396 change = packet_get_char(); 397 if (change) 398 log("password change not supported"); 399 password = packet_get_string(&len); 400 packet_done(); 401 if (authctxt->valid && 402 #ifdef USE_PAM 403 auth_pam_password(authctxt, password) == 1 404 #else 405 auth_password(authctxt, password) == 1 406 #endif 407 ) 408 authenticated = 1; 409 memset(password, 0, len); 410 xfree(password); 411 return authenticated; 412 } 413 414 int 415 userauth_kbdint(Authctxt *authctxt) 416 { 417 int authenticated = 0; 418 char *lang = NULL; 419 char *devs = NULL; 420 421 lang = packet_get_string(NULL); 422 devs = packet_get_string(NULL); 423 packet_done(); 424 425 debug("keyboard-interactive language %s devs %s", lang, devs); 426 427 if (options.challenge_reponse_authentication) 428 authenticated = auth2_challenge(authctxt, devs); 429 430 xfree(lang); 431 xfree(devs); 432 return authenticated; 433 } 434 435 int 436 userauth_pubkey(Authctxt *authctxt) 437 { 438 Buffer b; 439 Key *key; 440 char *pkalg, *pkblob, *sig; 441 u_int alen, blen, slen; 442 int have_sig, pktype; 443 int authenticated = 0; 444 445 if (!authctxt->valid) { 446 debug2("userauth_pubkey: disabled because of invalid user"); 447 return 0; 448 } 449 have_sig = packet_get_char(); 450 if (datafellows & SSH_BUG_PKAUTH) { 451 debug2("userauth_pubkey: SSH_BUG_PKAUTH"); 452 /* no explicit pkalg given */ 453 pkblob = packet_get_string(&blen); 454 buffer_init(&b); 455 buffer_append(&b, pkblob, blen); 456 /* so we have to extract the pkalg from the pkblob */ 457 pkalg = buffer_get_string(&b, &alen); 458 buffer_free(&b); 459 } else { 460 pkalg = packet_get_string(&alen); 461 pkblob = packet_get_string(&blen); 462 } 463 pktype = key_type_from_name(pkalg); 464 if (pktype == KEY_UNSPEC) { 465 /* this is perfectly legal */ 466 log("userauth_pubkey: unsupported public key algorithm: %s", pkalg); 467 xfree(pkalg); 468 xfree(pkblob); 469 return 0; 470 } 471 key = key_from_blob(pkblob, blen); 472 if (key != NULL) { 473 if (have_sig) { 474 sig = packet_get_string(&slen); 475 packet_done(); 476 buffer_init(&b); 477 if (datafellows & SSH_OLD_SESSIONID) { 478 buffer_append(&b, session_id2, session_id2_len); 479 } else { 480 buffer_put_string(&b, session_id2, session_id2_len); 481 } 482 /* reconstruct packet */ 483 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 484 buffer_put_cstring(&b, authctxt->user); 485 buffer_put_cstring(&b, 486 datafellows & SSH_BUG_PKSERVICE ? 487 "ssh-userauth" : 488 authctxt->service); 489 if (datafellows & SSH_BUG_PKAUTH) { 490 buffer_put_char(&b, have_sig); 491 } else { 492 buffer_put_cstring(&b, "publickey"); 493 buffer_put_char(&b, have_sig); 494 buffer_put_cstring(&b, pkalg); 495 } 496 buffer_put_string(&b, pkblob, blen); 497 #ifdef DEBUG_PK 498 buffer_dump(&b); 499 #endif 500 /* test for correct signature */ 501 if (user_key_allowed(authctxt->pw, key) && 502 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 503 authenticated = 1; 504 buffer_clear(&b); 505 xfree(sig); 506 } else { 507 debug("test whether pkalg/pkblob are acceptable"); 508 packet_done(); 509 510 /* XXX fake reply and always send PK_OK ? */ 511 /* 512 * XXX this allows testing whether a user is allowed 513 * to login: if you happen to have a valid pubkey this 514 * message is sent. the message is NEVER sent at all 515 * if a user is not allowed to login. is this an 516 * issue? -markus 517 */ 518 if (user_key_allowed(authctxt->pw, key)) { 519 packet_start(SSH2_MSG_USERAUTH_PK_OK); 520 packet_put_string(pkalg, alen); 521 packet_put_string(pkblob, blen); 522 packet_send(); 523 packet_write_wait(); 524 authctxt->postponed = 1; 525 } 526 } 527 if (authenticated != 1) 528 auth_clear_options(); 529 key_free(key); 530 } 531 debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); 532 xfree(pkalg); 533 xfree(pkblob); 534 return authenticated; 535 } 536 537 int 538 userauth_hostbased(Authctxt *authctxt) 539 { 540 Buffer b; 541 Key *key; 542 char *pkalg, *pkblob, *sig, *cuser, *chost, *service; 543 u_int alen, blen, slen; 544 int pktype; 545 int authenticated = 0; 546 547 if (!authctxt->valid) { 548 debug2("userauth_hostbased: disabled because of invalid user"); 549 return 0; 550 } 551 pkalg = packet_get_string(&alen); 552 pkblob = packet_get_string(&blen); 553 chost = packet_get_string(NULL); 554 cuser = packet_get_string(NULL); 555 sig = packet_get_string(&slen); 556 557 debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", 558 cuser, chost, pkalg, slen); 559 #ifdef DEBUG_PK 560 debug("signature:"); 561 buffer_init(&b); 562 buffer_append(&b, sig, slen); 563 buffer_dump(&b); 564 buffer_free(&b); 565 #endif 566 pktype = key_type_from_name(pkalg); 567 if (pktype == KEY_UNSPEC) { 568 /* this is perfectly legal */ 569 log("userauth_hostbased: unsupported " 570 "public key algorithm: %s", pkalg); 571 goto done; 572 } 573 key = key_from_blob(pkblob, blen); 574 if (key == NULL) { 575 debug("userauth_hostbased: cannot decode key: %s", pkalg); 576 goto done; 577 } 578 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : 579 authctxt->service; 580 buffer_init(&b); 581 buffer_put_string(&b, session_id2, session_id2_len); 582 /* reconstruct packet */ 583 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 584 buffer_put_cstring(&b, authctxt->user); 585 buffer_put_cstring(&b, service); 586 buffer_put_cstring(&b, "hostbased"); 587 buffer_put_string(&b, pkalg, alen); 588 buffer_put_string(&b, pkblob, blen); 589 buffer_put_cstring(&b, chost); 590 buffer_put_cstring(&b, cuser); 591 #ifdef DEBUG_PK 592 buffer_dump(&b); 593 #endif 594 /* test for allowed key and correct signature */ 595 if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && 596 key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 597 authenticated = 1; 598 599 buffer_clear(&b); 600 key_free(key); 601 602 done: 603 debug2("userauth_hostbased: authenticated %d", authenticated); 604 xfree(pkalg); 605 xfree(pkblob); 606 xfree(cuser); 607 xfree(chost); 608 xfree(sig); 609 return authenticated; 610 } 611 612 /* get current user */ 613 614 struct passwd* 615 auth_get_user(void) 616 { 617 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; 618 } 619 620 #define DELIM "," 621 622 char * 623 authmethods_get(void) 624 { 625 Authmethod *method = NULL; 626 u_int size = 0; 627 char *list; 628 629 for (method = authmethods; method->name != NULL; method++) { 630 if (strcmp(method->name, "none") == 0) 631 continue; 632 if (method->enabled != NULL && *(method->enabled) != 0) { 633 if (size != 0) 634 size += strlen(DELIM); 635 size += strlen(method->name); 636 } 637 } 638 size++; /* trailing '\0' */ 639 list = xmalloc(size); 640 list[0] = '\0'; 641 642 for (method = authmethods; method->name != NULL; method++) { 643 if (strcmp(method->name, "none") == 0) 644 continue; 645 if (method->enabled != NULL && *(method->enabled) != 0) { 646 if (list[0] != '\0') 647 strlcat(list, DELIM, size); 648 strlcat(list, method->name, size); 649 } 650 } 651 return list; 652 } 653 654 Authmethod * 655 authmethod_lookup(const char *name) 656 { 657 Authmethod *method = NULL; 658 if (name != NULL) 659 for (method = authmethods; method->name != NULL; method++) 660 if (method->enabled != NULL && 661 *(method->enabled) != 0 && 662 strcmp(name, method->name) == 0) 663 return method; 664 debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); 665 return NULL; 666 } 667 668 /* return 1 if user allows given key */ 669 int 670 user_key_allowed(struct passwd *pw, Key *key) 671 { 672 char line[8192], file[MAXPATHLEN]; 673 int found_key = 0; 674 FILE *f; 675 u_long linenum = 0; 676 struct stat st; 677 Key *found; 678 679 if (pw == NULL) 680 return 0; 681 682 /* Temporarily use the user's uid. */ 683 temporarily_use_uid(pw); 684 685 /* The authorized keys. */ 686 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, 687 _PATH_SSH_USER_PERMITTED_KEYS2); 688 689 /* Fail quietly if file does not exist */ 690 if (stat(file, &st) < 0) { 691 /* Restore the privileged uid. */ 692 restore_uid(); 693 return 0; 694 } 695 /* Open the file containing the authorized keys. */ 696 f = fopen(file, "r"); 697 if (!f) { 698 /* Restore the privileged uid. */ 699 restore_uid(); 700 return 0; 701 } 702 if (options.strict_modes) { 703 int fail = 0; 704 char buf[1024]; 705 /* Check open file in order to avoid open/stat races */ 706 if (fstat(fileno(f), &st) < 0 || 707 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 708 (st.st_mode & 022) != 0) { 709 snprintf(buf, sizeof buf, 710 "%s authentication refused for %.100s: " 711 "bad ownership or modes for '%s'.", 712 key_type(key), pw->pw_name, file); 713 fail = 1; 714 } else { 715 /* Check path to _PATH_SSH_USER_PERMITTED_KEYS */ 716 int i; 717 static const char *check[] = { 718 "", _PATH_SSH_USER_DIR, NULL 719 }; 720 for (i = 0; check[i]; i++) { 721 snprintf(line, sizeof line, "%.500s/%.100s", 722 pw->pw_dir, check[i]); 723 if (stat(line, &st) < 0 || 724 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 725 (st.st_mode & 022) != 0) { 726 snprintf(buf, sizeof buf, 727 "%s authentication refused for %.100s: " 728 "bad ownership or modes for '%s'.", 729 key_type(key), pw->pw_name, line); 730 fail = 1; 731 break; 732 } 733 } 734 } 735 if (fail) { 736 fclose(f); 737 log("%s", buf); 738 restore_uid(); 739 return 0; 740 } 741 } 742 found_key = 0; 743 found = key_new(key->type); 744 745 while (fgets(line, sizeof(line), f)) { 746 char *cp, *options = NULL; 747 linenum++; 748 /* Skip leading whitespace, empty and comment lines. */ 749 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 750 ; 751 if (!*cp || *cp == '\n' || *cp == '#') 752 continue; 753 754 if (key_read(found, &cp) == -1) { 755 /* no key? check if there are options for this key */ 756 int quoted = 0; 757 debug2("user_key_allowed: check options: '%s'", cp); 758 options = cp; 759 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 760 if (*cp == '\\' && cp[1] == '"') 761 cp++; /* Skip both */ 762 else if (*cp == '"') 763 quoted = !quoted; 764 } 765 /* Skip remaining whitespace. */ 766 for (; *cp == ' ' || *cp == '\t'; cp++) 767 ; 768 if (key_read(found, &cp) == -1) { 769 debug2("user_key_allowed: advance: '%s'", cp); 770 /* still no key? advance to next line*/ 771 continue; 772 } 773 } 774 if (key_equal(found, key) && 775 auth_parse_options(pw, options, file, linenum) == 1) { 776 found_key = 1; 777 debug("matching key found: file %s, line %ld", 778 file, linenum); 779 break; 780 } 781 } 782 restore_uid(); 783 fclose(f); 784 key_free(found); 785 if (!found_key) 786 debug2("key not found"); 787 return found_key; 788 } 789 790 /* return 1 if given hostkey is allowed */ 791 int 792 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 793 Key *key) 794 { 795 Key *found; 796 const char *resolvedname, *ipaddr, *lookup; 797 struct stat st; 798 char *user_hostfile; 799 int host_status, len; 800 801 resolvedname = get_canonical_hostname(options.reverse_mapping_check); 802 ipaddr = get_remote_ipaddr(); 803 804 debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", 805 chost, resolvedname, ipaddr); 806 807 if (options.hostbased_uses_name_from_packet_only) { 808 if (auth_rhosts2(pw, cuser, chost, chost) == 0) 809 return 0; 810 lookup = chost; 811 } else { 812 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { 813 debug2("stripping trailing dot from chost %s", chost); 814 chost[len - 1] = '\0'; 815 } 816 if (strcasecmp(resolvedname, chost) != 0) 817 log("userauth_hostbased mismatch: " 818 "client sends %s, but we resolve %s to %s", 819 chost, ipaddr, resolvedname); 820 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) 821 return 0; 822 lookup = resolvedname; 823 } 824 debug2("userauth_hostbased: access allowed by auth_rhosts2"); 825 826 /* XXX this is copied from auth-rh-rsa.c and should be shared */ 827 found = key_new(key->type); 828 host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE2, lookup, 829 key, found, NULL); 830 831 if (host_status != HOST_OK && !options.ignore_user_known_hosts) { 832 user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE2, 833 pw->pw_uid); 834 if (options.strict_modes && 835 (stat(user_hostfile, &st) == 0) && 836 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 837 (st.st_mode & 022) != 0)) { 838 log("Hostbased authentication refused for %.100s: " 839 "bad owner or modes for %.200s", 840 pw->pw_name, user_hostfile); 841 } else { 842 temporarily_use_uid(pw); 843 host_status = check_host_in_hostfile(user_hostfile, 844 lookup, key, found, NULL); 845 restore_uid(); 846 } 847 xfree(user_hostfile); 848 } 849 key_free(found); 850 851 debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ? 852 "ok" : "not found", lookup); 853 return (host_status == HOST_OK); 854 } 855