diff options
Diffstat (limited to 'source4/torture/rpc/lsa_lookup.c')
-rw-r--r-- | source4/torture/rpc/lsa_lookup.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/source4/torture/rpc/lsa_lookup.c b/source4/torture/rpc/lsa_lookup.c new file mode 100644 index 0000000..f641827 --- /dev/null +++ b/source4/torture/rpc/lsa_lookup.c @@ -0,0 +1,428 @@ +/* + Unix SMB/CIFS implementation. + test suite for lsa rpc lookup operations + + Copyright (C) Volker Lendecke 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/rpc/torture_rpc.h" +#include "librpc/gen_ndr/ndr_lsa_c.h" +#include "libcli/security/security.h" + +static bool open_policy(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + struct policy_handle **handle) +{ + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy2 r; + + *handle = talloc(tctx, struct policy_handle); + if (!*handle) { + return false; + } + + 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_FLAG_MAXIMUM_ALLOWED; + r.out.handle = *handle; + + torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenPolicy2_r(b, tctx, &r), + "OpenPolicy2 failed"); + + return NT_STATUS_IS_OK(r.out.result); +} + +static bool get_domainsid(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + struct policy_handle *handle, + struct dom_sid **sid) +{ + struct lsa_QueryInfoPolicy r; + union lsa_PolicyInformation *info = NULL; + + r.in.level = LSA_POLICY_INFO_DOMAIN; + r.in.handle = handle; + r.out.info = &info; + + torture_assert_ntstatus_ok(tctx, dcerpc_lsa_QueryInfoPolicy_r(b, tctx, &r), + "QueryInfoPolicy failed"); + torture_assert_ntstatus_ok(tctx, r.out.result, "QueryInfoPolicy failed"); + + *sid = info->domain.sid; + return true; +} + +static NTSTATUS lookup_sids(struct torture_context *tctx, + uint16_t level, + struct dcerpc_binding_handle *b, + struct policy_handle *handle, + struct dom_sid **sids, uint32_t num_sids, + struct lsa_TransNameArray *names) +{ + struct lsa_LookupSids r; + struct lsa_SidArray sidarray; + struct lsa_RefDomainList *domains; + uint32_t count = 0; + uint32_t i; + NTSTATUS status; + + names->count = 0; + names->names = NULL; + + sidarray.num_sids = num_sids; + sidarray.sids = talloc_array(tctx, struct lsa_SidPtr, num_sids); + + for (i=0; i<num_sids; i++) { + sidarray.sids[i].sid = sids[i]; + } + + r.in.handle = handle; + r.in.sids = &sidarray; + r.in.names = names; + r.in.level = level; + r.in.count = &count; + r.out.names = names; + r.out.count = &count; + r.out.domains = &domains; + + status = dcerpc_lsa_LookupSids_r(b, tctx, &r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return r.out.result; +} + +static bool test_lookupsids(struct torture_context *tctx, + struct dcerpc_binding_handle *b, + struct policy_handle *handle, + struct dom_sid **sids, uint32_t num_sids, + int level, NTSTATUS expected_result, + enum lsa_SidType *types) +{ + struct lsa_TransNameArray names; + NTSTATUS status; + uint32_t i; + bool ret = true; + + status = lookup_sids(tctx, level, b, handle, sids, num_sids, + &names); + if (!NT_STATUS_EQUAL(status, expected_result)) { + printf("For level %d expected %s, got %s\n", + level, nt_errstr(expected_result), + nt_errstr(status)); + return false; + } + + if (!NT_STATUS_EQUAL(status, NT_STATUS_OK) && + !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) { + return true; + } + + for (i=0; i<num_sids; i++) { + if (names.names[i].sid_type != types[i]) { + printf("In level %d, for sid %s expected %s, " + "got %s\n", level, + dom_sid_string(tctx, sids[i]), + sid_type_lookup(types[i]), + sid_type_lookup(names.names[i].sid_type)); + ret = false; + } + } + return ret; +} + +static bool get_downleveltrust(struct torture_context *tctx, struct dcerpc_binding_handle *b, + struct policy_handle *handle, + struct dom_sid **sid) +{ + struct lsa_EnumTrustDom r; + uint32_t resume_handle = 0; + struct lsa_DomainList domains; + int i; + + r.in.handle = handle; + r.in.resume_handle = &resume_handle; + r.in.max_size = 1000; + r.out.domains = &domains; + r.out.resume_handle = &resume_handle; + + torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumTrustDom_r(b, tctx, &r), + "EnumTrustDom failed"); + + if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NO_MORE_ENTRIES)) + torture_fail(tctx, "no trusts"); + + if (domains.count == 0) { + torture_fail(tctx, "no trusts"); + } + + for (i=0; i<domains.count; i++) { + struct lsa_QueryTrustedDomainInfoBySid q; + union lsa_TrustedDomainInfo *info = NULL; + + if (domains.domains[i].sid == NULL) + continue; + + q.in.handle = handle; + q.in.dom_sid = domains.domains[i].sid; + q.in.level = 6; + q.out.info = &info; + + torture_assert_ntstatus_ok(tctx, dcerpc_lsa_QueryTrustedDomainInfoBySid_r(b, tctx, &q), + "QueryTrustedDomainInfoBySid failed"); + if (!NT_STATUS_IS_OK(q.out.result)) continue; + + if ((info->info_ex.trust_direction & 2) && + (info->info_ex.trust_type == 1)) { + *sid = domains.domains[i].sid; + return true; + } + } + + torture_fail(tctx, "I need a AD DC with an outgoing trust to NT4"); +} + +#define NUM_SIDS 8 + +bool torture_rpc_lsa_lookup(struct torture_context *torture) +{ + NTSTATUS status; + struct dcerpc_pipe *p; + bool ret = true; + struct policy_handle *handle; + struct dom_sid *dom_sid = NULL; + struct dom_sid *trusted_sid = NULL; + struct dom_sid *sids[NUM_SIDS]; + struct dcerpc_binding_handle *b; + enum dcerpc_transport_t transport; + + status = torture_rpc_connection(torture, &p, &ndr_table_lsarpc); + if (!NT_STATUS_IS_OK(status)) { + torture_fail(torture, "unable to connect to table"); + } + b = p->binding_handle; + transport = dcerpc_binding_get_transport(p->binding); + + if (transport != NCACN_NP && transport != NCALRPC) { + torture_comment(torture, + "torture_rpc_lsa_lookup is only available " + "over NCACN_NP or NCALRPC"); + return true; + } + + ret &= open_policy(torture, b, &handle); + if (!ret) return false; + + ret &= get_domainsid(torture, b, handle, &dom_sid); + if (!ret) return false; + + ret &= get_downleveltrust(torture, b, handle, &trusted_sid); + if (!ret) return false; + + torture_comment(torture, "domain sid: %s\n", + dom_sid_string(torture, dom_sid)); + + sids[0] = dom_sid_parse_talloc(torture, "S-1-1-0"); + sids[1] = dom_sid_parse_talloc(torture, "S-1-5-4"); + sids[2] = dom_sid_parse_talloc(torture, "S-1-5-32"); + sids[3] = dom_sid_parse_talloc(torture, "S-1-5-32-545"); + sids[4] = dom_sid_dup(torture, dom_sid); + sids[5] = dom_sid_add_rid(torture, dom_sid, 512); + sids[6] = dom_sid_dup(torture, trusted_sid); + sids[7] = dom_sid_add_rid(torture, trusted_sid, 512); + + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 0, + NT_STATUS_INVALID_PARAMETER, NULL); + + { + enum lsa_SidType types[NUM_SIDS] = + { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN, + SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; + + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 1, + NT_STATUS_OK, types); + } + + { + enum lsa_SidType types[NUM_SIDS] = + { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 2, + STATUS_SOME_UNMAPPED, types); + } + + { + enum lsa_SidType types[NUM_SIDS] = + { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 3, + STATUS_SOME_UNMAPPED, types); + } + + { + enum lsa_SidType types[NUM_SIDS] = + { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 4, + STATUS_SOME_UNMAPPED, types); + } + + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 5, + NT_STATUS_NONE_MAPPED, NULL); + + { + enum lsa_SidType types[NUM_SIDS] = + { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, + SID_NAME_DOMAIN, SID_NAME_DOM_GRP, + SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 6, + STATUS_SOME_UNMAPPED, types); + } + + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 7, + NT_STATUS_INVALID_PARAMETER, NULL); + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 8, + NT_STATUS_INVALID_PARAMETER, NULL); + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 9, + NT_STATUS_INVALID_PARAMETER, NULL); + ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 10, + NT_STATUS_INVALID_PARAMETER, NULL); + + return ret; +} + +static bool test_LookupSidsReply(struct torture_context *tctx, + struct dcerpc_pipe *p) +{ + struct policy_handle *handle = NULL; + + struct dom_sid **sids = NULL; + uint32_t num_sids = 1; + + struct lsa_LookupSids r; + struct lsa_SidArray sidarray; + struct lsa_RefDomainList *domains = NULL; + struct lsa_TransNameArray names; + uint32_t count = 0; + + uint32_t i; + const char *dom_sid = "S-1-5-21-1111111111-2222222222-3333333333"; + const char *dom_admin_sid; + struct dcerpc_binding_handle *b = p->binding_handle; + enum dcerpc_transport_t transport = dcerpc_binding_get_transport(p->binding); + + ZERO_STRUCT(r); + ZERO_STRUCT(sidarray); + ZERO_STRUCT(names); + + if (transport != NCACN_NP && transport != NCALRPC) { + torture_comment(tctx, + "test_LookupSidsReply is only available " + "over NCACN_NP or NCALRPC"); + return true; + } + + if (!open_policy(tctx, b, &handle)) { + return false; + } + + dom_admin_sid = talloc_asprintf(tctx, "%s-%d", dom_sid, 512); + + sids = talloc_zero_array(tctx, struct dom_sid *, num_sids); + + sids[0] = dom_sid_parse_talloc(tctx, dom_admin_sid); + + names.count = 0; + names.names = NULL; + + sidarray.num_sids = num_sids; + sidarray.sids = talloc_zero_array(tctx, struct lsa_SidPtr, num_sids); + + for (i=0; i<num_sids; i++) { + sidarray.sids[i].sid = sids[i]; + } + + r.in.handle = handle; + r.in.sids = &sidarray; + r.in.names = &names; + r.in.level = LSA_LOOKUP_NAMES_ALL; + r.in.count = &count; + r.out.names = &names; + r.out.count = &count; + r.out.domains = &domains; + + torture_assert_ntstatus_ok(tctx, dcerpc_lsa_LookupSids_r(b, tctx, &r), + "LookupSids failed"); + + torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NONE_MAPPED, + "unexpected error code"); + + torture_assert_int_equal(tctx, names.count, num_sids, + "unexpected names count"); + torture_assert(tctx, names.names, + "unexpected names pointer"); + torture_assert_str_equal(tctx, names.names[0].name.string, dom_admin_sid, + "unexpected names[0].string"); + +#if 0 + /* vista sp1 passes, w2k3 sp2 fails */ + torture_assert_int_equal(tctx, domains->count, num_sids, + "unexpected domains count"); + torture_assert(tctx, domains->domains, + "unexpected domains pointer"); + torture_assert_str_equal(tctx, dom_sid_string(tctx, domains->domains[0].sid), dom_sid, + "unexpected domain sid"); +#endif + + return true; +} + +/* check for lookup sids results */ +struct torture_suite *torture_rpc_lsa_lookup_sids(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite; + struct torture_rpc_tcase *tcase; + + suite = torture_suite_create(mem_ctx, "lsa.lookupsids"); + tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa", + &ndr_table_lsarpc); + + torture_rpc_tcase_add_test(tcase, "LookupSidsReply", test_LookupSidsReply); + + return suite; +} |