From 9aec081fd9f8fb46e7d97090f97a75ee5cbebde3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 17 Nov 2004 11:56:13 +0000 Subject: r3804: Add more comparison tests in RPC-SAMSYNC. This compares values for the domain and for secrets. We still have some problems we need to sort out for secrets. Also rename a number of structures in samr.idl and netlogon.idl, to better express their consistancy. Andrew Bartlett (This used to be commit 3f52fa3a42b030c9aef21c8bd88aad87a0aae078) --- source4/torture/rpc/samsync.c | 254 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 220 insertions(+), 34 deletions(-) (limited to 'source4/torture/rpc/samsync.c') diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index 711adc79ca..9b5df2b681 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -27,6 +27,7 @@ #include "auth/auth.h" #include "dlinklist.h" #include "lib/crypto/crypto.h" +#include "system/time.h" #define TEST_MACHINE_NAME "samsynctest" @@ -108,6 +109,8 @@ struct samsync_state { struct dom_sid *sid[2]; struct dcerpc_pipe *p; struct dcerpc_pipe *p_samr; + struct dcerpc_pipe *p_lsa; + struct policy_handle *lsa_handle; }; struct samsync_secret { @@ -161,11 +164,49 @@ static struct policy_handle *samsync_open_domain(TALLOC_CTX *mem_ctx, return domain_handle; } + +#define TEST_UINT64_EQUAL(i1, i2) do {\ + if (i1 != i2) {\ + printf("uint64 mismatch: " #i1 ": 0x%08x%08x (%lld) != " #i2 ": 0x%08x%08x (%lld)\n", \ + (uint32_t)(i1 >> 32), (uint32_t)(i1 & 0xFFFFFFFF), i1, \ + (uint32_t)(i2 >> 32), (uint32_t)(i2 & 0xFFFFFFFF), i2);\ + ret = False;\ + } \ +} while (0) +#define TEST_INT_EQUAL(i1, i2) do {\ + if (i1 != i2) {\ + printf("integer mismatch: " #i1 ":%d != " #i2 ": %d\n", \ + i1, i2);\ + ret = False;\ + } \ +} while (0) +#define TEST_TIME_EQUAL(t1, t2) do {\ + if (t1 != t2) {\ + printf("NTTIME mismatch: " #t1 ":%s != " #t2 ": %s\n", \ + nt_time_string(mem_ctx, t1), nt_time_string(mem_ctx, t2));\ + ret = False;\ + } \ +} while (0) +#define TEST_STRING_EQUAL(s1, s2) do {\ + if (!((!s1.string || s1.string[0]=='\0') && (!s2.string || s2.string[0]=='\0')) \ + && strcmp_safe(s1.string, s2.string) != 0) {\ + printf("string mismatch: " #s1 ":%s != " #s2 ": %s\n", \ + s1.string, s2.string);\ + ret = False;\ + } \ +} while (0) + static BOOL samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain; struct dom_sid *dom_sid; + struct samr_QueryDomainInfo q[14]; /* q[0] will be unused simple for clarity */ + uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13}; + NTSTATUS nt_status; + int i; + BOOL ret = True; + samsync_state->seq_num[database_id] = domain->sequence_num; switch (database_id) { @@ -205,7 +246,40 @@ static BOOL samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam printf("\tsequence_nums[%d/%s]=%llu\n", database_id, domain->domain_name.string, samsync_state->seq_num[database_id]); - return True; + + for (i=0;idomain_handle[database_id]; + q[levels[i]].in.level = levels[i]; + + nt_status = dcerpc_samr_QueryDomainInfo(samsync_state->p_samr, mem_ctx, &q[levels[i]]); + + if (!NT_STATUS_IS_OK(nt_status)) { + printf("QueryDomainInfo level %u failed - %s\n", + q[levels[i]].in.level, nt_errstr(nt_status)); + return False; + } + } + + TEST_STRING_EQUAL(q[5].out.info->info5.domain_name, domain->domain_name); + + TEST_STRING_EQUAL(q[2].out.info->info2.comment, domain->comment); + TEST_STRING_EQUAL(q[4].out.info->info4.comment, domain->comment); + TEST_TIME_EQUAL(q[2].out.info->info2.force_logoff_time, domain->force_logoff_time); + TEST_TIME_EQUAL(q[3].out.info->info3.force_logoff_time, domain->force_logoff_time); + + TEST_TIME_EQUAL(q[1].out.info->info1.min_password_length, domain->min_password_length); + TEST_TIME_EQUAL(q[1].out.info->info1.password_history_length, domain->password_history_length); + TEST_TIME_EQUAL(q[1].out.info->info1.max_password_age, domain->max_password_age); + TEST_TIME_EQUAL(q[1].out.info->info1.min_password_age, domain->min_password_age); + + TEST_UINT64_EQUAL(q[8].out.info->info8.sequence_num, + domain->sequence_num); + TEST_TIME_EQUAL(q[8].out.info->info8.domain_create_time, + domain->domain_create_time); + TEST_TIME_EQUAL(q[13].out.info->info13.domain_create_time, + domain->domain_create_time); + + return ret; } static BOOL samsync_handle_policy(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, @@ -239,30 +313,6 @@ static BOOL samsync_handle_policy(TALLOC_CTX *mem_ctx, struct samsync_state *sam return True; } -#define TEST_INT_EQUAL(i1, i2) do {\ - if (i1 != i2) {\ - printf("integer mismatch: " #i1 ":%d != " #i2 ": %d\n", \ - i1, i2);\ - ret = False;\ - } \ -} while (0) -#define TEST_TIME_EQUAL(t1, t2) do {\ - if (t1 != t2) {\ - printf("NTTIME mismatch: " #t1 ":%s != " #t2 ": %s\n", \ - nt_time_string(mem_ctx, t1), nt_time_string(mem_ctx, t2));\ - ret = False;\ - } \ -} while (0) -#define TEST_STRING_EQUAL(s1, s2) do {\ - if (!((!s1.string || s1.string[0]=='\0') && (!s2.string || s2.string[0]=='\0')) \ - && strcmp_safe(s1.string, s2.string) != 0) {\ - printf("string mismatch: " #s1 ":%s != " #s2 ": %s\n", \ - s1.string, s2.string);\ - ret = False;\ - } \ -} while (0) - - static BOOL samsync_handle_user(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { @@ -395,12 +445,6 @@ static BOOL samsync_handle_user(TALLOC_CTX *mem_ctx, struct samsync_state *samsy } - if (!lm_hash_p && !nt_hash_p) { - printf("NO password set for %s\n", - user->account_name.string); - return True; - } - nt_status = test_SamLogon(samsync_state->p, mem_ctx, samsync_state->creds, domain, username, @@ -432,6 +476,10 @@ static BOOL samsync_handle_user(TALLOC_CTX *mem_ctx, struct samsync_state *samsy if (user->acct_flags & ACB_AUTOLOCK) { return True; } + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { + if (!lm_hash_p && !nt_hash_p) { + return True; + } } else if (NT_STATUS_IS_OK(nt_status)) { TEST_INT_EQUAL(user->rid, info3->base.rid); TEST_INT_EQUAL(user->primary_gid, info3->base.primary_gid); @@ -473,6 +521,14 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam struct netr_DELTA_SECRET *secret = delta->delta_union.secret; const char *name = delta->delta_id_union.name; struct samsync_secret *new = talloc_p(samsync_state, struct samsync_secret); + struct lsa_QuerySecret q; + struct lsa_OpenSecret o; + struct policy_handle sec_handle; + struct lsa_DATA_BUF_PTR bufp1; + NTTIME new_mtime; + BOOL ret = True; + DATA_BLOB lsa_blob1, lsa_blob_out, session_key; + NTSTATUS status; creds_arcfour_crypt(samsync_state->creds, secret->current_cipher.cipher_data, secret->current_cipher.maxlen); @@ -485,7 +541,71 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam DLIST_ADD(samsync_state->secrets, new); - return True; + o.in.handle = samsync_state->lsa_handle; + o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + o.in.name.name = name; + o.out.sec_handle = &sec_handle; + + status = dcerpc_lsa_OpenSecret(samsync_state->p_lsa, mem_ctx, &o); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenSecret failed - %s\n", nt_errstr(status)); + ret = False; + } + + status = dcerpc_fetch_session_key(samsync_state->p_lsa, &session_key); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_fetch_session_key failed - %s\n", nt_errstr(status)); + ret = False; + } + + + ZERO_STRUCT(new_mtime); + + /* fetch the secret back again */ + q.in.handle = &sec_handle; + q.in.new_val = &bufp1; + q.in.new_mtime = &new_mtime; + q.in.old_val = NULL; + q.in.old_mtime = NULL; + + bufp1.buf = NULL; + + status = dcerpc_lsa_QuerySecret(samsync_state->p_lsa, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + printf("QuerySecret failed - %s\n", nt_errstr(status)); + ret = False; + } + + if (q.out.new_val->buf == NULL) { + printf("No secret buffer returned\n"); + ret = False; + } else { + lsa_blob1.data = q.out.new_val->buf->data; + lsa_blob1.length = q.out.new_val->buf->length; + + lsa_blob_out = data_blob(NULL, lsa_blob1.length); + + sess_crypt_blob(&lsa_blob_out, &lsa_blob1, &session_key, 0); + + if (new->secret.length != lsa_blob_out.length) { + printf("Returned secret %s doesn't match: %d != %d\n", + new->name, new->secret.length, lsa_blob_out.length); + ret = False; + } + + if (memcmp(lsa_blob_out.data, + new->secret.data, new->secret.length) != 0) { + printf("Returned secret %s doesn't match: \n", + new->name); + DEBUG(1, ("SamSync Secret:\n")); + dump_data(1, new->secret.data, new->secret.length); + DEBUG(1, ("LSA Secret:\n")); + dump_data(1, lsa_blob_out.data, lsa_blob_out.length); + ret = False; + } + } + + return ret; } static BOOL samsync_handle_trusted_domain(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, @@ -615,7 +735,7 @@ static BOOL test_DatabaseSync(struct samsync_state *samsync_state, NULL); if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { - printf("Verifiction of trust password to %s: should have failed (wrong password), instead: %s\n", + printf("Verifiction of trust password to %s: should have failed (nologon interdomain trust account), instead: %s\n", t->name, nt_errstr(nt_status)); ret = False; ret = False; @@ -738,6 +858,12 @@ BOOL torture_rpc_samsync(void) const char *binding = lp_parm_string(-1, "torture", "binding"); struct dcerpc_binding b; struct samr_Connect c; + struct samr_SetDomainInfo s; + struct policy_handle *domain_policy; + + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy2 r; struct samsync_state *samsync_state; @@ -754,6 +880,7 @@ BOOL torture_rpc_samsync(void) samsync_state->p_samr = torture_join_samr_pipe(join_ctx); samsync_state->connect_handle = talloc_zero_p(samsync_state, struct policy_handle); + samsync_state->lsa_handle = talloc_zero_p(samsync_state, struct policy_handle); c.in.system_name = NULL; c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; c.out.connect_handle = samsync_state->connect_handle; @@ -765,10 +892,69 @@ BOOL torture_rpc_samsync(void) goto failed; } + domain_policy = samsync_open_domain(mem_ctx, samsync_state, lp_workgroup(), NULL); + if (!domain_policy) { + printf("samrsync_open_domain failed\n"); + ret = False; + goto failed; + } + + s.in.domain_handle = domain_policy; + s.in.level = 4; + s.in.info = talloc_p(mem_ctx, union samr_DomainInfo); + + s.in.info->info4.comment.string + = talloc_asprintf(mem_ctx, + "Tortured by Samba4: %s", + timestring(mem_ctx, time(NULL))); + status = dcerpc_samr_SetDomainInfo(samsync_state->p_samr, mem_ctx, &s); + + if (!NT_STATUS_IS_OK(status)) { + printf("SetDomainInfo level %u failed - %s\n", + s.in.level, nt_errstr(status)); + ret = False; + goto failed; + } + + status = dcerpc_parse_binding(mem_ctx, binding, &b); if (!NT_STATUS_IS_OK(status)) { printf("Bad binding string %s\n", binding); - return False; + ret = False; + goto failed; + } + + status = torture_rpc_connection(&samsync_state->p_lsa, + DCERPC_LSARPC_NAME, + DCERPC_LSARPC_UUID, + DCERPC_LSARPC_VERSION); + + if (!NT_STATUS_IS_OK(status)) { + ret = False; + goto failed; + } + + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = "\\"; + r.in.attr = &attr; + r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + r.out.handle = samsync_state->lsa_handle; + + status = dcerpc_lsa_OpenPolicy2(samsync_state->p_lsa, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenPolicy2 failed - %s\n", nt_errstr(status)); + ret = False; goto failed; } -- cgit