00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "includes.h"
00050
00051 extern struct passdb_ops pdb_ops;
00052
00053 static NTSTATUS check_oem_password(const char *user,
00054 uchar password_encrypted_with_lm_hash[516],
00055 const uchar old_lm_hash_encrypted[16],
00056 uchar password_encrypted_with_nt_hash[516],
00057 const uchar old_nt_hash_encrypted[16],
00058 struct samu **hnd, char *new_passwd,
00059 int new_passwd_size);
00060
00061 #if ALLOW_CHANGE_PASSWORD
00062
00063 static int findpty(char **slave)
00064 {
00065 int master;
00066 static fstring line;
00067 SMB_STRUCT_DIR *dirp;
00068 const char *dpname;
00069
00070 #if defined(HAVE_GRANTPT)
00071
00072 if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0)
00073 {
00074 grantpt(master);
00075 unlockpt(master);
00076 *slave = (char *)ptsname(master);
00077 if (*slave == NULL)
00078 {
00079 DEBUG(0,
00080 ("findpty: Unable to create master/slave pty pair.\n"));
00081
00082 close(master);
00083 return -1;
00084 }
00085 else
00086 {
00087 DEBUG(10,
00088 ("findpty: Allocated slave pty %s\n", *slave));
00089 return (master);
00090 }
00091 }
00092 #endif
00093
00094 fstrcpy(line, "/dev/ptyXX");
00095
00096 dirp = sys_opendir("/dev");
00097 if (!dirp)
00098 return (-1);
00099 while ((dpname = readdirname(dirp)) != NULL)
00100 {
00101 if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5)
00102 {
00103 DEBUG(3,
00104 ("pty: try to open %s, line was %s\n", dpname,
00105 line));
00106 line[8] = dpname[3];
00107 line[9] = dpname[4];
00108 if ((master = sys_open(line, O_RDWR, 0)) >= 0)
00109 {
00110 DEBUG(3, ("pty: opened %s\n", line));
00111 line[5] = 't';
00112 *slave = line;
00113 sys_closedir(dirp);
00114 return (master);
00115 }
00116 }
00117 }
00118 sys_closedir(dirp);
00119 return (-1);
00120 }
00121
00122 static int dochild(int master, const char *slavedev, const struct passwd *pass,
00123 const char *passwordprogram, BOOL as_root)
00124 {
00125 int slave;
00126 struct termios stermios;
00127 gid_t gid;
00128 uid_t uid;
00129 char * const eptrs[1] = { NULL };
00130
00131 if (pass == NULL)
00132 {
00133 DEBUG(0,
00134 ("dochild: user doesn't exist in the UNIX password database.\n"));
00135 return False;
00136 }
00137
00138 gid = pass->pw_gid;
00139 uid = pass->pw_uid;
00140
00141 gain_root_privilege();
00142
00143
00144 if (setsid() < 0)
00145 {
00146 DEBUG(3,
00147 ("Weirdness, couldn't let go of controlling terminal\n"));
00148 return (False);
00149 }
00150
00151
00152 if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0)
00153 {
00154 DEBUG(3, ("More weirdness, could not open %s\n", slavedev));
00155 return (False);
00156 }
00157 #if defined(TIOCSCTTY) && !defined(SUNOS5)
00158
00159
00160
00161
00162
00163 if (ioctl(slave, TIOCSCTTY, 0) < 0)
00164 {
00165 DEBUG(3, ("Error in ioctl call for slave pty\n"));
00166
00167 }
00168 #elif defined(I_PUSH) && defined(I_FIND)
00169 if (ioctl(slave, I_FIND, "ptem") == 0) {
00170 ioctl(slave, I_PUSH, "ptem");
00171 }
00172 if (ioctl(slave, I_FIND, "ldterm") == 0) {
00173 ioctl(slave, I_PUSH, "ldterm");
00174 }
00175 #endif
00176
00177
00178 close(master);
00179
00180
00181
00182 if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO)
00183 {
00184 DEBUG(3, ("Could not re-direct stdin\n"));
00185 return (False);
00186 }
00187 if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
00188 {
00189 DEBUG(3, ("Could not re-direct stdout\n"));
00190 return (False);
00191 }
00192 if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO)
00193 {
00194 DEBUG(3, ("Could not re-direct stderr\n"));
00195 return (False);
00196 }
00197 if (slave > 2)
00198 close(slave);
00199
00200
00201
00202
00203 if (tcgetattr(0, &stermios) < 0)
00204 {
00205 DEBUG(3,
00206 ("could not read default terminal attributes on pty\n"));
00207 return (False);
00208 }
00209 stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
00210 stermios.c_lflag |= ICANON;
00211 #ifdef ONLCR
00212 stermios.c_oflag &= ~(ONLCR);
00213 #endif
00214 if (tcsetattr(0, TCSANOW, &stermios) < 0)
00215 {
00216 DEBUG(3, ("could not set attributes of pty\n"));
00217 return (False);
00218 }
00219
00220
00221 if (!as_root)
00222 {
00223 become_user_permanently(uid, gid);
00224 }
00225
00226 DEBUG(10,
00227 ("Invoking '%s' as password change program.\n",
00228 passwordprogram));
00229
00230
00231 if (execle("/bin/sh", "sh", "-c", passwordprogram, NULL, eptrs) < 0)
00232 {
00233 DEBUG(3, ("Bad status returned from %s\n", passwordprogram));
00234 return (False);
00235 }
00236 return (True);
00237 }
00238
00239 static int expect(int master, char *issue, char *expected)
00240 {
00241 pstring buffer;
00242 int attempts, timeout, nread, len;
00243 BOOL match = False;
00244
00245 for (attempts = 0; attempts < 2; attempts++) {
00246 if (!strequal(issue, ".")) {
00247 if (lp_passwd_chat_debug())
00248 DEBUG(100, ("expect: sending [%s]\n", issue));
00249
00250 if ((len = sys_write(master, issue, strlen(issue))) != strlen(issue)) {
00251 DEBUG(2,("expect: (short) write returned %d\n", len ));
00252 return False;
00253 }
00254 }
00255
00256 if (strequal(expected, "."))
00257 return True;
00258
00259
00260 timeout = lp_passwd_chat_timeout() * 1000;
00261 nread = 0;
00262 buffer[nread] = 0;
00263
00264 while ((len = read_socket_with_timeout(master, buffer + nread, 1,
00265 sizeof(buffer) - nread - 1,
00266 timeout)) > 0) {
00267 nread += len;
00268 buffer[nread] = 0;
00269
00270 {
00271
00272 pstring str;
00273 pstrcpy( str, buffer);
00274 trim_char( str, ' ', ' ');
00275
00276 if ((match = unix_wild_match(expected, str)) == True) {
00277
00278 timeout = lp_passwd_chat_timeout() * 100;
00279 }
00280 }
00281 }
00282
00283 if (lp_passwd_chat_debug())
00284 DEBUG(100, ("expect: expected [%s] received [%s] match %s\n",
00285 expected, buffer, match ? "yes" : "no" ));
00286
00287 if (match)
00288 break;
00289
00290 if (len < 0) {
00291 DEBUG(2, ("expect: %s\n", strerror(errno)));
00292 return False;
00293 }
00294 }
00295
00296 DEBUG(10,("expect: returning %s\n", match ? "True" : "False" ));
00297 return match;
00298 }
00299
00300 static void pwd_sub(char *buf)
00301 {
00302 all_string_sub(buf, "\\n", "\n", 0);
00303 all_string_sub(buf, "\\r", "\r", 0);
00304 all_string_sub(buf, "\\s", " ", 0);
00305 all_string_sub(buf, "\\t", "\t", 0);
00306 }
00307
00308 static int talktochild(int master, const char *seq)
00309 {
00310 int count = 0;
00311 fstring issue, expected;
00312
00313 fstrcpy(issue, ".");
00314
00315 while (next_token(&seq, expected, NULL, sizeof(expected)))
00316 {
00317 pwd_sub(expected);
00318 count++;
00319
00320 if (!expect(master, issue, expected))
00321 {
00322 DEBUG(3, ("Response %d incorrect\n", count));
00323 return False;
00324 }
00325
00326 if (!next_token(&seq, issue, NULL, sizeof(issue)))
00327 fstrcpy(issue, ".");
00328
00329 pwd_sub(issue);
00330 }
00331 if (!strequal(issue, ".")) {
00332
00333 fstrcpy(expected, ".");
00334 if (!expect(master, issue, expected))
00335 return False;
00336 }
00337
00338 return (count > 0);
00339 }
00340
00341 static BOOL chat_with_program(char *passwordprogram, const struct passwd *pass,
00342 char *chatsequence, BOOL as_root)
00343 {
00344 char *slavedev;
00345 int master;
00346 pid_t pid, wpid;
00347 int wstat;
00348 BOOL chstat = False;
00349
00350 if (pass == NULL) {
00351 DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n"));
00352 return False;
00353 }
00354
00355
00356 if ((master = findpty(&slavedev)) < 0) {
00357 DEBUG(3, ("chat_with_program: Cannot Allocate pty for password change: %s\n", pass->pw_name));
00358 return (False);
00359 }
00360
00361
00362
00363
00364
00365
00366 CatchChildLeaveStatus();
00367
00368 if ((pid = sys_fork()) < 0) {
00369 DEBUG(3, ("chat_with_program: Cannot fork() child for password change: %s\n", pass->pw_name));
00370 close(master);
00371 CatchChild();
00372 return (False);
00373 }
00374
00375
00376 if (pid > 0) {
00377 if ((chstat = talktochild(master, chatsequence)) == False) {
00378 DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name));
00379 kill(pid, SIGKILL);
00380 }
00381
00382 while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
00383 if (errno == EINTR) {
00384 errno = 0;
00385 continue;
00386 }
00387 break;
00388 }
00389
00390 if (wpid < 0) {
00391 DEBUG(3, ("chat_with_program: The process is no longer waiting!\n\n"));
00392 close(master);
00393 CatchChild();
00394 return (False);
00395 }
00396
00397
00398
00399
00400 CatchChild();
00401
00402 close(master);
00403
00404 if (pid != wpid) {
00405 DEBUG(3, ("chat_with_program: We were waiting for the wrong process ID\n"));
00406 return (False);
00407 }
00408 if (WIFEXITED(wstat) && (WEXITSTATUS(wstat) != 0)) {
00409 DEBUG(3, ("chat_with_program: The process exited with status %d \
00410 while we were waiting\n", WEXITSTATUS(wstat)));
00411 return (False);
00412 }
00413 #if defined(WIFSIGNALLED) && defined(WTERMSIG)
00414 else if (WIFSIGNALLED(wstat)) {
00415 DEBUG(3, ("chat_with_program: The process was killed by signal %d \
00416 while we were waiting\n", WTERMSIG(wstat)));
00417 return (False);
00418 }
00419 #endif
00420 } else {
00421
00422
00423
00424
00425
00426 drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
00427 drop_effective_capability(DMAPI_ACCESS_CAPABILITY);
00428
00429
00430 alarm(20);
00431
00432 if (as_root)
00433 become_root();
00434
00435 DEBUG(3, ("chat_with_program: Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name,
00436 (int)getuid(), (int)getgid(), BOOLSTR(as_root) ));
00437 chstat = dochild(master, slavedev, pass, passwordprogram, as_root);
00438
00439 if (as_root)
00440 unbecome_root();
00441
00442
00443
00444
00445
00446 DEBUG(0, ("chat_with_program: Error: dochild() returned %d\n", chstat));
00447 exit(1);
00448 }
00449
00450 if (chstat)
00451 DEBUG(3, ("chat_with_program: Password change %ssuccessful for user %s\n",
00452 (chstat ? "" : "un"), pass->pw_name));
00453 return (chstat);
00454 }
00455
00456 BOOL chgpasswd(const char *name, const struct passwd *pass,
00457 const char *oldpass, const char *newpass, BOOL as_root)
00458 {
00459 pstring passwordprogram;
00460 pstring chatsequence;
00461 size_t i;
00462 size_t len;
00463
00464 if (!oldpass) {
00465 oldpass = "";
00466 }
00467
00468 DEBUG(3, ("chgpasswd: Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name));
00469
00470 #ifdef DEBUG_PASSWORD
00471 DEBUG(100, ("chgpasswd: Passwords: old=%s new=%s\n", oldpass, newpass));
00472 #endif
00473
00474
00475
00476
00477 if (strcmp(oldpass, newpass) == 0) {
00478
00479 DEBUG(2, ("chgpasswd: Password Change: %s, New password is same as old\n", name));
00480 return (False);
00481 }
00482
00483
00484
00485
00486
00487
00488 len = strlen(oldpass);
00489 for (i = 0; i < len; i++) {
00490 if (iscntrl((int)oldpass[i])) {
00491 DEBUG(0, ("chgpasswd: oldpass contains control characters (disallowed).\n"));
00492 return False;
00493 }
00494 }
00495
00496 len = strlen(newpass);
00497 for (i = 0; i < len; i++) {
00498 if (iscntrl((int)newpass[i])) {
00499 DEBUG(0, ("chgpasswd: newpass contains control characters (disallowed).\n"));
00500 return False;
00501 }
00502 }
00503
00504 #ifdef WITH_PAM
00505 if (lp_pam_password_change()) {
00506 BOOL ret;
00507 #ifdef HAVE_SETLOCALE
00508 char *prevlocale = setlocale(LC_ALL, "C");
00509 #endif
00510
00511 if (as_root)
00512 become_root();
00513
00514 if (pass) {
00515 ret = smb_pam_passchange(pass->pw_name, oldpass, newpass);
00516 } else {
00517 ret = smb_pam_passchange(name, oldpass, newpass);
00518 }
00519
00520 if (as_root)
00521 unbecome_root();
00522
00523 #ifdef HAVE_SETLOCALE
00524 setlocale(LC_ALL, prevlocale);
00525 #endif
00526
00527 return ret;
00528 }
00529 #endif
00530
00531
00532
00533 if (pass == NULL) {
00534 DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name));
00535 return False;
00536 }
00537
00538 pstrcpy(passwordprogram, lp_passwd_program());
00539 pstrcpy(chatsequence, lp_passwd_chat());
00540
00541 if (!*chatsequence) {
00542 DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n"));
00543 return (False);
00544 }
00545
00546 if (!*passwordprogram) {
00547 DEBUG(2, ("chgpasswd: Null password program - no password changing\n"));
00548 return (False);
00549 }
00550
00551 if (as_root) {
00552
00553 if (strstr_m(passwordprogram, "%u") == NULL) {
00554 DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \
00555 the string %%u, and the given string %s does not.\n", passwordprogram ));
00556 return False;
00557 }
00558 }
00559
00560 pstring_sub(passwordprogram, "%u", name);
00561
00562
00563
00564
00565 pstring_sub(chatsequence, "%u", name);
00566 all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring));
00567 all_string_sub(chatsequence, "%n", newpass, sizeof(pstring));
00568 return (chat_with_program
00569 (passwordprogram, pass, chatsequence, as_root));
00570 }
00571
00572 #else
00573
00574 BOOL chgpasswd(const char *name, const struct passwd *pass,
00575 const char *oldpass, const char *newpass, BOOL as_root)
00576 {
00577 DEBUG(0, ("chgpasswd: Unix Password changing not compiled in (user=%s)\n", name));
00578 return (False);
00579 }
00580 #endif
00581
00582
00583
00584
00585
00586 BOOL check_lanman_password(char *user, uchar * pass1,
00587 uchar * pass2, struct samu **hnd)
00588 {
00589 uchar unenc_new_pw[16];
00590 uchar unenc_old_pw[16];
00591 struct samu *sampass = NULL;
00592 uint32 acct_ctrl;
00593 const uint8 *lanman_pw;
00594 BOOL ret;
00595
00596 if ( !(sampass = samu_new(NULL)) ) {
00597 DEBUG(0, ("samu_new() failed!\n"));
00598 return False;
00599 }
00600
00601 become_root();
00602 ret = pdb_getsampwnam(sampass, user);
00603 unbecome_root();
00604
00605 if (ret == False) {
00606 DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n"));
00607 TALLOC_FREE(sampass);
00608 return False;
00609 }
00610
00611 acct_ctrl = pdb_get_acct_ctrl (sampass);
00612 lanman_pw = pdb_get_lanman_passwd (sampass);
00613
00614 if (acct_ctrl & ACB_DISABLED) {
00615 DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
00616 TALLOC_FREE(sampass);
00617 return False;
00618 }
00619
00620 if (lanman_pw == NULL) {
00621 if (acct_ctrl & ACB_PWNOTREQ) {
00622
00623 *hnd = sampass;
00624 return True;
00625 } else {
00626 DEBUG(0, ("check_lanman_password: no lanman password !\n"));
00627 TALLOC_FREE(sampass);
00628 return False;
00629 }
00630 }
00631
00632
00633 D_P16(lanman_pw, pass2, unenc_new_pw);
00634
00635
00636 D_P16(unenc_new_pw, pass1, unenc_old_pw);
00637
00638
00639 if (memcmp(lanman_pw, unenc_old_pw, 16)) {
00640 DEBUG(0,("check_lanman_password: old password doesn't match.\n"));
00641 TALLOC_FREE(sampass);
00642 return False;
00643 }
00644
00645
00646 *hnd = sampass;
00647 return True;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 BOOL change_lanman_password(struct samu *sampass, uchar *pass2)
00659 {
00660 static uchar null_pw[16];
00661 uchar unenc_new_pw[16];
00662 BOOL ret;
00663 uint32 acct_ctrl;
00664 const uint8 *pwd;
00665
00666 if (sampass == NULL) {
00667 DEBUG(0,("change_lanman_password: no smb password entry.\n"));
00668 return False;
00669 }
00670
00671 acct_ctrl = pdb_get_acct_ctrl(sampass);
00672 pwd = pdb_get_lanman_passwd(sampass);
00673
00674 if (acct_ctrl & ACB_DISABLED) {
00675 DEBUG(0,("change_lanman_password: account %s disabled.\n",
00676 pdb_get_username(sampass)));
00677 return False;
00678 }
00679
00680 if (pwd == NULL) {
00681 if (acct_ctrl & ACB_PWNOTREQ) {
00682 uchar no_pw[14];
00683 memset(no_pw, '\0', 14);
00684 E_P16(no_pw, null_pw);
00685
00686
00687 D_P16(null_pw, pass2, unenc_new_pw);
00688 } else {
00689 DEBUG(0,("change_lanman_password: no lanman password !\n"));
00690 return False;
00691 }
00692 } else {
00693
00694 D_P16(pwd, pass2, unenc_new_pw);
00695 }
00696
00697 if (!pdb_set_lanman_passwd(sampass, unenc_new_pw, PDB_CHANGED)) {
00698 return False;
00699 }
00700
00701 if (!pdb_set_nt_passwd (sampass, NULL, PDB_CHANGED)) {
00702 return False;
00703 }
00704
00705 if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) {
00706 TALLOC_FREE(sampass);
00707
00708 return False;
00709 }
00710
00711
00712 ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
00713
00714 return ret;
00715 }
00716
00717
00718
00719
00720
00721 NTSTATUS pass_oem_change(char *user,
00722 uchar password_encrypted_with_lm_hash[516],
00723 const uchar old_lm_hash_encrypted[16],
00724 uchar password_encrypted_with_nt_hash[516],
00725 const uchar old_nt_hash_encrypted[16],
00726 uint32 *reject_reason)
00727 {
00728 pstring new_passwd;
00729 struct samu *sampass = NULL;
00730 NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash,
00731 old_lm_hash_encrypted,
00732 password_encrypted_with_nt_hash,
00733 old_nt_hash_encrypted,
00734 &sampass, new_passwd, sizeof(new_passwd));
00735
00736 if (!NT_STATUS_IS_OK(nt_status))
00737 return nt_status;
00738
00739
00740 become_root();
00741 nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason);
00742 unbecome_root();
00743
00744 memset(new_passwd, 0, sizeof(new_passwd));
00745
00746 TALLOC_FREE(sampass);
00747
00748 return nt_status;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 static NTSTATUS check_oem_password(const char *user,
00764 uchar password_encrypted_with_lm_hash[516],
00765 const uchar old_lm_hash_encrypted[16],
00766 uchar password_encrypted_with_nt_hash[516],
00767 const uchar old_nt_hash_encrypted[16],
00768 struct samu **hnd, char *new_passwd,
00769 int new_passwd_size)
00770 {
00771 static uchar null_pw[16];
00772 static uchar null_ntpw[16];
00773 struct samu *sampass = NULL;
00774 uint8 *password_encrypted;
00775 const uint8 *encryption_key;
00776 const uint8 *lanman_pw, *nt_pw;
00777 uint32 acct_ctrl;
00778 uint32 new_pw_len;
00779 uchar new_nt_hash[16];
00780 uchar new_lm_hash[16];
00781 uchar verifier[16];
00782 char no_pw[2];
00783 BOOL ret;
00784
00785 BOOL nt_pass_set = (password_encrypted_with_nt_hash && old_nt_hash_encrypted);
00786 BOOL lm_pass_set = (password_encrypted_with_lm_hash && old_lm_hash_encrypted);
00787
00788 *hnd = NULL;
00789
00790 if ( !(sampass = samu_new( NULL )) ) {
00791 return NT_STATUS_NO_MEMORY;
00792 }
00793
00794 become_root();
00795 ret = pdb_getsampwnam(sampass, user);
00796 unbecome_root();
00797
00798 if (ret == False) {
00799 DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n"));
00800 TALLOC_FREE(sampass);
00801 return NT_STATUS_NO_SUCH_USER;
00802 }
00803
00804 acct_ctrl = pdb_get_acct_ctrl(sampass);
00805
00806 if (acct_ctrl & ACB_DISABLED) {
00807 DEBUG(2,("check_lanman_password: account %s disabled.\n", user));
00808 TALLOC_FREE(sampass);
00809 return NT_STATUS_ACCOUNT_DISABLED;
00810 }
00811
00812 if ((acct_ctrl & ACB_PWNOTREQ) && lp_null_passwords()) {
00813
00814 no_pw[0] = 0;
00815 no_pw[1] = 0;
00816 nt_lm_owf_gen(no_pw, null_ntpw, null_pw);
00817 lanman_pw = null_pw;
00818 nt_pw = null_pw;
00819
00820 } else {
00821
00822 if (lp_lanman_auth()) {
00823 lanman_pw = pdb_get_lanman_passwd(sampass);
00824 } else {
00825 lanman_pw = NULL;
00826 }
00827 nt_pw = pdb_get_nt_passwd(sampass);
00828 }
00829
00830 if (nt_pw && nt_pass_set) {
00831
00832
00833
00834 password_encrypted = password_encrypted_with_nt_hash;
00835 encryption_key = nt_pw;
00836 } else if (lanman_pw && lm_pass_set) {
00837
00838 password_encrypted = password_encrypted_with_lm_hash;
00839 encryption_key = lanman_pw;
00840 } else if (nt_pass_set) {
00841 DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n",
00842 user));
00843 TALLOC_FREE(sampass);
00844 return NT_STATUS_WRONG_PASSWORD;
00845 } else if (lm_pass_set) {
00846 if (lp_lanman_auth()) {
00847 DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n",
00848 user));
00849 } else {
00850 DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n",
00851 user));
00852 }
00853 TALLOC_FREE(sampass);
00854 return NT_STATUS_WRONG_PASSWORD;
00855 } else {
00856 DEBUG(1, ("password change requested for user %s, but no password supplied!\n",
00857 user));
00858 TALLOC_FREE(sampass);
00859 return NT_STATUS_WRONG_PASSWORD;
00860 }
00861
00862
00863
00864
00865 SamOEMhash( password_encrypted, encryption_key, 516);
00866
00867 if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len,
00868 nt_pass_set ? STR_UNICODE : STR_ASCII)) {
00869 TALLOC_FREE(sampass);
00870 return NT_STATUS_WRONG_PASSWORD;
00871 }
00872
00873
00874
00875
00876
00877
00878 if (nt_pass_set) {
00879
00880
00881
00882 memset(new_nt_hash, '\0', 16);
00883 E_md4hash(new_passwd, new_nt_hash);
00884
00885 if (nt_pw) {
00886
00887
00888
00889 E_old_pw_hash(new_nt_hash, nt_pw, verifier);
00890 if (memcmp(verifier, old_nt_hash_encrypted, 16)) {
00891 DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00892 TALLOC_FREE(sampass);
00893 return NT_STATUS_WRONG_PASSWORD;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 #ifdef DEBUG_PASSWORD
00906 DEBUG(100,
00907 ("check_oem_password: password %s ok\n", new_passwd));
00908 #endif
00909 *hnd = sampass;
00910 return NT_STATUS_OK;
00911 }
00912
00913 if (lanman_pw) {
00914
00915
00916
00917 E_old_pw_hash(new_nt_hash, lanman_pw, verifier);
00918 if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
00919 DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00920 TALLOC_FREE(sampass);
00921 return NT_STATUS_WRONG_PASSWORD;
00922 }
00923 #ifdef DEBUG_PASSWORD
00924 DEBUG(100,
00925 ("check_oem_password: password %s ok\n", new_passwd));
00926 #endif
00927 *hnd = sampass;
00928 return NT_STATUS_OK;
00929 }
00930 }
00931
00932 if (lanman_pw && lm_pass_set) {
00933
00934 E_deshash(new_passwd, new_lm_hash);
00935
00936
00937
00938
00939 E_old_pw_hash(new_lm_hash, lanman_pw, verifier);
00940 if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
00941 DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
00942 TALLOC_FREE(sampass);
00943 return NT_STATUS_WRONG_PASSWORD;
00944 }
00945
00946 #ifdef DEBUG_PASSWORD
00947 DEBUG(100,
00948 ("check_oem_password: password %s ok\n", new_passwd));
00949 #endif
00950 *hnd = sampass;
00951 return NT_STATUS_OK;
00952 }
00953
00954
00955 TALLOC_FREE(sampass);
00956 return NT_STATUS_WRONG_PASSWORD;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965 static BOOL check_passwd_history(struct samu *sampass, const char *plaintext)
00966 {
00967 uchar new_nt_p16[NT_HASH_LEN];
00968 uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN];
00969 const uint8 *nt_pw;
00970 const uint8 *pwhistory;
00971 BOOL found = False;
00972 int i;
00973 uint32 pwHisLen, curr_pwHisLen;
00974
00975 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen);
00976 if (pwHisLen == 0) {
00977 return False;
00978 }
00979
00980 pwhistory = pdb_get_pw_history(sampass, &curr_pwHisLen);
00981 if (!pwhistory || curr_pwHisLen == 0) {
00982 return False;
00983 }
00984
00985
00986
00987 pwHisLen = MIN(pwHisLen,curr_pwHisLen);
00988
00989 nt_pw = pdb_get_nt_passwd(sampass);
00990
00991 E_md4hash(plaintext, new_nt_p16);
00992
00993 if (!memcmp(nt_pw, new_nt_p16, NT_HASH_LEN)) {
00994 DEBUG(10,("check_passwd_history: proposed new password for user %s is the same as the current password !\n",
00995 pdb_get_username(sampass) ));
00996 return True;
00997 }
00998
00999 dump_data(100, (const char *)new_nt_p16, NT_HASH_LEN);
01000 dump_data(100, (const char *)pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen);
01001
01002 memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN);
01003 for (i=0; i<pwHisLen; i++) {
01004 uchar new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN];
01005 const uchar *current_salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
01006 const uchar *old_nt_pw_salted_md5_hash = &pwhistory[(i*PW_HISTORY_ENTRY_LEN)+
01007 PW_HISTORY_SALT_LEN];
01008 if (!memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
01009
01010 continue;
01011 }
01012
01013 E_md5hash(current_salt, new_nt_p16, new_nt_pw_salted_md5_hash);
01014
01015 if (!memcmp(new_nt_pw_salted_md5_hash, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
01016 DEBUG(1,("check_passwd_history: proposed new password for user %s found in history list !\n",
01017 pdb_get_username(sampass) ));
01018 found = True;
01019 break;
01020 }
01021 }
01022 return found;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032 NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)
01033 {
01034 uint32 min_len;
01035 struct passwd *pass = NULL;
01036 const char *username = pdb_get_username(hnd);
01037 time_t can_change_time = pdb_get_pass_can_change_time(hnd);
01038
01039 if (samr_reject_reason) {
01040 *samr_reject_reason = Undefined;
01041 }
01042
01043
01044 if (!pdb_get_pass_can_change(hnd)) {
01045 DEBUG(1, ("user %s does not have permissions to change password\n", username));
01046 if (samr_reject_reason) {
01047 *samr_reject_reason = REJECT_REASON_OTHER;
01048 }
01049 return NT_STATUS_ACCOUNT_RESTRICTION;
01050 }
01051
01052
01053
01054 if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
01055 DEBUG(1, ("user %s cannot change password now, must "
01056 "wait until %s\n", username,
01057 http_timestring(can_change_time)));
01058 if (samr_reject_reason) {
01059 *samr_reject_reason = REJECT_REASON_OTHER;
01060 }
01061 return NT_STATUS_ACCOUNT_RESTRICTION;
01062 }
01063
01064 if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
01065 DEBUG(1, ("user %s cannot change password - password too short\n",
01066 username));
01067 DEBUGADD(1, (" account policy min password len = %d\n", min_len));
01068 if (samr_reject_reason) {
01069 *samr_reject_reason = REJECT_REASON_TOO_SHORT;
01070 }
01071 return NT_STATUS_PASSWORD_RESTRICTION;
01072
01073 }
01074
01075 if (check_passwd_history(hnd,new_passwd)) {
01076 if (samr_reject_reason) {
01077 *samr_reject_reason = REJECT_REASON_IN_HISTORY;
01078 }
01079 return NT_STATUS_PASSWORD_RESTRICTION;
01080 }
01081
01082 pass = Get_Pwnam(username);
01083 if (!pass) {
01084 DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username));
01085 return NT_STATUS_ACCESS_DENIED;
01086 }
01087
01088
01089 if (lp_check_password_script() && *(lp_check_password_script())) {
01090 int check_ret;
01091
01092 check_ret = smbrunsecret(lp_check_password_script(), new_passwd);
01093 DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret));
01094
01095 if (check_ret != 0) {
01096 DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
01097 if (samr_reject_reason) {
01098 *samr_reject_reason = REJECT_REASON_NOT_COMPLEX;
01099 }
01100 return NT_STATUS_PASSWORD_RESTRICTION;
01101 }
01102 }
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 if(lp_unix_password_sync() &&
01117 !chgpasswd(username, pass, old_passwd, new_passwd, as_root)) {
01118 return NT_STATUS_ACCESS_DENIED;
01119 }
01120
01121 if (!pdb_set_plaintext_passwd (hnd, new_passwd)) {
01122 return NT_STATUS_ACCESS_DENIED;
01123 }
01124
01125
01126 return pdb_update_sam_account (hnd);
01127 }