static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23,
struct samu *pwd)
{
- pstring plaintext_buf;
- uint32 len;
+ char *plaintext_buf = NULL;
+ uint32 len = 0;
uint16 acct_ctrl;
NTSTATUS status;
-
+
if (id23 == NULL) {
DEBUG(5, ("set_user_info_23: NULL id23\n"));
return NT_STATUS_INVALID_PARAMETER;
}
-
+
DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
pdb_get_username(pwd)));
acct_ctrl = pdb_get_acct_ctrl(pwd);
- if (!decode_pw_buffer(id23->pass, plaintext_buf, 256, &len, STR_UNICODE)) {
+ if (!decode_pw_buffer(mem_ctx,
+ id23->pass,
+ &plaintext_buf,
+ &len,
+ STR_UNICODE)) {
TALLOC_FREE(pwd);
return NT_STATUS_INVALID_PARAMETER;
}
-
+
if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
TALLOC_FREE(pwd);
return NT_STATUS_ACCESS_DENIED;
}
-
+
copy_id23_to_sam_passwd(pwd, id23);
-
+
/* if it's a trust account, don't update /etc/passwd */
if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) ||
( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) ||
if ((passwd = Get_Pwnam(pdb_get_username(pwd))) == NULL) {
DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
}
-
+
if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
TALLOC_FREE(pwd);
return NT_STATUS_ACCESS_DENIED;
}
}
}
-
- ZERO_STRUCT(plaintext_buf);
-
+
+ memset(plaintext_buf, '\0', strlen(plaintext_buf));
+
if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) &&
(!NT_STATUS_IS_OK(status = pdb_set_unix_primary_group(mem_ctx,
pwd)))) {
TALLOC_FREE(pwd);
return status;
}
-
+
TALLOC_FREE(pwd);
return NT_STATUS_OK;
static bool set_user_info_pw(uint8 *pass, struct samu *pwd)
{
- uint32 len;
- pstring plaintext_buf;
+ uint32 len = 0;
+ char *plaintext_buf = NULL;
uint32 acct_ctrl;
time_t last_set_time;
enum pdb_value_state last_set_state;
-
+
DEBUG(5, ("Attempting administrator password change for user %s\n",
pdb_get_username(pwd)));
last_set_state = pdb_get_init_flags(pwd, PDB_PASSLASTSET);
last_set_time = pdb_get_pass_last_set_time(pwd);
- ZERO_STRUCT(plaintext_buf);
-
- if (!decode_pw_buffer(pass, plaintext_buf, 256, &len, STR_UNICODE)) {
+ if (!decode_pw_buffer(talloc_tos(),
+ pass,
+ &plaintext_buf,
+ &len,
+ STR_UNICODE)) {
TALLOC_FREE(pwd);
return False;
}
TALLOC_FREE(pwd);
return False;
}
-
+
/* if it's a trust account, don't update /etc/passwd */
if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) ||
( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) ||
if ((passwd = Get_Pwnam(pdb_get_username(pwd))) == NULL) {
DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
}
-
+
if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
TALLOC_FREE(pwd);
return False;
}
}
}
-
- ZERO_STRUCT(plaintext_buf);
-
+
+ memset(plaintext_buf, '\0', strlen(plaintext_buf));
+
/* restore last set time as this is an admin change, not a user pw change */
pdb_set_pass_last_set_time (pwd, last_set_time, last_set_state);
-
+
DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
-
+
/* update the SAMBA password */
if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
TALLOC_FREE(pwd);
* 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
extern struct passdb_ops pdb_ops;
static NTSTATUS check_oem_password(const char *user,
- uchar password_encrypted_with_lm_hash[516],
+ uchar password_encrypted_with_lm_hash[516],
const uchar old_lm_hash_encrypted[16],
- uchar password_encrypted_with_nt_hash[516],
+ uchar password_encrypted_with_nt_hash[516],
const uchar old_nt_hash_encrypted[16],
- struct samu **hnd, char *new_passwd,
- int new_passwd_size);
+ struct samu **hnd,
+ char **pp_new_passwd);
#if ALLOW_CHANGE_PASSWORD
static int expect(int master, char *issue, char *expected)
{
- pstring buffer;
+ char buffer[1024];
int attempts, timeout, nread, len;
bool match = False;
return (chstat);
}
-bool chgpasswd(const char *name, const struct passwd *pass,
+bool chgpasswd(const char *name, const struct passwd *pass,
const char *oldpass, const char *newpass, bool as_root)
{
- pstring passwordprogram;
- pstring chatsequence;
+ char *passwordprogram = NULL;
+ char *chatsequence = NULL;
size_t i;
size_t len;
+ TALLOC_CTX *ctx = talloc_tos();
if (!oldpass) {
oldpass = "";
return (False); /* inform the user */
}
- /*
+ /*
* Check the old and new passwords don't contain any control
* characters.
*/
return False;
}
}
-
+
#ifdef WITH_PAM
if (lp_pam_password_change()) {
bool ret;
} else {
ret = smb_pam_passchange(name, oldpass, newpass);
}
-
+
if (as_root)
unbecome_root();
if (pass == NULL) {
DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name));
- return False;
+ return false;
}
- pstrcpy(passwordprogram, lp_passwd_program());
- pstrcpy(chatsequence, lp_passwd_chat());
-
- if (!*chatsequence) {
- DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n"));
- return (False);
- }
-
- if (!*passwordprogram) {
+ passwordprogram = talloc_strdup(ctx, lp_passwd_program());
+ if (!passwordprogram || !*passwordprogram) {
DEBUG(2, ("chgpasswd: Null password program - no password changing\n"));
- return (False);
+ return false;
+ }
+ chatsequence = talloc_strdup(ctx, lp_passwd_chat());
+ if (!chatsequence || !*chatsequence) {
+ DEBUG(2, ("chgpasswd: Null chat sequence - no password changing\n"));
+ return false;
}
if (as_root) {
if (strstr_m(passwordprogram, "%u") == NULL) {
DEBUG(0,("chgpasswd: Running as root the 'passwd program' parameter *MUST* contain \
the string %%u, and the given string %s does not.\n", passwordprogram ));
- return False;
+ return false;
}
}
- pstring_sub(passwordprogram, "%u", name);
+ passwordprogram = talloc_string_sub(ctx, passwordprogram, "%u", name);
+ if (!passwordprogram) {
+ return false;
+ }
+
/* note that we do NOT substitute the %o and %n in the password program
as this would open up a security hole where the user could use
a new password containing shell escape characters */
- pstring_sub(chatsequence, "%u", name);
- all_string_sub(chatsequence, "%o", oldpass, sizeof(pstring));
- all_string_sub(chatsequence, "%n", newpass, sizeof(pstring));
- return (chat_with_program
- (passwordprogram, pass, chatsequence, as_root));
+ chatsequence = talloc_string_sub(ctx, chatsequence, "%u", name);
+ if (!chatsequence) {
+ return false;
+ }
+ chatsequence = talloc_all_string_sub(ctx,
+ chatsequence,
+ "%o",
+ oldpass);
+ if (!chatsequence) {
+ return false;
+ }
+ chatsequence = talloc_all_string_sub(ctx,
+ chatsequence,
+ "%n",
+ newpass);
+ return chat_with_program(passwordprogram,
+ pass,
+ chatsequence,
+ as_root);
}
#else /* ALLOW_CHANGE_PASSWORD */
if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) {
TALLOC_FREE(sampass);
/* Not quite sure what this one qualifies as, but this will do */
- return False;
+ return False;
}
-
+
/* Now flush the sam_passwd struct to persistent storage */
ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
************************************************************/
NTSTATUS pass_oem_change(char *user,
- uchar password_encrypted_with_lm_hash[516],
+ uchar password_encrypted_with_lm_hash[516],
const uchar old_lm_hash_encrypted[16],
- uchar password_encrypted_with_nt_hash[516],
+ uchar password_encrypted_with_nt_hash[516],
const uchar old_nt_hash_encrypted[16],
uint32 *reject_reason)
{
- pstring new_passwd;
+ char *new_passwd = NULL;
struct samu *sampass = NULL;
- NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash,
- old_lm_hash_encrypted,
- password_encrypted_with_nt_hash,
+ NTSTATUS nt_status = check_oem_password(user,
+ password_encrypted_with_lm_hash,
+ old_lm_hash_encrypted,
+ password_encrypted_with_nt_hash,
old_nt_hash_encrypted,
- &sampass, new_passwd, sizeof(new_passwd));
-
- if (!NT_STATUS_IS_OK(nt_status))
+ &sampass,
+ &new_passwd);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
+ }
/* We've already checked the old password here.... */
become_root();
nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason);
unbecome_root();
- memset(new_passwd, 0, sizeof(new_passwd));
+ memset(new_passwd, 0, strlen(new_passwd));
TALLOC_FREE(sampass);
}
/***********************************************************
- Decrypt and verify a user password change.
+ Decrypt and verify a user password change.
- The 516 byte long buffers are encrypted with the old NT and
- old LM passwords, and if the NT passwords are present, both
+ The 516 byte long buffers are encrypted with the old NT and
+ old LM passwords, and if the NT passwords are present, both
buffers contain a unicode string.
After decrypting the buffers, check the password is correct by
matching the old hashed passwords with the passwords in the passdb.
-
+
************************************************************/
static NTSTATUS check_oem_password(const char *user,
- uchar password_encrypted_with_lm_hash[516],
+ uchar password_encrypted_with_lm_hash[516],
const uchar old_lm_hash_encrypted[16],
- uchar password_encrypted_with_nt_hash[516],
+ uchar password_encrypted_with_nt_hash[516],
const uchar old_nt_hash_encrypted[16],
- struct samu **hnd, char *new_passwd,
- int new_passwd_size)
+ struct samu **hnd,
+ char **pp_new_passwd)
{
static uchar null_pw[16];
static uchar null_ntpw[16];
if (ret == False) {
DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n"));
TALLOC_FREE(sampass);
- return NT_STATUS_NO_SUCH_USER;
+ return NT_STATUS_NO_SUCH_USER;
}
acct_ctrl = pdb_get_acct_ctrl(sampass);
-
+
if (acct_ctrl & ACB_DISABLED) {
DEBUG(2,("check_lanman_password: account %s disabled.\n", user));
TALLOC_FREE(sampass);
if (nt_pw && nt_pass_set) {
/* IDEAL Case: passwords are in unicode, and we can
- * read use the password encrypted with the NT hash
+ * read use the password encrypted with the NT hash
*/
password_encrypted = password_encrypted_with_nt_hash;
encryption_key = nt_pw;
DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n",
user));
TALLOC_FREE(sampass);
- return NT_STATUS_WRONG_PASSWORD;
+ return NT_STATUS_WRONG_PASSWORD;
} else if (lm_pass_set) {
if (lp_lanman_auth()) {
DEBUG(1, ("LM password change supplied for user %s, but we have no LanMan password to check it with\n",
return NT_STATUS_WRONG_PASSWORD;
}
- /*
- * Decrypt the password with the key
+ /*
+ * Decrypt the password with the key
*/
SamOEMhash( password_encrypted, encryption_key, 516);
- if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len,
- nt_pass_set ? STR_UNICODE : STR_ASCII)) {
+ if (!decode_pw_buffer(talloc_tos(),
+ password_encrypted,
+ pp_new_passwd,
+ &new_pw_len,
+ nt_pass_set ? STR_UNICODE : STR_ASCII)) {
TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
if (nt_pass_set) {
/* NT passwords, verify the NT hash. */
-
+
/* Calculate the MD4 hash (NT compatible) of the password */
memset(new_nt_hash, '\0', 16);
- E_md4hash(new_passwd, new_nt_hash);
+ E_md4hash(*pp_new_passwd, new_nt_hash);
if (nt_pw) {
/*
TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* We could check the LM password here, but there is
* little point, we already know the password is
* correct, and the LM password might not even be
* change */
#ifdef DEBUG_PASSWORD
DEBUG(100,
- ("check_oem_password: password %s ok\n", new_passwd));
+ ("check_oem_password: password %s ok\n", *pp_new_passwd));
#endif
*hnd = sampass;
return NT_STATUS_OK;
}
-
+
if (lanman_pw) {
/*
* check the lm verifier
}
#ifdef DEBUG_PASSWORD
DEBUG(100,
- ("check_oem_password: password %s ok\n", new_passwd));
+ ("check_oem_password: password %s ok\n", *pp_new_passwd));
#endif
*hnd = sampass;
return NT_STATUS_OK;
if (lanman_pw && lm_pass_set) {
- E_deshash(new_passwd, new_lm_hash);
+ E_deshash(*pp_new_passwd, new_lm_hash);
/*
* check the lm verifier
TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
-
+
#ifdef DEBUG_PASSWORD
DEBUG(100,
- ("check_oem_password: password %s ok\n", new_passwd));
+ ("check_oem_password: password %s ok\n", *pp_new_passwd));
#endif
*hnd = sampass;
return NT_STATUS_OK;