From 749617125e2781168d573e77169fc6f72deeb3e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 3 Sep 2018 09:55:18 +0200 Subject: [PATCH 1/8] s4:torture/rpc/netlogon: assert that cli_credentials_get_{workstation,password} don't return NULL This is better that generating a segfault while dereferencing a NULL pointer later. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit dffc182c6943d21513d8db9f6cf66bdc09206b17) --- source4/torture/rpc/netlogon.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index b3dc06de588a..e9f2757f53c7 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -307,7 +307,9 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx, struct dcerpc_binding_handle *b = p->binding_handle; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge\n"); @@ -377,7 +379,9 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx, uint32_t negotiate_flags = 0; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge\n"); @@ -1255,7 +1259,9 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx, struct dcerpc_binding_handle *b2 = NULL; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); @@ -1334,7 +1340,9 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx, struct dcerpc_binding_handle *b3 = NULL; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); @@ -1429,7 +1437,9 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx, struct dcerpc_binding_handle *b2 = NULL; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); @@ -1517,7 +1527,9 @@ static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx, struct dcerpc_binding_handle *b2 = NULL; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); @@ -1607,7 +1619,9 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx, struct dcerpc_binding_handle *b2 = NULL; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); @@ -1722,7 +1736,9 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx, struct dcerpc_binding_handle *b = p->binding_handle; machine_name = cli_credentials_get_workstation(machine_credentials); + torture_assert(tctx, machine_name != NULL, "machine_name"); plain_pass = cli_credentials_get_password(machine_credentials); + torture_assert(tctx, plain_pass != NULL, "plain_pass"); torture_comment(tctx, "Testing ServerReqChallenge on b1\n"); -- 2.17.1 From f05bbf0379bd1a467a3e3acb5a097dfb9b856c2c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 17:46:46 +0200 Subject: [PATCH 2/8] s4:torture/rpc/netlogon: verify the trusted domains output of LogonGetDomainInfo() This makes sure we don't treat trusted domains in the same way we treat our primary domain. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d5dd8fdc647d6a202c5da0451d395116c2cd92b9) --- selftest/knownfail.d/logon_domain_info | 1 + source4/torture/rpc/netlogon.c | 130 ++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 selftest/knownfail.d/logon_domain_info diff --git a/selftest/knownfail.d/logon_domain_info b/selftest/knownfail.d/logon_domain_info new file mode 100644 index 000000000000..37b32e2fc3e7 --- /dev/null +++ b/selftest/knownfail.d/logon_domain_info @@ -0,0 +1 @@ +^samba4.rpc.netlogon.*netlogon.GetDomainInfo\(ad_dc\) diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index e9f2757f53c7..026d86d50e47 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -4085,9 +4085,13 @@ static bool test_GetDomainInfo(struct torture_context *tctx, const char *old_dnsname = NULL; char **spns = NULL; int num_spns = 0; - char *temp_str; + char *temp_str = NULL; + char *temp_str2 = NULL; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; + struct netr_OneDomainInfo *odi1 = NULL; + struct netr_OneDomainInfo *odi2 = NULL; + struct netr_trust_extension *tex2 = NULL; torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n"); @@ -4464,6 +4468,130 @@ static bool test_GetDomainInfo(struct torture_context *tctx, && (info.domain_info->trusted_domains != NULL), "Trusted domains have been requested!"); + odi1 = &info.domain_info->primary_domain; + + torture_assert(tctx, !GUID_all_zero(&odi1->domain_guid), + "primary domain_guid needs to be valid"); + + for (i=0; i < info.domain_info->trusted_domain_count; i++) { + struct netr_OneDomainInfo *odiT = + &info.domain_info->trusted_domains[i]; + struct netr_trust_extension *texT = NULL; + + torture_assert_int_equal(tctx, odiT->trust_extension.length, 16, + "trust_list should have extension"); + torture_assert(tctx, odiT->trust_extension.info != NULL, + "trust_list should have extension"); + texT = odiT->trust_extension.info; + + if (GUID_equal(&odiT->domain_guid, &odi1->domain_guid)) { + odi2 = odiT; + tex2 = texT; + continue; + } + + torture_assert_int_equal(tctx, + texT->flags & NETR_TRUST_FLAG_PRIMARY, + 0, + "trust_list flags should not have PRIMARY"); + + torture_assert(tctx, odiT->domainname.string != NULL, + "trust_list domainname should be valid"); + if (texT->trust_type == LSA_TRUST_TYPE_DOWNLEVEL) { + torture_assert(tctx, odiT->dns_domainname.string == NULL, + "trust_list dns_domainname should be NULL for downlevel"); + } else { + torture_assert(tctx, odiT->dns_domainname.string != NULL, + "trust_list dns_domainname should be valid for uplevel"); + } + torture_assert(tctx, odiT->dns_forestname.string == NULL, + "trust_list dns_forestname needs to be NULL"); + + torture_assert(tctx, odiT->domain_sid != NULL, + "trust_list domain_sid needs to be valid"); + } + + torture_assert(tctx, odi2 != NULL, + "trust_list primary domain not found."); + + torture_assert_str_equal(tctx, + odi1->domainname.string, + odi2->domainname.string, + "netbios name should match"); + + temp_str = talloc_strdup(tctx, odi1->dns_domainname.string); + torture_assert(tctx, temp_str != NULL, + "primary_domain dns_domainname copy"); + temp_str2 = strrchr(temp_str, '.'); + torture_assert(tctx, temp_str2 != NULL && temp_str2[1] == '\0', + "primary_domain dns_domainname needs trailing '.'"); + temp_str2[0] = '\0'; + torture_assert_str_equal(tctx, + temp_str, + odi2->dns_domainname.string, + "dns domainname should match " + "(without trailing '.')"); + + temp_str = talloc_strdup(tctx, odi1->dns_forestname.string); + torture_assert(tctx, temp_str != NULL, + "primary_domain dns_forestname copy"); + temp_str2 = strrchr(temp_str, '.'); + torture_assert(tctx, temp_str2 != NULL && temp_str2[1] == '\0', + "primary_domain dns_forestname needs trailing '.'"); + temp_str2[0] = '\0'; + torture_assert(tctx, odi2->dns_forestname.string == NULL, + "trust_list dns_forestname needs to be NULL"); + + torture_assert_guid_equal(tctx, odi1->domain_guid, odi2->domain_guid, + "domain_guid should match"); + torture_assert(tctx, odi1->domain_sid != NULL, + "primary domain_sid needs to be valid"); + torture_assert(tctx, odi2->domain_sid != NULL, + "trust_list domain_sid needs to be valid"); + torture_assert_sid_equal(tctx, odi1->domain_sid, odi2->domain_sid, + "domain_sid should match"); + + torture_assert_int_equal(tctx, odi1->trust_extension.length, 0, + "primary_domain should not have extension"); + torture_assert_int_equal(tctx, odi2->trust_extension.length, 16, + "trust_list should have extension"); + torture_assert(tctx, odi2->trust_extension.info != NULL, + "trust_list should have extension"); + tex2 = odi2->trust_extension.info; + torture_assert_int_equal(tctx, + tex2->flags & NETR_TRUST_FLAG_PRIMARY, + NETR_TRUST_FLAG_PRIMARY, + "trust_list flags should have PRIMARY"); + torture_assert_int_equal(tctx, + tex2->flags & NETR_TRUST_FLAG_IN_FOREST, + NETR_TRUST_FLAG_IN_FOREST, + "trust_list flags should have IN_FOREST"); + torture_assert_int_equal(tctx, + tex2->flags & NETR_TRUST_FLAG_NATIVE, + NETR_TRUST_FLAG_NATIVE, + "trust_list flags should have NATIVE"); + torture_assert_int_equal(tctx, + tex2->flags & ~NETR_TRUST_FLAG_TREEROOT, + NETR_TRUST_FLAG_IN_FOREST | + NETR_TRUST_FLAG_PRIMARY | + NETR_TRUST_FLAG_NATIVE, + "trust_list flags IN_FOREST, PRIMARY, NATIVE " + "(TREEROOT optional)"); + if (strcmp(odi1->dns_domainname.string, odi1->dns_forestname.string) == 0) { + torture_assert_int_equal(tctx, + tex2->flags & NETR_TRUST_FLAG_TREEROOT, + NETR_TRUST_FLAG_TREEROOT, + "trust_list flags TREEROOT on forest root"); + torture_assert_int_equal(tctx, + tex2->parent_index, 0, + "trust_list no parent on foreset root"); + } + torture_assert_int_equal(tctx, + tex2->trust_type, LSA_TRUST_TYPE_UPLEVEL, + "trust_list uplevel"); + torture_assert_int_equal(tctx, + tex2->trust_attributes, 0, + "trust_list no attributes"); torture_comment(tctx, "Testing netr_LogonGetDomainInfo 6th call (no DNS hostname)\n"); netlogon_creds_client_authenticator(creds, &a); -- 2.17.1 From a2d4e46e7b849010f8b3f3caf193f9e049ccd2a1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 1 Feb 2018 23:08:08 +0100 Subject: [PATCH 3/8] dsdb/util_trusts: domain_dn is an input parameter of dsdb_trust_crossref_tdo_info() We should not overwrite it within the function. Currently it doesn't matter as we don't have multiple domains within our forest, but that will change in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit f5f96f558b499770cdeb3d38998167a387e058b9) --- source4/dsdb/common/util_trusts.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source4/dsdb/common/util_trusts.c b/source4/dsdb/common/util_trusts.c index a083d869f6eb..bb34aa1054be 100644 --- a/source4/dsdb/common/util_trusts.c +++ b/source4/dsdb/common/util_trusts.c @@ -481,12 +481,6 @@ static NTSTATUS dsdb_trust_crossref_tdo_info(TALLOC_CTX *mem_ctx, *_trust_parent_tdo = NULL; } - domain_dn = ldb_get_default_basedn(sam_ctx); - if (domain_dn == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_INTERNAL_ERROR; - } - partitions_dn = samdb_partitions_dn(sam_ctx, frame); if (partitions_dn == NULL) { TALLOC_FREE(frame); -- 2.17.1 From aab69a9c9e07140b2edd7aed9123a35d95628782 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 1 Feb 2018 23:09:26 +0100 Subject: [PATCH 4/8] 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. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c1b0ac95db5c6112d90356c7ada8c3d445e9b668) --- 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 bb34aa1054be..fd3c549ff980 100644 --- a/source4/dsdb/common/util_trusts.c +++ b/source4/dsdb/common/util_trusts.c @@ -827,6 +827,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 b8506b90f7a17b5e4065db4bb6e446e16d7702c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 11:52:27 +0200 Subject: [PATCH 5/8] s4:dsdb/common: add samdb_domain_guid() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 0e442e094240abbf79aaca00a9d1a053a200a7e8) --- 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 cecef81e8cf8..1724d2a807e4 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1294,6 +1294,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 = NULL; + struct GUID *domain_guid = NULL; + const char *attrs[] = { + "objectGUID", + NULL + }; + struct ldb_result *res = NULL; + 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 853ae85c8a77718cbe27aa298c4c204955bfea35 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 11:46:16 +0200 Subject: [PATCH 6/8] s4:rpc_server/netlogon: use samdb_domain_guid()/dsdb_trust_local_tdo_info() to build our netr_OneDomainInfo values The logic for constructing the values for our own primary domain differs from the values of trusted domains. In order to make the code easier to understand we have a new fill_our_one_domain_info() helper that only takes care of our primary domain. The cleanup for the trust case will follow in a separate commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 61333f7787d78e3ec5c7bd2874d5a0f1f536275a) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 109 +++++++++++++++--- 1 file changed, 91 insertions(+), 18 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 2ed0840c6409..71ab942ae9ba 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1961,6 +1961,71 @@ 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; + /* + * 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; + } + + 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 */ @@ -2034,7 +2099,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; @@ -2249,17 +2316,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) { @@ -2273,11 +2339,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, @@ -2294,10 +2363,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->trusted_domains[i], + 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 b8e2168565b996090086005b83781a26933d14ec Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 16:30:17 +0200 Subject: [PATCH 7/8] s4:rpc_server/netlogon: make use of talloc_zero_array() for the netr_OneDomainInfo array It's much safer than having uninitialized memory when we hit an error case. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit ef0b489ad0d93199e08415dd895da5cfe2d1c11a) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 71ab942ae9ba..12d6bcd14c26 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2349,7 +2349,7 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal } domain_info->trusted_domain_count = ret3 + 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); -- 2.17.1 From 40f47098aa1687ad51b56749023679412cd09272 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Aug 2018 12:52:31 +0200 Subject: [PATCH 8/8] s4:rpc_server/netlogon: don't treet trusted domains as primary in LogonGetDomainInfo() We need to handle trusted domains differently than our primary domain. The most important part is that we don't return NETR_TRUST_FLAG_PRIMARY for them. NETR_TRUST_FLAG_{INBOUND,OUTBOUND,IN_FOREST} are the relavant flags for trusts. This is an example of what Windows returns in a complex trust environment: netr_LogonGetDomainInfo: struct netr_LogonGetDomainInfo out: struct netr_LogonGetDomainInfo return_authenticator : * return_authenticator: struct netr_Authenticator cred: struct netr_Credential data : f48b51ff12ff8c6c timestamp : Tue Aug 28 22:59:03 2018 CEST info : * info : union netr_DomainInfo(case 1) domain_info : * domain_info: struct netr_DomainInformation primary_domain: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x0014 (20) size : 0x0016 (22) string : * string : 'W2012R2-L4' dns_domainname: struct lsa_StringLarge length : 0x0020 (32) size : 0x0022 (34) string : * string : 'w2012r2-l4.base.' dns_forestname: struct lsa_StringLarge length : 0x0020 (32) size : 0x0022 (34) string : * string : 'w2012r2-l4.base.' domain_guid : 0a133c91-8eac-4df0-96ac-ede69044a38b domain_sid : * domain_sid : S-1-5-21-2930975464-1937418634-1288008815 trust_extension: struct netr_trust_extension_container length : 0x0000 (0) size : 0x0000 (0) info : NULL dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domain_count : 0x00000006 (6) trusted_domains : * trusted_domains: ARRAY(6) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x000e (14) size : 0x0010 (16) string : * string : 'FREEIPA' dns_domainname: struct lsa_StringLarge length : 0x0018 (24) size : 0x001a (26) string : * string : 'freeipa.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : 00000000-0000-0000-0000-000000000000 domain_sid : * domain_sid : S-1-5-21-429948374-2562621466-335716826 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x00000022 (34) 0: NETR_TRUST_FLAG_IN_FOREST 1: NETR_TRUST_FLAG_OUTBOUND 0: NETR_TRUST_FLAG_TREEROOT 0: NETR_TRUST_FLAG_PRIMARY 0: NETR_TRUST_FLAG_NATIVE 1: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000000 (0) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000008 (8) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 1: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x0016 (22) size : 0x0018 (24) string : * string : 'S1-W2012-L4' dns_domainname: struct lsa_StringLarge length : 0x0036 (54) size : 0x0038 (56) string : * string : 's1-w2012-l4.w2012r2-l4.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : afe7fbde-af82-46cf-88a2-2df6920fc33e domain_sid : * domain_sid : S-1-5-21-1368093395-3821428921-3924672915 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x00000023 (35) 1: NETR_TRUST_FLAG_IN_FOREST 1: NETR_TRUST_FLAG_OUTBOUND 0: NETR_TRUST_FLAG_TREEROOT 0: NETR_TRUST_FLAG_PRIMARY 0: NETR_TRUST_FLAG_NATIVE 1: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000004 (4) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000020 (32) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 0: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 1: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x0006 (6) size : 0x0008 (8) string : * string : 'BLA' dns_domainname: struct lsa_StringLarge length : 0x0010 (16) size : 0x0012 (18) string : * string : 'bla.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : 00000000-0000-0000-0000-000000000000 domain_sid : * domain_sid : S-1-5-21-4053568372-2049667917-3384589010 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x00000022 (34) 0: NETR_TRUST_FLAG_IN_FOREST 1: NETR_TRUST_FLAG_OUTBOUND 0: NETR_TRUST_FLAG_TREEROOT 0: NETR_TRUST_FLAG_PRIMARY 0: NETR_TRUST_FLAG_NATIVE 1: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000000 (0) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000008 (8) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 1: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x000c (12) size : 0x000e (14) string : * string : 'S4XDOM' dns_domainname: struct lsa_StringLarge length : 0x0016 (22) size : 0x0018 (24) string : * string : 's4xdom.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : 00000000-0000-0000-0000-000000000000 domain_sid : * domain_sid : S-1-5-21-313966788-4060240134-2249344781 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x00000022 (34) 0: NETR_TRUST_FLAG_IN_FOREST 1: NETR_TRUST_FLAG_OUTBOUND 0: NETR_TRUST_FLAG_TREEROOT 0: NETR_TRUST_FLAG_PRIMARY 0: NETR_TRUST_FLAG_NATIVE 1: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000000 (0) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000008 (8) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 1: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x0014 (20) size : 0x0016 (22) string : * string : 'W2012R2-L4' dns_domainname: struct lsa_StringLarge length : 0x001e (30) size : 0x0020 (32) string : * string : 'w2012r2-l4.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : 0a133c91-8eac-4df0-96ac-ede69044a38b domain_sid : * domain_sid : S-1-5-21-2930975464-1937418634-1288008815 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x0000001d (29) 1: NETR_TRUST_FLAG_IN_FOREST 0: NETR_TRUST_FLAG_OUTBOUND 1: NETR_TRUST_FLAG_TREEROOT 1: NETR_TRUST_FLAG_PRIMARY 1: NETR_TRUST_FLAG_NATIVE 0: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000000 (0) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000000 (0) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 0: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) trusted_domains: struct netr_OneDomainInfo domainname: struct lsa_StringLarge length : 0x0016 (22) size : 0x0018 (24) string : * string : 'S2-W2012-L4' dns_domainname: struct lsa_StringLarge length : 0x004e (78) size : 0x0050 (80) string : * string : 's2-w2012-l4.s1-w2012-l4.w2012r2-l4.base' dns_forestname: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL domain_guid : 29daace6-cded-4ce3-a754-7482a4d9127c domain_sid : * domain_sid : S-1-5-21-167342819-981449877-2130266853 trust_extension: struct netr_trust_extension_container length : 0x0010 (16) size : 0x0010 (16) info : * info: struct netr_trust_extension length : 0x00000008 (8) dummy : 0x00000000 (0) size : 0x00000008 (8) flags : 0x00000001 (1) 1: NETR_TRUST_FLAG_IN_FOREST 0: NETR_TRUST_FLAG_OUTBOUND 0: NETR_TRUST_FLAG_TREEROOT 0: NETR_TRUST_FLAG_PRIMARY 0: NETR_TRUST_FLAG_NATIVE 0: NETR_TRUST_FLAG_INBOUND 0: NETR_TRUST_FLAG_MIT_KRB5 0: NETR_TRUST_FLAG_AES parent_index : 0x00000001 (1) trust_type : LSA_TRUST_TYPE_UPLEVEL (2) trust_attributes : 0x00000000 (0) 0: LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY 0: LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 0: LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE 0: LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION 0: LSA_TRUST_ATTRIBUTE_WITHIN_FOREST 0: LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL 0: LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_long1 : 0x00000000 (0) dummy_long2 : 0x00000000 (0) dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) lsa_policy: struct netr_LsaPolicyInformation policy_size : 0x00000000 (0) policy : NULL dns_hostname: struct lsa_StringLarge length : 0x0036 (54) size : 0x0038 (56) string : * string : 'torturetest.w2012r2-l4.base' dummy_string2: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string3: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL dummy_string4: struct lsa_StringLarge length : 0x0000 (0) size : 0x0000 (0) string : NULL workstation_flags : 0x00000003 (3) 1: NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS 1: NETR_WS_FLAG_HANDLES_SPN_UPDATE supported_enc_types : 0x0000001f (31) 1: KERB_ENCTYPE_DES_CBC_CRC 1: KERB_ENCTYPE_DES_CBC_MD5 1: KERB_ENCTYPE_RC4_HMAC_MD5 1: KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 1: KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 0: KERB_ENCTYPE_FAST_SUPPORTED 0: KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED 0: KERB_ENCTYPE_CLAIMS_SUPPORTED 0: KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED dummy_long3 : 0x00000000 (0) dummy_long4 : 0x00000000 (0) result : NT_STATUS_OK Best viewed with: git show --histogram -w BUG: https://bugzilla.samba.org/show_bug.cgi?id=11517 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 2099add0657126e4a5427ec2db0fe8025478b355) --- selftest/knownfail.d/logon_domain_info | 1 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 139 +++++++++++------- 2 files changed, 82 insertions(+), 58 deletions(-) delete mode 100644 selftest/knownfail.d/logon_domain_info diff --git a/selftest/knownfail.d/logon_domain_info b/selftest/knownfail.d/logon_domain_info deleted file mode 100644 index 37b32e2fc3e7..000000000000 --- a/selftest/knownfail.d/logon_domain_info +++ /dev/null @@ -1 +0,0 @@ -^samba4.rpc.netlogon.*netlogon.GetDomainInfo\(ad_dc\) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 12d6bcd14c26..007785a1ad7d 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -2027,57 +2027,57 @@ 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, + struct GUID domain_guid, + 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 (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { + tei->flags |= NETR_TRUST_FLAG_IN_FOREST; } - 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"); + /* + * 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; + if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) { + info->dns_domainname.string = tdo->domain_name.string; } 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); + info->dns_domainname.string = NULL; } + info->domain_sid = tdo->sid; + info->domain_guid = domain_guid; + + /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */ + info->dns_forestname.string = NULL; return NT_STATUS_OK; } @@ -2093,21 +2093,29 @@ 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; 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, @@ -2326,10 +2334,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 */ + trusts_attrs, + mem_ctx, + &trusts_res); + if (!NT_STATUS_IS_OK(status)) { + return status; } domain_info = talloc(mem_ctx, struct netr_DomainInformation); @@ -2348,19 +2359,33 @@ 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_zero_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]; + /* we can't know the guid of trusts outside our forest */ + struct GUID trust_domain_guid = GUID_zero(); + 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, + trust_domain_guid, + tdo, + o); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } status = fill_our_one_domain_info(mem_ctx, -- 2.17.1