1/* 2 Unix SMB/CIFS implementation. 3 Password checking 4 Copyright (C) Andrew Tridgell 1992-1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20/* this module is for checking a username/password against a system 21 password database. The SMB encrypted password support is elsewhere */ 22 23#include "includes.h" 24 25#undef DBGC_CLASS 26#define DBGC_CLASS DBGC_AUTH 27 28/* these are kept here to keep the string_combinations function simple */ 29static char *ths_user; 30 31static const char *get_this_user(void) 32{ 33 if (!ths_user) { 34 return ""; 35 } 36 return ths_user; 37} 38 39#if defined(WITH_PAM) || defined(OSF1_ENH_SEC) 40static const char *set_this_user(const char *newuser) 41{ 42 char *orig_user = ths_user; 43 ths_user = SMB_STRDUP(newuser); 44 SAFE_FREE(orig_user); 45 return ths_user; 46} 47#endif 48 49#if !defined(WITH_PAM) 50static char *ths_salt; 51/* This must be writable. */ 52static char *get_this_salt(void) 53{ 54 return ths_salt; 55} 56 57/* We may be setting a modified version of the same 58 * string, so don't free before use. */ 59 60static const char *set_this_salt(const char *newsalt) 61{ 62 char *orig_salt = ths_salt; 63 ths_salt = SMB_STRDUP(newsalt); 64 SAFE_FREE(orig_salt); 65 return ths_salt; 66} 67 68static char *ths_crypted; 69static const char *get_this_crypted(void) 70{ 71 if (!ths_crypted) { 72 return ""; 73 } 74 return ths_crypted; 75} 76 77static const char *set_this_crypted(const char *newcrypted) 78{ 79 char *orig_crypted = ths_crypted; 80 ths_crypted = SMB_STRDUP(newcrypted); 81 SAFE_FREE(orig_crypted); 82 return ths_crypted; 83} 84#endif 85 86#ifdef WITH_AFS 87 88#include <afs/stds.h> 89#include <afs/kautils.h> 90 91/******************************************************************* 92check on AFS authentication 93********************************************************************/ 94static bool afs_auth(char *user, char *password) 95{ 96 long password_expires = 0; 97 char *reason; 98 99 /* For versions of AFS prior to 3.3, this routine has few arguments, */ 100 /* but since I can't find the old documentation... :-) */ 101 setpag(); 102 if (ka_UserAuthenticateGeneral 103 (KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG, user, (char *)0, /* instance */ 104 (char *)0, /* cell */ 105 password, 0, /* lifetime, default */ 106 &password_expires, /*days 'til it expires */ 107 0, /* spare 2 */ 108 &reason) == 0) 109 { 110 return (True); 111 } 112 DEBUG(1, 113 ("AFS authentication for \"%s\" failed (%s)\n", user, reason)); 114 return (False); 115} 116#endif 117 118 119#ifdef WITH_DFS 120 121#include <dce/dce_error.h> 122#include <dce/sec_login.h> 123 124/***************************************************************** 125 This new version of the DFS_AUTH code was donated by Karsten Muuss 126 <muuss@or.uni-bonn.de>. It fixes the following problems with the 127 old code : 128 129 - Server credentials may expire 130 - Client credential cache files have wrong owner 131 - purge_context() function is called with invalid argument 132 133 This new code was modified to ensure that on exit the uid/gid is 134 still root, and the original directory is restored. JRA. 135******************************************************************/ 136 137sec_login_handle_t my_dce_sec_context; 138int dcelogin_atmost_once = 0; 139 140/******************************************************************* 141check on a DCE/DFS authentication 142********************************************************************/ 143static bool dfs_auth(char *user, char *password) 144{ 145 struct tm *t; 146 error_status_t err; 147 int err2; 148 int prterr; 149 signed32 expire_time, current_time; 150 boolean32 password_reset; 151 struct passwd *pw; 152 sec_passwd_rec_t passwd_rec; 153 sec_login_auth_src_t auth_src = sec_login_auth_src_network; 154 unsigned char dce_errstr[dce_c_error_string_len]; 155 gid_t egid; 156 157 if (dcelogin_atmost_once) 158 return (False); 159 160#ifdef HAVE_CRYPT 161 /* 162 * We only go for a DCE login context if the given password 163 * matches that stored in the local password file.. 164 * Assumes local passwd file is kept in sync w/ DCE RGY! 165 */ 166 167 if (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted())) 168 { 169 return (False); 170 } 171#endif 172 173 sec_login_get_current_context(&my_dce_sec_context, &err); 174 if (err != error_status_ok) 175 { 176 dce_error_inq_text(err, dce_errstr, &err2); 177 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr)); 178 179 return (False); 180 } 181 182 sec_login_certify_identity(my_dce_sec_context, &err); 183 if (err != error_status_ok) 184 { 185 dce_error_inq_text(err, dce_errstr, &err2); 186 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr)); 187 188 return (False); 189 } 190 191 sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); 192 if (err != error_status_ok) 193 { 194 dce_error_inq_text(err, dce_errstr, &err2); 195 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr)); 196 197 return (False); 198 } 199 200 time(¤t_time); 201 202 if (expire_time < (current_time + 60)) 203 { 204 struct passwd *pw; 205 sec_passwd_rec_t *key; 206 207 sec_login_get_pwent(my_dce_sec_context, 208 (sec_login_passwd_t *) & pw, &err); 209 if (err != error_status_ok) 210 { 211 dce_error_inq_text(err, dce_errstr, &err2); 212 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); 213 214 return (False); 215 } 216 217 sec_login_refresh_identity(my_dce_sec_context, &err); 218 if (err != error_status_ok) 219 { 220 dce_error_inq_text(err, dce_errstr, &err2); 221 DEBUG(0, ("DCE can't refresh identity. %s\n", 222 dce_errstr)); 223 224 return (False); 225 } 226 227 sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL, 228 (unsigned char *)pw->pw_name, 229 sec_c_key_version_none, 230 (void **)&key, &err); 231 if (err != error_status_ok) 232 { 233 dce_error_inq_text(err, dce_errstr, &err2); 234 DEBUG(0, ("DCE can't get key for %s. %s\n", 235 pw->pw_name, dce_errstr)); 236 237 return (False); 238 } 239 240 sec_login_valid_and_cert_ident(my_dce_sec_context, key, 241 &password_reset, &auth_src, 242 &err); 243 if (err != error_status_ok) 244 { 245 dce_error_inq_text(err, dce_errstr, &err2); 246 DEBUG(0, 247 ("DCE can't validate and certify identity for %s. %s\n", 248 pw->pw_name, dce_errstr)); 249 } 250 251 sec_key_mgmt_free_key(key, &err); 252 if (err != error_status_ok) 253 { 254 dce_error_inq_text(err, dce_errstr, &err2); 255 DEBUG(0, ("DCE can't free key.\n", dce_errstr)); 256 } 257 } 258 259 if (sec_login_setup_identity((unsigned char *)user, 260 sec_login_no_flags, 261 &my_dce_sec_context, &err) == 0) 262 { 263 dce_error_inq_text(err, dce_errstr, &err2); 264 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n", 265 user, dce_errstr)); 266 return (False); 267 } 268 269 sec_login_get_pwent(my_dce_sec_context, 270 (sec_login_passwd_t *) & pw, &err); 271 if (err != error_status_ok) 272 { 273 dce_error_inq_text(err, dce_errstr, &err2); 274 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); 275 276 return (False); 277 } 278 279 sec_login_purge_context(&my_dce_sec_context, &err); 280 if (err != error_status_ok) 281 { 282 dce_error_inq_text(err, dce_errstr, &err2); 283 DEBUG(0, ("DCE can't purge context. %s\n", dce_errstr)); 284 285 return (False); 286 } 287 288 /* 289 * NB. I'd like to change these to call something like change_to_user() 290 * instead but currently we don't have a connection 291 * context to become the correct user. This is already 292 * fairly platform specific code however, so I think 293 * this should be ok. I have added code to go 294 * back to being root on error though. JRA. 295 */ 296 297 egid = getegid(); 298 299 set_effective_gid(pw->pw_gid); 300 set_effective_uid(pw->pw_uid); 301 302 if (sec_login_setup_identity((unsigned char *)user, 303 sec_login_no_flags, 304 &my_dce_sec_context, &err) == 0) 305 { 306 dce_error_inq_text(err, dce_errstr, &err2); 307 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n", 308 user, dce_errstr)); 309 goto err; 310 } 311 312 sec_login_get_pwent(my_dce_sec_context, 313 (sec_login_passwd_t *) & pw, &err); 314 if (err != error_status_ok) 315 { 316 dce_error_inq_text(err, dce_errstr, &err2); 317 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); 318 goto err; 319 } 320 321 passwd_rec.version_number = sec_passwd_c_version_none; 322 passwd_rec.pepper = NULL; 323 passwd_rec.key.key_type = sec_passwd_plain; 324 passwd_rec.key.tagged_union.plain = (idl_char *) password; 325 326 sec_login_validate_identity(my_dce_sec_context, 327 &passwd_rec, &password_reset, 328 &auth_src, &err); 329 if (err != error_status_ok) 330 { 331 dce_error_inq_text(err, dce_errstr, &err2); 332 DEBUG(0, 333 ("DCE Identity Validation failed for principal %s: %s\n", 334 user, dce_errstr)); 335 goto err; 336 } 337 338 sec_login_certify_identity(my_dce_sec_context, &err); 339 if (err != error_status_ok) 340 { 341 dce_error_inq_text(err, dce_errstr, &err2); 342 DEBUG(0, ("DCE certify identity failed: %s\n", dce_errstr)); 343 goto err; 344 } 345 346 if (auth_src != sec_login_auth_src_network) 347 { 348 DEBUG(0, ("DCE context has no network credentials.\n")); 349 } 350 351 sec_login_set_context(my_dce_sec_context, &err); 352 if (err != error_status_ok) 353 { 354 dce_error_inq_text(err, dce_errstr, &err2); 355 DEBUG(0, 356 ("DCE login failed for principal %s, cant set context: %s\n", 357 user, dce_errstr)); 358 359 sec_login_purge_context(&my_dce_sec_context, &err); 360 goto err; 361 } 362 363 sec_login_get_pwent(my_dce_sec_context, 364 (sec_login_passwd_t *) & pw, &err); 365 if (err != error_status_ok) 366 { 367 dce_error_inq_text(err, dce_errstr, &err2); 368 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); 369 goto err; 370 } 371 372 DEBUG(0, ("DCE login succeeded for principal %s on pid %d\n", 373 user, sys_getpid())); 374 375 DEBUG(3, ("DCE principal: %s\n" 376 " uid: %d\n" 377 " gid: %d\n", 378 pw->pw_name, pw->pw_uid, pw->pw_gid)); 379 DEBUG(3, (" info: %s\n" 380 " dir: %s\n" 381 " shell: %s\n", 382 pw->pw_gecos, pw->pw_dir, pw->pw_shell)); 383 384 sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); 385 if (err != error_status_ok) 386 { 387 dce_error_inq_text(err, dce_errstr, &err2); 388 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr)); 389 goto err; 390 } 391 392 set_effective_uid(0); 393 set_effective_gid(0); 394 395 t = localtime(&expire_time); 396 if (t) { 397 const char *asct = asctime(t); 398 if (asct) { 399 DEBUG(0,("DCE context expires: %s", asct)); 400 } 401 } 402 403 dcelogin_atmost_once = 1; 404 return (True); 405 406 err: 407 408 /* Go back to root, JRA. */ 409 set_effective_uid(0); 410 set_effective_gid(egid); 411 return (False); 412} 413 414void dfs_unlogin(void) 415{ 416 error_status_t err; 417 int err2; 418 unsigned char dce_errstr[dce_c_error_string_len]; 419 420 sec_login_purge_context(&my_dce_sec_context, &err); 421 if (err != error_status_ok) 422 { 423 dce_error_inq_text(err, dce_errstr, &err2); 424 DEBUG(0, 425 ("DCE purge login context failed for server instance %d: %s\n", 426 sys_getpid(), dce_errstr)); 427 } 428} 429#endif 430 431#ifdef LINUX_BIGCRYPT 432/**************************************************************************** 433an enhanced crypt for Linux to handle password longer than 8 characters 434****************************************************************************/ 435static int linux_bigcrypt(char *password, char *salt1, char *crypted) 436{ 437#define LINUX_PASSWORD_SEG_CHARS 8 438 char salt[3]; 439 int i; 440 441 StrnCpy(salt, salt1, 2); 442 crypted += 2; 443 444 for (i = strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { 445 char *p = crypt(password, salt) + 2; 446 if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) 447 return (0); 448 password += LINUX_PASSWORD_SEG_CHARS; 449 crypted += strlen(p); 450 } 451 452 return (1); 453} 454#endif 455 456#ifdef OSF1_ENH_SEC 457/**************************************************************************** 458an enhanced crypt for OSF1 459****************************************************************************/ 460static char *osf1_bigcrypt(char *password, char *salt1) 461{ 462 static char result[AUTH_MAX_PASSWD_LENGTH] = ""; 463 char *p1; 464 char *p2 = password; 465 char salt[3]; 466 int i; 467 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS; 468 if (strlen(password) % AUTH_CLEARTEXT_SEG_CHARS) 469 parts++; 470 471 StrnCpy(salt, salt1, 2); 472 StrnCpy(result, salt1, 2); 473 result[2] = '\0'; 474 475 for (i = 0; i < parts; i++) { 476 p1 = crypt(p2, salt); 477 strncat(result, p1 + 2, 478 AUTH_MAX_PASSWD_LENGTH - strlen(p1 + 2) - 1); 479 StrnCpy(salt, &result[2 + i * AUTH_CIPHERTEXT_SEG_CHARS], 2); 480 p2 += AUTH_CLEARTEXT_SEG_CHARS; 481 } 482 483 return (result); 484} 485#endif 486 487 488/**************************************************************************** 489apply a function to upper/lower case combinations 490of a string and return true if one of them returns true. 491try all combinations with N uppercase letters. 492offset is the first char to try and change (start with 0) 493it assumes the string starts lowercased 494****************************************************************************/ 495static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const char *), 496 int N) 497{ 498 int len = strlen(s); 499 int i; 500 NTSTATUS nt_status; 501 502#ifdef PASSWORD_LENGTH 503 len = MIN(len, PASSWORD_LENGTH); 504#endif 505 506 if (N <= 0 || offset >= len) 507 return (fn(s)); 508 509 for (i = offset; i < (len - (N - 1)); i++) { 510 char c = s[i]; 511 if (!islower_ascii(c)) 512 continue; 513 s[i] = toupper_ascii(c); 514 if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) { 515 return (nt_status); 516 } 517 s[i] = c; 518 } 519 return (NT_STATUS_WRONG_PASSWORD); 520} 521 522/**************************************************************************** 523apply a function to upper/lower case combinations 524of a string and return true if one of them returns true. 525try all combinations with up to N uppercase letters. 526offset is the first char to try and change (start with 0) 527it assumes the string starts lowercased 528****************************************************************************/ 529static NTSTATUS string_combinations(char *s, NTSTATUS (*fn) (const char *), int N) 530{ 531 int n; 532 NTSTATUS nt_status; 533 for (n = 1; n <= N; n++) 534 if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, 0, fn, n), NT_STATUS_WRONG_PASSWORD)) 535 return nt_status; 536 return NT_STATUS_WRONG_PASSWORD; 537} 538 539 540/**************************************************************************** 541core of password checking routine 542****************************************************************************/ 543static NTSTATUS password_check(const char *password) 544{ 545#ifdef WITH_PAM 546 return smb_pam_passcheck(get_this_user(), password); 547#else 548 549 bool ret; 550 551#ifdef WITH_AFS 552 if (afs_auth(get_this_user(), password)) 553 return NT_STATUS_OK; 554#endif /* WITH_AFS */ 555 556#ifdef WITH_DFS 557 if (dfs_auth(get_this_user(), password)) 558 return NT_STATUS_OK; 559#endif /* WITH_DFS */ 560 561#ifdef OSF1_ENH_SEC 562 563 ret = (strcmp(osf1_bigcrypt(password, get_this_salt()), 564 get_this_crypted()) == 0); 565 if (!ret) { 566 DEBUG(2, 567 ("OSF1_ENH_SEC failed. Trying normal crypt.\n")); 568 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0); 569 } 570 if (ret) { 571 return NT_STATUS_OK; 572 } else { 573 return NT_STATUS_WRONG_PASSWORD; 574 } 575 576#endif /* OSF1_ENH_SEC */ 577 578#ifdef ULTRIX_AUTH 579 ret = (strcmp((char *)crypt16(password, get_this_salt()), get_this_crypted()) == 0); 580 if (ret) { 581 return NT_STATUS_OK; 582 } else { 583 return NT_STATUS_WRONG_PASSWORD; 584 } 585 586#endif /* ULTRIX_AUTH */ 587 588#ifdef LINUX_BIGCRYPT 589 ret = (linux_bigcrypt(password, get_this_salt(), get_this_crypted())); 590 if (ret) { 591 return NT_STATUS_OK; 592 } else { 593 return NT_STATUS_WRONG_PASSWORD; 594 } 595#endif /* LINUX_BIGCRYPT */ 596 597#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS) 598 599 /* 600 * Some systems have bigcrypt in the C library but might not 601 * actually use it for the password hashes (HPUX 10.20) is 602 * a noteable example. So we try bigcrypt first, followed 603 * by crypt. 604 */ 605 606 if (strcmp(bigcrypt(password, get_this_salt()), get_this_crypted()) == 0) 607 return NT_STATUS_OK; 608 else 609 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0); 610 if (ret) { 611 return NT_STATUS_OK; 612 } else { 613 return NT_STATUS_WRONG_PASSWORD; 614 } 615#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ 616 617#ifdef HAVE_BIGCRYPT 618 ret = (strcmp(bigcrypt(password, get_this_salt()), get_this_crypted()) == 0); 619 if (ret) { 620 return NT_STATUS_OK; 621 } else { 622 return NT_STATUS_WRONG_PASSWORD; 623 } 624#endif /* HAVE_BIGCRYPT */ 625 626#ifndef HAVE_CRYPT 627 DEBUG(1, ("Warning - no crypt available\n")); 628 return NT_STATUS_LOGON_FAILURE; 629#else /* HAVE_CRYPT */ 630 ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0); 631 if (ret) { 632 return NT_STATUS_OK; 633 } else { 634 return NT_STATUS_WRONG_PASSWORD; 635 } 636#endif /* HAVE_CRYPT */ 637#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ 638#endif /* WITH_PAM */ 639} 640 641 642 643/**************************************************************************** 644CHECK if a username/password is OK 645the function pointer fn() points to a function to call when a successful 646match is found and is used to update the encrypted password file 647return NT_STATUS_OK on correct match, appropriate error otherwise 648****************************************************************************/ 649 650NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *password, 651 int pwlen, bool (*fn) (const char *, const char *), bool run_cracker) 652{ 653 char *pass2 = NULL; 654 int level = lp_passwordlevel(); 655 656 NTSTATUS nt_status; 657 658#ifdef DEBUG_PASSWORD 659 DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password)); 660#endif 661 662 if (!password) 663 return NT_STATUS_LOGON_FAILURE; 664 665 if (((!*password) || (!pwlen)) && !lp_null_passwords()) 666 return NT_STATUS_LOGON_FAILURE; 667 668#if defined(WITH_PAM) 669 670 /* 671 * If we're using PAM we want to short-circuit all the 672 * checks below and dive straight into the PAM code. 673 */ 674 675 if (set_this_user(user) == NULL) { 676 return NT_STATUS_NO_MEMORY; 677 } 678 679 DEBUG(4, ("pass_check: Checking (PAM) password for user %s (l=%d)\n", user, pwlen)); 680 681#else /* Not using PAM */ 682 683 DEBUG(4, ("pass_check: Checking password for user %s (l=%d)\n", user, pwlen)); 684 685 if (!pass) { 686 DEBUG(3, ("Couldn't find user %s\n", user)); 687 return NT_STATUS_NO_SUCH_USER; 688 } 689 690 691 /* Copy into global for the convenience of looping code */ 692 /* Also the place to keep the 'password' no matter what 693 crazy struct it started in... */ 694 if (set_this_crypted(pass->pw_passwd) == NULL) { 695 return NT_STATUS_NO_MEMORY; 696 } 697 if (set_this_salt(pass->pw_passwd) == NULL) { 698 return NT_STATUS_NO_MEMORY; 699 } 700 701#ifdef HAVE_GETSPNAM 702 { 703 struct spwd *spass; 704 705 /* many shadow systems require you to be root to get 706 the password, in most cases this should already be 707 the case when this function is called, except 708 perhaps for IPC password changing requests */ 709 710 spass = getspnam(pass->pw_name); 711 if (spass && spass->sp_pwdp) { 712 if (set_this_crypted(spass->sp_pwdp) == NULL) { 713 return NT_STATUS_NO_MEMORY; 714 } 715 if (set_this_salt(spass->sp_pwdp) == NULL) { 716 return NT_STATUS_NO_MEMORY; 717 } 718 } 719 } 720#elif defined(IA_UINFO) 721 { 722 /* Need to get password with SVR4.2's ia_ functions 723 instead of get{sp,pw}ent functions. Required by 724 UnixWare 2.x, tested on version 725 2.1. (tangent@cyberport.com) */ 726 uinfo_t uinfo; 727 if (ia_openinfo(pass->pw_name, &uinfo) != -1) 728 ia_get_logpwd(uinfo, &(pass->pw_passwd)); 729 } 730#endif 731 732#ifdef HAVE_GETPRPWNAM 733 { 734 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); 735 if (pr_pw && pr_pw->ufld.fd_encrypt) { 736 if (set_this_crypted(pr_pw->ufld.fd_encrypt) == NULL) { 737 return NT_STATUS_NO_MEMORY; 738 } 739 } 740 } 741#endif 742 743#ifdef HAVE_GETPWANAM 744 { 745 struct passwd_adjunct *pwret; 746 pwret = getpwanam(s); 747 if (pwret && pwret->pwa_passwd) { 748 if (set_this_crypted(pwret->pwa_passwd) == NULL) { 749 return NT_STATUS_NO_MEMORY; 750 } 751 } 752 } 753#endif 754 755#ifdef OSF1_ENH_SEC 756 { 757 struct pr_passwd *mypasswd; 758 DEBUG(5, ("Checking password for user %s in OSF1_ENH_SEC\n", 759 user)); 760 mypasswd = getprpwnam(user); 761 if (mypasswd) { 762 if (set_this_user(mypasswd->ufld.fd_name) == NULL) { 763 return NT_STATUS_NO_MEMORY; 764 } 765 if (set_this_crypted(mypasswd->ufld.fd_encrypt) == NULL) { 766 return NT_STATUS_NO_MEMORY; 767 } 768 } else { 769 DEBUG(5, 770 ("OSF1_ENH_SEC: No entry for user %s in protected database !\n", 771 user)); 772 } 773 } 774#endif 775 776#ifdef ULTRIX_AUTH 777 { 778 AUTHORIZATION *ap = getauthuid(pass->pw_uid); 779 if (ap) { 780 if (set_this_crypted(ap->a_password) == NULL) { 781 endauthent(); 782 return NT_STATUS_NO_MEMORY; 783 } 784 endauthent(); 785 } 786 } 787#endif 788 789#if defined(HAVE_TRUNCATED_SALT) 790 /* crypt on some platforms (HPUX in particular) 791 won't work with more than 2 salt characters. */ 792 { 793 char *trunc_salt = get_this_salt(); 794 if (!trunc_salt || strlen(trunc_salt) < 2) { 795 return NT_STATUS_LOGON_FAILURE; 796 } 797 trunc_salt[2] = 0; 798 if (set_this_salt(trunc_salt) == NULL) { 799 return NT_STATUS_NO_MEMORY; 800 } 801 } 802#endif 803 804 if (!get_this_crypted() || !*get_this_crypted()) { 805 if (!lp_null_passwords()) { 806 DEBUG(2, ("Disallowing %s with null password\n", 807 get_this_user())); 808 return NT_STATUS_LOGON_FAILURE; 809 } 810 if (!*password) { 811 DEBUG(3, 812 ("Allowing access to %s with null password\n", 813 get_this_user())); 814 return NT_STATUS_OK; 815 } 816 } 817 818#endif /* defined(WITH_PAM) */ 819 820 /* try it as it came to us */ 821 nt_status = password_check(password); 822 if NT_STATUS_IS_OK(nt_status) { 823 if (fn) { 824 fn(user, password); 825 } 826 return (nt_status); 827 } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { 828 /* No point continuing if its not the password thats to blame (ie PAM disabled). */ 829 return (nt_status); 830 } 831 832 if (!run_cracker) { 833 return (nt_status); 834 } 835 836 /* if the password was given to us with mixed case then we don't 837 * need to proceed as we know it hasn't been case modified by the 838 * client */ 839 if (strhasupper(password) && strhaslower(password)) { 840 return nt_status; 841 } 842 843 /* make a copy of it */ 844 pass2 = talloc_strdup(talloc_tos(), password); 845 if (!pass2) { 846 return NT_STATUS_NO_MEMORY; 847 } 848 849 /* try all lowercase if it's currently all uppercase */ 850 if (strhasupper(pass2)) { 851 strlower_m(pass2); 852 if NT_STATUS_IS_OK(nt_status = password_check(pass2)) { 853 if (fn) 854 fn(user, pass2); 855 return (nt_status); 856 } 857 } 858 859 /* give up? */ 860 if (level < 1) { 861 return NT_STATUS_WRONG_PASSWORD; 862 } 863 864 /* last chance - all combinations of up to level chars upper! */ 865 strlower_m(pass2); 866 867 if (NT_STATUS_IS_OK(nt_status = string_combinations(pass2, password_check, level))) { 868 if (fn) 869 fn(user, pass2); 870 return nt_status; 871 } 872 873 return NT_STATUS_WRONG_PASSWORD; 874} 875