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