diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-11-13 13:48:59 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:47 -0500 |
commit | 3b217ffcf2788af8405594c618507cd65ef281c7 (patch) | |
tree | 84cca06e9fc804c440d4b9f8a52dc1012b4a5537 /source4 | |
parent | 50916c8f2fd3e1c8e56b74bbed95d72f328637bc (diff) | |
download | samba-3b217ffcf2788af8405594c618507cd65ef281c7.tar.gz samba-3b217ffcf2788af8405594c618507cd65ef281c7.tar.bz2 samba-3b217ffcf2788af8405594c618507cd65ef281c7.zip |
r3725: The new RPC-SAMSYNC test, complete with SAMR comparisons. This is
certainly not complete, we need to verify all incoming data, not just
accounts.
This needs to be exercised against some 'intersting' users, but for
now it shows that the IDL is already very accurate, particularly after
the previous commits cleanups of names.
Also commit the changes to keep RPC-LOGIN building.
Andrew Bartlett
(This used to be commit 87ec6834bc75012527454abc0e854b1cf2120088)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/torture/rpc/samsync.c | 508 | ||||
-rw-r--r-- | source4/torture/rpc/xplogin.c | 12 |
2 files changed, 378 insertions, 142 deletions
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index aaab3ef988..711adc79ca 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -97,10 +97,17 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } struct samsync_state { - uint64_t seq_num; - char *domain_name; +/* we remember the sequence numbers so we can easily do a DatabaseDelta */ + uint64_t seq_num[3]; + char *domain_name[2]; struct samsync_secret *secrets; struct samsync_trusted_domain *trusted_domains; + struct creds_CredentialState *creds; + struct policy_handle *connect_handle; + struct policy_handle *domain_handle[2]; + struct dom_sid *sid[2]; + struct dcerpc_pipe *p; + struct dcerpc_pipe *p_samr; }; struct samsync_secret { @@ -115,29 +122,149 @@ struct samsync_trusted_domain { char *name; }; -static struct samsync_state *samsync_state; +static struct policy_handle *samsync_open_domain(TALLOC_CTX *mem_ctx, + struct samsync_state *samsync_state, + const char *domain, + struct dom_sid **sid) +{ + struct samr_String name; + struct samr_OpenDomain o; + struct samr_LookupDomain l; + struct policy_handle *domain_handle = talloc_p(mem_ctx, struct policy_handle); + NTSTATUS nt_status; + + name.string = domain; + l.in.connect_handle = samsync_state->connect_handle; + l.in.domain = &name; + + nt_status = dcerpc_samr_LookupDomain(samsync_state->p_samr, mem_ctx, &l); + if (!NT_STATUS_IS_OK(nt_status)) { + printf("LookupDomain failed - %s\n", nt_errstr(nt_status)); + return NULL; + } -static BOOL samsync_handle_domain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, + o.in.connect_handle = samsync_state->connect_handle; + o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + o.in.sid = l.out.sid; + o.out.domain_handle = domain_handle; + + if (sid) { + *sid = l.out.sid; + } + + nt_status = dcerpc_samr_OpenDomain(samsync_state->p_samr, mem_ctx, &o); + if (!NT_STATUS_IS_OK(nt_status)) { + printf("OpenDomain failed - %s\n", nt_errstr(nt_status)); + return NULL; + } + + return domain_handle; +} + +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; - - samsync_state[database_id].seq_num = + struct dom_sid *dom_sid; + samsync_state->seq_num[database_id] = domain->sequence_num; + switch (database_id) { + case SAM_DATABASE_DOMAIN: + break; + case SAM_DATABASE_BUILTIN: + if (StrCaseCmp("BUILTIN", domain->domain_name.string) != 0) { + printf("BUILTIN domain has different name: %s\n", domain->domain_name.string); + } + break; + case SAM_DATABASE_PRIVS: + printf("DOMAIN entry on privs DB!\n"); + return False; + break; + } + + if (!samsync_state->domain_name[database_id]) { + samsync_state->domain_name[database_id] = + talloc_reference(samsync_state, domain->domain_name.string); + } else { + if (StrCaseCmp(samsync_state->domain_name[database_id], domain->domain_name.string) != 0) { + printf("Domain has name varies!: %s != %s\n", samsync_state->domain_name[database_id], + domain->domain_name.string); + return False; + } + } - samsync_state[database_id].domain_name = - talloc_reference(samsync_state, domain->domain_name.string); + if (!samsync_state->domain_handle[database_id]) { + samsync_state->domain_handle[database_id] + = samsync_open_domain(mem_ctx, samsync_state, samsync_state->domain_name[database_id], + &dom_sid); + } + if (samsync_state->domain_handle[database_id]) { + samsync_state->sid[database_id] = talloc_reference(samsync_state, dom_sid); + } printf("\tsequence_nums[%d/%s]=%llu\n", - database_id, samsync_state[database_id].domain_name, - samsync_state[database_id].seq_num); + database_id, domain->domain_name.string, + samsync_state->seq_num[database_id]); return True; } -static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, - int database_id, struct netr_DELTA_ENUM *delta) +static BOOL samsync_handle_policy(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, + int database_id, struct netr_DELTA_ENUM *delta) +{ + struct netr_DELTA_POLICY *policy = delta->delta_union.policy; + + samsync_state->seq_num[database_id] = + policy->sequence_num; + + if (!samsync_state->domain_name[SAM_DATABASE_DOMAIN]) { + samsync_state->domain_name[SAM_DATABASE_DOMAIN] = + talloc_reference(samsync_state, policy->primary_domain_name.string); + } else { + if (StrCaseCmp(samsync_state->domain_name[SAM_DATABASE_DOMAIN], policy->primary_domain_name.string) != 0) { + printf("PRIMARY domain has name varies between DOMAIN and POLICY!: %s != %s\n", samsync_state->domain_name[SAM_DATABASE_DOMAIN], + policy->primary_domain_name.string); + return False; + } + } + + if (!sid_equal(samsync_state->sid[SAM_DATABASE_DOMAIN], policy->sid)) { + printf("Domain SID from POLICY (%s) does not match domain sid from SAMR (%s)\n", + dom_sid_string(mem_ctx, policy->sid), dom_sid_string(mem_ctx, samsync_state->sid[SAM_DATABASE_DOMAIN])); + return False; + } + + printf("\tsequence_nums[%d/PRIVS]=%llu\n", + database_id, + samsync_state->seq_num[database_id]); + 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) { uint32 rid = delta->delta_id_union.rid; struct netr_DELTA_USER *user = delta->delta_union.user; @@ -146,19 +273,100 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samr_Password nt_hash; struct samr_Password *lm_hash_p = NULL; struct samr_Password *nt_hash_p = NULL; - const char *domain = samsync_state[database_id].domain_name - ? samsync_state[database_id].domain_name - : lp_workgroup(); + const char *domain = samsync_state->domain_name[database_id]; const char *username = user->account_name.string; + NTSTATUS nt_status; + BOOL ret = True; + struct samr_OpenUser r; + struct samr_QueryUserInfo q; + struct policy_handle user_handle; - NTSTATUS nt_status; + if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { + printf("SamSync needs domain information before the users\n"); + return False; + } + + r.in.domain_handle = samsync_state->domain_handle[database_id]; + r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + r.in.rid = rid; + r.out.user_handle = &user_handle; + + nt_status = dcerpc_samr_OpenUser(samsync_state->p_samr, mem_ctx, &r); + if (!NT_STATUS_IS_OK(nt_status)) { + printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(nt_status)); + return False; + } + + q.in.user_handle = &user_handle; + q.in.level = 21; - if (user->lmpassword_present) { + nt_status = dcerpc_samr_QueryUserInfo(samsync_state->p_samr, mem_ctx, &q); + if (!test_samr_handle_Close(samsync_state->p_samr, mem_ctx, &user_handle)) { + return False; + } + + if (!NT_STATUS_IS_OK(nt_status)) { + printf("QueryUserInfo level %u failed - %s\n", + q.in.level, nt_errstr(nt_status)); + return False; + } + + TEST_STRING_EQUAL(q.out.info->info21.account_name, user->account_name); + TEST_STRING_EQUAL(q.out.info->info21.full_name, user->full_name); + TEST_INT_EQUAL(q.out.info->info21.rid, user->rid); + TEST_INT_EQUAL(q.out.info->info21.primary_gid, user->primary_gid); + TEST_STRING_EQUAL(q.out.info->info21.home_directory, user->home_directory); + TEST_STRING_EQUAL(q.out.info->info21.home_drive, user->home_drive); + TEST_STRING_EQUAL(q.out.info->info21.logon_script, user->logon_script); + TEST_STRING_EQUAL(q.out.info->info21.description, user->description); + TEST_STRING_EQUAL(q.out.info->info21.workstations, user->workstations); + + TEST_TIME_EQUAL(q.out.info->info21.last_logon, user->last_logon); + TEST_TIME_EQUAL(q.out.info->info21.last_logoff, user->last_logoff); + + + TEST_INT_EQUAL(q.out.info->info21.logon_hours.units_per_week, + user->logon_hours.units_per_week); + if (ret) { + if (memcmp(q.out.info->info21.logon_hours.bitmap, user->logon_hours.bitmap, + q.out.info->info21.logon_hours.units_per_week/8) != 0) { + printf("Logon hours mismatch\n"); + ret = False; + } + } + + TEST_INT_EQUAL(q.out.info->info21.bad_password_count, + user->bad_password_count); + TEST_INT_EQUAL(q.out.info->info21.logon_count, + user->logon_count); + + TEST_TIME_EQUAL(q.out.info->info21.last_password_change, + user->last_password_change); + TEST_TIME_EQUAL(q.out.info->info21.acct_expiry, + user->acct_expiry); + + TEST_INT_EQUAL(q.out.info->info21.logon_hours.units_per_week, + user->logon_hours.units_per_week); + + TEST_INT_EQUAL(q.out.info->info21.acct_flags, user->acct_flags); + TEST_INT_EQUAL(q.out.info->info21.nt_password_set, user->nt_password_present); + TEST_INT_EQUAL(q.out.info->info21.lm_password_set, user->lm_password_present); + TEST_INT_EQUAL(q.out.info->info21.password_expired, user->password_expired); + + TEST_STRING_EQUAL(q.out.info->info21.comment, user->comment); + TEST_STRING_EQUAL(q.out.info->info21.parameters, user->parameters); + + TEST_INT_EQUAL(q.out.info->info21.country_code, user->country_code); + TEST_INT_EQUAL(q.out.info->info21.code_page, user->code_page); + + TEST_STRING_EQUAL(q.out.info->info21.profile_path, user->profile_path); + + if (user->lm_password_present) { sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0); lm_hash_p = &lm_hash; } - if (user->ntpassword_present) { + if (user->nt_password_present) { sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0); nt_hash_p = &nt_hash; } @@ -168,37 +376,32 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct netr_USER_KEYS keys; data.data = user->user_private_info.SensitiveData; data.length = user->user_private_info.DataLength; - creds_arcfour_crypt(creds, data.data, data.length); + creds_arcfour_crypt(samsync_state->creds, data.data, data.length); #if 0 printf("Sensitive Data for %s:\n", username); dump_data(0, data.data, data.length); #endif nt_status = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); - if (!NT_STATUS_IS_OK(nt_status)) { - return False; - } - if (keys.keys.keys2.lmpassword.length == 16) { - sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0); - dump_data(0, keys.keys.keys2.lmpassword.pwd.hash, - sizeof(keys.keys.keys2.lmpassword.pwd.hash)); - - lm_hash_p = &lm_hash; - } - if (keys.keys.keys2.ntpassword.length == 16) { - sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0); - dump_data(0, keys.keys.keys2.ntpassword.pwd.hash, - sizeof(keys.keys.keys2.ntpassword.pwd.hash)); - nt_hash_p = &nt_hash; + if (NT_STATUS_IS_OK(nt_status)) { + if (keys.keys.keys2.lmpassword.length == 16) { + sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0); + lm_hash_p = &lm_hash; + } + if (keys.keys.keys2.ntpassword.length == 16) { + sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0); + nt_hash_p = &nt_hash; + } } } + if (!lm_hash_p && !nt_hash_p) { printf("NO password set for %s\n", user->account_name.string); return True; } - nt_status = test_SamLogon(p, mem_ctx, creds, + nt_status = test_SamLogon(samsync_state->p, mem_ctx, samsync_state->creds, domain, username, lm_hash_p, @@ -229,18 +432,33 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, if (user->acct_flags & ACB_AUTOLOCK) { return True; } - } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OK)) { - if (user->acct_flags != info3->base.acct_flags) { - printf("Account flags mismatch: %d != %d\n", - user->acct_flags, info3->base.acct_flags); - return False; + } 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); + TEST_INT_EQUAL(user->acct_flags, info3->base.acct_flags); + TEST_STRING_EQUAL(user->account_name, info3->base.account_name); + TEST_STRING_EQUAL(user->full_name, info3->base.full_name); + TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script); + TEST_STRING_EQUAL(user->profile_path, info3->base.profile_path); + TEST_STRING_EQUAL(user->home_directory, info3->base.home_directory); + TEST_STRING_EQUAL(user->home_drive, info3->base.home_drive); + TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script); + + + TEST_TIME_EQUAL(user->last_logon, info3->base.last_logon); + TEST_TIME_EQUAL(user->acct_expiry, info3->base.acct_expiry); + TEST_TIME_EQUAL(user->last_password_change, info3->base.last_password_change); + + /* Does the concept of a logoff time ever really + * exist? (not in any sensible way, according to the + * doco I read -- abartlet) */ + + /* This copes with the two different versions of 0 I see */ + if (!((user->last_logoff == 0) + && (info3->base.last_logoff == 0x7fffffffffffffffLL))) { + TEST_TIME_EQUAL(user->last_logoff, info3->base.last_logoff); } - if (strcmp_safe(user->full_name.string, info3->base.full_name.string) != 0) { - printf("Full name mismatch: %s != %s\n", - user->full_name.string, info3->base.full_name.string); - return False; - } - return True; + return ret; } else { printf("Could not validate password for user %s\\%s: %s\n", domain, username, nt_errstr(nt_status)); @@ -249,30 +467,28 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return False; } -static BOOL samsync_handle_secret(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, +static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { 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); - creds_arcfour_crypt(creds, secret->current_cipher.cipher_data, + creds_arcfour_crypt(samsync_state->creds, secret->current_cipher.cipher_data, secret->current_cipher.maxlen); - creds_arcfour_crypt(creds, secret->old_cipher.cipher_data, + creds_arcfour_crypt(samsync_state->creds, secret->old_cipher.cipher_data, secret->old_cipher.maxlen); new->name = talloc_reference(new, name); new->secret = data_blob_talloc(new, secret->current_cipher.cipher_data, secret->current_cipher.maxlen); - DLIST_ADD(samsync_state[database_id].secrets, new); + DLIST_ADD(samsync_state->secrets, new); return True; } -static BOOL samsync_handle_trusted_domain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds, +static BOOL samsync_handle_trusted_domain(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain; @@ -282,19 +498,16 @@ static BOOL samsync_handle_trusted_domain(struct dcerpc_pipe *p, TALLOC_CTX *mem new->name = talloc_reference(new, trusted_domain->domain_name.string); new->sid = talloc_reference(new, dom_sid); - DLIST_ADD(samsync_state[database_id].trusted_domains, new); + DLIST_ADD(samsync_state->trusted_domains, new); return True; } -/* we remember the sequence numbers so we can easily do a DatabaseDelta */ -static uint64_t sequence_nums[3]; - /* try a netlogon DatabaseSync */ -static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds) +static BOOL test_DatabaseSync(struct samsync_state *samsync_state, + TALLOC_CTX *mem_ctx) { NTSTATUS status; struct netr_DatabaseSync r; @@ -304,9 +517,9 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct samsync_trusted_domain *t; struct samsync_secret *s; - samsync_state = talloc_zero_array_p(mem_ctx, struct samsync_state, 3); + const char *domain, *username; - r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); + r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p)); r.in.computername = TEST_MACHINE_NAME; r.in.preferredmaximumlength = (uint32_t)-1; ZERO_STRUCT(r.in.return_authenticator); @@ -318,9 +531,9 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, printf("Testing DatabaseSync of id %d\n", r.in.database_id); do { - creds_client_authenticator(creds, &r.in.credential); + creds_client_authenticator(samsync_state->creds, &r.in.credential); - status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r); + status = dcerpc_netr_DatabaseSync(samsync_state->p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { printf("DatabaseSync - %s\n", nt_errstr(status)); @@ -328,7 +541,7 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, break; } - if (!creds_client_check(creds, &r.out.return_authenticator.cred)) { + if (!creds_client_check(samsync_state->creds, &r.out.return_authenticator.cred)) { printf("Credential chaining failed\n"); } @@ -337,76 +550,81 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, for (d=0; d < r.out.delta_enum_array->num_deltas; d++) { switch (r.out.delta_enum_array->delta_enum[d].delta_type) { case NETR_DELTA_DOMAIN: - ret &= samsync_handle_domain(p, mem_ctx, creds, + ret &= samsync_handle_domain(mem_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d]); break; case NETR_DELTA_USER: - ret &= samsync_handle_user(p, mem_ctx, creds, + ret &= samsync_handle_user(mem_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d]); break; case NETR_DELTA_TRUSTED_DOMAIN: - ret &= samsync_handle_trusted_domain(p, mem_ctx, creds, + ret &= samsync_handle_trusted_domain(mem_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d]); break; case NETR_DELTA_SECRET: - ret &= samsync_handle_secret(p, mem_ctx, creds, + ret &= samsync_handle_secret(mem_ctx, samsync_state, + r.in.database_id, &r.out.delta_enum_array->delta_enum[d]); + break; + case NETR_DELTA_POLICY: + ret &= samsync_handle_policy(mem_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d]); break; } } } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); + + } - for (t=samsync_state[r.in.database_id].trusted_domains; t; t=t->next) { - const char *domain = samsync_state[r.in.database_id].domain_name - ? samsync_state[r.in.database_id].domain_name - : lp_workgroup(); - char *username = talloc_asprintf(mem_ctx, "%s$", domain); - char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name); - for (s=samsync_state[r.in.database_id].secrets; s; s=s->next) { - printf("Checking secret %s against %s\n", - s->name, secret_name); - if (StrCaseCmp(s->name, secret_name) == 0) { - NTSTATUS nt_status; - struct samr_Password nt_hash; - mdfour(nt_hash.hash, s->secret.data, s->secret.length); - + domain = samsync_state->domain_name[SAM_DATABASE_DOMAIN]; + if (!domain) { + printf("Never got a DOMAIN object in samsync!\n"); + return False; + } + + username = talloc_asprintf(mem_ctx, "%s$", domain); + for (t=samsync_state->trusted_domains; t; t=t->next) { + char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name); + for (s=samsync_state->secrets; s; s=s->next) { + printf("Checking secret %s against %s\n", + s->name, secret_name); + if (StrCaseCmp(s->name, secret_name) == 0) { + NTSTATUS nt_status; + struct samr_Password nt_hash; + mdfour(nt_hash.hash, s->secret.data, s->secret.length); + printf("Checking password for %s\\%s\n", t->name, username); - nt_status = test_SamLogon(p, mem_ctx, creds, - t->name, - username, - NULL, - &nt_hash, - NULL); - if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) { - printf("Could not verify trust password to %s: %s\n", - t->name, nt_errstr(nt_status)); - ret = False; - } - - /* break it */ - nt_hash.hash[0]++; - nt_status = test_SamLogon(p, mem_ctx, creds, - t->name, - username, - NULL, - &nt_hash, - 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", - t->name, nt_errstr(nt_status)); - ret = False; - ret = False; - } - - break; + nt_status = test_SamLogon(samsync_state->p, mem_ctx, samsync_state->creds, + t->name, + username, + NULL, + &nt_hash, + NULL); + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) { + printf("Could not verify trust password to %s: %s\n", + t->name, nt_errstr(nt_status)); + ret = False; + } + + /* break it */ + nt_hash.hash[0]++; + nt_status = test_SamLogon(samsync_state->p, mem_ctx, samsync_state->creds, + t->name, + username, + NULL, + &nt_hash, + 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", + t->name, nt_errstr(nt_status)); + ret = False; + ret = False; } + + break; } - talloc_free(secret_name); - talloc_free(username); } } - return ret; } @@ -414,8 +632,7 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, /* try a netlogon DatabaseDeltas */ -static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds) +static BOOL test_DatabaseDeltas(struct samsync_state *samsync_state, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct netr_DatabaseDeltas r; @@ -423,14 +640,14 @@ static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, int i; BOOL ret = True; - r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); + r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p)); r.in.computername = TEST_MACHINE_NAME; r.in.preferredmaximumlength = (uint32_t)-1; ZERO_STRUCT(r.in.return_authenticator); for (i=0;i<ARRAY_SIZE(database_ids);i++) { r.in.database_id = database_ids[i]; - r.in.sequence_num = sequence_nums[r.in.database_id]; + r.in.sequence_num = samsync_state->seq_num[i]; if (r.in.sequence_num == 0) continue; @@ -441,9 +658,9 @@ static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.database_id, r.in.sequence_num); do { - creds_client_authenticator(creds, &r.in.credential); + creds_client_authenticator(samsync_state->creds, &r.in.credential); - status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r); + status = dcerpc_netr_DatabaseDeltas(samsync_state->p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { printf("DatabaseDeltas - %s\n", nt_errstr(status)); @@ -451,7 +668,7 @@ static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, break; } - if (!creds_client_check(creds, &r.out.return_authenticator.cred)) { + if (!creds_client_check(samsync_state->creds, &r.out.return_authenticator.cred)) { printf("Credential chaining failed\n"); } @@ -514,14 +731,15 @@ static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, BOOL torture_rpc_samsync(void) { NTSTATUS status; - struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx; BOOL ret = True; struct test_join *join_ctx; const char *machine_password; const char *binding = lp_parm_string(-1, "torture", "binding"); struct dcerpc_binding b; - struct creds_CredentialState *creds; + struct samr_Connect c; + + struct samsync_state *samsync_state; mem_ctx = talloc_init("torture_rpc_netlogon"); @@ -531,17 +749,33 @@ BOOL torture_rpc_samsync(void) printf("Failed to join as BDC\n"); return False; } + + samsync_state = talloc_zero_p(mem_ctx, struct samsync_state); + + samsync_state->p_samr = torture_join_samr_pipe(join_ctx); + samsync_state->connect_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; + + status = dcerpc_samr_Connect(samsync_state->p_samr, mem_ctx, &c); + if (!NT_STATUS_IS_OK(status)) { + printf("samr_Connect failed\n"); + 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; + goto failed; } b.flags &= ~DCERPC_AUTH_OPTIONS; - b.flags |= DCERPC_SCHANNEL_BDC | DCERPC_SEAL | DCERPC_SCHANNEL_128; + b.flags |= DCERPC_SCHANNEL_BDC | DCERPC_SIGN | DCERPC_SCHANNEL_128; - status = dcerpc_pipe_connect_b(&p, &b, + status = dcerpc_pipe_connect_b(&samsync_state->p, &b, DCERPC_NETLOGON_UUID, DCERPC_NETLOGON_VERSION, lp_workgroup(), @@ -549,30 +783,32 @@ BOOL torture_rpc_samsync(void) machine_password); if (!NT_STATUS_IS_OK(status)) { - return False; + ret = False; + goto failed; } - status = dcerpc_schannel_creds(p->security_state.generic_state, mem_ctx, &creds); + status = dcerpc_schannel_creds(samsync_state->p->security_state.generic_state, mem_ctx, &samsync_state->creds); if (!NT_STATUS_IS_OK(status)) { - return False; + ret = False; } - if (!test_DatabaseSync(p, mem_ctx, creds)) { + if (!test_DatabaseSync(samsync_state, mem_ctx)) { ret = False; } - if (!test_DatabaseDeltas(p, mem_ctx, creds)) { + if (!test_DatabaseDeltas(samsync_state, mem_ctx)) { ret = False; } - if (!test_DatabaseSync2(p, mem_ctx, creds)) { + if (!test_DatabaseSync2(samsync_state->p, mem_ctx, samsync_state->creds)) { ret = False; } - talloc_destroy(mem_ctx); - - torture_rpc_close(p); +failed: + torture_rpc_close(samsync_state->p); torture_leave_domain(join_ctx); + talloc_destroy(mem_ctx); + return ret; } diff --git a/source4/torture/rpc/xplogin.c b/source4/torture/rpc/xplogin.c index e0bb706255..9a47934fe7 100644 --- a/source4/torture/rpc/xplogin.c +++ b/source4/torture/rpc/xplogin.c @@ -664,7 +664,7 @@ static NTSTATUS test_getgroups(struct smbcli_transport *transport, struct samr_LookupDomain l; struct samr_OpenDomain o; - if (strcmp(e.out.sam->entries[i].name.name, + if (strcmp(e.out.sam->entries[i].name.string, "Builtin") == 0) continue; @@ -692,10 +692,10 @@ static NTSTATUS test_getgroups(struct smbcli_transport *transport, { struct samr_LookupNames l; - struct samr_Name samr_name; + struct samr_String samr_name; struct samr_OpenUser o; - samr_name.name = name; + samr_name.string = name; l.in.domain_handle = &domain_handle; l.in.num_names = 1; @@ -829,7 +829,7 @@ static NTSTATUS test_getallsids(struct smbcli_transport *transport, struct samr_LookupDomain l; - if (strcmp(e.out.sam->entries[i].name.name, + if (strcmp(e.out.sam->entries[i].name.string, "Builtin") == 0) continue; @@ -866,10 +866,10 @@ static NTSTATUS test_getallsids(struct smbcli_transport *transport, { struct samr_LookupNames l; - struct samr_Name samr_name; + struct samr_String samr_name; struct samr_OpenUser o; - samr_name.name = name; + samr_name.string = name; l.in.domain_handle = &domain_handle; l.in.num_names = 1; |