Hey again,
I'm just starting to make sense of all this fun password change code.
I've started writing a function which I intended to be a master
function, but I see now that it really more of a super
pdb_set_plaintext_password, with a little extra something.
>From what I can tell, it seems that the sequence of password changes,
while sometimes skipping a step, goes like this:
pass_oem_change -> change_oem_password ->
check_oem_password -> pdb_set_plaintext_password
Ideally, (if this diagram is somewhat correct), I'd like to write
something that merges all those steps into something a bit more logical.
How far off base am I?
Oh, and Andrew, thanks for putting up with my constant pestering and
questions =)
--
Patrick McCarty
Video Technician
Azusa Pacific University
Logic is a systematic method of coming to the wrong conclusion with confidence.
NTSTATUS master_change_password(const char *user_name, const char *new_passwd, int
*pcb_flags)
{
SAM_ACCOUNT *sam_pass=NULL;
uint16 acct_ctrl;
uint32 min_pass_len;
uchar new_lanman_p16[16];
uchar new_nt_p16[16];
/* Validate existence of arguments */
if (!user_name || !new_passwd || !pcb_flags)
return NT_STATUS_UNSUCCESSFUL;
/* Get the smb passwd entry for this user */
pdb_init_sam(&sam_pass);
if(!pdb_getsampwnam(sam_pass, user_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_UNSUCCESSFUL;
}
acct_ctrl = pdb_get_acct_ctrl(sampass);
/* Check to see if the account is disabled */
if (acct_ctrl & ACB_DISABLED) {
DEBUG(0,("master_change_password: account %s disabled.\n",
pdb_get_username(sampass)));
return NT_STATUS_UNSUCCESSFUL;
}
/* Check to see if user's password is locked */
if (acct_ctrl & ACB_PWLOCK) {
DEBUG(0,("master_change_password: account %s password locked.\n",
pdb_get_username(sampass)));
return NT_STATUS_ACCESS_DENIED;
}
/* Generate hashes */
nt_lm_owf_gen(new_passwd, new_nt_p16, new_lanman_p16);
/* Check to see if we were passed a LANMAN hash only */
if (pcb_flags & PCB_LMHASH)
{
if (!pdb_set_lanman_passwd (sampass, new_lanman_p16))
return NT_STATUS_UNSUCCESSFUL;
if (!pdb_set_pass_changed_now (sampass))
return NT_STATUS_UNSUCCESSFUL;
DEBUG(0,("master_change_password: changed lanman password for: %s.\n",
pdb_get_username(sampass)));
return NT_STATUS_OK;
}
/* If we get here, we have a plaintext password, so we can check length, etc
*/
/* Check minimum password length */
account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
if (strlen(new_passwd) < min_pass_len) {
DEBUG(0,("master_change_password: min_passwd_length %i, not changed.\n",
min_pass_len));
return NT_STATUS_UNSUCCESSFUL;
}
/* TODO: Add cracklib check here */
/* Lets go set our passwords now */
if (!pdb_set_nt_passwd (sampass, new_nt_p16))
return NT_STATUS_UNSUCCESSFUL;
if (!pdb_set_lanman_passwd (sampass, new_lanman_p16))
return NT_STATUS_UNSUCCESSFUL;
if (!pdb_set_pass_changed_now (sampass))
return NT_STATUS_UNSUCCESSFUL;
return NT_STATUS_OK;
}