From 442b961b7b457889400a84ca9fd082998eb0a178 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Feb 2025 20:03:56 +0100 Subject: [PATCH] s4:rpc_server/netlogon: let dcesrv_netr_NTLMv2_RESPONSE_verify generate trust_forest_domain_info array MS-NRPC 3.5.4.5.1.1 Pass-through domain name validation, requires to pass information about the trust topology to NTLMv2_RESPONSE_verify_netlogon_creds()... Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index e1d66a86cdf..f9919466ba4 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1427,6 +1427,127 @@ static NTSTATUS dcesrv_netr_NTLMv2_RESPONSE_verify( size_t num_trusts = 0; struct trust_forest_domain_info *trusts = NULL; + if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN || + creds->secure_channel_type == SEC_CHAN_DOMAIN) + { + static const char * const trust_attrs[] = { + "objectGUID", + "securityIdentifier", + "flatName", + "trustPartner", + "trustType", + "trustAttributes", + "trustDirection", + "msDS-TrustForestTrustInfo", + NULL + }; + struct trust_forest_domain_info *remote_d = NULL; + struct ldb_result *trusts_res = NULL; + struct ldb_context *sam_ctx = NULL; + size_t ti; + + sam_ctx = dcesrv_samdb_connect_as_system(frame, + dce_call); + if (sam_ctx == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_DS_UNAVAILABLE; + } + + /* fetch all trusted domain objects */ + status = dsdb_trust_search_tdos(sam_ctx, + NULL, + trust_attrs, + frame, + &trusts_res); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + trusts = talloc_zero_array(frame, + struct trust_forest_domain_info, + trusts_res->count + 1); + if (trusts == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + /* + * information about our own forest/domain + */ + status = dsdb_trust_local_tdo_info(trusts, + sam_ctx, + &trusts[0].tdo); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + status = dsdb_trust_xref_forest_info(trusts, + sam_ctx, + &trusts[0].fti); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + trusts[0].is_local_forest = true; + + for (ti = 0; ti < trusts_res->count; ti++) { + struct trust_forest_domain_info *d = + &trusts[ti+1]; + struct ldb_message *msg = trusts_res->msgs[ti]; + struct ForestTrustInfo *fti = NULL; + struct GUID tdo_guid; + + tdo_guid = samdb_result_guid(msg, "objectGUID"); + + status = dsdb_trust_parse_tdo_info(trusts, + msg, + &d->tdo); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = dsdb_trust_parse_forest_info(trusts, + msg, + &fti); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { + fti = NULL; + status = NT_STATUS_OK; + } + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + if (fti != NULL) { + status = trust_forest_info_to_lsa2(trusts, + fti, + &d->fti); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + } + + if (GUID_equal(&creds->tdo_guid, &tdo_guid)) { + d->is_checked_trust = true; + remote_d = d; + } + } + + if (remote_d == NULL) { + /* + * We should at least find the tdo + * of the remote domain + */ + TALLOC_FREE(frame); + return NT_STATUS_TRUSTED_DOMAIN_FAILURE; + } + + num_trusts = trusts_res->count + 1; + } + status = NTLMv2_RESPONSE_verify_netlogon_creds( user_info->client.account_name, user_info->client.domain_name, -- 2.47.2