1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-04 17:47:26 +03:00

Added SamOEMChangePassword functionality.

Jeremy.
This commit is contained in:
Jeremy Allison -
parent 112cf61cb6
commit e02e3bcbbd
4 changed files with 219 additions and 0 deletions

View File

@ -38,6 +38,10 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass);
BOOL check_lanman_password(char *user, unsigned char *pass1,
unsigned char *pass2, struct smb_passwd **psmbpw);
BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2);
BOOL check_oem_password(char *user, unsigned char *data,
struct smb_passwd **psmbpw, char *new_passwd,
int new_passwd_size);
BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd);
/*The following definitions come from client.c */
@ -1664,6 +1668,7 @@ void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key);
void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key);
void SamOEMhash( unsigned char *data, unsigned char *key);
/*The following definitions come from smbencrypt.c */

View File

@ -341,3 +341,43 @@ void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
smbhash(out, buf, key2, 1);
}
void SamOEMhash( unsigned char *data, unsigned char *key)
{
unsigned char s_box[256];
unsigned char index_i = 0;
unsigned char index_j = 0;
unsigned char j = 0;
int ind;
for (ind = 0; ind < 256; ind++)
{
s_box[ind] = (unsigned char)ind;
}
for( ind = 0; ind < 256; ind++)
{
unsigned char tc;
j += (s_box[ind] + key[ind%16]);
tc = s_box[ind];
s_box[ind] = s_box[j];
s_box[j] = tc;
}
for( ind = 0; ind < 516; ind++)
{
unsigned char tc;
unsigned char t;
index_i++;
index_j += s_box[index_i];
tc = s_box[index_i];
s_box[index_i] = s_box[index_j];
s_box[index_j] = tc;
t = s_box[index_i] + s_box[index_j];
data[ind] = data[ind] ^ s_box[t];
}
}

View File

@ -493,3 +493,117 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi
return ret;
}
/***********************************************************
Code to check the OEM hashed password.
************************************************************/
BOOL check_oem_password(char *user, unsigned char *data,
struct smb_passwd **psmbpw, char *new_passwd,
int new_passwd_size)
{
struct smb_passwd *smbpw = NULL;
int new_pw_len;
fstring upper_case_new_passwd;
unsigned char new_p16[16];
unsigned char unenc_old_pw[16];
become_root(0);
*psmbpw = smbpw = get_smbpwd_entry(user, 0);
unbecome_root(0);
if(smbpw == NULL)
{
DEBUG(0,("check_oem_password: get_smbpwd_entry returned NULL\n"));
return False;
}
if(smbpw->acct_ctrl & ACB_DISABLED)
{
DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
return False;
}
if(smbpw->smb_passwd == NULL)
{
DEBUG(0,("check_oem_password: no lanman password !\n"));
return False;
}
/*
* Call the hash function to get the new password.
*/
SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd);
/*
* 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) {
DEBUG(0,("check_oem_password: incorrect password length.\n"));
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);
if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) {
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.
************************************************************/
BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd)
{
int ret;
fstring upper_case_new_passwd;
unsigned char new_nt_p16[16];
unsigned char new_p16[16];
fstrcpy(upper_case_new_passwd, new_passwd);
strupper(upper_case_new_passwd);
E_P16((uchar *)upper_case_new_passwd, new_p16);
smbpw->smb_passwd = new_p16;
E_md4hash((uchar *) new_passwd, new_nt_p16);
smbpw->smb_nt_passwd = new_nt_p16;
/* Now write it into the file. */
become_root(0);
ret = mod_smbpwd_entry(smbpw);
unbecome_root(0);
memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd));
memset(new_passwd, '\0', strlen(new_passwd));
return ret;
}

View File

@ -1662,6 +1662,65 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
return(True);
}
/****************************************************************************
Set the user password (SamOEM version - gets plaintext).
****************************************************************************/
static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
fstring user;
fstring new_passwd;
struct smb_passwd *smbpw = NULL;
char *p = param + 2;
*rparam_len = 2;
*rparam = REALLOC(*rparam,*rparam_len);
*rdata_len = 0;
SSVAL(*rparam,0,NERR_badpass);
/*
* Check the parameter definition is correct.
*/
if(!strequal(param + 2, "zsT")) {
DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
return False;
}
p = skip_string(p, 1);
if(!strequal(p, "B516B16")) {
DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
return False;
}
p = skip_string(p,1);
fstrcpy(user,p);
p = skip_string(p,1);
if(check_oem_password( user, data, &smbpw, new_passwd, sizeof(new_passwd)) == False) {
return True;
}
/*
* At this point we have the new case-sensitive plaintext
* password in the fstring new_passwd. If we wanted to synchronise
* with UNIX passwords we would call a UNIX password changing
* function here. However it would have to be done as root
* as the plaintext of the old users password is not
* available. JRA.
*/
if(change_oem_password( smbpw, new_passwd)) {
SSVAL(*rparam,0,NERR_Success);
}
return(True);
}
/****************************************************************************
delete a print job
Form: <W> <>
@ -3410,6 +3469,7 @@ struct
{"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
{"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
{"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
{"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0},
{NULL, -1, (BOOL (*)())api_Unsupported,0}};