summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-10-20 03:17:42 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:44:59 -0500
commit02c32587a88fa8a0a336981e7a5cf88042b75e6d (patch)
tree4706e871304574b0220871c574235307e527187d
parentddb1c4aa136733b01e7a9505b1131e04804234b6 (diff)
downloadsamba-02c32587a88fa8a0a336981e7a5cf88042b75e6d.tar.gz
samba-02c32587a88fa8a0a336981e7a5cf88042b75e6d.tar.bz2
samba-02c32587a88fa8a0a336981e7a5cf88042b75e6d.zip
r11195: Add a new helper function (needed by my kpasswdd work, but hooked in
for netlogon as well) to change/set a user's password, given only their SID. This avoids the callers doing the lookups, and also performs the actual 'set', as these callers do not wish any further buisness with the entry. Andrew Bartlett (This used to be commit 060a2a7bcca6b58d50bc4e0930c13616742a55d3)
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c192
-rw-r--r--source4/rpc_server/samr/samr_password.c186
2 files changed, 136 insertions, 242 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 99701fc4f1..472fcca785 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -223,13 +223,13 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
return NT_STATUS_ACCESS_DENIED;
}
- pipe_state->creds->account_name = talloc_reference(pipe_state->creds, r->in.account_name);
+ pipe_state->creds->account_name = talloc_steal(pipe_state->creds, r->in.account_name);
- pipe_state->creds->computer_name = talloc_reference(pipe_state->creds, r->in.computer_name);
+ pipe_state->creds->computer_name = talloc_steal(pipe_state->creds, r->in.computer_name);
pipe_state->creds->secure_channel_type = r->in.secure_channel_type;
- pipe_state->creds->rid = *r->out.rid;
+ pipe_state->creds->sid = samdb_result_dom_sid(pipe_state->creds, msgs[0], "objectSid");
pipe_state->creds->domain = talloc_strdup(pipe_state->creds, lp_workgroup());
@@ -305,19 +305,8 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
{
struct server_pipe_state *pipe_state = dce_call->context->private;
- void *sam_ctx;
- int num_records;
- int num_records_domain;
- int ret;
- struct ldb_message **msgs;
- struct ldb_message **msgs_domain;
+ struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- struct ldb_message *mod;
- struct dom_sid *domain_sid;
-
- const char *attrs[] = {"objectSid", NULL };
-
- const char **domain_attrs = attrs;
nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -326,79 +315,18 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
- /* pull the user attributes */
- num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
- "(&(sAMAccountName=%s)(objectclass=user))",
- pipe_state->creds->account_name);
- if (num_records == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- if (num_records == 0) {
- DEBUG(3,("Couldn't find user [%s] in samdb.\n",
- pipe_state->creds->account_name));
- return NT_STATUS_NO_SUCH_USER;
- }
-
- if (num_records > 1) {
- DEBUG(0,("Found %d records matching user [%s]\n", num_records,
- pipe_state->creds->account_name));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
- if (!domain_sid) {
- DEBUG(0,("no objectSid in user record\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* find the domain's DN */
- num_records_domain = gendb_search(sam_ctx, mem_ctx, NULL,
- &msgs_domain, domain_attrs,
- "(&(objectSid=%s)(objectclass=domain))",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
- if (num_records_domain == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- if (num_records_domain == 0) {
- DEBUG(3,("Couldn't find domain [%s] in samdb.\n",
- dom_sid_string(mem_ctx, domain_sid)));
- return NT_STATUS_NO_SUCH_USER;
- }
- if (num_records_domain > 1) {
- DEBUG(0,("Found %d records matching domain [%s]\n",
- num_records_domain, dom_sid_string(mem_ctx, domain_sid)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- mod = talloc_zero(mem_ctx, struct ldb_message);
- NT_STATUS_HAVE_NO_MEMORY(mod);
- mod->dn = talloc_reference(mod, msgs[0]->dn);
-
creds_des_decrypt(pipe_state->creds, &r->in.new_password);
- /* set the password - samdb needs to know both the domain and user DNs,
- so the domain password policy can be used */
- nt_status = samdb_set_password(sam_ctx, mod,
- msgs[0]->dn,
- msgs_domain[0]->dn,
- mod,
- NULL, /* Don't have plaintext */
- NULL, &r->in.new_password,
- False, /* This is not considered a password change */
- False, /* don't restrict this password change (match w2k3) */
- NULL);
- NT_STATUS_NOT_OK_RETURN(nt_status);
-
- ret = samdb_replace(sam_ctx, mem_ctx, mod);
- if (ret != 0) {
- /* we really need samdb.c to return NTSTATUS */
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- return NT_STATUS_OK;
+ /* Using the sid for the account as the key, set the password */
+ nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
+ pipe_state->creds->sid,
+ NULL, /* Don't have plaintext */
+ NULL, &r->in.new_password,
+ False, /* This is not considered a password change */
+ False, /* don't restrict this password change (match w2k3) */
+ NULL, NULL);
+ return nt_status;
}
@@ -1013,24 +941,14 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
{
struct server_pipe_state *pipe_state = dce_call->context->private;
- void *sam_ctx;
- int num_records;
- int num_records_domain;
- int ret;
- struct ldb_message **msgs;
- struct ldb_message **msgs_domain;
+ struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- struct ldb_message *mod;
- struct dom_sid *domain_sid;
char new_pass[512];
uint32_t new_pass_len;
+ BOOL ret;
struct samr_CryptPassword password_buf;
- const char *attrs[] = {"objectSid", NULL };
-
- const char **domain_attrs = attrs;
-
nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -1038,58 +956,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
- /* pull the user attributes */
- num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
- "(&(sAMAccountName=%s)(objectclass=user))",
- pipe_state->creds->account_name);
- if (num_records == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- if (num_records == 0) {
- DEBUG(3,("Couldn't find user [%s] in samdb.\n",
- pipe_state->creds->account_name));
- return NT_STATUS_NO_SUCH_USER;
- }
-
- if (num_records > 1) {
- DEBUG(0,("Found %d records matching user [%s]\n", num_records,
- pipe_state->creds->account_name));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
- if (!domain_sid) {
- DEBUG(0,("no objectSid in user record\n"));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- /* find the domain's DN */
- num_records_domain = gendb_search(sam_ctx, mem_ctx, NULL,
- &msgs_domain, domain_attrs,
- "(&(objectSid=%s)(objectclass=domain))",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
- if (num_records_domain == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- if (num_records_domain == 0) {
- DEBUG(3,("Couldn't find domain [%s] in samdb.\n",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)));
- return NT_STATUS_NO_SUCH_USER;
- }
- if (num_records_domain > 1) {
- DEBUG(0,("Found %d records matching domain [%s]\n",
- num_records_domain,
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- mod = talloc_zero(mem_ctx, struct ldb_message);
- NT_STATUS_HAVE_NO_MEMORY(mod);
- mod->dn = talloc_reference(mod, msgs[0]->dn);
-
memcpy(password_buf.data, r->in.new_password.data, 512);
SIVAL(password_buf.data,512,r->in.new_password.length);
creds_arcfour_crypt(pipe_state->creds, password_buf.data, 516);
@@ -1101,26 +968,15 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
return NT_STATUS_ACCESS_DENIED;
}
- /* set the password - samdb needs to know both the domain and user DNs,
- so the domain password policy can be used */
- nt_status = samdb_set_password(sam_ctx, mod,
- msgs[0]->dn,
- msgs_domain[0]->dn,
- mod, new_pass, /* we have plaintext */
- NULL, NULL,
- False, /* This is not considered a password change */
- False, /* don't restrict this password change (match w2k3) */
- NULL);
- ZERO_STRUCT(new_pass);
- NT_STATUS_NOT_OK_RETURN(nt_status);
-
- ret = samdb_replace(sam_ctx, mem_ctx, mod);
- if (ret != 0) {
- /* we really need samdb.c to return NTSTATUS */
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- return NT_STATUS_OK;
+ /* Using the sid for the account as the key, set the password */
+ nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
+ pipe_state->creds->sid,
+ new_pass, /* we have plaintext */
+ NULL, NULL,
+ False, /* This is not considered a password change */
+ False, /* don't restrict this password change (match w2k3) */
+ NULL, NULL);
+ return nt_status;
}
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
index 6fab231619..2b04903ebd 100644
--- a/source4/rpc_server/samr/samr_password.c
+++ b/source4/rpc_server/samr/samr_password.c
@@ -125,6 +125,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX
msg, NULL, &new_lmPwdHash, &new_ntPwdHash,
True, /* this is a user password change */
True, /* run restriction tests */
+ NULL,
NULL);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -150,7 +151,7 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
uint32_t new_pass_len;
struct samr_CryptPassword *pwbuf = r->in.password;
struct ldb_context *sam_ctx;
- const struct ldb_dn *user_dn, *domain_dn;
+ const struct ldb_dn *user_dn;
int ret;
struct ldb_message **res, *mod;
const char * const attrs[] = { "objectSid", "lmPwdHash", "unicodePwd", NULL };
@@ -158,7 +159,6 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
DATA_BLOB lm_pwd_blob;
uint8_t new_lm_hash[16];
struct samr_Password lm_verifier;
- struct dom_sid *domain_sid;
if (pwbuf == NULL) {
return NT_STATUS_WRONG_PASSWORD;
@@ -210,19 +210,6 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
return NT_STATUS_WRONG_PASSWORD;
}
- /* work out the domain dn */
- domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
- if (domain_sid == NULL) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- domain_dn = samdb_search_dn(sam_ctx, mem_ctx, NULL,
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
- if (!domain_dn) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
return NT_STATUS_NO_MEMORY;
@@ -236,11 +223,12 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
status = samdb_set_password(sam_ctx, mem_ctx,
- user_dn, domain_dn,
+ user_dn, NULL,
mod, new_pass,
NULL, NULL,
True, /* this is a user password change */
True, /* run restriction tests */
+ NULL,
NULL);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -267,14 +255,10 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
char new_pass[512];
uint32_t new_pass_len;
struct ldb_context *sam_ctx;
- const struct ldb_dn *user_dn, *domain_dn = NULL;
+ const struct ldb_dn *user_dn;
int ret;
struct ldb_message **res, *mod;
- const char * const attrs[] = { "objectSid", "ntPwdHash", "lmPwdHash", "unicodePwd", NULL };
- const char * const dom_attrs[] = { "minPwdLength", "pwdHistoryLength",
- "pwdProperties", "minPwdAge", "maxPwdAge",
- NULL };
- struct dom_sid *domain_sid;
+ const char * const attrs[] = { "ntPwdHash", "lmPwdHash", "unicodePwd", NULL };
struct samr_Password *nt_pwd, *lm_pwd;
DATA_BLOB nt_pwd_blob;
struct samr_DomInfo1 *dominfo;
@@ -358,21 +342,6 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
}
- /* work out the domain dn */
- domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
- if (domain_sid == NULL) {
- status = NT_STATUS_NO_SUCH_DOMAIN;
- goto failed;
- }
-
- domain_dn = samdb_search_dn(sam_ctx, mem_ctx, NULL,
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
- if (!domain_dn) {
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- goto failed;
- }
-
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
return NT_STATUS_NO_MEMORY;
@@ -387,12 +356,13 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
status = samdb_set_password(sam_ctx, mem_ctx,
- user_dn, domain_dn,
+ user_dn, NULL,
mod, new_pass,
NULL, NULL,
True, /* this is a user password change */
True, /* run restriction tests */
- &reason);
+ &reason,
+ &dominfo);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
@@ -407,26 +377,11 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
return NT_STATUS_OK;
failed:
- if (domain_dn) {
- ret = gendb_search_dn(sam_ctx, mem_ctx,
- domain_dn, &res, dom_attrs);
-
- if (ret != 1) {
- return status;
- }
- }
- /* on failure we need to fill in the reject reasons */
- dominfo = talloc(mem_ctx, struct samr_DomInfo1);
- if (dominfo == NULL) {
- return status;
- }
reject = talloc(mem_ctx, struct samr_ChangeReject);
if (reject == NULL) {
return status;
}
-
- ZERO_STRUCTP(dominfo);
ZERO_STRUCTP(reject);
reject->reason = reason;
@@ -434,16 +389,6 @@ failed:
r->out.dominfo = dominfo;
r->out.reject = reject;
- if (!domain_dn) {
- return status;
- }
-
- dominfo->min_password_length = samdb_result_uint (res[0], "minPwdLength", 0);
- dominfo->password_properties = samdb_result_uint (res[0], "pwdProperties", 0);
- dominfo->password_history_length = samdb_result_uint (res[0], "pwdHistoryLength", 0);
- dominfo->max_password_age = samdb_result_int64(res[0], "maxPwdAge", 0);
- dominfo->min_password_age = samdb_result_int64(res[0], "minPwdAge", 0);
-
return status;
}
@@ -489,7 +434,7 @@ static BOOL samdb_password_complexity_ok(const char *pass)
called. This allows the caller to combine the change with other
changes (as is needed by some of the set user info levels)
*/
-NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
+NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
const struct ldb_dn *user_dn,
const struct ldb_dn *domain_dn,
struct ldb_message *mod,
@@ -498,12 +443,13 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
struct samr_Password *ntNewHash,
BOOL user_change,
BOOL restrictions,
- uint32_t *reject_reason)
+ uint32_t *reject_reason,
+ struct samr_DomInfo1 **_dominfo)
{
const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
"ntPwdHistory", "unicodePwd",
"lmPwdHash", "ntPwdHash", "badPwdCount",
- NULL };
+ "objectSid", NULL };
const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength",
"maxPwdAge", "minPwdAge",
"minPwdLength", "pwdLastSet", NULL };
@@ -517,6 +463,7 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
struct samr_Password local_lmNewHash, local_ntNewHash;
int lmPwdHistory_len, ntPwdHistory_len;
uint_t kvno;
+ struct dom_sid *domain_sid;
struct ldb_message **res;
int count;
time_t now = time(NULL);
@@ -543,16 +490,47 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0);
kvno = samdb_result_uint(res[0], "msDS-KeyVersionNumber", 0);
- /* pull the domain parameters */
- count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs);
- if (count != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ if (domain_dn) {
+ /* pull the domain parameters */
+ count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs);
+ if (count != 1) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ } else {
+ /* work out the domain sid, and pull the domain from there */
+ domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
+ if (domain_sid == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs,
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
+ if (count != 1) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
}
+
pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0);
pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0);
minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0);
+ if (_dominfo) {
+ struct samr_DomInfo1 *dominfo;
+ /* on failure we need to fill in the reject reasons */
+ dominfo = talloc(mem_ctx, struct samr_DomInfo1);
+ if (dominfo == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ dominfo->min_password_length = minPwdLength;
+ dominfo->password_properties = pwdProperties;
+ dominfo->password_history_length = pwdHistoryLength;
+ dominfo->max_password_age = minPwdAge;
+ dominfo->min_password_age = minPwdAge;
+ *_dominfo = dominfo;
+ }
+
if (new_pass) {
/* check the various password restrictions */
if (restrictions && minPwdLength > strlen_m(new_pass)) {
@@ -780,7 +758,7 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
NULL, NULL,
False, /* This is a password set, not change */
True, /* run restriction tests */
- NULL);
+ NULL, NULL);
}
@@ -790,7 +768,7 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
password when applied
*/
NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
- void *sam_ctx,
+ struct ldb_context *sam_ctx,
const struct ldb_dn *account_dn, const struct ldb_dn *domain_dn,
TALLOC_CTX *mem_ctx,
struct ldb_message *msg,
@@ -834,6 +812,66 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
NULL, NULL,
False, /* This is a password set, not change */
True, /* run restriction tests */
- NULL);
+ NULL, NULL);
}
+/*
+ set the user password using plaintext, obeying any user or domain
+ password restrictions
+
+ This wrapper function takes a SID as input, rather than a user DN,
+ and actually performs the password change
+
+*/
+NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ const char *new_pass,
+ struct samr_Password *lmNewHash,
+ struct samr_Password *ntNewHash,
+ BOOL user_change,
+ BOOL restrictions,
+ uint32_t *reject_reason,
+ struct samr_DomInfo1 **_dominfo)
+{
+ NTSTATUS nt_status;
+ struct ldb_dn *user_dn;
+ struct ldb_message *msg;
+ int count;
+ int ret;
+
+ user_dn = samdb_search_dn(ctx, mem_ctx, NULL,
+ "((objectSid=%s)(objectClass=user))",
+ ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
+ if (count != 1) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ msg->dn = ldb_dn_copy(msg, user_dn);
+ if (!msg->dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = samdb_set_password(ctx, mem_ctx,
+ user_dn, NULL,
+ msg, new_pass,
+ lmNewHash, ntNewHash,
+ user_change, /* This is a password set, not change */
+ restrictions, /* run restriction tests */
+ reject_reason, _dominfo);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ /* modify the samdb record */
+ ret = samdb_replace(ctx, mem_ctx, msg);
+ if (ret != 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}