From 643e120a5f226e01c0d89d7d39d29f8b354b3fff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 1 Feb 2018 23:09:26 +0100 Subject: [PATCH 1/6] dsdb:util_trusts: add dsdb_trust_local_tdo_info() helper function This is similar to dsdb_trust_xref_tdo_info(), but will also work if we ever support more than one domain in our forest. Signed-off-by: Stefan Metzmacher (cherry picked from commit 44593ecdd6767480061f6fef014a9eff22893655) --- source4/dsdb/common/util_trusts.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source4/dsdb/common/util_trusts.c b/source4/dsdb/common/util_trusts.c index 7dcbea2ce6d6..7ee0316dca9e 100644 --- a/source4/dsdb/common/util_trusts.c +++ b/source4/dsdb/common/util_trusts.c @@ -834,6 +834,22 @@ static bool dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation return false; } +NTSTATUS dsdb_trust_local_tdo_info(TALLOC_CTX *mem_ctx, + struct ldb_context *sam_ctx, + struct lsa_TrustDomainInfoInfoEx **_tdo) +{ + struct ldb_dn *domain_dn = NULL; + + domain_dn = ldb_get_default_basedn(sam_ctx); + if (domain_dn == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } + + return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx, + domain_dn, NULL, + _tdo, NULL, NULL); +} + NTSTATUS dsdb_trust_xref_tdo_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, struct lsa_TrustDomainInfoInfoEx **_tdo) -- 2.17.1 From 3817e413126a1beed5f59c55390f0877428b76be Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 11:52:27 +0200 Subject: [PATCH 2/6] samdb_domain_guid() --- source4/dsdb/common/util.c | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 36c98df24b36..02cba7bc8075 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1296,6 +1296,61 @@ failed: return false; } +/* + work out the domain guid for the current open ldb +*/ +const struct GUID *samdb_domain_guid(struct ldb_context *ldb) +{ + TALLOC_CTX *tmp_ctx; + struct GUID *domain_guid = NULL; + const char *attrs[] = { + "objectGUID", + NULL + }; + struct ldb_result *res; + int ret; + + /* see if we have a cached copy */ + domain_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.domain_guid"); + if (domain_guid) { + return domain_guid; + } + + tmp_ctx = talloc_new(ldb); + if (tmp_ctx == NULL) { + goto failed; + } + + ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectGUID=*"); + if (ret != LDB_SUCCESS) { + goto failed; + } + + if (res->count != 1) { + goto failed; + } + + domain_guid = talloc(tmp_ctx, struct GUID); + if (domain_guid == NULL) { + goto failed; + } + *domain_guid = samdb_result_guid(res->msgs[0], "objectGUID"); + + /* cache the domain_sid in the ldb */ + if (ldb_set_opaque(ldb, "cache.domain_guid", domain_guid) != LDB_SUCCESS) { + goto failed; + } + + talloc_steal(ldb, domain_guid); + talloc_free(tmp_ctx); + + return domain_guid; + +failed: + talloc_free(tmp_ctx); + return NULL; +} + bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in) { TALLOC_CTX *tmp_ctx; -- 2.17.1 From 0d2b82c92778d4f3ca6b4087e1f2e5fe97e84d62 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 11:46:16 +0200 Subject: [PATCH 3/6] fill_our_one_domain_info --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 104 +++++++++++++++--- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index b4046bdd2037..d98251b0e37d 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2191,6 +2191,66 @@ static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TAL } +/* + fill in a netr_OneDomainInfo from our own domain/forest +*/ +static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx, + const struct lsa_TrustDomainInfoInfoEx *our_tdo, + struct GUID domain_guid, + struct netr_OneDomainInfo *info, + bool is_trust_list) +{ + ZERO_STRUCTP(info); + + if (is_trust_list) { + struct netr_trust_extension *tei = NULL; + + /* w2k8 only fills this on trusted domains */ + tei = talloc_zero(mem_ctx, struct netr_trust_extension); + if (tei == NULL) { + return NT_STATUS_NO_MEMORY; + } + tei->flags |= NETR_TRUST_FLAG_PRIMARY; + + /* + * We're always within a native forest + */ + tei->flags |= NETR_TRUST_FLAG_IN_FOREST; + tei->flags |= NETR_TRUST_FLAG_NATIVE; + + /* For now we assume we're always the tree root */ + tei->flags |= NETR_TRUST_FLAG_TREEROOT; + tei->parent_index = 0; + + tei->trust_type = our_tdo->trust_type; + tei->trust_attributes = our_tdo->trust_attributes; + + info->trust_extension.info = tei; + info->trust_extension.length = 16; + } + + if (is_trust_list) { + info->dns_domainname.string = our_tdo->domain_name.string; + + /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ + info->dns_forestname.string = NULL; + } else { + info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", + our_tdo->domain_name.string); + if (info->dns_domainname.string == NULL) { + return NT_STATUS_NO_MEMORY; + } + + info->dns_forestname.string = info->dns_domainname.string; + } + + info->domainname.string = our_tdo->netbios_name.string; + info->domain_sid = our_tdo->sid; + info->domain_guid = domain_guid; + + return NT_STATUS_OK; +} + /* fill in a netr_OneDomainInfo from a ldb search result */ @@ -2264,7 +2324,9 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal "msDS-SupportedEncryptionTypes", NULL }; const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2; struct ldb_context *sam_ctx; - struct ldb_message **res1, **res2, **res3, *new_msg; + const struct GUID *our_domain_guid = NULL; + struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL; + struct ldb_message **res1, **res3, *new_msg; struct ldb_dn *workstation_dn; struct netr_DomainInformation *domain_info; struct netr_LsaPolicyInformation *lsa_policy_info; @@ -2482,17 +2544,16 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal /* Writes back the domain information */ - /* 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 - put the primary domain into the lists of returned trusts as - well. */ - ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx), - &res2, attrs); - if (ret != 1) { + our_domain_guid = samdb_domain_guid(sam_ctx); + if (our_domain_guid == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } + status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs, "(objectClass=trustedDomain)"); if (ret3 == -1) { @@ -2506,11 +2567,14 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal /* Informations about the local and trusted domains */ - status = fill_one_domain_info(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, - sam_ctx, res2[0], &domain_info->primary_domain, - true, false); - NT_STATUS_NOT_OK_RETURN(status); + status = fill_our_one_domain_info(mem_ctx, + our_tdo, + *our_domain_guid, + &domain_info->primary_domain, + false); + if (!NT_STATUS_IS_OK(status)) { + return status; + } domain_info->trusted_domain_count = ret3 + 1; domain_info->trusted_domains = talloc_array(mem_ctx, @@ -2527,10 +2591,14 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal NT_STATUS_NOT_OK_RETURN(status); } - status = fill_one_domain_info(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0], - &domain_info->trusted_domains[i], true, true); - NT_STATUS_NOT_OK_RETURN(status); + status = fill_our_one_domain_info(mem_ctx, + our_tdo, + *our_domain_guid, + &domain_info->primary_domain, + true); + if (!NT_STATUS_IS_OK(status)) { + return status; + } /* Sets the supported encryption types */ domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0], -- 2.17.1 From 36b344ba1658b02e5618a1890b0b1474f8626590 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 12:52:31 +0200 Subject: [PATCH 4/6] fill_trust_one_domain_info --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 130 ++++++++++-------- 1 file changed, 75 insertions(+), 55 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index d98251b0e37d..628b3edb516d 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2252,58 +2252,65 @@ static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx, } /* - fill in a netr_OneDomainInfo from a ldb search result + fill in a netr_OneDomainInfo from a trust tdo */ -static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx, - struct loadparm_context *lp_ctx, - struct ldb_context *sam_ctx, - struct ldb_message *res, - struct netr_OneDomainInfo *info, - bool is_local, bool is_trust_list) +static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx, + const struct lsa_TrustDomainInfoInfoEx *tdo, + struct netr_OneDomainInfo *info) { - ZERO_STRUCTP(info); + struct netr_trust_extension *tei = NULL; - if (is_trust_list) { - /* w2k8 only fills this on trusted domains */ - info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension); - info->trust_extension.length = 16; - info->trust_extension.info->flags = - NETR_TRUST_FLAG_TREEROOT | - NETR_TRUST_FLAG_IN_FOREST | - NETR_TRUST_FLAG_PRIMARY | - NETR_TRUST_FLAG_NATIVE; + ZERO_STRUCTP(info); - info->trust_extension.info->parent_index = 0; /* should be index into array - of parent */ - info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */ - info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */ + /* w2k8 only fills this on trusted domains */ + tei = talloc_zero(mem_ctx, struct netr_trust_extension); + if (tei == NULL) { + return NT_STATUS_NO_MEMORY; } - if (is_trust_list) { - /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ - info->dns_forestname.string = NULL; - } else { - info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx); - NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string); - info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string); - NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string); + if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) { + tei->flags |= NETR_TRUST_FLAG_INBOUND; + } + if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) { + tei->flags |= NETR_TRUST_FLAG_OUTBOUND; } - if (is_local) { - info->domainname.string = lpcfg_workgroup(lp_ctx); - info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx); - info->domain_guid = samdb_result_guid(res, "objectGUID"); - info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid"); + /* + * We only assume trusts outside of our forest ... + */ + if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { + /* + * We're always within a native forest + */ + tei->flags |= NETR_TRUST_FLAG_IN_FOREST; + tei->flags |= NETR_TRUST_FLAG_NATIVE; } else { - info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL); - info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL); - info->domain_guid = samdb_result_guid(res, "objectGUID"); - info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier"); - } - if (!is_trust_list) { - info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string); + tei->parent_index = 0; } + /* + * TODO: once we support multiple domains within our forest, + * we need to fill this correct (or let the caller do it + * for all domains marked with NETR_TRUST_FLAG_IN_FOREST). + */ + tei->parent_index = 0; + + tei->trust_type = tdo->trust_type; + tei->trust_attributes = tdo->trust_attributes; + + info->trust_extension.info = tei; + info->trust_extension.length = 16; + + info->domainname.string = tdo->netbios_name.string; + info->dns_domainname.string = tdo->domain_name.string; + info->domain_sid = tdo->sid; + + /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ + info->dns_forestname.string = NULL; + + /* we can't know the guid of trusts outside our forest */ + info->domain_guid = GUID_zero(); + return NT_STATUS_OK; } @@ -2326,13 +2333,14 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal struct ldb_context *sam_ctx; const struct GUID *our_domain_guid = NULL; struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL; - struct ldb_message **res1, **res3, *new_msg; + struct ldb_message **res1, *new_msg; + struct ldb_result *trusts_res = NULL; struct ldb_dn *workstation_dn; struct netr_DomainInformation *domain_info; struct netr_LsaPolicyInformation *lsa_policy_info; uint32_t default_supported_enc_types = 0xFFFFFFFF; bool update_dns_hostname = true; - int ret, ret3, i; + int ret, i; NTSTATUS status; status = dcesrv_netr_creds_server_step_check(dce_call, @@ -2554,10 +2562,13 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal return status; } - ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs, - "(objectClass=trustedDomain)"); - if (ret3 == -1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; + status = dsdb_trust_search_tdos(sam_ctx, + NULL, /* exclude */ + attrs, + mem_ctx, + &trusts_res); + if (!NT_STATUS_IS_OK(status)) { + return status; } domain_info = talloc(mem_ctx, struct netr_DomainInformation); @@ -2576,19 +2587,28 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal return status; } - domain_info->trusted_domain_count = ret3 + 1; + domain_info->trusted_domain_count = trusts_res->count + 1; domain_info->trusted_domains = talloc_array(mem_ctx, struct netr_OneDomainInfo, domain_info->trusted_domain_count); NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains); - for (i=0;iconn->dce_ctx->lp_ctx, - sam_ctx, res3[i], - &domain_info->trusted_domains[i], - false, true); - NT_STATUS_NOT_OK_RETURN(status); + for (i=0; i < trusts_res->count; i++) { + struct netr_OneDomainInfo *o = + &domain_info->trusted_domains[i]; + struct lsa_TrustDomainInfoInfoEx *tdo = NULL; + + status = dsdb_trust_parse_tdo_info(mem_ctx, + trusts_res->msgs[i], + &tdo); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = fill_trust_one_domain_info(mem_ctx, tdo, o); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } status = fill_our_one_domain_info(mem_ctx, -- 2.17.1 From 8848fd4bb4f6cbbfd36f1c404d58d17be454b0b0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 13:28:04 +0200 Subject: [PATCH 5/6] fixes... --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 628b3edb516d..eb6ba2b82fdf 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2325,8 +2325,15 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r) { struct netlogon_creds_CredentialState *creds; - const char * const attrs[] = { "objectSid", "objectGUID", "flatName", - "securityIdentifier", "trustPartner", NULL }; + const char * const trusts_attrs[] = { + "securityIdentifier", + "flatName", + "trustPartner", + "trustAttributes", + "trustDirection", + "trustType", + NULL + }; const char * const attrs2[] = { "sAMAccountName", "dNSHostName", "msDS-SupportedEncryptionTypes", NULL }; const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2; @@ -2564,7 +2571,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal status = dsdb_trust_search_tdos(sam_ctx, NULL, /* exclude */ - attrs, + trusts_attrs, mem_ctx, &trusts_res); if (!NT_STATUS_IS_OK(status)) { @@ -2588,7 +2595,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal } domain_info->trusted_domain_count = trusts_res->count + 1; - domain_info->trusted_domains = talloc_array(mem_ctx, + domain_info->trusted_domains = talloc_zero_array(mem_ctx, struct netr_OneDomainInfo, domain_info->trusted_domain_count); NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains); @@ -2614,7 +2621,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal status = fill_our_one_domain_info(mem_ctx, our_tdo, *our_domain_guid, - &domain_info->primary_domain, + &domain_info->trusted_domains[i], true); if (!NT_STATUS_IS_OK(status)) { return status; -- 2.17.1 From 2a81a24378c05c433d60af1a2365f5e8367cd951 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 13:36:12 +0200 Subject: [PATCH 6/6] match windows... --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index eb6ba2b82fdf..cbc8c808c37b 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2223,7 +2223,12 @@ static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx, tei->parent_index = 0; tei->trust_type = our_tdo->trust_type; - tei->trust_attributes = our_tdo->trust_attributes; + /* + * This needs to be 0 instead of our_tdo->trust_attributes + * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't + * be set, while NETR_TRUST_FLAG_IN_FOREST is set above. + */ + tei->trust_attributes = 0; info->trust_extension.info = tei; info->trust_extension.length = 16; @@ -2302,7 +2307,11 @@ static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx, info->trust_extension.length = 16; info->domainname.string = tdo->netbios_name.string; - info->dns_domainname.string = tdo->domain_name.string; + if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) { + info->dns_domainname.string = tdo->domain_name.string; + } else { + info->dns_domainname.string = NULL; + } info->domain_sid = tdo->sid; /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ -- 2.17.1