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.20 2000/10/14 12:16:56 markus Exp $"); 27 RCSID("$FreeBSD$"); 28 29 #include <openssl/dsa.h> 30 #include <openssl/rsa.h> 31 #include <openssl/evp.h> 32 33 #include "xmalloc.h" 34 #include "rsa.h" 35 #include "ssh.h" 36 #include "pty.h" 37 #include "packet.h" 38 #include "buffer.h" 39 #include "servconf.h" 40 #include "compat.h" 41 #include "channels.h" 42 #include "bufaux.h" 43 #include "ssh2.h" 44 #include "auth.h" 45 #include "session.h" 46 #include "dispatch.h" 47 #include "auth.h" 48 #include "key.h" 49 #include "kex.h" 50 51 #include "dsa.h" 52 #include "uidswap.h" 53 #include "auth-options.h" 54 55 #ifdef HAVE_LOGIN_CAP 56 #include <login_cap.h> 57 #endif /* HAVE_LOGIN_CAP */ 58 59 /* import */ 60 extern ServerOptions options; 61 extern unsigned char *session_id2; 62 extern int session_id2_len; 63 64 static Authctxt *x_authctxt = NULL; 65 static int one = 1; 66 67 typedef struct Authmethod Authmethod; 68 struct Authmethod { 69 char *name; 70 int (*userauth)(Authctxt *authctxt); 71 int *enabled; 72 }; 73 74 /* protocol */ 75 76 void input_service_request(int type, int plen, void *ctxt); 77 void input_userauth_request(int type, int plen, void *ctxt); 78 void protocol_error(int type, int plen, void *ctxt); 79 80 81 /* helper */ 82 Authmethod *authmethod_lookup(const char *name); 83 struct passwd *pwcopy(struct passwd *pw); 84 int user_dsa_key_allowed(struct passwd *pw, Key *key); 85 char *authmethods_get(void); 86 87 /* auth */ 88 int userauth_none(Authctxt *authctxt); 89 int userauth_passwd(Authctxt *authctxt); 90 int userauth_pubkey(Authctxt *authctxt); 91 int userauth_kbdint(Authctxt *authctxt); 92 93 Authmethod authmethods[] = { 94 {"none", 95 userauth_none, 96 &one}, 97 {"publickey", 98 userauth_pubkey, 99 &options.dsa_authentication}, 100 {"keyboard-interactive", 101 userauth_kbdint, 102 &options.kbd_interactive_authentication}, 103 {"password", 104 userauth_passwd, 105 &options.password_authentication}, 106 {NULL, NULL, NULL} 107 }; 108 109 /* 110 * loop until authctxt->success == TRUE 111 */ 112 113 void 114 do_authentication2() 115 { 116 Authctxt *authctxt = xmalloc(sizeof(*authctxt)); 117 memset(authctxt, 'a', sizeof(*authctxt)); 118 authctxt->valid = 0; 119 authctxt->attempt = 0; 120 authctxt->success = 0; 121 x_authctxt = authctxt; /*XXX*/ 122 123 #ifdef KRB4 124 /* turn off kerberos, not supported by SSH2 */ 125 options.krb4_authentication = 0; 126 #endif 127 dispatch_init(&protocol_error); 128 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 129 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 130 do_authenticated2(); 131 } 132 133 void 134 protocol_error(int type, int plen, void *ctxt) 135 { 136 log("auth: protocol error: type %d plen %d", type, plen); 137 packet_start(SSH2_MSG_UNIMPLEMENTED); 138 packet_put_int(0); 139 packet_send(); 140 packet_write_wait(); 141 } 142 143 void 144 input_service_request(int type, int plen, void *ctxt) 145 { 146 Authctxt *authctxt = ctxt; 147 unsigned int len; 148 int accept = 0; 149 char *service = packet_get_string(&len); 150 packet_done(); 151 152 if (authctxt == NULL) 153 fatal("input_service_request: no authctxt"); 154 155 if (strcmp(service, "ssh-userauth") == 0) { 156 if (!authctxt->success) { 157 accept = 1; 158 /* now we can handle user-auth requests */ 159 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 160 } 161 } 162 /* XXX all other service requests are denied */ 163 164 if (accept) { 165 packet_start(SSH2_MSG_SERVICE_ACCEPT); 166 packet_put_cstring(service); 167 packet_send(); 168 packet_write_wait(); 169 } else { 170 debug("bad service request %s", service); 171 packet_disconnect("bad service request %s", service); 172 } 173 xfree(service); 174 } 175 176 void 177 input_userauth_request(int type, int plen, void *ctxt) 178 { 179 Authctxt *authctxt = ctxt; 180 Authmethod *m = NULL; 181 int authenticated = 0; 182 char *user, *service, *method, *authmsg = NULL; 183 #ifdef HAVE_LOGIN_CAP 184 login_cap_t *lc; 185 #endif /* HAVE_LOGIN_CAP */ 186 #if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) 187 const char *from_host, *from_ip; 188 189 from_host = get_canonical_hostname(); 190 from_ip = get_remote_ipaddr(); 191 #endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ 192 193 if (authctxt == NULL) 194 fatal("input_userauth_request: no authctxt"); 195 if (authctxt->attempt++ >= AUTH_FAIL_MAX) 196 packet_disconnect("too many failed userauth_requests"); 197 198 user = packet_get_string(NULL); 199 service = packet_get_string(NULL); 200 method = packet_get_string(NULL); 201 debug("userauth-request for user %s service %s method %s", user, service, method); 202 debug("attempt #%d", authctxt->attempt); 203 204 if (authctxt->attempt == 1) { 205 /* setup auth context */ 206 struct passwd *pw = NULL; 207 setproctitle("%s", user); 208 pw = getpwnam(user); 209 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { 210 authctxt->pw = pwcopy(pw); 211 authctxt->valid = 1; 212 debug2("input_userauth_request: setting up authctxt for %s", user); 213 #ifdef USE_PAM 214 start_pam(pw); 215 #endif 216 } else { 217 log("input_userauth_request: illegal user %s", user); 218 } 219 authctxt->user = xstrdup(user); 220 authctxt->service = xstrdup(service); 221 } else if (authctxt->valid) { 222 if (strcmp(user, authctxt->user) != 0 || 223 strcmp(service, authctxt->service) != 0) { 224 log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)", 225 user, service, authctxt->user, authctxt->service); 226 authctxt->valid = 0; 227 } 228 } 229 230 #ifdef HAVE_LOGIN_CAP 231 if (authctxt->pw != NULL) { 232 lc = login_getpwclass(authctxt->pw); 233 if (lc == NULL) 234 lc = login_getclassbyname(NULL, authctxt->pw); 235 if (!auth_hostok(lc, from_host, from_ip)) { 236 log("Denied connection for %.200s from %.200s [%.200s].", 237 authctxt->pw->pw_name, from_host, from_ip); 238 packet_disconnect("Sorry, you are not allowed to connect."); 239 } 240 if (!auth_timeok(lc, time(NULL))) { 241 log("LOGIN %.200s REFUSED (TIME) FROM %.200s", 242 authctxt->pw->pw_name, from_host); 243 packet_disconnect("Logins not available right now."); 244 } 245 login_close(lc); 246 lc = NULL; 247 } 248 #endif /* HAVE_LOGIN_CAP */ 249 #ifdef LOGIN_ACCESS 250 if (authctxt->pw != NULL && 251 !login_access(authctxt->pw->pw_name, from_host)) { 252 log("Denied connection for %.200s from %.200s [%.200s].", 253 authctxt->pw->pw_name, from_host, from_ip); 254 packet_disconnect("Sorry, you are not allowed to connect."); 255 } 256 #endif /* LOGIN_ACCESS */ 257 258 m = authmethod_lookup(method); 259 if (m != NULL) { 260 debug2("input_userauth_request: try method %s", method); 261 authenticated = m->userauth(authctxt); 262 } else { 263 debug2("input_userauth_request: unsupported method %s", method); 264 } 265 if (!authctxt->valid && authenticated == 1) { 266 log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method); 267 authenticated = 0; 268 } 269 270 /* Special handling for root */ 271 if (authenticated == 1 && 272 authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) { 273 authenticated = 0; 274 log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname()); 275 } 276 277 #ifdef USE_PAM 278 if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL)) 279 authenticated = 0; 280 #endif /* USE_PAM */ 281 282 /* Log before sending the reply */ 283 userauth_log(authctxt, authenticated, method); 284 userauth_reply(authctxt, authenticated); 285 286 xfree(service); 287 xfree(user); 288 xfree(method); 289 } 290 291 292 void 293 userauth_log(Authctxt *authctxt, int authenticated, char *method) 294 { 295 void (*authlog) (const char *fmt,...) = verbose; 296 char *user = NULL, *authmsg = NULL; 297 298 /* Raise logging level */ 299 if (authenticated == 1 || 300 !authctxt->valid || 301 authctxt->attempt >= AUTH_FAIL_LOG || 302 strcmp(method, "password") == 0) 303 authlog = log; 304 305 if (authenticated == 1) { 306 authmsg = "Accepted"; 307 } else if (authenticated == 0) { 308 authmsg = "Failed"; 309 } else { 310 authmsg = "Postponed"; 311 } 312 313 if (authctxt->valid) { 314 user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user; 315 } else { 316 user = "NOUSER"; 317 } 318 319 authlog("%s %s for %.200s from %.200s port %d ssh2", 320 authmsg, 321 method, 322 user, 323 get_remote_ipaddr(), 324 get_remote_port()); 325 } 326 327 void 328 userauth_reply(Authctxt *authctxt, int authenticated) 329 { 330 /* XXX todo: check if multiple auth methods are needed */ 331 if (authenticated == 1) { 332 /* turn off userauth */ 333 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); 334 packet_start(SSH2_MSG_USERAUTH_SUCCESS); 335 packet_send(); 336 packet_write_wait(); 337 /* now we can break out */ 338 authctxt->success = 1; 339 } else if (authenticated == 0) { 340 char *methods = authmethods_get(); 341 packet_start(SSH2_MSG_USERAUTH_FAILURE); 342 packet_put_cstring(methods); 343 packet_put_char(0); /* XXX partial success, unused */ 344 packet_send(); 345 packet_write_wait(); 346 xfree(methods); 347 } else { 348 /* do nothing, we did already send a reply */ 349 } 350 } 351 352 int 353 userauth_none(Authctxt *authctxt) 354 { 355 /* disable method "none", only allowed one time */ 356 Authmethod *m = authmethod_lookup("none"); 357 if (m != NULL) 358 m->enabled = NULL; 359 packet_done(); 360 #ifdef USE_PAM 361 return authctxt->valid ? auth_pam_password(authctxt->pw, "") : 0; 362 #else /* !USE_PAM */ 363 return authctxt->valid ? auth_password(authctxt->pw, "") : 0; 364 #endif /* USE_PAM */ 365 } 366 367 int 368 userauth_passwd(Authctxt *authctxt) 369 { 370 char *password; 371 int authenticated = 0; 372 int change; 373 unsigned int len; 374 change = packet_get_char(); 375 if (change) 376 log("password change not supported"); 377 password = packet_get_string(&len); 378 packet_done(); 379 if (authctxt->valid && 380 #ifdef USE_PAM 381 auth_pam_password(authctxt->pw, password) == 1 382 #else 383 auth_password(authctxt->pw, password) == 1 384 #endif 385 ) 386 authenticated = 1; 387 memset(password, 0, len); 388 xfree(password); 389 return authenticated; 390 } 391 392 int 393 userauth_kbdint(Authctxt *authctxt) 394 { 395 int authenticated = 0; 396 char *lang = NULL; 397 char *devs = NULL; 398 399 lang = packet_get_string(NULL); 400 devs = packet_get_string(NULL); 401 packet_done(); 402 403 debug("keyboard-interactive language %s devs %s", lang, devs); 404 #ifdef SKEY 405 /* XXX hardcoded, we should look at devs */ 406 if (options.skey_authentication != 0) 407 authenticated = auth2_skey(authctxt); 408 #endif 409 xfree(lang); 410 xfree(devs); 411 return authenticated; 412 } 413 414 int 415 userauth_pubkey(Authctxt *authctxt) 416 { 417 Buffer b; 418 Key *key; 419 char *pkalg, *pkblob, *sig; 420 unsigned int alen, blen, slen; 421 int have_sig; 422 int authenticated = 0; 423 424 if (!authctxt->valid) { 425 debug2("userauth_pubkey: disabled because of invalid user"); 426 return 0; 427 } 428 have_sig = packet_get_char(); 429 pkalg = packet_get_string(&alen); 430 if (strcmp(pkalg, KEX_DSS) != 0) { 431 log("bad pkalg %s", pkalg); /*XXX*/ 432 xfree(pkalg); 433 return 0; 434 } 435 pkblob = packet_get_string(&blen); 436 key = dsa_key_from_blob(pkblob, blen); 437 if (key != NULL) { 438 if (have_sig) { 439 sig = packet_get_string(&slen); 440 packet_done(); 441 buffer_init(&b); 442 if (datafellows & SSH_OLD_SESSIONID) { 443 buffer_append(&b, session_id2, session_id2_len); 444 } else { 445 buffer_put_string(&b, session_id2, session_id2_len); 446 } 447 /* reconstruct packet */ 448 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 449 buffer_put_cstring(&b, authctxt->user); 450 buffer_put_cstring(&b, 451 datafellows & SSH_BUG_PUBKEYAUTH ? 452 "ssh-userauth" : 453 authctxt->service); 454 buffer_put_cstring(&b, "publickey"); 455 buffer_put_char(&b, have_sig); 456 buffer_put_cstring(&b, KEX_DSS); 457 buffer_put_string(&b, pkblob, blen); 458 #ifdef DEBUG_DSS 459 buffer_dump(&b); 460 #endif 461 /* test for correct signature */ 462 if (user_dsa_key_allowed(authctxt->pw, key) && 463 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 464 authenticated = 1; 465 buffer_clear(&b); 466 xfree(sig); 467 } else { 468 debug("test whether pkalg/pkblob are acceptable"); 469 packet_done(); 470 471 /* XXX fake reply and always send PK_OK ? */ 472 /* 473 * XXX this allows testing whether a user is allowed 474 * to login: if you happen to have a valid pubkey this 475 * message is sent. the message is NEVER sent at all 476 * if a user is not allowed to login. is this an 477 * issue? -markus 478 */ 479 if (user_dsa_key_allowed(authctxt->pw, key)) { 480 packet_start(SSH2_MSG_USERAUTH_PK_OK); 481 packet_put_string(pkalg, alen); 482 packet_put_string(pkblob, blen); 483 packet_send(); 484 packet_write_wait(); 485 authenticated = -1; 486 } 487 } 488 if (authenticated != 1) 489 auth_clear_options(); 490 key_free(key); 491 } 492 xfree(pkalg); 493 xfree(pkblob); 494 return authenticated; 495 } 496 497 /* get current user */ 498 499 struct passwd* 500 auth_get_user(void) 501 { 502 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; 503 } 504 505 #define DELIM "," 506 507 char * 508 authmethods_get(void) 509 { 510 Authmethod *method = NULL; 511 unsigned int size = 0; 512 char *list; 513 514 for (method = authmethods; method->name != NULL; method++) { 515 if (strcmp(method->name, "none") == 0) 516 continue; 517 if (method->enabled != NULL && *(method->enabled) != 0) { 518 if (size != 0) 519 size += strlen(DELIM); 520 size += strlen(method->name); 521 } 522 } 523 size++; /* trailing '\0' */ 524 list = xmalloc(size); 525 list[0] = '\0'; 526 527 for (method = authmethods; method->name != NULL; method++) { 528 if (strcmp(method->name, "none") == 0) 529 continue; 530 if (method->enabled != NULL && *(method->enabled) != 0) { 531 if (list[0] != '\0') 532 strlcat(list, DELIM, size); 533 strlcat(list, method->name, size); 534 } 535 } 536 return list; 537 } 538 539 Authmethod * 540 authmethod_lookup(const char *name) 541 { 542 Authmethod *method = NULL; 543 if (name != NULL) 544 for (method = authmethods; method->name != NULL; method++) 545 if (method->enabled != NULL && 546 *(method->enabled) != 0 && 547 strcmp(name, method->name) == 0) 548 return method; 549 debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); 550 return NULL; 551 } 552 553 /* return 1 if user allows given key */ 554 int 555 user_dsa_key_allowed(struct passwd *pw, Key *key) 556 { 557 char line[8192], file[1024]; 558 int found_key = 0; 559 unsigned int bits = -1; 560 FILE *f; 561 unsigned long linenum = 0; 562 struct stat st; 563 Key *found; 564 565 if (pw == NULL) 566 return 0; 567 568 /* Temporarily use the user's uid. */ 569 temporarily_use_uid(pw->pw_uid); 570 571 /* The authorized keys. */ 572 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, 573 SSH_USER_PERMITTED_KEYS2); 574 575 /* Fail quietly if file does not exist */ 576 if (stat(file, &st) < 0) { 577 /* Restore the privileged uid. */ 578 restore_uid(); 579 return 0; 580 } 581 /* Open the file containing the authorized keys. */ 582 f = fopen(file, "r"); 583 if (!f) { 584 /* Restore the privileged uid. */ 585 restore_uid(); 586 return 0; 587 } 588 if (options.strict_modes) { 589 int fail = 0; 590 char buf[1024]; 591 /* Check open file in order to avoid open/stat races */ 592 if (fstat(fileno(f), &st) < 0 || 593 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 594 (st.st_mode & 022) != 0) { 595 snprintf(buf, sizeof buf, 596 "%s authentication refused for %.100s: " 597 "bad ownership or modes for '%s'.", 598 key_type(key), pw->pw_name, file); 599 fail = 1; 600 } else { 601 /* Check path to SSH_USER_PERMITTED_KEYS */ 602 int i; 603 static const char *check[] = { 604 "", SSH_USER_DIR, NULL 605 }; 606 for (i = 0; check[i]; i++) { 607 snprintf(line, sizeof line, "%.500s/%.100s", 608 pw->pw_dir, check[i]); 609 if (stat(line, &st) < 0 || 610 (st.st_uid != 0 && st.st_uid != pw->pw_uid) || 611 (st.st_mode & 022) != 0) { 612 snprintf(buf, sizeof buf, 613 "%s authentication refused for %.100s: " 614 "bad ownership or modes for '%s'.", 615 key_type(key), pw->pw_name, line); 616 fail = 1; 617 break; 618 } 619 } 620 } 621 if (fail) { 622 fclose(f); 623 log("%s",buf); 624 restore_uid(); 625 return 0; 626 } 627 } 628 found_key = 0; 629 found = key_new(key->type); 630 631 while (fgets(line, sizeof(line), f)) { 632 char *cp, *options = NULL; 633 linenum++; 634 /* Skip leading whitespace, empty and comment lines. */ 635 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 636 ; 637 if (!*cp || *cp == '\n' || *cp == '#') 638 continue; 639 640 bits = key_read(found, &cp); 641 if (bits == 0) { 642 /* no key? check if there are options for this key */ 643 int quoted = 0; 644 options = cp; 645 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 646 if (*cp == '\\' && cp[1] == '"') 647 cp++; /* Skip both */ 648 else if (*cp == '"') 649 quoted = !quoted; 650 } 651 /* Skip remaining whitespace. */ 652 for (; *cp == ' ' || *cp == '\t'; cp++) 653 ; 654 bits = key_read(found, &cp); 655 if (bits == 0) { 656 /* still no key? advance to next line*/ 657 continue; 658 } 659 } 660 if (key_equal(found, key) && 661 auth_parse_options(pw, options, linenum) == 1) { 662 found_key = 1; 663 debug("matching key found: file %s, line %ld", 664 file, linenum); 665 break; 666 } 667 } 668 restore_uid(); 669 fclose(f); 670 key_free(found); 671 return found_key; 672 } 673 674 struct passwd * 675 pwcopy(struct passwd *pw) 676 { 677 struct passwd *copy = xmalloc(sizeof(*copy)); 678 memset(copy, 0, sizeof(*copy)); 679 copy->pw_name = xstrdup(pw->pw_name); 680 copy->pw_passwd = xstrdup(pw->pw_passwd); 681 copy->pw_uid = pw->pw_uid; 682 copy->pw_gid = pw->pw_gid; 683 copy->pw_class = xstrdup(pw->pw_class); 684 copy->pw_dir = xstrdup(pw->pw_dir); 685 copy->pw_shell = xstrdup(pw->pw_shell); 686 copy->pw_expire = pw->pw_expire; 687 copy->pw_change = pw->pw_change; 688 return copy; 689 } 690