From e54964c61840e108f34b6a9c931fb15a35c4f48c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 12 Jan 2005 07:57:33 +0000 Subject: r4703: Add support for EnumTrustDomain, and expand the testsuite. Add my copyright to the SAMR server. Andrew Bartlett (This used to be commit 51e94fa26cc602ddca652776c213cd7096f9703a) --- source4/librpc/idl/lsa.idl | 5 +- source4/rpc_server/lsa/dcesrv_lsa.c | 86 +++++++++++- source4/rpc_server/samr/dcesrv_samr.c | 1 + source4/torture/rpc/lsa.c | 244 +++++++++++++++++++--------------- 4 files changed, 223 insertions(+), 113 deletions(-) diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 8aeb40b3bc..9ed8756016 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -270,6 +270,9 @@ /******************/ /* Function: 0x0d */ + /* w2k3 treats max_size as max_domains*60 */ + const int LSA_ENUM_TRUST_DOMAIN_MULTIPLIER = 60; + typedef struct { lsa_String name; dom_sid2 *sid; @@ -283,7 +286,7 @@ NTSTATUS lsa_EnumTrustDom ( [in,ref] policy_handle *handle, [in,out,ref] uint32 *resume_handle, - [in,range(0,1000)] uint32 num_entries, + [in,range(0,1000)] uint32 max_size, [out,ref] lsa_DomainList *domains ); diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 2ea4d8aa25..6ea8d4b78c 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -627,7 +627,7 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_NO_MEMORY; } - samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "securityIdentifier", name); + samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "securityIdentifier", sid_string); } /* pull in all the template attributes. Note this is always from the global samdb */ @@ -761,11 +761,12 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call, if (!trusted_domain_state) { return NT_STATUS_NO_MEMORY; } + trusted_domain_state->policy = policy_state; /* search for the trusted_domain record */ ret = samdb_search(trusted_domain_state->policy->sam_ctx, mem_ctx, policy_state->system_dn, &msgs, attrs, - "(&(cn=%s)(objectclass=trustedDomain))", + "(&(flatname=%s)(objectclass=trustedDomain))", r->in.name.string); if (ret == 0) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -818,7 +819,7 @@ static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLO lsa_DeleteTrustDomain */ static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_DeleteTrustDomain *r) + struct lsa_DeleteTrustDomain *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } @@ -885,13 +886,88 @@ static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call, } +/* + comparison function for sorting lsa_DomainInformation array +*/ +static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2) +{ + return strcasecmp(e1->name.string, e2->name.string); +} + /* lsa_EnumTrustDom */ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_EnumTrustDom *r) + struct lsa_EnumTrustDom *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + struct dcesrv_handle *policy_handle; + struct lsa_DomainInformation *entries; + struct lsa_policy_state *policy_state; + struct ldb_message **domains; + const char *attrs[] = { + "flatname", + "securityIdentifier", + NULL + }; + + + int count, i; + + *r->out.resume_handle = 0; + + r->out.domains->domains = NULL; + r->out.domains->count = 0; + + DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); + + policy_state = policy_handle->data; + + /* search for all users in this domain. This could possibly be cached and + resumed based on resume_key */ + count = samdb_search(policy_state->sam_ctx, mem_ctx, policy_state->system_dn, &domains, attrs, + "objectclass=trustedDomain"); + if (count == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + if (count == 0 || r->in.max_size == 0) { + return NT_STATUS_OK; + } + + /* convert to lsa_DomainInformation format */ + entries = talloc_array_p(mem_ctx, struct lsa_DomainInformation, count); + if (!entries) { + return NT_STATUS_NO_MEMORY; + } + for (i=0;iin.resume_handle >= count) { + *r->out.resume_handle = -1; + + return NT_STATUS_NO_MORE_ENTRIES; + } + + /* return the rest, limit by max_size. Note that we + use the w2k3 element size value of 60 */ + r->out.domains->count = count - *r->in.resume_handle; + r->out.domains->count = MIN(r->out.domains->count, + 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER)); + + r->out.domains->domains = entries + *r->in.resume_handle; + r->out.domains->count = r->out.domains->count; + + if (r->out.domains->count < count - *r->in.resume_handle) { + *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count; + return STATUS_MORE_ENTRIES; + } + + return NT_STATUS_OK; } diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 7cbe63056a..c3ec8bf80f 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2004 Copyright (C) Volker Lendecke 2004 + Copyright (C) Andrew Bartlett 2004-2005 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 diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 5bb282a033..2c802ea5de 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -557,7 +557,7 @@ static BOOL test_Delete(struct dcerpc_pipe *p, NTSTATUS status; struct lsa_Delete r; - printf("\ntesting Delete\n"); + printf("testing Delete\n"); r.in.handle = handle; status = dcerpc_lsa_Delete(p, mem_ctx, &r); @@ -566,8 +566,6 @@ static BOOL test_Delete(struct dcerpc_pipe *p, return False; } - printf("\n"); - return True; } @@ -1235,90 +1233,68 @@ static BOOL test_EnumPrivs(struct dcerpc_pipe *p, return ret; } - -static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, - TALLOC_CTX *mem_ctx, - struct policy_handle *handle) +static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + struct lsa_DomainList *domains) { - struct lsa_EnumTrustDom r; NTSTATUS status; - uint32_t resume_handle = 0; - struct lsa_DomainList domains; int i,j; BOOL ret = True; - - printf("\nTesting EnumTrustDom\n"); - - r.in.handle = handle; - r.in.resume_handle = &resume_handle; - r.in.num_entries = 100; - r.out.domains = &domains; - r.out.resume_handle = &resume_handle; - - status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r); - - /* NO_MORE_ENTRIES is allowed */ - if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) { - return True; - } - - if (!NT_STATUS_IS_OK(status)) { - printf("EnumTrustDom failed - %s\n", nt_errstr(status)); - return False; - } - + printf("\nTesting OpenTrustedDomain, OpenTrustedDomainByName and QueryInfoTrustedDomain\n"); - - for (i=0; i< domains.count; i++) { + for (i=0; i< domains->count; i++) { struct lsa_OpenTrustedDomain trust; struct lsa_OpenTrustedDomainByName trust_by_name; struct policy_handle trustdom_handle; struct policy_handle handle2; struct lsa_Close c; int levels [] = {1, 3, 6, 8, 12}; - - trust.in.handle = handle; - trust.in.sid = domains.domains[i].sid; - trust.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - trust.out.trustdom_handle = &trustdom_handle; - - status = dcerpc_lsa_OpenTrustedDomain(p, mem_ctx, &trust); - - if (!NT_STATUS_IS_OK(status)) { - printf("OpenTrustedDomain failed - %s\n", nt_errstr(status)); - return False; - } - - c.in.handle = &trustdom_handle; - c.out.handle = &handle2; - - for (j=0; j < ARRAY_SIZE(levels); j++) { - struct lsa_QueryTrustedDomainInfo q; - union lsa_TrustedDomainInfo info; - q.in.trustdom_handle = &trustdom_handle; - q.in.level = levels[j]; - q.out.info = &info; - status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); + + if (domains->domains[i].sid) { + trust.in.handle = handle; + trust.in.sid = domains->domains[i].sid; + trust.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + trust.out.trustdom_handle = &trustdom_handle; + + status = dcerpc_lsa_OpenTrustedDomain(p, mem_ctx, &trust); + if (!NT_STATUS_IS_OK(status)) { - printf("QueryTrustedDomainInfo level %d failed - %s\n", - levels[j], nt_errstr(status)); - ret = False; + printf("OpenTrustedDomain failed - %s\n", nt_errstr(status)); + return False; + } + + c.in.handle = &trustdom_handle; + c.out.handle = &handle2; + + for (j=0; j < ARRAY_SIZE(levels); j++) { + struct lsa_QueryTrustedDomainInfo q; + union lsa_TrustedDomainInfo info; + q.in.trustdom_handle = &trustdom_handle; + q.in.level = levels[j]; + q.out.info = &info; + status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + printf("QueryTrustedDomainInfo level %d failed - %s\n", + levels[j], nt_errstr(status)); + ret = False; + } + } + + status = dcerpc_lsa_Close(p, mem_ctx, &c); + if (!NT_STATUS_IS_OK(status)) { + printf("Close of trusted domain failed - %s\n", nt_errstr(status)); + return False; } - } - - status = dcerpc_lsa_Close(p, mem_ctx, &c); - if (!NT_STATUS_IS_OK(status)) { - printf("Close of trusted domain failed - %s\n", nt_errstr(status)); - return False; } trust_by_name.in.handle = handle; - trust_by_name.in.name = domains.domains[i].name; + trust_by_name.in.name = domains->domains[i].name; trust_by_name.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; trust_by_name.out.trustdom_handle = &trustdom_handle; - + status = dcerpc_lsa_OpenTrustedDomainByName(p, mem_ctx, &trust_by_name); - + if (!NT_STATUS_IS_OK(status)) { printf("OpenTrustedDomainByName failed - %s\n", nt_errstr(status)); return False; @@ -1350,8 +1326,13 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, for (j=0; j < ARRAY_SIZE(levels); j++) { struct lsa_QueryTrustedDomainInfoBySid q; union lsa_TrustedDomainInfo info; + + if (!domains->domains[i].sid) { + continue; + } + q.in.handle = handle; - q.in.dom_sid = domains.domains[i].sid; + q.in.dom_sid = domains->domains[i].sid; q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q); @@ -1366,7 +1347,7 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, struct lsa_QueryTrustedDomainInfoByName q; union lsa_TrustedDomainInfo info; q.in.handle = handle; - q.in.trusted_domain = domains.domains[i].name; + q.in.trusted_domain = domains->domains[i].name; q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfoByName(p, mem_ctx, &q); @@ -1376,10 +1357,51 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, ret = False; } } + } + return ret; +} + +static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + struct lsa_EnumTrustDom r; + NTSTATUS enum_status; + uint32_t resume_handle = 0; + struct lsa_DomainList domains; + BOOL ret = True; + + printf("\nTesting EnumTrustDom\n"); + + do { + r.in.handle = handle; + r.in.resume_handle = &resume_handle; + r.in.max_size = LSA_ENUM_TRUST_DOMAIN_MULTIPLIER * 3; + r.out.domains = &domains; + r.out.resume_handle = &resume_handle; + + enum_status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r); + /* NO_MORE_ENTRIES is allowed */ + if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) { + return True; + } else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) { + /* Windows 2003 gets this off by one on the first run */ + if (r.out.domains->count < 3 || r.out.domains->count > 4) { + printf("EnumTrustDom didn't fill the buffer we " + "asked it to (got %d, expected %d / %d == %d entries)\n", + r.out.domains->count, LSA_ENUM_TRUST_DOMAIN_MULTIPLIER * 3, + LSA_ENUM_TRUST_DOMAIN_MULTIPLIER, r.in.max_size); + ret = False; + } + } else if (!NT_STATUS_IS_OK(enum_status)) { + printf("EnumTrustDom failed - %s\n", nt_errstr(enum_status)); + return False; + } + ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains); - } + } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))); return ret; } @@ -1392,46 +1414,52 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p, BOOL ret = True; struct lsa_CreateTrustedDomain r; struct lsa_TrustInformation trustinfo; - struct dom_sid *domsid; - struct policy_handle trustdom_handle; + struct dom_sid *domsid[12]; + struct policy_handle trustdom_handle[12]; struct lsa_QueryTrustedDomainInfo q; + int i; - printf("Testing CreateTrustedDomain\n"); - - domsid = dom_sid_parse_talloc(mem_ctx, "S-1-5-21-97398-379795-12345"); + printf("Testing CreateTrustedDomain for 12 domains\n"); - trustinfo.sid = domsid; - init_lsa_String(&trustinfo.name, "torturedomain"); + for (i=0; i< 12; i++) { + char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i); + char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i); + + domsid[i] = dom_sid_parse_talloc(mem_ctx, trust_sid); - r.in.handle = handle; - r.in.info = &trustinfo; - r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r.out.trustdom_handle = &trustdom_handle; + trustinfo.sid = domsid[i]; + init_lsa_String(&trustinfo.name, trust_name); - status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r); - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.name); + r.in.handle = handle; + r.in.info = &trustinfo; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.trustdom_handle = &trustdom_handle[i]; + status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r); - } - if (!NT_STATUS_IS_OK(status)) { - printf("CreateTrustedDomain failed - %s\n", nt_errstr(status)); - return False; - } - - q.in.trustdom_handle = &trustdom_handle; - q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME; - status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); - if (!NT_STATUS_IS_OK(status)) { - printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status)); - ret = False; - } - if (!q.out.info) { - ret = False; - } else { - if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) { - printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n", - q.out.info->name.netbios_name.string, trustinfo.name.string); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + test_DeleteTrustedDomain(p, mem_ctx, handle, trustinfo.name); + status = dcerpc_lsa_CreateTrustedDomain(p, mem_ctx, &r); + } + if (!NT_STATUS_IS_OK(status)) { + printf("CreateTrustedDomain failed - %s\n", nt_errstr(status)); ret = False; + } else { + + q.in.trustdom_handle = &trustdom_handle[i]; + q.in.level = LSA_TRUSTED_DOMAIN_INFO_NAME; + status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); + if (!NT_STATUS_IS_OK(status)) { + printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status)); + ret = False; + } else if (!q.out.info) { + ret = False; + } else { + if (strcmp(q.out.info->name.netbios_name.string, trustinfo.name.string) != 0) { + printf("QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n", + q.out.info->name.netbios_name.string, trustinfo.name.string); + ret = False; + } + } } } @@ -1439,9 +1467,11 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p, if (!test_EnumTrustDom(p, mem_ctx, handle)) { ret = False; } - - if (!test_Delete(p, mem_ctx, &trustdom_handle)) { - ret = False; + + for (i=0; i<12; i++) { + if (!test_Delete(p, mem_ctx, &trustdom_handle[i])) { + ret = False; + } } return ret; -- cgit