0001-01-01 02:30:17 +02:30
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Samba utility functions
0001-01-01 02:30:17 +02:30
Copyright ( C ) Andrew Tridgell 1992 - 1998
0001-01-01 02:30:17 +02:30
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
0001-01-01 02:30:17 +02:30
/* fork a child process to exec passwd and write to its
* tty to change a users password . This is running as the
* user who is attempting to change the password .
*/
/*
* This code was copied / borrowed and stolen from various sources .
* The primary source was the poppasswd . c from the authors of POPMail . This software
* was included as a client to change passwords using the ' passwd ' program
* on the remote machine .
*
* This routine is called by set_user_password ( ) in password . c only if ALLOW_PASSWORD_CHANGE
* is defined in the compiler directives located in the Makefile .
*
* This code has been hacked by Bob Nance ( nance @ niehs . nih . gov ) and Evan Patterson
* ( patters2 @ niehs . nih . gov ) at the National Institute of Environmental Health Sciences
* and rights to modify , distribute or incorporate this change to the CAP suite or
* using it for any other reason are granted , so long as this disclaimer is left intact .
*/
/*
This code was hacked considerably for inclusion in Samba , primarily
by Andrew . Tridgell @ anu . edu . au . The biggest change was the addition
of the " password chat " option , which allows the easy runtime
specification of the expected sequence of events to change a
password .
*/
# include "includes.h"
extern int DEBUGLEVEL ;
# ifdef ALLOW_CHANGE_PASSWORD
# define MINPASSWDLENGTH 5
# define BUFSIZE 512
static int findpty ( char * * slave )
{
int master ;
0001-01-01 02:30:17 +02:30
# if defined(SVR4) || defined(SUNOS5)
0001-01-01 02:30:17 +02:30
extern char * ptsname ( ) ;
0001-01-01 02:30:17 +02:30
# else /* defined(SVR4) || defined(SUNOS5) */
0001-01-01 02:30:17 +02:30
static fstring line ;
0001-01-01 02:30:17 +02:30
void * dirp ;
char * dpname ;
0001-01-01 02:30:17 +02:30
# endif /* defined(SVR4) || defined(SUNOS5) */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# if defined(SVR4) || defined(SUNOS5)
0001-01-01 02:30:17 +02:30
if ( ( master = open ( " /dev/ptmx " , O_RDWR ) ) > = 1 ) {
grantpt ( master ) ;
unlockpt ( master ) ;
* slave = ptsname ( master ) ;
return ( master ) ;
}
0001-01-01 02:30:17 +02:30
# else /* defined(SVR4) || defined(SUNOS5) */
0001-01-01 02:30:17 +02:30
fstrcpy ( line , " /dev/ptyXX " ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
dirp = OpenDir ( - 1 , " /dev " , True ) ;
0001-01-01 02:30:17 +02:30
if ( ! dirp ) return ( - 1 ) ;
while ( ( dpname = ReadDirName ( dirp ) ) ! = NULL ) {
if ( strncmp ( dpname , " pty " , 3 ) = = 0 & & strlen ( dpname ) = = 5 ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " pty: try to open %s, line was %s \n " , dpname , line ) ) ;
0001-01-01 02:30:17 +02:30
line [ 8 ] = dpname [ 3 ] ;
line [ 9 ] = dpname [ 4 ] ;
if ( ( master = open ( line , O_RDWR ) ) > = 0 ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " pty: opened %s \n " , line ) ) ;
0001-01-01 02:30:17 +02:30
line [ 5 ] = ' t ' ;
* slave = line ;
CloseDir ( dirp ) ;
return ( master ) ;
}
}
}
CloseDir ( dirp ) ;
0001-01-01 02:30:17 +02:30
# endif /* defined(SVR4) || defined(SUNOS5) */
0001-01-01 02:30:17 +02:30
return ( - 1 ) ;
}
0001-01-01 02:30:17 +02:30
static int dochild ( int master , char * slavedev , char * name , char * passwordprogram , BOOL as_root )
0001-01-01 02:30:17 +02:30
{
int slave ;
struct termios stermios ;
struct passwd * pass = Get_Pwnam ( name , True ) ;
0001-01-01 02:30:17 +02:30
int gid ;
int uid ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( pass = = NULL ) {
DEBUG ( 0 , ( " dochild: user name %s doesn't exist in the UNIX password database. \n " ,
name ) ) ;
return False ;
}
gid = pass - > pw_gid ;
uid = pass - > pw_uid ;
0001-01-01 02:30:17 +02:30
# ifdef USE_SETRES
setresuid ( 0 , 0 , 0 ) ;
0001-01-01 02:30:17 +02:30
# else /* USE_SETRES */
0001-01-01 02:30:17 +02:30
setuid ( 0 ) ;
0001-01-01 02:30:17 +02:30
# endif /* USE_SETRES */
0001-01-01 02:30:17 +02:30
/* Start new session - gets rid of controlling terminal. */
if ( setsid ( ) < 0 ) {
DEBUG ( 3 , ( " Weirdness, couldn't let go of controlling terminal \n " ) ) ;
return ( False ) ;
}
/* Open slave pty and acquire as new controlling terminal. */
if ( ( slave = open ( slavedev , O_RDWR ) ) < 0 ) {
DEBUG ( 3 , ( " More weirdness, could not open %s \n " ,
slavedev ) ) ;
return ( False ) ;
}
0001-01-01 02:30:17 +02:30
# if defined(SVR4) || defined(SUNOS5) || defined(SCO)
0001-01-01 02:30:17 +02:30
ioctl ( slave , I_PUSH , " ptem " ) ;
ioctl ( slave , I_PUSH , " ldterm " ) ;
0001-01-01 02:30:17 +02:30
# else /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */
0001-01-01 02:30:17 +02:30
if ( ioctl ( slave , TIOCSCTTY , 0 ) < 0 ) {
DEBUG ( 3 , ( " Error in ioctl call for slave pty \n " ) ) ;
/* return(False); */
}
0001-01-01 02:30:17 +02:30
# endif /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */
0001-01-01 02:30:17 +02:30
/* Close master. */
close ( master ) ;
/* Make slave stdin/out/err of child. */
if ( dup2 ( slave , STDIN_FILENO ) ! = STDIN_FILENO ) {
DEBUG ( 3 , ( " Could not re-direct stdin \n " ) ) ;
return ( False ) ;
}
if ( dup2 ( slave , STDOUT_FILENO ) ! = STDOUT_FILENO ) {
DEBUG ( 3 , ( " Could not re-direct stdout \n " ) ) ;
return ( False ) ;
}
if ( dup2 ( slave , STDERR_FILENO ) ! = STDERR_FILENO ) {
DEBUG ( 3 , ( " Could not re-direct stderr \n " ) ) ;
return ( False ) ;
}
if ( slave > 2 ) close ( slave ) ;
/* Set proper terminal attributes - no echo, canonical input processing,
no map NL to CR / NL on output . */
if ( tcgetattr ( 0 , & stermios ) < 0 ) {
DEBUG ( 3 , ( " could not read default terminal attributes on pty \n " ) ) ;
return ( False ) ;
}
stermios . c_lflag & = ~ ( ECHO | ECHOE | ECHOK | ECHONL ) ;
stermios . c_lflag | = ICANON ;
stermios . c_oflag & = ~ ( ONLCR ) ;
if ( tcsetattr ( 0 , TCSANOW , & stermios ) < 0 ) {
DEBUG ( 3 , ( " could not set attributes of pty \n " ) ) ;
return ( False ) ;
}
/* make us completely into the right uid */
0001-01-01 02:30:17 +02:30
if ( ! as_root ) {
0001-01-01 02:30:17 +02:30
# ifdef USE_SETRES
0001-01-01 02:30:17 +02:30
setresgid ( 0 , 0 , 0 ) ;
setresuid ( 0 , 0 , 0 ) ;
setresgid ( gid , gid , gid ) ;
setresuid ( uid , uid , uid ) ;
0001-01-01 02:30:17 +02:30
# else
0001-01-01 02:30:17 +02:30
setuid ( 0 ) ;
seteuid ( 0 ) ;
setgid ( gid ) ;
setegid ( gid ) ;
setuid ( uid ) ;
seteuid ( uid ) ;
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/* execl() password-change application */
if ( execl ( " /bin/sh " , " sh " , " -c " , passwordprogram , NULL ) < 0 ) {
DEBUG ( 3 , ( " Bad status returned from %s \n " , passwordprogram ) ) ;
return ( False ) ;
}
return ( True ) ;
}
static int expect ( int master , char * expected , char * buf )
{
int n , m ;
n = 0 ;
buf [ 0 ] = 0 ;
while ( 1 ) {
if ( n > = BUFSIZE - 1 ) {
return False ;
}
/* allow 4 seconds for some output to appear */
0001-01-01 02:30:17 +02:30
m = read_with_timeout ( master , buf + n , 1 , BUFSIZE - 1 - n , 4000 ) ;
0001-01-01 02:30:17 +02:30
if ( m < 0 )
return False ;
n + = m ;
buf [ n ] = 0 ;
{
pstring s1 , s2 ;
0001-01-01 02:30:17 +02:30
pstrcpy ( s1 , buf ) ;
pstrcpy ( s2 , expected ) ;
0001-01-01 02:30:17 +02:30
if ( do_match ( s1 , s2 , False ) )
return ( True ) ;
}
}
}
static void pwd_sub ( char * buf )
{
string_sub ( buf , " \\ n " , " \n " ) ;
string_sub ( buf , " \\ r " , " \r " ) ;
string_sub ( buf , " \\ s " , " " ) ;
string_sub ( buf , " \\ t " , " \t " ) ;
}
static void writestring ( int fd , char * s )
{
int l ;
l = strlen ( s ) ;
write ( fd , s , l ) ;
}
static int talktochild ( int master , char * chatsequence )
{
char buf [ BUFSIZE ] ;
int count = 0 ;
char * ptr = chatsequence ;
fstring chatbuf ;
* buf = 0 ;
sleep ( 1 ) ;
while ( next_token ( & ptr , chatbuf , NULL ) ) {
BOOL ok = True ;
count + + ;
pwd_sub ( chatbuf ) ;
if ( ! strequal ( chatbuf , " . " ) )
ok = expect ( master , chatbuf , buf ) ;
0001-01-01 02:30:17 +02:30
if ( lp_passwd_chat_debug ( ) )
DEBUG ( 100 , ( " talktochild: chatbuf=[%s] responsebuf=[%s] \n " , chatbuf , buf ) ) ;
0001-01-01 02:30:17 +02:30
if ( ! ok ) {
DEBUG ( 3 , ( " response %d incorrect \n " , count ) ) ;
return ( False ) ;
}
if ( ! next_token ( & ptr , chatbuf , NULL ) ) break ;
pwd_sub ( chatbuf ) ;
if ( ! strequal ( chatbuf , " . " ) )
writestring ( master , chatbuf ) ;
0001-01-01 02:30:17 +02:30
if ( lp_passwd_chat_debug ( ) )
DEBUG ( 100 , ( " talktochild: sendbuf=[%s] \n " , chatbuf ) ) ;
0001-01-01 02:30:17 +02:30
}
if ( count < 1 ) return ( False ) ;
return ( True ) ;
}
0001-01-01 02:30:17 +02:30
BOOL chat_with_program ( char * passwordprogram , char * name , char * chatsequence , BOOL as_root )
0001-01-01 02:30:17 +02:30
{
char * slavedev ;
int master ;
pid_t pid , wpid ;
int wstat ;
BOOL chstat ;
/* allocate a pseudo-terminal device */
if ( ( master = findpty ( & slavedev ) ) < 0 ) {
DEBUG ( 3 , ( " Cannot Allocate pty for password change: %s " , name ) ) ;
return ( False ) ;
}
if ( ( pid = fork ( ) ) < 0 ) {
DEBUG ( 3 , ( " Cannot fork() child for password change: %s " , name ) ) ;
return ( False ) ;
}
/* we now have a pty */
if ( pid > 0 ) { /* This is the parent process */
if ( ( chstat = talktochild ( master , chatsequence ) ) = = False ) {
DEBUG ( 3 , ( " Child failed to change password: %s \n " , name ) ) ;
kill ( pid , SIGKILL ) ; /* be sure to end this process */
return ( False ) ;
}
0001-01-01 02:30:17 +02:30
if ( ( wpid = sys_waitpid ( pid , & wstat , 0 ) ) < 0 ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " The process is no longer waiting! \n \n " ) ) ;
return ( False ) ;
}
if ( pid ! = wpid ) {
DEBUG ( 3 , ( " We were waiting for the wrong process ID \n " ) ) ;
return ( False ) ;
}
if ( WIFEXITED ( wstat ) = = 0 ) {
DEBUG ( 3 , ( " The process exited while we were waiting \n " ) ) ;
return ( False ) ;
}
if ( WEXITSTATUS ( wstat ) ! = 0 ) {
DEBUG ( 3 , ( " The status of the process exiting was %d \n " , wstat ) ) ;
return ( False ) ;
}
} else {
/* CHILD */
/* make sure it doesn't freeze */
alarm ( 20 ) ;
0001-01-01 02:30:17 +02:30
if ( as_root )
become_root ( False ) ;
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " Dochild for user %s (uid=%d,gid=%d) \n " , name , getuid ( ) , getgid ( ) ) ) ;
0001-01-01 02:30:17 +02:30
chstat = dochild ( master , slavedev , name , passwordprogram , as_root ) ;
if ( as_root )
unbecome_root ( False ) ;
0001-01-01 02:30:17 +02:30
}
DEBUG ( 3 , ( " Password change %ssuccessful for user %s \n " , ( chstat ? " " : " un " ) , name ) ) ;
return ( chstat ) ;
}
0001-01-01 02:30:17 +02:30
BOOL chgpasswd ( char * name , char * oldpass , char * newpass , BOOL as_root )
0001-01-01 02:30:17 +02:30
{
pstring passwordprogram ;
pstring chatsequence ;
0001-01-01 02:30:17 +02:30
int i ;
int len ;
0001-01-01 02:30:17 +02:30
strlower ( name ) ;
DEBUG ( 3 , ( " Password change for user: %s \n " , name ) ) ;
# if DEBUG_PASSWORD
DEBUG ( 100 , ( " Passwords: old=%s new=%s \n " , oldpass , newpass ) ) ;
# endif
/* Take the passed information and test it for minimum criteria */
/* Minimum password length */
if ( strlen ( newpass ) < MINPASSWDLENGTH ) /* too short, must be at least MINPASSWDLENGTH */
{
DEBUG ( 2 , ( " Password Change: %s, New password is shorter than MINPASSWDLENGTH \n " , name ) ) ;
return ( False ) ; /* inform the user */
}
/* Password is same as old password */
if ( strcmp ( oldpass , newpass ) = = 0 ) /* don't allow same password */
{
DEBUG ( 2 , ( " Password Change: %s, New password is same as old \n " , name ) ) ; /* log the attempt */
return ( False ) ; /* inform the user */
}
# if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT))
0001-01-01 02:30:17 +02:30
pstrcpy ( passwordprogram , PASSWD_PROGRAM ) ;
pstrcpy ( chatsequence , PASSWD_CHAT ) ;
0001-01-01 02:30:17 +02:30
# else
0001-01-01 02:30:17 +02:30
pstrcpy ( passwordprogram , lp_passwd_program ( ) ) ;
pstrcpy ( chatsequence , lp_passwd_chat ( ) ) ;
0001-01-01 02:30:17 +02:30
# endif
if ( ! * chatsequence ) {
DEBUG ( 2 , ( " Null chat sequence - no password changing \n " ) ) ;
return ( False ) ;
}
if ( ! * passwordprogram ) {
DEBUG ( 2 , ( " Null password program - no password changing \n " ) ) ;
return ( False ) ;
}
0001-01-01 02:30:17 +02:30
/*
* Check the old and new passwords don ' t contain any control
* characters .
*/
len = strlen ( oldpass ) ;
for ( i = 0 ; i < len ; i + + ) {
if ( iscntrl ( oldpass [ i ] ) ) {
DEBUG ( 0 , ( " chat_with_program: oldpass contains control characters (disallowed). \n " ) ) ;
return False ;
}
}
len = strlen ( newpass ) ;
for ( i = 0 ; i < len ; i + + ) {
if ( iscntrl ( newpass [ i ] ) ) {
DEBUG ( 0 , ( " chat_with_program: newpass contains control characters (disallowed). \n " ) ) ;
return False ;
}
}
0001-01-01 02:30:17 +02:30
string_sub ( passwordprogram , " %u " , name ) ;
string_sub ( passwordprogram , " %o " , oldpass ) ;
string_sub ( passwordprogram , " %n " , newpass ) ;
string_sub ( chatsequence , " %u " , name ) ;
string_sub ( chatsequence , " %o " , oldpass ) ;
string_sub ( chatsequence , " %n " , newpass ) ;
0001-01-01 02:30:17 +02:30
return ( chat_with_program ( passwordprogram , name , chatsequence , as_root ) ) ;
0001-01-01 02:30:17 +02:30
}
# else
0001-01-01 02:30:17 +02:30
BOOL chgpasswd ( char * name , char * oldpass , char * newpass , BOOL as_root )
0001-01-01 02:30:17 +02:30
{
DEBUG ( 0 , ( " Password changing not compiled in (user=%s) \n " , name ) ) ;
return ( False ) ;
}
# endif
0001-01-01 02:30:17 +02:30
/***********************************************************
Code to check the lanman hashed password .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL check_lanman_password ( char * user , unsigned char * pass1 ,
0001-01-01 02:30:17 +02:30
unsigned char * pass2 , struct smb_passwd * * psampw )
0001-01-01 02:30:17 +02:30
{
unsigned char unenc_new_pw [ 16 ] ;
unsigned char unenc_old_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
unsigned char null_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
struct smb_passwd * sampw ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
* psampw = NULL ;
0001-01-01 02:30:17 +02:30
become_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
sampw = getsampwnam ( user ) ;
0001-01-01 02:30:17 +02:30
unbecome_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
if ( sampw = = NULL )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_lanman_password: getsampwnam returned NULL \n " ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
if ( sampw - > acct_ctrl & ACB_DISABLED )
0001-01-01 02:30:17 +02:30
{
DEBUG ( 0 , ( " check_lanman_password: account %s disabled. \n " , user ) ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
if ( ( sampw - > smb_passwd = = NULL ) & & ( sampw - > acct_ctrl & ACB_PWNOTREQ ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
unsigned char no_pw [ 14 ] ;
memset ( no_pw , ' \0 ' , 14 ) ;
E_P16 ( ( uchar * ) no_pw , ( uchar * ) null_pw ) ;
0001-01-01 02:30:17 +02:30
sampw - > smb_passwd = null_pw ;
} else if ( sampw - > smb_passwd = = NULL ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_lanman_password: no lanman password ! \n " ) ) ;
return False ;
}
/* Get the new lanman hash. */
0001-01-01 02:30:17 +02:30
D_P16 ( sampw - > smb_passwd , pass2 , unenc_new_pw ) ;
0001-01-01 02:30:17 +02:30
/* Use this to get the old lanman hash. */
D_P16 ( unenc_new_pw , pass1 , unenc_old_pw ) ;
/* Check that the two old passwords match. */
0001-01-01 02:30:17 +02:30
if ( memcmp ( sampw - > smb_passwd , unenc_old_pw , 16 ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_lanman_password: old password doesn't match. \n " ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
* psampw = sampw ;
0001-01-01 02:30:17 +02:30
return True ;
}
/***********************************************************
Code to change the lanman hashed password .
It nulls out the NT hashed password as it will
no longer be valid .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
BOOL change_lanman_password ( struct smb_passwd * sampw , unsigned char * pass1 , unsigned char * pass2 )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
unsigned char unenc_new_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
unsigned char null_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
BOOL ret ;
0001-01-01 02:30:17 +02:30
if ( sampw = = NULL )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " change_lanman_password: no smb password entry. \n " ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
if ( sampw - > acct_ctrl & ACB_DISABLED )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " change_lanman_password: account %s disabled. \n " , sampw - > smb_name ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
if ( ( sampw - > smb_passwd = = NULL ) & & ( sampw - > acct_ctrl & ACB_PWNOTREQ ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
unsigned char no_pw [ 14 ] ;
memset ( no_pw , ' \0 ' , 14 ) ;
E_P16 ( ( uchar * ) no_pw , ( uchar * ) null_pw ) ;
0001-01-01 02:30:17 +02:30
sampw - > smb_passwd = null_pw ;
} else if ( sampw - > smb_passwd = = NULL ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " change_lanman_password: no lanman password ! \n " ) ) ;
return False ;
}
/* Get the new lanman hash. */
0001-01-01 02:30:17 +02:30
D_P16 ( sampw - > smb_passwd , pass2 , unenc_new_pw ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
sampw - > smb_passwd = unenc_new_pw ;
sampw - > smb_nt_passwd = NULL ; /* We lose the NT hash. Sorry. */
0001-01-01 02:30:17 +02:30
/* Now write it into the file. */
become_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
ret = mod_sampwd_entry ( sampw , False ) ;
0001-01-01 02:30:17 +02:30
unbecome_root ( 0 ) ;
return ret ;
}
0001-01-01 02:30:17 +02:30
/***********************************************************
Code to check the OEM hashed password .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL check_oem_password ( char * user , unsigned char * data ,
0001-01-01 02:30:17 +02:30
struct smb_passwd * * psampw , char * new_passwd ,
0001-01-01 02:30:17 +02:30
int new_passwd_size )
{
0001-01-01 02:30:17 +02:30
struct smb_passwd * sampw = NULL ;
0001-01-01 02:30:17 +02:30
int new_pw_len ;
fstring upper_case_new_passwd ;
unsigned char new_p16 [ 16 ] ;
unsigned char unenc_old_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
unsigned char null_pw [ 16 ] ;
0001-01-01 02:30:17 +02:30
become_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
* psampw = sampw = getsampwnam ( user ) ;
0001-01-01 02:30:17 +02:30
unbecome_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
if ( sampw = = NULL )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_oem_password: getsampwnam returned NULL \n " ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
if ( sampw - > acct_ctrl & ACB_DISABLED )
0001-01-01 02:30:17 +02:30
{
DEBUG ( 0 , ( " check_lanman_password: account %s disabled. \n " , user ) ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
if ( ( sampw - > smb_passwd = = NULL ) & & ( sampw - > acct_ctrl & ACB_PWNOTREQ ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
unsigned char no_pw [ 14 ] ;
memset ( no_pw , ' \0 ' , 14 ) ;
E_P16 ( ( uchar * ) no_pw , ( uchar * ) null_pw ) ;
0001-01-01 02:30:17 +02:30
sampw - > smb_passwd = null_pw ;
} else if ( sampw - > smb_passwd = = NULL ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_oem_password: no lanman password ! \n " ) ) ;
return False ;
}
/*
* Call the hash function to get the new password .
*/
0001-01-01 02:30:17 +02:30
SamOEMhash ( ( unsigned char * ) data , ( unsigned char * ) sampw - > smb_passwd , True ) ;
0001-01-01 02:30:17 +02:30
/*
* The length of the new password is in the last 4 bytes of
* the data buffer .
*/
new_pw_len = IVAL ( data , 512 ) ;
if ( new_pw_len < 0 | | new_pw_len > new_passwd_size - 1 ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_oem_password: incorrect password length (%d). \n " , new_pw_len ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
memcpy ( new_passwd , & data [ 512 - new_pw_len ] , new_pw_len ) ;
new_passwd [ new_pw_len ] = ' \0 ' ;
/*
* To ensure we got the correct new password , hash it and
* use it as a key to test the passed old password .
*/
memset ( upper_case_new_passwd , ' \0 ' , sizeof ( upper_case_new_passwd ) ) ;
fstrcpy ( upper_case_new_passwd , new_passwd ) ;
strupper ( upper_case_new_passwd ) ;
E_P16 ( ( uchar * ) upper_case_new_passwd , new_p16 ) ;
/*
* Now use new_p16 as the key to see if the old
* password matches .
*/
D_P16 ( new_p16 , & data [ 516 ] , unenc_old_pw ) ;
0001-01-01 02:30:17 +02:30
if ( memcmp ( sampw - > smb_passwd , unenc_old_pw , 16 ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " check_oem_password: old password doesn't match. \n " ) ) ;
return False ;
}
memset ( upper_case_new_passwd , ' \0 ' , strlen ( upper_case_new_passwd ) ) ;
return True ;
}
/***********************************************************
Code to change the oem password . Changes both the lanman
and NT hashes .
0001-01-01 02:30:17 +02:30
override = False , normal
override = True , override XXXXXXXXXX ' d password
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
BOOL change_oem_password ( struct smb_passwd * sampw , char * new_passwd , BOOL override )
0001-01-01 02:30:17 +02:30
{
int ret ;
fstring upper_case_new_passwd ;
unsigned char new_nt_p16 [ 16 ] ;
unsigned char new_p16 [ 16 ] ;
0001-01-01 02:30:17 +02:30
memset ( upper_case_new_passwd , ' \0 ' , sizeof ( upper_case_new_passwd ) ) ;
0001-01-01 02:30:17 +02:30
fstrcpy ( upper_case_new_passwd , new_passwd ) ;
strupper ( upper_case_new_passwd ) ;
E_P16 ( ( uchar * ) upper_case_new_passwd , new_p16 ) ;
0001-01-01 02:30:17 +02:30
sampw - > smb_passwd = new_p16 ;
0001-01-01 02:30:17 +02:30
E_md4hash ( ( uchar * ) new_passwd , new_nt_p16 ) ;
0001-01-01 02:30:17 +02:30
sampw - > smb_nt_passwd = new_nt_p16 ;
0001-01-01 02:30:17 +02:30
/* Now write it into the file. */
become_root ( 0 ) ;
0001-01-01 02:30:17 +02:30
ret = mod_sampwd_entry ( sampw , override ) ;
0001-01-01 02:30:17 +02:30
unbecome_root ( 0 ) ;
memset ( upper_case_new_passwd , ' \0 ' , strlen ( upper_case_new_passwd ) ) ;
memset ( new_passwd , ' \0 ' , strlen ( new_passwd ) ) ;
return ret ;
}