summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2005-01-12 07:22:34 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:08:45 -0500
commit516dbfd5ed45159366840087398669c5224d2844 (patch)
tree8d754716b8d21454739c1398c9a97114cbdc62c5
parentfef48c0cc8b58536ed2f3338fc7c790a846f305d (diff)
downloadsamba-516dbfd5ed45159366840087398669c5224d2844.tar.gz
samba-516dbfd5ed45159366840087398669c5224d2844.tar.bz2
samba-516dbfd5ed45159366840087398669c5224d2844.zip
r4702: implment idl, torture test and server code for netr_ServerPasswordSet2()
metze (This used to be commit 7d8ba92da2b8babe7165f105591fd3e5738b2319)
-rw-r--r--source4/librpc/idl/netlogon.idl12
-rw-r--r--source4/librpc/idl/samr.idl2
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c113
-rw-r--r--source4/torture/rpc/netlogon.c71
4 files changed, 188 insertions, 10 deletions
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 3b4f299d7c..8251969982 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -1004,9 +1004,17 @@ interface netlogon
[out,switch_is(level)] netr_DomainInfo info
);
- /****************/
+ /*****************/
/* Function 0x1e */
- WERROR netr_NETRSERVERPASSWORDSET2();
+ NTSTATUS netr_ServerPasswordSet2(
+ [in] unistr *server_name,
+ [in] unistr account_name,
+ [in] netr_SchannelType secure_channel_type,
+ [in] unistr computer_name,
+ [in] netr_Authenticator credential,
+ [in] samr_CryptPassword new_password,
+ [out] netr_Authenticator return_authenticator
+ );
/****************/
/* Function 0x1f */
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl
index 56387936c7..84aaa2a10a 100644
--- a/source4/librpc/idl/samr.idl
+++ b/source4/librpc/idl/samr.idl
@@ -717,7 +717,7 @@
uint8 unknown4;
} samr_UserInfo21;
- typedef [flag(NDR_PAHEX)] struct {
+ typedef [public, flag(NDR_PAHEX)] struct {
uint8 data[516];
} samr_CryptPassword;
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 731905e2a6..9eed9eb1f3 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -364,7 +364,7 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
}
if (num_records_domain == 0) {
- DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
+ DEBUG(3,("Couldn't find domain [%s] in samdb.\n",
domain_sid));
return NT_STATUS_NO_SUCH_USER;
}
@@ -1000,12 +1000,115 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
/*
- netr_NETRSERVERPASSWORDSET2
+ netr_ServerPasswordSet2
*/
-static WERROR netr_NETRSERVERPASSWORDSET2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_NETRSERVERPASSWORDSET2 *r)
+static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_ServerPasswordSet2 *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ 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;
+ NTSTATUS nt_status;
+ struct ldb_message *mod;
+ const char *domain_sid;
+ char new_pass[512];
+ uint32_t new_pass_len;
+
+ 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);
+
+ sam_ctx = samdb_connect(mem_ctx);
+ if (sam_ctx == NULL) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ /* pull the user attributes */
+ num_records = samdb_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 = samdb_search(sam_ctx, mem_ctx, NULL,
+ &msgs_domain, domain_attrs,
+ "(&(objectSid=%s)(objectclass=domain))",
+ 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",
+ 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, 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_arcfour_crypt(pipe_state->creds, r->in.new_password.data, 516);
+
+ ret = decode_pw_buffer(r->in.new_password.data, new_pass, sizeof(new_pass),
+ &new_pass_len, STR_UNICODE);
+ if (!ret) {
+ DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
+ 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 */,
+ NULL);
+ ZERO_ARRAY(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;
}
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 67e0bc9393..00a12b361b 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -318,6 +318,74 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
}
/*
+ try a change password for our machine account
+*/
+static BOOL test_SetPassword2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+ struct netr_ServerPasswordSet2 r;
+ const char *password;
+ struct creds_CredentialState creds;
+
+ if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME,
+ machine_password, &creds)) {
+ return False;
+ }
+
+ r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
+ r.in.secure_channel_type = SEC_CHAN_BDC;
+ r.in.computer_name = TEST_MACHINE_NAME;
+
+ password = generate_random_str(mem_ctx, 8);
+ encode_pw_buffer(r.in.new_password.data, password, STR_UNICODE);
+ creds_arcfour_crypt(&creds, r.in.new_password.data, 516);
+
+ printf("Testing ServerPasswordSet2 on machine account\n");
+ printf("Changing machine account password to '%s'\n", password);
+
+ creds_client_authenticator(&creds, &r.in.credential);
+
+ status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ServerPasswordSet2 - %s\n", nt_errstr(status));
+ return False;
+ }
+
+ if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
+ printf("Credential chaining failed\n");
+ }
+
+ /* by changing the machine password twice we test the
+ credentials chaining fully, and we verify that the server
+ allows the password to be set to the same value twice in a
+ row (match win2k3) */
+ printf("Testing a second ServerPasswordSet2 on machine account\n");
+ printf("Changing machine account password to '%s' (same as previous run)\n", password);
+
+ creds_client_authenticator(&creds, &r.in.credential);
+
+ status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
+ return False;
+ }
+
+ if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
+ printf("Credential chaining failed\n");
+ }
+
+ machine_password = password;
+
+ if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
+ printf("ServerPasswordSet failed to actually change the password\n");
+ return False;
+ }
+
+ return True;
+}
+
+/*
try a netlogon SamLogon
*/
static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
@@ -398,8 +466,6 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
return ret;
}
-
-
/* we remember the sequence numbers so we can easily do a DatabaseDelta */
static uint64_t sequence_nums[3];
@@ -1216,6 +1282,7 @@ BOOL torture_rpc_netlogon(void)
ret &= test_LogonUasLogoff(p, mem_ctx);
ret &= test_SamLogon(p, mem_ctx);
ret &= test_SetPassword(p, mem_ctx);
+ ret &= test_SetPassword2(p, mem_ctx);
ret &= test_GetDomainInfo(p, mem_ctx);
ret &= test_DatabaseSync(p, mem_ctx);
ret &= test_DatabaseDeltas(p, mem_ctx);