summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+}