auth1.c revision 74147
1/* 2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * All rights reserved 4 * 5 * As far as I am concerned, the code I have written for this software 6 * can be used freely for any purpose. Any derived versions of this 7 * software must be clearly marked as such, and if the derived work is 8 * incompatible with the protocol description in the RFC file, it must be 9 * called by a name other than "ssh" or "Secure Shell". 10 */ 11 12#include "includes.h" 13RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $"); 14RCSID("$FreeBSD: head/crypto/openssh/auth1.c 74147 2001-03-12 08:14:22Z assar $"); 15 16#include "xmalloc.h" 17#include "rsa.h" 18#include "ssh.h" 19#include "packet.h" 20#include "buffer.h" 21#include "mpaux.h" 22#include "servconf.h" 23#include "compat.h" 24#include "auth.h" 25#include "session.h" 26#include <login_cap.h> 27#include <security/pam_appl.h> 28 29#ifdef KRB5 30extern krb5_context ssh_context; 31krb5_principal tkt_client = NULL; /* Principal from the received ticket. 32Also is used as an indication of succesful krb5 authentization. */ 33#endif 34 35/* import */ 36extern ServerOptions options; 37extern char *forced_command; 38 39/* 40 * convert ssh auth msg type into description 41 */ 42char * 43get_authname(int type) 44{ 45 static char buf[1024]; 46 switch (type) { 47 case SSH_CMSG_AUTH_PASSWORD: 48 return "password"; 49 case SSH_CMSG_AUTH_RSA: 50 return "rsa"; 51 case SSH_CMSG_AUTH_RHOSTS_RSA: 52 return "rhosts-rsa"; 53 case SSH_CMSG_AUTH_RHOSTS: 54 return "rhosts"; 55#if defined(KRB4) || defined(KRB5) 56 case SSH_CMSG_AUTH_KERBEROS: 57 return "kerberos"; 58#endif 59#ifdef SKEY 60 case SSH_CMSG_AUTH_TIS_RESPONSE: 61 return "s/key"; 62#endif 63 } 64 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); 65 return buf; 66} 67 68/* 69 * read packets and try to authenticate local user 'luser'. 70 * return if authentication is successfull. not that pw == NULL 71 * if the user does not exists or is not allowed to login. 72 * each auth method has to 'fake' authentication for nonexisting 73 * users. 74 */ 75void 76do_authloop(struct passwd * pw, char *luser) 77{ 78 int authenticated = 0; 79 int attempt = 0; 80 unsigned int bits; 81 RSA *client_host_key; 82 BIGNUM *n; 83 char *client_user, *password; 84 char user[1024]; 85 unsigned int dlen; 86 int plen, nlen, elen; 87 unsigned int ulen; 88 int type = 0; 89 void (*authlog) (const char *fmt,...) = verbose; 90#ifdef HAVE_LOGIN_CAP 91 login_cap_t *lc; 92#endif /* HAVE_LOGIN_CAP */ 93#ifdef USE_PAM 94 struct inverted_pam_cookie *pam_cookie; 95#endif /* USE_PAM */ 96#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) 97 const char *from_host, *from_ip; 98 99 from_host = get_canonical_hostname(); 100 from_ip = get_remote_ipaddr(); 101#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ 102#if 0 103#ifdef KRB5 104 { 105 krb5_error_code ret; 106 107 ret = krb5_init_context(&ssh_context); 108 if (ret) 109 verbose("Error while initializing Kerberos V5."); 110 krb5_init_ets(ssh_context); 111 112 } 113#endif /* KRB5 */ 114#endif 115 116 /* Indicate that authentication is needed. */ 117 packet_start(SSH_SMSG_FAILURE); 118 packet_send(); 119 packet_write_wait(); 120 121 client_user = NULL; 122 123 for (attempt = 1;; attempt++) { 124 /* default to fail */ 125 authenticated = 0; 126 127 strlcpy(user, "", sizeof user); 128 129 /* Get a packet from the client. */ 130 type = packet_read(&plen); 131 132 /* Process the packet. */ 133 switch (type) { 134#ifdef AFS 135#ifndef KRB5 136 case SSH_CMSG_HAVE_KRB4_TGT: 137 if (!options.krb4_tgt_passing) { 138 /* packet_get_all(); */ 139 verbose("Kerberos v4 tgt passing disabled."); 140 break; 141 } else { 142 /* Accept Kerberos v4 tgt. */ 143 char *tgt = packet_get_string(&dlen); 144 packet_integrity_check(plen, 4 + dlen, type); 145 if (!auth_krb4_tgt(pw, tgt)) 146 verbose("Kerberos v4 tgt REFUSED for %s", luser); 147 xfree(tgt); 148 } 149 continue; 150#endif /* !KRB5 */ 151 case SSH_CMSG_HAVE_AFS_TOKEN: 152 if (!options.afs_token_passing || !k_hasafs()) { 153 verbose("AFS token passing disabled."); 154 break; 155 } else { 156 /* Accept AFS token. */ 157 char *token_string = packet_get_string(&dlen); 158 packet_integrity_check(plen, 4 + dlen, type); 159 if (!auth_afs_token(pw, token_string)) 160 verbose("AFS token REFUSED for %.100s", luser); 161 xfree(token_string); 162 } 163 continue; 164#endif /* AFS */ 165#if defined(KRB4) || defined(KRB5) 166 case SSH_CMSG_AUTH_KERBEROS: 167 if (!options.kerberos_authentication) { 168 verbose("Kerberos authentication disabled."); 169 } else { 170 unsigned int length; 171 char *kdata = packet_get_string(&length); 172 packet_integrity_check(plen, 4 + length, type); 173 174 /* 4 == KRB_PROT_VERSION */ 175 if (kdata[0] == 4) { 176#ifndef KRB4 177 verbose("Kerberos v4 authentication disabled."); 178#else 179 char *tkt_user = NULL; 180 KTEXT_ST auth; 181 auth.length = length; 182 if (auth.length < MAX_KTXT_LEN) 183 memcpy(auth.dat, kdata, auth.length); 184 185 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user); 186 187 if (authenticated) { 188 snprintf(user, sizeof user, " tktuser %s", tkt_user); 189 xfree(tkt_user); 190 } 191 #endif /* KRB4 */ 192 } else { 193#ifndef KRB5 194 verbose("Kerberos v5 authentication disabled."); 195#else 196 krb5_data k5data; 197 k5data.length = length; 198 k5data.data = kdata; 199 #if 0 200 if (krb5_init_context(&ssh_context)) { 201 verbose("Error while initializing Kerberos V5."); 202 break; 203 } 204 krb5_init_ets(ssh_context); 205 #endif 206 /* pw->name is passed just for logging purposes */ 207 if (auth_krb5(pw->pw_name, &k5data, &tkt_client)) { 208 /* authorize client against .k5login */ 209 if (krb5_kuserok(ssh_context, 210 tkt_client, 211 pw->pw_name)) 212 authenticated = 1; 213 } 214#endif /* KRB5 */ 215 } 216 xfree(kdata); 217 } 218 break; 219#endif /* KRB4 || KRB5 */ 220 221 case SSH_CMSG_AUTH_RHOSTS: 222 if (!options.rhosts_authentication) { 223 verbose("Rhosts authentication disabled."); 224 break; 225 } 226 /* 227 * Get client user name. Note that we just have to 228 * trust the client; this is one reason why rhosts 229 * authentication is insecure. (Another is 230 * IP-spoofing on a local network.) 231 */ 232 client_user = packet_get_string(&ulen); 233 packet_integrity_check(plen, 4 + ulen, type); 234 235 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ 236 authenticated = auth_rhosts(pw, client_user); 237 238 snprintf(user, sizeof user, " ruser %s", client_user); 239 break; 240 241 case SSH_CMSG_AUTH_RHOSTS_RSA: 242 if (!options.rhosts_rsa_authentication) { 243 verbose("Rhosts with RSA authentication disabled."); 244 break; 245 } 246 /* 247 * Get client user name. Note that we just have to 248 * trust the client; root on the client machine can 249 * claim to be any user. 250 */ 251 client_user = packet_get_string(&ulen); 252 253 /* Get the client host key. */ 254 client_host_key = RSA_new(); 255 if (client_host_key == NULL) 256 fatal("RSA_new failed"); 257 client_host_key->e = BN_new(); 258 client_host_key->n = BN_new(); 259 if (client_host_key->e == NULL || client_host_key->n == NULL) 260 fatal("BN_new failed"); 261 bits = packet_get_int(); 262 packet_get_bignum(client_host_key->e, &elen); 263 packet_get_bignum(client_host_key->n, &nlen); 264 265 if (bits != BN_num_bits(client_host_key->n)) 266 verbose("Warning: keysize mismatch for client_host_key: " 267 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits); 268 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type); 269 270 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key); 271 RSA_free(client_host_key); 272 273 snprintf(user, sizeof user, " ruser %s", client_user); 274 break; 275 276 case SSH_CMSG_AUTH_RSA: 277 if (!options.rsa_authentication) { 278 verbose("RSA authentication disabled."); 279 break; 280 } 281 /* RSA authentication requested. */ 282 n = BN_new(); 283 packet_get_bignum(n, &nlen); 284 packet_integrity_check(plen, nlen, type); 285 authenticated = auth_rsa(pw, n); 286 BN_clear_free(n); 287 break; 288 289 case SSH_CMSG_AUTH_PASSWORD: 290 if (!options.password_authentication) { 291 verbose("Password authentication disabled."); 292 break; 293 } 294 /* 295 * Read user password. It is in plain text, but was 296 * transmitted over the encrypted channel so it is 297 * not visible to an outside observer. 298 */ 299 password = packet_get_string(&dlen); 300 packet_integrity_check(plen, 4 + dlen, type); 301 302#ifdef USE_PAM 303 /* Do PAM auth with password */ 304 authenticated = auth_pam_password(pw, password); 305#else /* !USE_PAM */ 306 /* Try authentication with the password. */ 307 authenticated = auth_password(pw, password); 308#endif /* USE_PAM */ 309 310 memset(password, 0, strlen(password)); 311 xfree(password); 312 break; 313 314#ifdef USE_PAM 315 case SSH_CMSG_AUTH_TIS: 316 debug("rcvd SSH_CMSG_AUTH_TIS: Trying PAM"); 317 pam_cookie = ipam_start_auth("csshd", pw->pw_name); 318 /* We now have data available to send as a challenge */ 319 if (pam_cookie->num_msg != 1 || 320 (pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_OFF && 321 pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_ON)) { 322 /* We got several challenges or an unknown challenge type */ 323 ipam_free_cookie(pam_cookie); 324 pam_cookie = NULL; 325 break; 326 } 327 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); 328 packet_put_string(pam_cookie->msg[0]->msg, strlen(pam_cookie->msg[0]->msg)); 329 packet_send(); 330 packet_write_wait(); 331 continue; 332 case SSH_CMSG_AUTH_TIS_RESPONSE: 333 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); 334 if (pam_cookie == NULL) 335 break; 336 { 337 char *response = packet_get_string(&dlen); 338 339 packet_integrity_check(plen, 4 + dlen, type); 340 pam_cookie->resp[0]->resp = strdup(response); 341 xfree(response); 342 authenticated = ipam_complete_auth(pam_cookie); 343 ipam_free_cookie(pam_cookie); 344 pam_cookie = NULL; 345 } 346 break; 347#elif defined(SKEY) 348 case SSH_CMSG_AUTH_TIS: 349 debug("rcvd SSH_CMSG_AUTH_TIS"); 350 if (options.skey_authentication == 1) { 351 char *skeyinfo = pw ? opie_keyinfo(pw->pw_name) : 352 NULL; 353 if (skeyinfo == NULL) { 354 debug("generating fake skeyinfo for %.100s.", luser); 355 skeyinfo = skey_fake_keyinfo(luser); 356 } 357 if (skeyinfo != NULL) { 358 /* we send our s/key- in tis-challenge messages */ 359 debug("sending challenge '%s'", skeyinfo); 360 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); 361 packet_put_cstring(skeyinfo); 362 packet_send(); 363 packet_write_wait(); 364 continue; 365 } 366 } 367 break; 368 case SSH_CMSG_AUTH_TIS_RESPONSE: 369 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); 370 if (options.skey_authentication == 1) { 371 char *response = packet_get_string(&dlen); 372 debug("skey response == '%s'", response); 373 packet_integrity_check(plen, 4 + dlen, type); 374 authenticated = (pw != NULL && 375 opie_haskey(pw->pw_name) == 0 && 376 opie_passverify(pw->pw_name, response) != -1); 377 xfree(response); 378 } 379 break; 380#else 381 case SSH_CMSG_AUTH_TIS: 382 /* TIS Authentication is unsupported */ 383 log("TIS authentication unsupported."); 384 break; 385#endif 386#ifdef KRB5 387 case SSH_CMSG_HAVE_KERBEROS_TGT: 388 /* Passing krb5 ticket */ 389 if (!options.krb5_tgt_passing 390 /*|| !options.krb5_authentication */) { 391 392 } 393 394 if (tkt_client == NULL) { 395 /* passing tgt without krb5 authentication */ 396 } 397 398 { 399 krb5_data tgt; 400 u_int tgtlen; 401 tgt.data = packet_get_string(&tgtlen); 402 tgt.length = tgtlen; 403 404 if (!auth_krb5_tgt(luser, &tgt, tkt_client)) 405 verbose ("Kerberos V5 TGT refused for %.100s", luser); 406 xfree(tgt.data); 407 408 break; 409 } 410#endif /* KRB5 */ 411 412 default: 413 /* 414 * Any unknown messages will be ignored (and failure 415 * returned) during authentication. 416 */ 417 log("Unknown message during authentication: type %d", type); 418 break; 419 } 420 if (authenticated && pw == NULL) 421 fatal("internal error: authenticated for pw == NULL"); 422 423 /* 424 * Check if the user is logging in as root and root logins 425 * are disallowed. 426 * Note that root login is allowed for forced commands. 427 */ 428 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { 429 if (forced_command) { 430 log("Root login accepted for forced command."); 431 } else { 432 authenticated = 0; 433 log("ROOT LOGIN REFUSED FROM %.200s", 434 get_canonical_hostname()); 435 } 436 } 437 438#ifdef HAVE_LOGIN_CAP 439 if (pw != NULL) { 440 lc = login_getpwclass(pw); 441 if (lc == NULL) 442 lc = login_getclassbyname(NULL, pw); 443 if (!auth_hostok(lc, from_host, from_ip)) { 444 log("Denied connection for %.200s from %.200s [%.200s].", 445 pw->pw_name, from_host, from_ip); 446 packet_disconnect("Sorry, you are not allowed to connect."); 447 } 448 if (!auth_timeok(lc, time(NULL))) { 449 log("LOGIN %.200s REFUSED (TIME) FROM %.200s", 450 pw->pw_name, from_host); 451 packet_disconnect("Logins not available right now."); 452 } 453 login_close(lc); 454 lc = NULL; 455 } 456#endif /* HAVE_LOGIN_CAP */ 457#ifdef LOGIN_ACCESS 458 if (pw != NULL && !login_access(pw->pw_name, from_host)) { 459 log("Denied connection for %.200s from %.200s [%.200s].", 460 pw->pw_name, from_host, from_ip); 461 packet_disconnect("Sorry, you are not allowed to connect."); 462 } 463#endif /* LOGIN_ACCESS */ 464 465 if (pw != NULL && pw->pw_uid == 0) 466 log("ROOT LOGIN as '%.100s' from %.100s", 467 pw->pw_name, get_canonical_hostname()); 468 469 /* Raise logging level */ 470 if (authenticated || 471 attempt == AUTH_FAIL_LOG || 472 type == SSH_CMSG_AUTH_PASSWORD) 473 authlog = log; 474 475 authlog("%s %s for %s%.100s from %.200s port %d%s", 476 authenticated ? "Accepted" : "Failed", 477 get_authname(type), 478 pw ? "" : "illegal user ", 479 pw && pw->pw_uid == 0 ? "ROOT" : luser, 480 get_remote_ipaddr(), 481 get_remote_port(), 482 user); 483 484 if (authenticated) 485 return; 486 487#ifdef USE_PAM 488 if (authenticated && !do_pam_account(pw->pw_name, client_user)) 489 authenticated = 0; 490#endif 491 492 if (client_user != NULL) { 493 xfree(client_user); 494 client_user = NULL; 495 } 496 497 if (attempt > AUTH_FAIL_MAX) 498 packet_disconnect(AUTH_FAIL_MSG, luser); 499 500 /* Send a message indicating that the authentication attempt failed. */ 501 packet_start(SSH_SMSG_FAILURE); 502 packet_send(); 503 packet_write_wait(); 504 } 505} 506 507/* 508 * Performs authentication of an incoming connection. Session key has already 509 * been exchanged and encryption is enabled. 510 */ 511void 512do_authentication() 513{ 514 struct passwd *pw, pwcopy; 515 int plen; 516 unsigned int ulen; 517 char *user; 518 519 /* Get the name of the user that we wish to log in as. */ 520 packet_read_expect(&plen, SSH_CMSG_USER); 521 522 /* Get the user name. */ 523 user = packet_get_string(&ulen); 524 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER); 525 526 setproctitle("%s", user); 527 528#ifdef AFS 529 /* If machine has AFS, set process authentication group. */ 530 if (k_hasafs()) { 531 k_setpag(); 532 k_unlog(); 533 } 534#endif /* AFS */ 535 536 /* Verify that the user is a valid user. */ 537 pw = getpwnam(user); 538 if (pw && allowed_user(pw)) { 539 /* Take a copy of the returned structure. */ 540 memset(&pwcopy, 0, sizeof(pwcopy)); 541 pwcopy.pw_name = xstrdup(pw->pw_name); 542 pwcopy.pw_passwd = xstrdup(pw->pw_passwd); 543 pwcopy.pw_uid = pw->pw_uid; 544 pwcopy.pw_gid = pw->pw_gid; 545 pwcopy.pw_class = xstrdup(pw->pw_class); 546 pwcopy.pw_dir = xstrdup(pw->pw_dir); 547 pwcopy.pw_shell = xstrdup(pw->pw_shell); 548 pwcopy.pw_expire = pw->pw_expire; 549 pwcopy.pw_change = pw->pw_change; 550 pw = &pwcopy; 551 } else { 552 pw = NULL; 553 } 554 555#ifdef USE_PAM 556 if (pw != NULL) 557 start_pam(pw); 558#endif 559 /* 560 * If we are not running as root, the user must have the same uid as 561 * the server. 562 */ 563 if (getuid() != 0 && pw && pw->pw_uid != getuid()) 564 packet_disconnect("Cannot change user when server not running as root."); 565 566 debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user); 567 568 /* If the user has no password, accept authentication immediately. */ 569 if (options.password_authentication && 570#ifdef KRB5 571 !options.kerberos_authentication && 572#endif /* KRB5 */ 573#ifdef KRB4 574 (!options.kerberos_authentication || options.krb4_or_local_passwd) && 575#endif /* KRB4 */ 576#ifdef USE_PAM 577 auth_pam_password(pw, "") 578#else /* !USE_PAM */ 579 auth_password(pw, "") 580#endif /* USE_PAM */ 581 ) { 582 /* Authentication with empty password succeeded. */ 583 log("Login for user %s from %.100s, accepted without authentication.", 584 user, get_remote_ipaddr()); 585 } else { 586 /* Loop until the user has been authenticated or the 587 connection is closed, do_authloop() returns only if 588 authentication is successfull */ 589 do_authloop(pw, user); 590 } 591 if (pw == NULL) 592 fatal("internal error, authentication successfull for user '%.100s'", user); 593 594 /* The user has been authenticated and accepted. */ 595 packet_start(SSH_SMSG_SUCCESS); 596 packet_send(); 597 packet_write_wait(); 598 599 /* Perform session preparation. */ 600 do_authenticated(pw); 601} 602