From e905fed4e03a50f8c17b9ff0726fccc9558ca8c4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 31 Aug 2006 08:22:13 +0000 Subject: r17956: LSA Cleanup! This commit cleans up a number of aspects of the LSA interface. Firstly, we do 2 simple searches on opening the LSA policy, to obtain the basic information we need. This also avoids us searching for dnsDomain (an invented attribute). While I was at it, I added and tested new LSA calls, including the enumTrustedDomainsEx call. I have also merged the identical structures lsa_DomainInformation and lsa_DomainList. Also in this commit: Fix netlogon use of uninitialised variables. Andrew Bartlett (This used to be commit 3f3fa7f466df56612064029143fbae8effb668aa) --- source4/librpc/idl/lsa.idl | 56 ++-- source4/rpc_server/lsa/dcesrv_lsa.c | 395 +++++++++++++++++++++----- source4/rpc_server/netlogon/dcerpc_netlogon.c | 8 +- source4/torture/rpc/lsa.c | 110 ++++++- source4/torture/rpc/netlogon.c | 2 +- source4/winbind/wb_async_helpers.c | 4 +- 6 files changed, 467 insertions(+), 108 deletions(-) (limited to 'source4') diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 0953c6d025..3c05ab2e93 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -279,14 +279,9 @@ /*************************************************/ /* Function: 0x0c */ - typedef struct { - lsa_StringLarge name; - dom_sid2 *sid; - } lsa_TrustInformation; - NTSTATUS lsa_CreateTrustedDomain( [in] policy_handle *handle, - [in] lsa_TrustInformation *info, + [in] lsa_DomainInfo *info, [in] uint32 access_mask, [out] policy_handle *trustdom_handle ); @@ -298,14 +293,9 @@ /* w2k3 treats max_size as max_domains*60 */ const int LSA_ENUM_TRUST_DOMAIN_MULTIPLIER = 60; - typedef struct { - lsa_StringLarge name; - dom_sid2 *sid; - } lsa_DomainInformation; - typedef struct { uint32 count; - [size_is(count)] lsa_DomainInformation *domains; + [size_is(count)] lsa_DomainInfo *domains; } lsa_DomainList; NTSTATUS lsa_EnumTrustDom ( @@ -341,10 +331,11 @@ [size_is(count)] lsa_TranslatedSid *sids; } lsa_TransSidArray; + const int LSA_REF_DOMAIN_LIST_MULTIPLIER = 32; typedef struct { [range(0,1000)] uint32 count; - [size_is(count)] lsa_TrustInformation *domains; - uint32 max_count; + [size_is(count)] lsa_DomainInfo *domains; + uint32 max_size; } lsa_RefDomainList; NTSTATUS lsa_LookupNames ( @@ -674,9 +665,13 @@ ); /* Function: 0x28 */ - NTSTATUS lsa_SetTrustDomainInfo(); + NTSTATUS lsa_SetTrustedDomainInfo(); /* Function: 0x29 */ - NTSTATUS lsa_DeleteTrustDomain(); + NTSTATUS lsa_DeleteTrustedDomain( + [in] policy_handle *handle, + [in] dom_sid2 *dom_sid + ); + /* Function: 0x2a */ NTSTATUS lsa_StorePrivateData(); /* Function: 0x2b */ @@ -725,17 +720,40 @@ [out,unique,switch_is(level)] lsa_TrustedDomainInfo *info ); + /**********************/ /* Function 0x31 */ - NTSTATUS lsa_SetTrustedDomainInfoByName(); + NTSTATUS lsa_SetTrustedDomainInfoByName( + [in] policy_handle *handle, + [in] lsa_String trusted_domain, + [in] lsa_TrustDomInfoEnum level, + [in,unique,switch_is(level)] lsa_TrustedDomainInfo *info + ); /* Function 0x32 */ - NTSTATUS lsa_EnumTrustedDomainsEx(); + + /* w2k3 treats max_size as max_domains*82 */ + const int LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER = 82; + + typedef struct { + uint32 count; + [size_is(count)] lsa_TrustDomainInfoInfoEx *domains; + } lsa_DomainListEx; + + NTSTATUS lsa_EnumTrustedDomainsEx ( + [in] policy_handle *handle, + [in,out] uint32 *resume_handle, + [out] lsa_DomainListEx *domains, + [in] uint32 max_size + ); + /* Function 0x33 */ NTSTATUS lsa_CreateTrustedDomainEx(); /* Function 0x34 */ - NTSTATUS lsa_CloseTrustedDomainEx(); + NTSTATUS lsa_CloseTrustedDomainEx( + [in,out] policy_handle *handle + ); /* Function 0x35 */ diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 43bc91b149..5b3de2c22b 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -55,7 +55,9 @@ struct lsa_policy_state { const struct ldb_dn *builtin_dn; const struct ldb_dn *system_dn; const char *domain_name; + const char *domain_dns; struct dom_sid *domain_sid; + struct GUID domain_guid; struct dom_sid *builtin_sid; }; @@ -76,7 +78,7 @@ struct lsa_account_state { struct lsa_secret_state { struct lsa_policy_state *policy; uint32_t access_mask; - const struct ldb_dn *secret_dn; + struct ldb_dn *secret_dn; struct ldb_context *sam_ldb; BOOL global; }; @@ -268,6 +270,20 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ { struct lsa_policy_state *state; const struct ldb_dn *partitions_basedn; + struct ldb_result *dom_res; + const char *dom_attrs[] = { + "objectSid", + "objectGUID", + NULL + }; + struct ldb_result *ref_res; + const char *ref_attrs[] = { + "nETBIOSName", + "dnsRoot", + NULL + }; + char *ref_filter; + int ret; state = talloc(mem_ctx, struct lsa_policy_state); if (!state) { @@ -294,15 +310,59 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_MEMORY; } - state->domain_name - = samdb_search_string(state->sam_ldb, state, partitions_basedn, "nETBIOSName", - "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn)); + ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res); + if (ret != LDB_SUCCESS) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } + talloc_steal(state, dom_res); + if (dom_res->count != 1) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + + state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid"); + if (!state->domain_sid) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + + state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); + if (!state->domain_sid) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + + talloc_free(dom_res); + + ref_filter = talloc_asprintf(state, "(&(objectclass=crossRef)(ncName=%s))", + ldb_dn_linearize(mem_ctx, state->domain_dn)); + if (!ref_filter) { + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_search(state->sam_ldb, partitions_basedn, LDB_SCOPE_SUBTREE, ref_filter, ref_attrs, &ref_res); + talloc_steal(state, ref_res); + talloc_free(ref_filter); + + if (ret != LDB_SUCCESS) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } + if (ref_res->count != 1) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + + state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL); if (!state->domain_name) { return NT_STATUS_NO_SUCH_DOMAIN; } talloc_steal(state, state->domain_name); + state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL); + if (!state->domain_dns) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + talloc_steal(state, state->domain_dns); + + talloc_free(ref_res); + /* work out the builtin_dn - useful for so many calls its worth fetching here */ state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)"); @@ -318,14 +378,6 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_SUCH_DOMAIN; } - state->domain_sid = samdb_search_dom_sid(state->sam_ldb, state, - state->domain_dn, "objectSid", NULL); - if (!state->domain_sid) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - - talloc_steal(state, state->domain_sid); - state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN); if (!state->builtin_sid) { return NT_STATUS_NO_SUCH_DOMAIN; @@ -409,20 +461,11 @@ static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CT static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, struct lsa_DnsDomainInfo *info) { - const char * const attrs[] = { "dnsDomain", "objectGUID", "objectSid", NULL }; - int ret; - struct ldb_message **res; - - ret = gendb_search_dn(state->sam_ldb, mem_ctx, state->domain_dn, &res, attrs); - if (ret != 1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - info->name.string = state->domain_name; info->sid = state->domain_sid; - info->dns_domain.string = samdb_result_string(res[0], "dnsDomain", NULL); - info->dns_forest.string = samdb_result_string(res[0], "dnsDomain", NULL); - info->domain_guid = samdb_result_guid(res[0], "objectGUID"); + info->dns_domain.string = state->domain_dns; + info->dns_forest.string = state->domain_dns; + info->domain_guid = state->domain_guid; return NT_STATUS_OK; } @@ -702,10 +745,10 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn); /* create the trusted_domain */ - ret = samdb_add(trusted_domain_state->policy->sam_ldb, mem_ctx, msg); - if (ret != 0) { - DEBUG(0,("Failed to create trusted_domain record %s\n", - ldb_dn_linearize(mem_ctx, msg->dn))); + ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(0,("Failed to create trusted_domain record %s: %s\n", + ldb_dn_linearize(mem_ctx, msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -857,35 +900,81 @@ static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call, } + /* - lsa_QueryTrustedDomainInfoBySid + lsa_SetTrustedDomainInfo */ -static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_QueryTrustedDomainInfoBySid *r) +static NTSTATUS lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_SetTrustedDomainInfo *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } + /* - lsa_SetTrustDomainInfo + lsa_SetInfomrationTrustedDomain */ -static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_SetTrustDomainInfo *r) +static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_SetInformationTrustedDomain *r) { DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } /* - lsa_DeleteTrustDomain + lsa_DeleteTrustedDomain */ -static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_DeleteTrustDomain *r) +static NTSTATUS lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_DeleteTrustedDomain *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + NTSTATUS status; + struct lsa_OpenTrustedDomain open; + struct lsa_Delete delete; + struct dcesrv_handle *h; + + open.in.handle = r->in.handle; + open.in.sid = r->in.dom_sid; + open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle); + if (!open.out.trustdom_handle) { + return NT_STATUS_NO_MEMORY; + } + status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY); + talloc_steal(mem_ctx, h); + + delete.in.handle = open.out.trustdom_handle; + status = lsa_Delete(dce_call, mem_ctx, &delete); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return NT_STATUS_OK; } +static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + struct lsa_TrustDomainInfoInfoEx *info_ex) +{ + info_ex->domain_name.string + = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL); + info_ex->netbios_name.string + = ldb_msg_find_attr_as_string(msg, "flatname", NULL); + info_ex->sid + = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier"); + info_ex->trust_direction + = ldb_msg_find_attr_as_int(msg, "trustDirection", 0); + info_ex->trust_type + = ldb_msg_find_attr_as_int(msg, "trustType", 0); + info_ex->trust_attributes + = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0); + return NT_STATUS_OK; +} /* lsa_QueryTrustedDomainInfo @@ -899,10 +988,12 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T int ret; struct ldb_message **res; const char *attrs[] = { - "cn", - "flatname", - "posixOffset", + "flatname", + "trustPartner", "securityIdentifier", + "trustDirection", + "trustType", + "trustAttributes", NULL }; @@ -931,6 +1022,31 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T r->out.info->posix_offset.posix_offset = samdb_result_uint(msg, "posixOffset", 0); break; +#if 0 /* Win2k3 doesn't implement this */ + case LSA_TRUSTED_DOMAIN_INFO_BASIC: + r->out.info->info_basic.netbios_name.string + = ldb_msg_find_attr_as_string(msg, "flatname", NULL); + r->out.info->info_basic.sid + = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier"); + break; +#endif + case LSA_TRUSTED_DOMAIN_INFO_INFO_EX: + return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex); + + case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO: + ZERO_STRUCT(r->out.info->full_info); + return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex); + + case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL: + ZERO_STRUCT(r->out.info->info_all); + return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex); + + case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO: + case LSA_TRUSTED_DOMAIN_INFO_11: + /* oops, we don't want to return the info after all */ + talloc_free(r->out.info); + r->out.info = NULL; + return NT_STATUS_INVALID_PARAMETER; default: /* oops, we don't want to return the info after all */ talloc_free(r->out.info); @@ -943,23 +1059,40 @@ static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, T /* - lsa_SetInformationTrustedDomain + lsa_QueryTrustedDomainInfoBySid */ -static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct lsa_SetInformationTrustedDomain *r) +static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_QueryTrustedDomainInfoBySid *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); -} - + NTSTATUS status; + struct lsa_OpenTrustedDomain open; + struct lsa_QueryTrustedDomainInfo query; + struct dcesrv_handle *h; + open.in.handle = r->in.handle; + open.in.sid = r->in.dom_sid; + open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle); + if (!open.out.trustdom_handle) { + return NT_STATUS_NO_MEMORY; + } + status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open); + if (!NT_STATUS_IS_OK(status)) { + return status; + } -/* - lsa_QueryTrustedDomainInfoByName -*/ -static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct lsa_QueryTrustedDomainInfoByName *r) -{ - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + /* Ensure this handle goes away at the end of this call */ + DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY); + talloc_steal(mem_ctx, h); + + query.in.trustdom_handle = open.out.trustdom_handle; + query.in.level = r->in.level; + status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + r->out.info = query.out.info; + return NT_STATUS_OK; } /* @@ -972,31 +1105,62 @@ static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_cal DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } -/* - lsa_EnumTrustedDomainsEx +/* + lsa_QueryTrustedDomainInfoByName */ -static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct lsa_EnumTrustedDomainsEx *r) +static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + struct lsa_QueryTrustedDomainInfoByName *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + NTSTATUS status; + struct lsa_OpenTrustedDomainByName open; + struct lsa_QueryTrustedDomainInfo query; + struct dcesrv_handle *h; + open.in.handle = r->in.handle; + open.in.name = r->in.trusted_domain; + open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle); + if (!open.out.trustdom_handle) { + return NT_STATUS_NO_MEMORY; + } + status = lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Ensure this handle goes away at the end of this call */ + DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY); + talloc_steal(mem_ctx, h); + + query.in.trustdom_handle = open.out.trustdom_handle; + query.in.level = r->in.level; + status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + r->out.info = query.out.info; + return NT_STATUS_OK; } /* - lsa_CloseTrustedDomainEx + lsa_CloseTrustedDomainEx */ static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_CloseTrustedDomainEx *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + /* The result of a bad hair day from an IDL programmer? Not + * implmented in Win2k3. You should always just lsa_Close + * anyway. */ + return NT_STATUS_NOT_IMPLEMENTED; } /* comparison function for sorting lsa_DomainInformation array */ -static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2) +static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2) { return strcasecmp(e1->name.string, e2->name.string); } @@ -1008,7 +1172,7 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX struct lsa_EnumTrustDom *r) { struct dcesrv_handle *policy_handle; - struct lsa_DomainInformation *entries; + struct lsa_DomainInfo *entries; struct lsa_policy_state *policy_state; struct ldb_message **domains; const char *attrs[] = { @@ -1040,8 +1204,8 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_OK; } - /* convert to lsa_DomainInformation format */ - entries = talloc_array(mem_ctx, struct lsa_DomainInformation, count); + /* convert to lsa_TrustInformation format */ + entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count); if (!entries) { return NT_STATUS_NO_MEMORY; } @@ -1051,8 +1215,8 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX } /* sort the results by name */ - qsort(entries, count, sizeof(struct lsa_DomainInformation), - (comparison_fn_t)compare_DomainInformation); + qsort(entries, count, sizeof(*entries), + (comparison_fn_t)compare_DomainInfo); if (*r->in.resume_handle >= count) { *r->out.resume_handle = -1; @@ -1077,6 +1241,96 @@ static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_OK; } +/* + comparison function for sorting lsa_DomainInformation array +*/ +static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2) +{ + return strcasecmp(e1->domain_name.string, e2->domain_name.string); +} + +/* + lsa_EnumTrustedDomainsEx +*/ +static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct lsa_EnumTrustedDomainsEx *r) +{ + struct dcesrv_handle *policy_handle; + struct lsa_TrustDomainInfoInfoEx *entries; + struct lsa_policy_state *policy_state; + struct ldb_message **domains; + const char *attrs[] = { + "flatname", + "trustPartner", + "securityIdentifier", + "trustDirection", + "trustType", + "trustAttributes", + NULL + }; + NTSTATUS nt_status; + + 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 = gendb_search(policy_state->sam_ldb, 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(mem_ctx, struct lsa_TrustDomainInfoInfoEx, 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_EX_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; +} + /* return the authority name and authority sid, given a sid @@ -1141,7 +1395,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m domains->domains = talloc_realloc(domains, domains->domains, - struct lsa_TrustInformation, + struct lsa_DomainInfo, domains->count+1); if (domains->domains == NULL) { return NT_STATUS_NO_MEMORY; @@ -1149,6 +1403,7 @@ static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *m domains->domains[i].name.string = authority_name; domains->domains[i].sid = authority_sid; domains->count++; + domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count; *sid_index = i; return NT_STATUS_OK; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index dd6bdf3f6a..29b57ec2b2 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -889,7 +889,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL struct netr_DomainInfo1 *info1; int ret, ret1, ret2, i; NTSTATUS status; - const struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); + const struct ldb_dn *partitions_basedn; const char *local_domain; @@ -904,6 +904,8 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_INVALID_SYSTEM_SERVICE; } + partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); + /* we need to do two searches. The first will pull our primary domain and the second will pull any trusted domains. Our primary domain is also a "trusted" domain, so we need to @@ -1143,7 +1145,7 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, struct ldb_message **dom_res, **ref_res; const char * const dom_attrs[] = { "dnsDomain", "objectSid", "objectGUID", NULL }; const char * const ref_attrs[] = { "nETBIOSName", NULL }; - const struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); + const struct ldb_dn *partitions_basedn; ZERO_STRUCT(r->out); @@ -1152,6 +1154,8 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, return WERR_GENERAL_FAILURE; } + partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); + ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs); if (ret == -1) { return WERR_GENERAL_FAILURE; diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 099dd41430..7395a814e0 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -807,6 +807,26 @@ static BOOL test_DeleteTrustedDomain(struct dcerpc_pipe *p, return True; } +static BOOL test_DeleteTrustedDomainBySid(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + struct dom_sid *sid) +{ + NTSTATUS status; + struct lsa_DeleteTrustedDomain r; + + r.in.handle = handle; + r.in.dom_sid = sid; + + status = dcerpc_lsa_DeleteTrustedDomain(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("lsa_DeleteTrustedDomain failed - %s\n", nt_errstr(status)); + return False; + } + + return True; +} + static BOOL test_CreateSecret(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, @@ -1437,8 +1457,10 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, struct policy_handle trustdom_handle; struct policy_handle handle2; struct lsa_Close c; - int levels [] = {1, 3, 6, 8, 12}; - + struct lsa_CloseTrustedDomainEx c_trust; + int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + int ok[] = {1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1}; + if (domains->domains[i].sid) { trust.in.handle = handle; trust.in.sid = domains->domains[i].sid; @@ -1455,6 +1477,9 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, c.in.handle = &trustdom_handle; c.out.handle = &handle2; + c_trust.in.handle = &trustdom_handle; + c_trust.out.handle = &handle2; + for (j=0; j < ARRAY_SIZE(levels); j++) { struct lsa_QueryTrustedDomainInfo q; union lsa_TrustedDomainInfo info; @@ -1462,18 +1487,32 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && ok[j]) { printf("QueryTrustedDomainInfo level %d failed - %s\n", levels[j], nt_errstr(status)); ret = False; + } else if (NT_STATUS_IS_OK(status) && !ok[j]) { + printf("QueryTrustedDomainInfo level %d unexpectedly succeeded - %s\n", + levels[j], nt_errstr(status)); + ret = False; } } + status = dcerpc_lsa_CloseTrustedDomainEx(p, mem_ctx, &c_trust); + if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + printf("Expected CloseTrustedDomainEx to return NT_STATUS_NOT_IMPLEMENTED, instead - %s\n", nt_errstr(status)); + return False; + } + + c.in.handle = &trustdom_handle; + c.out.handle = &handle2; + 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; @@ -1495,10 +1534,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfo(p, mem_ctx, &q); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && ok[j]) { printf("QueryTrustedDomainInfo level %d failed - %s\n", levels[j], nt_errstr(status)); ret = False; + } else if (NT_STATUS_IS_OK(status) && !ok[j]) { + printf("QueryTrustedDomainInfo level %d unexpectedly succeeded - %s\n", + levels[j], nt_errstr(status)); + ret = False; } } @@ -1524,10 +1567,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && ok[j]) { printf("QueryTrustedDomainInfoBySid level %d failed - %s\n", levels[j], nt_errstr(status)); ret = False; + } else if (NT_STATUS_IS_OK(status) && !ok[j]) { + printf("QueryTrustedDomainInfoBySid level %d unexpectedly succeeded - %s\n", + levels[j], nt_errstr(status)); + ret = False; } } @@ -1539,10 +1586,14 @@ static BOOL test_query_each_TrustDom(struct dcerpc_pipe *p, q.in.level = levels[j]; q.out.info = &info; status = dcerpc_lsa_QueryTrustedDomainInfoByName(p, mem_ctx, &q); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && ok[j]) { printf("QueryTrustedDomainInfoByName level %d failed - %s\n", levels[j], nt_errstr(status)); ret = False; + } else if (NT_STATUS_IS_OK(status) && !ok[j]) { + printf("QueryTrustedDomainInfoByName level %d unexpectedly succeeded - %s\n", + levels[j], nt_errstr(status)); + ret = False; } } } @@ -1554,9 +1605,11 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, struct policy_handle *handle) { struct lsa_EnumTrustDom r; + struct lsa_EnumTrustedDomainsEx r_ex; NTSTATUS enum_status; uint32_t resume_handle = 0; struct lsa_DomainList domains; + struct lsa_DomainListEx domains_ex; BOOL ret = True; printf("\nTesting EnumTrustDom\n"); @@ -1587,14 +1640,43 @@ static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, return False; } - if (lp_parm_bool(-1, "target", "samba4", False)) { - printf("skipping 'each' Trusted Domains tests against Samba4\n"); - } else { - ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains); - } + ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains); } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))); + printf("\nTesting EnumTrustedDomainsEx\n"); + + resume_handle = 0; + do { + r_ex.in.handle = handle; + r_ex.in.resume_handle = &resume_handle; + r_ex.in.max_size = LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER * 3; + r_ex.out.domains = &domains_ex; + r_ex.out.resume_handle = &resume_handle; + + enum_status = dcerpc_lsa_EnumTrustedDomainsEx(p, mem_ctx, &r_ex); + + /* 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_ex.out.domains->count < 3 || r_ex.out.domains->count > 4) { + printf("EnumTrustDom didn't fill the buffer we " + "asked it to (got %d, expected %d / %d == %d entries)\n", + r_ex.out.domains->count, + r_ex.in.max_size, + LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER, + r_ex.in.max_size / LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER); + ret = False; + exit(1); + } + } else if (!NT_STATUS_IS_OK(enum_status)) { + printf("EnumTrustedDomainEx failed - %s\n", nt_errstr(enum_status)); + return False; + } + } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))); + return ret; } @@ -1605,7 +1687,7 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p, NTSTATUS status; BOOL ret = True; struct lsa_CreateTrustedDomain r; - struct lsa_TrustInformation trustinfo; + struct lsa_DomainInfo trustinfo; struct dom_sid *domsid[12]; struct policy_handle trustdom_handle[12]; struct lsa_QueryTrustedDomainInfo q; @@ -1661,7 +1743,7 @@ static BOOL test_CreateTrustedDomain(struct dcerpc_pipe *p, } for (i=0; i<12; i++) { - if (!test_Delete(p, mem_ctx, &trustdom_handle[i])) { + if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) { ret = False; } } @@ -1714,7 +1796,7 @@ static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p, printf("\nTesting QueryInfoPolicy\n"); if (lp_parm_bool(-1, "target", "samba4", False)) { - printf("skipping QueryInfoPolicy2 against Samba4\n"); + printf("skipping QueryInfoPolicy against Samba4\n"); return True; } diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 5b6575893d..66c344bb26 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -1481,7 +1481,7 @@ static BOOL test_ManyGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) dcerpc_server_name(p)); for (i=0; iname.string; diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index 7fe64ebcd1..53abcf5f65 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -337,7 +337,7 @@ static void lsa_lookupsids_recv_names(struct rpc_request *req) for (i=0; inum_sids; i++) { struct lsa_TranslatedName *name = &state->r.out.names->names[i]; - struct lsa_TrustInformation *dom; + struct lsa_DomainInfo *dom; state->result[i] = talloc_zero(state->result, struct wb_sid_object); @@ -494,7 +494,7 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req) for (i=0; inum_names; i++) { struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i]; - struct lsa_TrustInformation *dom; + struct lsa_DomainInfo *dom; state->result[i] = talloc_zero(state->result, struct wb_sid_object); -- cgit