Based on an original PAM patch by Andrew Bartlett, re-written by me to
[Samba.git] / source / smbd / chgpasswd.c
blob1b8798908131cbe90e1ff3c660e24f8e9b196765
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* fork a child process to exec passwd and write to its
23 * tty to change a users password. This is running as the
24 * user who is attempting to change the password.
27 /*
28 * This code was copied/borrowed and stolen from various sources.
29 * The primary source was the poppasswd.c from the authors of POPMail. This software
30 * was included as a client to change passwords using the 'passwd' program
31 * on the remote machine.
33 * This routine is called by set_user_password() in password.c only if ALLOW_PASSWORD_CHANGE
34 * is defined in the compiler directives located in the Makefile.
36 * This code has been hacked by Bob Nance (nance@niehs.nih.gov) and Evan Patterson
37 * (patters2@niehs.nih.gov) at the National Institute of Environmental Health Sciences
38 * and rights to modify, distribute or incorporate this change to the CAP suite or
39 * using it for any other reason are granted, so long as this disclaimer is left intact.
43 This code was hacked considerably for inclusion in Samba, primarily
44 by Andrew.Tridgell@anu.edu.au. The biggest change was the addition
45 of the "password chat" option, which allows the easy runtime
46 specification of the expected sequence of events to change a
47 password.
50 #include "includes.h"
52 extern int DEBUGLEVEL;
54 #if ALLOW_CHANGE_PASSWORD
56 #ifdef WITH_PAM
57 BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root)
59 BOOL ret;
61 if (as_root)
62 become_root();
64 ret = smb_pam_passchange(name, oldpass, newpass);
66 if (as_root)
67 unbecome_root();
69 return ret;
72 #else /* WITH_PAM */
74 static int findpty(char **slave)
76 int master;
77 static fstring line;
78 DIR *dirp;
79 char *dpname;
81 #if defined(HAVE_GRANTPT)
82 /* Try to open /dev/ptmx. If that fails, fall through to old method. */
83 if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0)
85 grantpt(master);
86 unlockpt(master);
87 *slave = (char *)ptsname(master);
88 if (*slave == NULL)
90 DEBUG(0,
91 ("findpty: Unable to create master/slave pty pair.\n"));
92 /* Stop fd leak on error. */
93 close(master);
94 return -1;
96 else
98 DEBUG(10,
99 ("findpty: Allocated slave pty %s\n", *slave));
100 return (master);
103 #endif /* HAVE_GRANTPT */
105 fstrcpy(line, "/dev/ptyXX");
107 dirp = opendir("/dev");
108 if (!dirp)
109 return (-1);
110 while ((dpname = readdirname(dirp)) != NULL)
112 if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5)
114 DEBUG(3,
115 ("pty: try to open %s, line was %s\n", dpname,
116 line));
117 line[8] = dpname[3];
118 line[9] = dpname[4];
119 if ((master = sys_open(line, O_RDWR, 0)) >= 0)
121 DEBUG(3, ("pty: opened %s\n", line));
122 line[5] = 't';
123 *slave = line;
124 closedir(dirp);
125 return (master);
129 closedir(dirp);
130 return (-1);
133 static int dochild(int master, char *slavedev, char *name,
134 char *passwordprogram, BOOL as_root)
136 int slave;
137 struct termios stermios;
138 struct passwd *pass = Get_Pwnam(name, True);
139 gid_t gid;
140 uid_t uid;
142 if (pass == NULL)
144 DEBUG(0,
145 ("dochild: user name %s doesn't exist in the UNIX password database.\n",
146 name));
147 return False;
150 gid = pass->pw_gid;
151 uid = pass->pw_uid;
153 gain_root_privilege();
155 /* Start new session - gets rid of controlling terminal. */
156 if (setsid() < 0)
158 DEBUG(3,
159 ("Weirdness, couldn't let go of controlling terminal\n"));
160 return (False);
163 /* Open slave pty and acquire as new controlling terminal. */
164 if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0)
166 DEBUG(3, ("More weirdness, could not open %s\n", slavedev));
167 return (False);
169 #ifdef I_PUSH
170 ioctl(slave, I_PUSH, "ptem");
171 ioctl(slave, I_PUSH, "ldterm");
172 #elif defined(TIOCSCTTY)
173 if (ioctl(slave, TIOCSCTTY, 0) < 0)
175 DEBUG(3, ("Error in ioctl call for slave pty\n"));
176 /* return(False); */
178 #endif
180 /* Close master. */
181 close(master);
183 /* Make slave stdin/out/err of child. */
185 if (dup2(slave, STDIN_FILENO) != STDIN_FILENO)
187 DEBUG(3, ("Could not re-direct stdin\n"));
188 return (False);
190 if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
192 DEBUG(3, ("Could not re-direct stdout\n"));
193 return (False);
195 if (dup2(slave, STDERR_FILENO) != STDERR_FILENO)
197 DEBUG(3, ("Could not re-direct stderr\n"));
198 return (False);
200 if (slave > 2)
201 close(slave);
203 /* Set proper terminal attributes - no echo, canonical input processing,
204 no map NL to CR/NL on output. */
206 if (tcgetattr(0, &stermios) < 0)
208 DEBUG(3,
209 ("could not read default terminal attributes on pty\n"));
210 return (False);
212 stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
213 stermios.c_lflag |= ICANON;
214 stermios.c_oflag &= ~(ONLCR);
215 if (tcsetattr(0, TCSANOW, &stermios) < 0)
217 DEBUG(3, ("could not set attributes of pty\n"));
218 return (False);
221 /* make us completely into the right uid */
222 if (!as_root)
224 become_user_permanently(uid, gid);
227 DEBUG(10,
228 ("Invoking '%s' as password change program.\n",
229 passwordprogram));
231 /* execl() password-change application */
232 if (execl("/bin/sh", "sh", "-c", passwordprogram, NULL) < 0)
234 DEBUG(3, ("Bad status returned from %s\n", passwordprogram));
235 return (False);
237 return (True);
240 static int expect(int master, char *issue, char *expected)
242 pstring buffer;
243 int attempts, timeout, nread, len;
244 BOOL match = False;
246 for (attempts = 0; attempts < 2; attempts++)
248 if (!strequal(issue, "."))
250 if (lp_passwd_chat_debug())
251 DEBUG(100, ("expect: sending [%s]\n", issue));
253 write(master, issue, strlen(issue));
256 if (strequal(expected, "."))
257 return True;
259 timeout = 2000;
260 nread = 0;
261 buffer[nread] = 0;
263 while ((len = read_with_timeout(master, buffer + nread, 1,
264 sizeof(buffer) - nread - 1,
265 timeout)) > 0)
267 nread += len;
268 buffer[nread] = 0;
270 if ((match = (ms_fnmatch(expected, buffer) == 0)))
271 timeout = 200;
274 if (lp_passwd_chat_debug())
275 DEBUG(100, ("expect: expected [%s] received [%s]\n",
276 expected, buffer));
278 if (match)
279 break;
281 if (len < 0)
283 DEBUG(2, ("expect: %s\n", strerror(errno)));
284 return False;
288 return match;
291 static void pwd_sub(char *buf)
293 all_string_sub(buf, "\\n", "\n", 0);
294 all_string_sub(buf, "\\r", "\r", 0);
295 all_string_sub(buf, "\\s", " ", 0);
296 all_string_sub(buf, "\\t", "\t", 0);
299 static int talktochild(int master, char *seq)
301 int count = 0;
302 fstring issue, expected;
304 fstrcpy(issue, ".");
306 while (next_token(&seq, expected, NULL, sizeof(expected)))
308 pwd_sub(expected);
309 count++;
311 if (!expect(master, issue, expected))
313 DEBUG(3, ("Response %d incorrect\n", count));
314 return False;
317 if (!next_token(&seq, issue, NULL, sizeof(issue)))
318 fstrcpy(issue, ".");
320 pwd_sub(issue);
323 return (count > 0);
326 static BOOL chat_with_program(char *passwordprogram, char *name,
327 char *chatsequence, BOOL as_root)
329 char *slavedev;
330 int master;
331 pid_t pid, wpid;
332 int wstat;
333 BOOL chstat = False;
335 /* allocate a pseudo-terminal device */
336 if ((master = findpty(&slavedev)) < 0)
338 DEBUG(3,
339 ("Cannot Allocate pty for password change: %s\n",
340 name));
341 return (False);
345 * We need to temporarily stop CatchChild from eating
346 * SIGCLD signals as it also eats the exit status code. JRA.
349 CatchChildLeaveStatus();
351 if ((pid = sys_fork()) < 0)
353 DEBUG(3,
354 ("Cannot fork() child for password change: %s\n",
355 name));
356 close(master);
357 CatchChild();
358 return (False);
361 /* we now have a pty */
362 if (pid > 0)
363 { /* This is the parent process */
364 if ((chstat = talktochild(master, chatsequence)) == False)
366 DEBUG(3,
367 ("Child failed to change password: %s\n",
368 name));
369 kill(pid, SIGKILL); /* be sure to end this process */
372 while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0)
374 if (errno == EINTR)
376 errno = 0;
377 continue;
379 break;
382 if (wpid < 0)
384 DEBUG(3, ("The process is no longer waiting!\n\n"));
385 close(master);
386 CatchChild();
387 return (False);
391 * Go back to ignoring children.
393 CatchChild();
395 close(master);
397 if (pid != wpid)
399 DEBUG(3,
400 ("We were waiting for the wrong process ID\n"));
401 return (False);
403 if (WIFEXITED(wstat) == 0)
405 DEBUG(3,
406 ("The process exited while we were waiting\n"));
407 return (False);
409 if (WEXITSTATUS(wstat) != 0)
411 DEBUG(3,
412 ("The status of the process exiting was %d\n",
413 wstat));
414 return (False);
418 else
420 /* CHILD */
423 * Lose any oplock capabilities.
425 oplock_set_capability(False, False);
427 /* make sure it doesn't freeze */
428 alarm(20);
430 if (as_root)
431 become_root();
433 DEBUG(3,
434 ("Dochild for user %s (uid=%d,gid=%d)\n", name,
435 (int)getuid(), (int)getgid()));
436 chstat =
437 dochild(master, slavedev, name, passwordprogram,
438 as_root);
440 if (as_root)
441 unbecome_root();
444 * The child should never return from dochild() ....
447 DEBUG(0,
448 ("chat_with_program: Error: dochild() returned %d\n",
449 chstat));
450 exit(1);
453 if (chstat)
454 DEBUG(3,
455 ("Password change %ssuccessful for user %s\n",
456 (chstat ? "" : "un"), name));
457 return (chstat);
461 BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root)
463 pstring passwordprogram;
464 pstring chatsequence;
465 size_t i;
466 size_t len;
468 strlower(name);
469 DEBUG(3, ("Password change for user: %s\n", name));
471 #if DEBUG_PASSWORD
472 DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass));
473 #endif
475 /* Take the passed information and test it for minimum criteria */
476 /* Minimum password length */
477 if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */
479 DEBUG(0,
480 ("Password Change: user %s, New password is shorter than minimum password length = %d\n",
481 name, lp_min_passwd_length()));
482 return (False); /* inform the user */
485 /* Password is same as old password */
486 if (strcmp(oldpass, newpass) == 0) /* don't allow same password */
488 DEBUG(2,
489 ("Password Change: %s, New password is same as old\n", name)); /* log the attempt */
490 return (False); /* inform the user */
493 pstrcpy(passwordprogram, lp_passwd_program());
494 pstrcpy(chatsequence, lp_passwd_chat());
496 if (!*chatsequence)
498 DEBUG(2, ("Null chat sequence - no password changing\n"));
499 return (False);
502 if (!*passwordprogram)
504 DEBUG(2, ("Null password program - no password changing\n"));
505 return (False);
509 * Check the old and new passwords don't contain any control
510 * characters.
513 len = strlen(oldpass);
514 for (i = 0; i < len; i++)
516 if (iscntrl((int)oldpass[i]))
518 DEBUG(0,
519 ("chat_with_program: oldpass contains control characters (disallowed).\n"));
520 return False;
524 len = strlen(newpass);
525 for (i = 0; i < len; i++)
527 if (iscntrl((int)newpass[i]))
529 DEBUG(0,
530 ("chat_with_program: newpass contains control characters (disallowed).\n"));
531 return False;
535 pstring_sub(passwordprogram, "%u", name);
536 /* note that we do NOT substitute the %o and %n in the password program
537 as this would open up a security hole where the user could use
538 a new password containing shell escape characters */
540 pstring_sub(chatsequence, "%u", name);
541 all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring));
542 all_string_sub(chatsequence, "%n", newpass, sizeof(pstring));
543 return (chat_with_program
544 (passwordprogram, name, chatsequence, as_root));
547 #endif /* WITH_PAM */
549 #else /* ALLOW_CHANGE_PASSWORD */
551 BOOL chgpasswd(char *name, char *oldpass, char *newpass, BOOL as_root)
553 DEBUG(0, ("Password changing not compiled in (user=%s)\n", name));
554 return (False);
556 #endif /* ALLOW_CHANGE_PASSWORD */
558 /***********************************************************
559 Code to check the lanman hashed password.
560 ************************************************************/
562 BOOL check_lanman_password(char *user, uchar * pass1,
563 uchar * pass2, struct smb_passwd **psmbpw)
565 static uchar null_pw[16];
566 uchar unenc_new_pw[16];
567 uchar unenc_old_pw[16];
568 struct smb_passwd *smbpw;
570 *psmbpw = NULL;
572 become_root();
573 smbpw = getsmbpwnam(user);
574 unbecome_root();
576 if (smbpw == NULL)
578 DEBUG(0,
579 ("check_lanman_password: getsmbpwnam returned NULL\n"));
580 return False;
583 if (smbpw->acct_ctrl & ACB_DISABLED)
585 DEBUG(0,
586 ("check_lanman_password: account %s disabled.\n",
587 user));
588 return False;
591 if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
593 uchar no_pw[14];
594 memset(no_pw, '\0', 14);
595 E_P16(no_pw, null_pw);
596 smbpw->smb_passwd = null_pw;
598 else if (smbpw->smb_passwd == NULL)
600 DEBUG(0, ("check_lanman_password: no lanman password !\n"));
601 return False;
604 /* Get the new lanman hash. */
605 D_P16(smbpw->smb_passwd, pass2, unenc_new_pw);
607 /* Use this to get the old lanman hash. */
608 D_P16(unenc_new_pw, pass1, unenc_old_pw);
610 /* Check that the two old passwords match. */
611 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
613 DEBUG(0,
614 ("check_lanman_password: old password doesn't match.\n"));
615 return False;
618 *psmbpw = smbpw;
619 return True;
622 /***********************************************************
623 Code to change the lanman hashed password.
624 It nulls out the NT hashed password as it will
625 no longer be valid.
626 ************************************************************/
628 BOOL change_lanman_password(struct smb_passwd *smbpw, uchar * pass1,
629 uchar * pass2)
631 static uchar null_pw[16];
632 uchar unenc_new_pw[16];
633 BOOL ret;
635 if (smbpw == NULL)
637 DEBUG(0,
638 ("change_lanman_password: no smb password entry.\n"));
639 return False;
642 if (smbpw->acct_ctrl & ACB_DISABLED)
644 DEBUG(0,
645 ("change_lanman_password: account %s disabled.\n",
646 smbpw->smb_name));
647 return False;
650 if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
652 uchar no_pw[14];
653 memset(no_pw, '\0', 14);
654 E_P16(no_pw, null_pw);
655 smbpw->smb_passwd = null_pw;
657 else if (smbpw->smb_passwd == NULL)
659 DEBUG(0, ("change_lanman_password: no lanman password !\n"));
660 return False;
663 /* Get the new lanman hash. */
664 D_P16(smbpw->smb_passwd, pass2, unenc_new_pw);
666 smbpw->smb_passwd = unenc_new_pw;
667 smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */
669 /* Now write it into the file. */
670 become_root();
671 ret = mod_smbpwd_entry(smbpw, False);
672 unbecome_root();
674 return ret;
677 /***********************************************************
678 Code to check and change the OEM hashed password.
679 ************************************************************/
680 BOOL pass_oem_change(char *user,
681 uchar * lmdata, uchar * lmhash,
682 uchar * ntdata, uchar * nthash)
684 fstring new_passwd;
685 struct smb_passwd *sampw;
686 BOOL ret = check_oem_password(user, lmdata, lmhash, ntdata, nthash,
687 &sampw,
688 new_passwd, sizeof(new_passwd));
691 * At this point we have the new case-sensitive plaintext
692 * password in the fstring new_passwd. If we wanted to synchronise
693 * with UNIX passwords we would call a UNIX password changing
694 * function here. However it would have to be done as root
695 * as the plaintext of the old users password is not
696 * available. JRA.
699 if (ret && lp_unix_password_sync())
701 ret = chgpasswd(user, "", new_passwd, True);
704 if (ret)
706 ret = change_oem_password(sampw, new_passwd, False);
709 memset(new_passwd, 0, sizeof(new_passwd));
711 return ret;
714 /***********************************************************
715 Code to check the OEM hashed password.
717 this function ignores the 516 byte nt OEM hashed password
718 but does use the lm OEM password to check the nt hashed-hash.
720 ************************************************************/
721 BOOL check_oem_password(char *user,
722 uchar * lmdata, uchar * lmhash,
723 uchar * ntdata, uchar * nthash,
724 struct smb_passwd **psmbpw, char *new_passwd,
725 int new_passwd_size)
727 static uchar null_pw[16];
728 static uchar null_ntpw[16];
729 struct smb_passwd *smbpw = NULL;
730 int new_pw_len;
731 uchar new_ntp16[16];
732 uchar unenc_old_ntpw[16];
733 uchar new_p16[16];
734 uchar unenc_old_pw[16];
735 char no_pw[2];
737 BOOL nt_pass_set = (ntdata != NULL && nthash != NULL);
739 become_root();
740 *psmbpw = smbpw = getsmbpwnam(user);
741 unbecome_root();
743 if (smbpw == NULL)
745 DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n"));
746 return False;
749 if (smbpw->acct_ctrl & ACB_DISABLED)
751 DEBUG(0,
752 ("check_lanman_password: account %s disabled.\n",
753 user));
754 return False;
757 /* construct a null password (in case one is needed */
758 no_pw[0] = 0;
759 no_pw[1] = 0;
760 nt_lm_owf_gen(no_pw, null_ntpw, null_pw);
762 /* check for null passwords */
763 if (smbpw->smb_passwd == NULL)
765 if (smbpw->acct_ctrl & ACB_PWNOTREQ)
767 smbpw->smb_passwd = null_pw;
769 else
771 DEBUG(0,
772 ("check_oem_password: no lanman password !\n"));
773 return False;
777 if (smbpw->smb_nt_passwd == NULL && nt_pass_set)
779 if (smbpw->acct_ctrl & ACB_PWNOTREQ)
781 smbpw->smb_nt_passwd = null_pw;
783 else
785 DEBUG(0,
786 ("check_oem_password: no ntlm password !\n"));
787 return False;
792 * Call the hash function to get the new password.
794 SamOEMhash((uchar *) lmdata, (uchar *) smbpw->smb_passwd, True);
797 * The length of the new password is in the last 4 bytes of
798 * the data buffer.
801 new_pw_len = IVAL(lmdata, 512);
802 if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
804 DEBUG(0,
805 ("check_oem_password: incorrect password length (%d).\n",
806 new_pw_len));
807 return False;
810 if (nt_pass_set)
813 * nt passwords are in unicode
815 int uni_pw_len = new_pw_len;
816 char *pw;
817 new_pw_len /= 2;
818 pw =
819 dos_unistrn2((uint16 *)(&lmdata[512 - uni_pw_len]),
820 new_pw_len);
821 memcpy(new_passwd, pw, new_pw_len + 1);
823 else
825 memcpy(new_passwd, &lmdata[512 - new_pw_len], new_pw_len);
826 new_passwd[new_pw_len] = '\0';
830 * To ensure we got the correct new password, hash it and
831 * use it as a key to test the passed old password.
834 nt_lm_owf_gen(new_passwd, new_ntp16, new_p16);
836 if (!nt_pass_set)
839 * Now use new_p16 as the key to see if the old
840 * password matches.
842 D_P16(new_p16, lmhash, unenc_old_pw);
844 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
846 DEBUG(0,
847 ("check_oem_password: old lm password doesn't match.\n"));
848 return False;
851 #ifdef DEBUG_PASSWORD
852 DEBUG(100,
853 ("check_oem_password: password %s ok\n", new_passwd));
854 #endif
855 return True;
859 * Now use new_p16 as the key to see if the old
860 * password matches.
862 D_P16(new_ntp16, lmhash, unenc_old_pw);
863 D_P16(new_ntp16, nthash, unenc_old_ntpw);
865 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
867 DEBUG(0,
868 ("check_oem_password: old lm password doesn't match.\n"));
869 return False;
872 if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16))
874 DEBUG(0,
875 ("check_oem_password: old nt password doesn't match.\n"));
876 return False;
878 #ifdef DEBUG_PASSWORD
879 DEBUG(100, ("check_oem_password: password %s ok\n", new_passwd));
880 #endif
881 return True;
884 /***********************************************************
885 Code to change the oem password. Changes both the lanman
886 and NT hashes.
887 override = False, normal
888 override = True, override XXXXXXXXXX'd password
889 ************************************************************/
891 BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd,
892 BOOL override)
894 int ret;
895 uchar new_nt_p16[16];
896 uchar new_p16[16];
898 nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16);
900 smbpw->smb_passwd = new_p16;
901 smbpw->smb_nt_passwd = new_nt_p16;
903 /* Now write it into the file. */
904 become_root();
905 ret = mod_smbpwd_entry(smbpw, override);
906 unbecome_root();
908 memset(new_passwd, '\0', strlen(new_passwd));
910 return ret;
913 /***********************************************************
914 Code to check a plaintext password against smbpasswd entries.
915 ***********************************************************/
917 BOOL check_plaintext_password(char *user, char *old_passwd,
918 int old_passwd_size, struct smb_passwd **psmbpw)
920 struct smb_passwd *smbpw = NULL;
921 uchar old_pw[16], old_ntpw[16];
923 become_root();
924 *psmbpw = smbpw = getsmbpwnam(user);
925 unbecome_root();
927 if (smbpw == NULL)
929 DEBUG(0,
930 ("check_plaintext_password: getsmbpwnam returned NULL\n"));
931 return False;
934 if (smbpw->acct_ctrl & ACB_DISABLED)
936 DEBUG(0,
937 ("check_plaintext_password: account %s disabled.\n",
938 user));
939 return (False);
942 nt_lm_owf_gen(old_passwd, old_ntpw, old_pw);
944 #ifdef DEBUG_PASSWORD
945 DEBUG(100, ("check_plaintext_password: smbpw->smb_nt_passwd \n"));
946 dump_data(100, smbpw->smb_nt_passwd, 16);
947 DEBUG(100, ("check_plaintext_password: old_ntpw \n"));
948 dump_data(100, old_ntpw, 16);
949 DEBUG(100, ("check_plaintext_password: smbpw->smb_passwd \n"));
950 dump_data(100, smbpw->smb_passwd, 16);
951 DEBUG(100, ("check_plaintext_password: old_pw\n"));
952 dump_data(100, old_pw, 16);
953 #endif
955 if (memcmp(smbpw->smb_nt_passwd, old_ntpw, 16)
956 && memcmp(smbpw->smb_passwd, old_pw, 16))
957 return (False);
958 else
959 return (True);