1/* 2 Unix SMB/Netbios implementation. 3 Version 1.9. 4 Samba utility functions 5 Copyright (C) Andrew Tridgell 1992-1998 6 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. 11 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. 16 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. 20*/ 21 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. 25*/ 26 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. 32 * 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. 35 * 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. 40 */ 41 42/* 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. 48 */ 49 50#include "includes.h" 51 52extern int DEBUGLEVEL; 53 54#if ALLOW_CHANGE_PASSWORD 55 56static int findpty(char **slave) 57{ 58 int master; 59 static fstring line; 60 void *dirp; 61 char *dpname; 62 63#if defined(HAVE_GRANTPT) 64 /* Try to open /dev/ptmx. If that fails, fall through to old method. */ 65 if ((master = sys_open("/dev/ptmx", O_RDWR, 0)) >= 0) { 66 grantpt(master); 67 unlockpt(master); 68 *slave = (char *)ptsname(master); 69 if (*slave == NULL) { 70 DEBUG(0,("findpty: Unable to create master/slave pty pair.\n")); 71 /* Stop fd leak on error. */ 72 close(master); 73 return -1; 74 } else { 75 DEBUG(10, ("findpty: Allocated slave pty %s\n", *slave)); 76 return (master); 77 } 78 } 79#endif /* HAVE_GRANTPT */ 80 81 fstrcpy( line, "/dev/ptyXX" ); 82 83 dirp = OpenDir(NULL, "/dev", False); 84 if (!dirp) 85 return(-1); 86 while ((dpname = ReadDirName(dirp)) != NULL) { 87 if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { 88 DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); 89 line[8] = dpname[3]; 90 line[9] = dpname[4]; 91 if ((master = sys_open(line, O_RDWR, 0)) >= 0) { 92 DEBUG(3,("pty: opened %s\n", line ) ); 93 line[5] = 't'; 94 *slave = line; 95 CloseDir(dirp); 96 return (master); 97 } 98 } 99 } 100 CloseDir(dirp); 101 return (-1); 102} 103 104static int dochild(int master,char *slavedev, char *name, char *passwordprogram, BOOL as_root) 105{ 106 int slave; 107 struct termios stermios; 108 struct passwd *pass = Get_Pwnam(name,True); 109 gid_t gid; 110 uid_t uid; 111 112 if (pass == NULL) { 113 DEBUG(0,("dochild: user name %s doesn't exist in the UNIX password database.\n", 114 name)); 115 return False; 116 } 117 118 gid = pass->pw_gid; 119 uid = pass->pw_uid; 120 121 gain_root_privilege(); 122 123 /* Start new session - gets rid of controlling terminal. */ 124 if (setsid() < 0) { 125 DEBUG(3,("Weirdness, couldn't let go of controlling terminal\n")); 126 return(False); 127 } 128 129 /* Open slave pty and acquire as new controlling terminal. */ 130 if ((slave = sys_open(slavedev, O_RDWR, 0)) < 0) { 131 DEBUG(3,("More weirdness, could not open %s\n", 132 slavedev)); 133 return(False); 134 } 135#ifdef I_PUSH 136 ioctl(slave, I_PUSH, "ptem"); 137 ioctl(slave, I_PUSH, "ldterm"); 138#elif defined(TIOCSCTTY) 139 if (ioctl(slave,TIOCSCTTY,0) <0) { 140 DEBUG(3,("Error in ioctl call for slave pty\n")); 141 /* return(False); */ 142 } 143#endif 144 145 /* Close master. */ 146 close(master); 147 148 /* Make slave stdin/out/err of child. */ 149 150 if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { 151 DEBUG(3,("Could not re-direct stdin\n")); 152 return(False); 153 } 154 if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { 155 DEBUG(3,("Could not re-direct stdout\n")); 156 return(False); 157 } 158 if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { 159 DEBUG(3,("Could not re-direct stderr\n")); 160 return(False); 161 } 162 if (slave > 2) close(slave); 163 164 /* Set proper terminal attributes - no echo, canonical input processing, 165 no map NL to CR/NL on output. */ 166 167 if (tcgetattr(0, &stermios) < 0) { 168 DEBUG(3,("could not read default terminal attributes on pty\n")); 169 return(False); 170 } 171 stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 172 stermios.c_lflag |= ICANON; 173 stermios.c_oflag &= ~(ONLCR); 174 if (tcsetattr(0, TCSANOW, &stermios) < 0) { 175 DEBUG(3,("could not set attributes of pty\n")); 176 return(False); 177 } 178 179 /* make us completely into the right uid */ 180 if (!as_root) { 181 become_user_permanently(uid, gid); 182 } 183 184 DEBUG(10, ("Invoking '%s' as password change program.\n", passwordprogram)); 185 186 /* execl() password-change application */ 187 if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { 188 DEBUG(3,("Bad status returned from %s\n",passwordprogram)); 189 return(False); 190 } 191 return(True); 192} 193 194static int expect(int master, char *issue, char *expected) 195{ 196 pstring buffer; 197 int attempts, timeout, nread, len; 198 BOOL match = False; 199 200 for (attempts = 0; attempts < 2; attempts++) 201 { 202 if (!strequal(issue, ".")) 203 { 204 if (lp_passwd_chat_debug()) 205 DEBUG(100, ("expect: sending [%s]\n", issue)); 206 207 write(master, issue, strlen(issue)); 208 } 209 210 if (strequal(expected, ".")) 211 return True; 212 213 timeout = 2000; 214 nread = 0; 215 buffer[nread] = 0; 216 217 while ((len = read_with_timeout(master, buffer + nread, 1, 218 sizeof(buffer) - nread - 1, timeout)) > 0) 219 { 220 nread += len; 221 buffer[nread] = 0; 222 223 if ((match = unix_do_match(buffer, expected, False))) 224 timeout = 200; 225 } 226 227 if (lp_passwd_chat_debug()) 228 DEBUG(100, ("expect: expected [%s] received [%s]\n", 229 expected, buffer)); 230 231 if (match) 232 break; 233 234 if (len < 0) 235 { 236 DEBUG(2, ("expect: %s\n", strerror(errno))); 237 return False; 238 } 239 } 240 241 return match; 242} 243 244static void pwd_sub(char *buf) 245{ 246 all_string_sub(buf,"\\n","\n",0); 247 all_string_sub(buf,"\\r","\r",0); 248 all_string_sub(buf,"\\s"," ",0); 249 all_string_sub(buf,"\\t","\t",0); 250} 251 252static int talktochild(int master, char *seq) 253{ 254 int count = 0; 255 fstring issue, expected; 256 257 fstrcpy(issue, "."); 258 259 while (next_token(&seq, expected, NULL, sizeof(expected))) 260 { 261 pwd_sub(expected); 262 count++; 263 264 if (!expect(master, issue, expected)) 265 { 266 DEBUG(3,("Response %d incorrect\n", count)); 267 return False; 268 } 269 270 if (!next_token(&seq, issue, NULL, sizeof(issue))) 271 fstrcpy(issue, "."); 272 273 pwd_sub(issue); 274 } 275 276 return (count > 0); 277} 278 279static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) 280{ 281 char *slavedev; 282 int master; 283 pid_t pid, wpid; 284 int wstat; 285 BOOL chstat = False; 286 287 /* allocate a pseudo-terminal device */ 288 if ((master = findpty (&slavedev)) < 0) { 289 DEBUG(3,("Cannot Allocate pty for password change: %s\n",name)); 290 return(False); 291 } 292 293 /* 294 * We need to temporarily stop CatchChild from eating 295 * SIGCLD signals as it also eats the exit status code. JRA. 296 */ 297 298 CatchChildLeaveStatus(); 299 300 if ((pid = fork()) < 0) { 301 DEBUG(3,("Cannot fork() child for password change: %s\n",name)); 302 close(master); 303 CatchChild(); 304 return(False); 305 } 306 307 /* we now have a pty */ 308 if (pid > 0){ /* This is the parent process */ 309 if ((chstat = talktochild(master, chatsequence)) == False) { 310 DEBUG(3,("Child failed to change password: %s\n",name)); 311 kill(pid, SIGKILL); /* be sure to end this process */ 312 } 313 314 while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { 315 if(errno == EINTR) { 316 errno = 0; 317 continue; 318 } 319 break; 320 } 321 322 if (wpid < 0) { 323 DEBUG(3,("The process is no longer waiting!\n\n")); 324 close(master); 325 CatchChild(); 326 return(False); 327 } 328 329 /* 330 * Go back to ignoring children. 331 */ 332 CatchChild(); 333 334 close(master); 335 336 if (pid != wpid) { 337 DEBUG(3,("We were waiting for the wrong process ID\n")); 338 return(False); 339 } 340 if (WIFEXITED(wstat) == 0) { 341 DEBUG(3,("The process exited while we were waiting\n")); 342 return(False); 343 } 344 if (WEXITSTATUS(wstat) != 0) { 345 DEBUG(3,("The status of the process exiting was %d\n", wstat)); 346 return(False); 347 } 348 349 } else { 350 /* CHILD */ 351 352 /* 353 * Lose any oplock capabilities. 354 */ 355 set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); 356 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); 357 358 /* make sure it doesn't freeze */ 359 alarm(20); 360 361 if (as_root) 362 become_root(False); 363 DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); 364 chstat = dochild(master, slavedev, name, passwordprogram, as_root); 365 366 /* 367 * The child should never return from dochild() .... 368 */ 369 370 DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat )); 371 exit(1); 372 } 373 374 if (chstat) 375 DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); 376 return (chstat); 377} 378 379 380BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) 381{ 382 pstring passwordprogram; 383 pstring chatsequence; 384 size_t i; 385 size_t len; 386 387 strlower(name); 388 DEBUG(3,("Password change for user: %s\n",name)); 389 390#if DEBUG_PASSWORD 391 DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); 392#endif 393 394 /* Take the passed information and test it for minimum criteria */ 395 /* Minimum password length */ 396 if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ 397 { 398 DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n", 399 name, lp_min_passwd_length())); 400 return (False); /* inform the user */ 401 } 402 403 /* Password is same as old password */ 404 if (strcmp(oldpass,newpass) == 0) /* don't allow same password */ 405 { 406 DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */ 407 return (False); /* inform the user */ 408 } 409 410 pstrcpy(passwordprogram,lp_passwd_program()); 411 pstrcpy(chatsequence,lp_passwd_chat()); 412 413 if (!*chatsequence) { 414 DEBUG(2,("Null chat sequence - no password changing\n")); 415 return(False); 416 } 417 418 if (!*passwordprogram) { 419 DEBUG(2,("Null password program - no password changing\n")); 420 return(False); 421 } 422 423 /* 424 * Check the old and new passwords don't contain any control 425 * characters. 426 */ 427 428 len = strlen(oldpass); 429 for(i = 0; i < len; i++) { 430 if (iscntrl((int)oldpass[i])) { 431 DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); 432 return False; 433 } 434 } 435 436 len = strlen(newpass); 437 for(i = 0; i < len; i++) { 438 if (iscntrl((int)newpass[i])) { 439 DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); 440 return False; 441 } 442 } 443 444 pstring_sub(passwordprogram,"%u",name); 445 /* note that we do NOT substitute the %o and %n in the password program 446 as this would open up a security hole where the user could use 447 a new password containing shell escape characters */ 448 449 pstring_sub(chatsequence,"%u",name); 450 all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring)); 451 all_string_sub(chatsequence,"%n",newpass,sizeof(pstring)); 452 return(chat_with_program(passwordprogram,name,chatsequence, as_root)); 453} 454 455#else /* ALLOW_CHANGE_PASSWORD */ 456BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) 457{ 458 DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); 459 return(False); 460} 461#endif /* ALLOW_CHANGE_PASSWORD */ 462 463/*********************************************************** 464 Code to check the lanman hashed password. 465************************************************************/ 466 467BOOL check_lanman_password(char *user, uchar *pass1, 468 uchar *pass2, struct smb_passwd **psmbpw) 469{ 470 static uchar null_pw[16]; 471 uchar unenc_new_pw[16]; 472 uchar unenc_old_pw[16]; 473 struct smb_passwd *smbpw; 474 475 *psmbpw = NULL; 476 477 become_root(0); 478 smbpw = getsmbpwnam(user); 479 unbecome_root(0); 480 481 if (smbpw == NULL) 482 { 483 DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n")); 484 return False; 485 } 486 487 if (smbpw->acct_ctrl & ACB_DISABLED) 488 { 489 DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); 490 return False; 491 } 492 493 if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) 494 { 495 uchar no_pw[14]; 496 memset(no_pw, '\0', 14); 497 E_P16(no_pw, null_pw); 498 smbpw->smb_passwd = null_pw; 499 } else if (smbpw->smb_passwd == NULL) { 500 DEBUG(0,("check_lanman_password: no lanman password !\n")); 501 return False; 502 } 503 504 /* Get the new lanman hash. */ 505 D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); 506 507 /* Use this to get the old lanman hash. */ 508 D_P16(unenc_new_pw, pass1, unenc_old_pw); 509 510 /* Check that the two old passwords match. */ 511 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) 512 { 513 DEBUG(0,("check_lanman_password: old password doesn't match.\n")); 514 return False; 515 } 516 517 *psmbpw = smbpw; 518 return True; 519} 520 521/*********************************************************** 522 Code to change the lanman hashed password. 523 It nulls out the NT hashed password as it will 524 no longer be valid. 525************************************************************/ 526 527BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2) 528{ 529 static uchar null_pw[16]; 530 uchar unenc_new_pw[16]; 531 BOOL ret; 532 533 if (smbpw == NULL) 534 { 535 DEBUG(0,("change_lanman_password: no smb password entry.\n")); 536 return False; 537 } 538 539 if (smbpw->acct_ctrl & ACB_DISABLED) 540 { 541 DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); 542 return False; 543 } 544 545 if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) 546 { 547 uchar no_pw[14]; 548 memset(no_pw, '\0', 14); 549 E_P16(no_pw, null_pw); 550 smbpw->smb_passwd = null_pw; 551 } else if (smbpw->smb_passwd == NULL) { 552 DEBUG(0,("change_lanman_password: no lanman password !\n")); 553 return False; 554 } 555 556 /* Get the new lanman hash. */ 557 D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); 558 559 smbpw->smb_passwd = unenc_new_pw; 560 smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ 561 562 /* Now write it into the file. */ 563 become_root(0); 564 ret = mod_smbpwd_entry(smbpw,False); 565 unbecome_root(0); 566 567 return ret; 568} 569 570/*********************************************************** 571 Code to check and change the OEM hashed password. 572************************************************************/ 573BOOL pass_oem_change(char *user, 574 uchar *lmdata, uchar *lmhash, 575 uchar *ntdata, uchar *nthash) 576{ 577 fstring new_passwd; 578 struct smb_passwd *sampw; 579 BOOL ret = check_oem_password( user, lmdata, lmhash, ntdata, nthash, 580 &sampw, 581 new_passwd, sizeof(new_passwd)); 582 583 /* 584 * At this point we have the new case-sensitive plaintext 585 * password in the fstring new_passwd. If we wanted to synchronise 586 * with UNIX passwords we would call a UNIX password changing 587 * function here. However it would have to be done as root 588 * as the plaintext of the old users password is not 589 * available. JRA. 590 */ 591 592 if ( ret && lp_unix_password_sync()) 593 { 594 ret = chgpasswd(user,"", new_passwd, True); 595 } 596 597 if (ret) 598 { 599 ret = change_oem_password( sampw, new_passwd, False ); 600 } 601 602 memset(new_passwd, 0, sizeof(new_passwd)); 603 604 return ret; 605} 606 607/*********************************************************** 608 Code to check the OEM hashed password. 609 610 this function ignores the 516 byte nt OEM hashed password 611 but does use the lm OEM password to check the nt hashed-hash. 612 613************************************************************/ 614BOOL check_oem_password(char *user, 615 uchar *lmdata, uchar *lmhash, 616 uchar *ntdata, uchar *nthash, 617 struct smb_passwd **psmbpw, char *new_passwd, 618 int new_passwd_size) 619{ 620 static uchar null_pw[16]; 621 static uchar null_ntpw[16]; 622 struct smb_passwd *smbpw = NULL; 623 int new_pw_len; 624 uchar new_ntp16[16]; 625 uchar unenc_old_ntpw[16]; 626 uchar new_p16[16]; 627 uchar unenc_old_pw[16]; 628 char no_pw[2]; 629 630 BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); 631 632 become_root(False); 633 *psmbpw = smbpw = getsmbpwnam(user); 634 unbecome_root(False); 635 636 if (smbpw == NULL) 637 { 638 DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); 639 return False; 640 } 641 642 if (smbpw->acct_ctrl & ACB_DISABLED) 643 { 644 DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); 645 return False; 646 } 647 648 /* construct a null password (in case one is needed */ 649 no_pw[0] = 0; 650 no_pw[1] = 0; 651 nt_lm_owf_gen(no_pw, null_ntpw, null_pw); 652 653 /* check for null passwords */ 654 if (smbpw->smb_passwd == NULL) 655 { 656 if (smbpw->acct_ctrl & ACB_PWNOTREQ) 657 { 658 smbpw->smb_passwd = null_pw; 659 } 660 else 661 { 662 DEBUG(0,("check_oem_password: no lanman password !\n")); 663 return False; 664 } 665 } 666 667 if (smbpw->smb_nt_passwd == NULL && nt_pass_set) 668 { 669 if (smbpw->acct_ctrl & ACB_PWNOTREQ) 670 { 671 smbpw->smb_nt_passwd = null_pw; 672 } 673 else 674 { 675 DEBUG(0,("check_oem_password: no ntlm password !\n")); 676 return False; 677 } 678 } 679 680 /* 681 * Call the hash function to get the new password. 682 */ 683 SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); 684 685 /* 686 * The length of the new password is in the last 4 bytes of 687 * the data buffer. 688 */ 689 690 new_pw_len = IVAL(lmdata, 512); 691 if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) 692 { 693 DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); 694 return False; 695 } 696 697 if (nt_pass_set) 698 { 699 /* 700 * nt passwords are in unicode 701 */ 702 int uni_pw_len = new_pw_len; 703 char *pw; 704 new_pw_len /= 2; 705 pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); 706 memcpy(new_passwd, pw, new_pw_len+1); 707 } 708 else 709 { 710 memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); 711 new_passwd[new_pw_len] = '\0'; 712 } 713 714 /* 715 * To ensure we got the correct new password, hash it and 716 * use it as a key to test the passed old password. 717 */ 718 719 nt_lm_owf_gen(new_passwd, new_ntp16, new_p16); 720 721 if (!nt_pass_set) 722 { 723 /* 724 * Now use new_p16 as the key to see if the old 725 * password matches. 726 */ 727 D_P16(new_p16 , lmhash, unenc_old_pw); 728 729 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) 730 { 731 DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); 732 return False; 733 } 734 735#ifdef DEBUG_PASSWORD 736 DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); 737#endif 738 return True; 739 } 740 741 /* 742 * Now use new_p16 as the key to see if the old 743 * password matches. 744 */ 745 D_P16(new_ntp16, lmhash, unenc_old_pw); 746 D_P16(new_ntp16, nthash, unenc_old_ntpw); 747 748 if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) 749 { 750 DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); 751 return False; 752 } 753 754 if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16)) 755 { 756 DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); 757 return False; 758 } 759#ifdef DEBUG_PASSWORD 760 DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); 761#endif 762 return True; 763} 764 765/*********************************************************** 766 Code to change the oem password. Changes both the lanman 767 and NT hashes. 768 override = False, normal 769 override = True, override XXXXXXXXXX'd password 770************************************************************/ 771 772BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) 773{ 774 int ret; 775 uchar new_nt_p16[16]; 776 uchar new_p16[16]; 777 778 nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); 779 780 smbpw->smb_passwd = new_p16; 781 smbpw->smb_nt_passwd = new_nt_p16; 782 783 /* Now write it into the file. */ 784 become_root(0); 785 ret = mod_smbpwd_entry(smbpw,override); 786 unbecome_root(0); 787 788 memset(new_passwd, '\0', strlen(new_passwd)); 789 790 return ret; 791} 792 793/*********************************************************** 794 Code to check a plaintext password against smbpasswd entries. 795***********************************************************/ 796 797BOOL check_plaintext_password(char *user,char *old_passwd, 798 int old_passwd_size, struct smb_passwd **psmbpw) 799{ 800 struct smb_passwd *smbpw = NULL; 801 uchar old_pw[16],old_ntpw[16]; 802 803 become_root(False); 804 *psmbpw = smbpw = getsmbpwnam(user); 805 unbecome_root(False); 806 807 if (smbpw == NULL) { 808 DEBUG(0,("check_plaintext_password: getsmbpwnam returned NULL\n")); 809 return False; 810 } 811 812 if (smbpw->acct_ctrl & ACB_DISABLED) { 813 DEBUG(0,("check_plaintext_password: account %s disabled.\n", user)); 814 return(False); 815 } 816 817 nt_lm_owf_gen(old_passwd,old_ntpw,old_pw); 818 819#ifdef DEBUG_PASSWORD 820 DEBUG(100,("check_plaintext_password: smbpw->smb_nt_passwd \n")); 821 dump_data(100,smbpw->smb_nt_passwd,16); 822 DEBUG(100,("check_plaintext_password: old_ntpw \n")); 823 dump_data(100,old_ntpw,16); 824 DEBUG(100,("check_plaintext_password: smbpw->smb_passwd \n")); 825 dump_data(100,smbpw->smb_passwd,16); 826 DEBUG(100,("check_plaintext_password: old_pw\n")); 827 dump_data(100,old_pw,16); 828#endif 829 830 if(memcmp(smbpw->smb_nt_passwd,old_ntpw,16) && memcmp(smbpw->smb_passwd,old_pw,16)) 831 return(False); 832 else 833 return(True); 834} 835