From 801d299067c1ad8e9e63e0c675a4d1284de2f85c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 3 Apr 2013 16:52:45 +0300 Subject: [PATCH 4/4] s3-netlogon: enumerate UPN suffixes from PASSDB when available Optionally append list of UPN suffixes if PDB module returns non-empty one. Refactor fill_forest_trust_array() in source3 to allow reuse of the code between _netr_DsRGetForestTrustInformation() and _netr_GetForestTrustInformation() Implement a special case of _netr_DsRGetForestTrustInformation in smbd when trusted_domain_name is NULL (covered by test_DsrEnumerateDomainTrusts() in rpc.netlogon torture tests, see comment in source4/torture/rpc/netlogon.c). Reviewed-by: Andreas Schneider Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Tue Apr 9 22:19:34 CEST 2013 on sn-devel-104 --- source3/rpc_server/netlogon/srv_netlog_nt.c | 106 ++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 12 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 9b50655..c45f33f 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -2309,22 +2309,16 @@ NTSTATUS _netr_ServerTrustPasswordsGet(struct pipes_struct *p, /**************************************************************** ****************************************************************/ -WERROR _netr_DsRGetForestTrustInformation(struct pipes_struct *p, - struct netr_DsRGetForestTrustInformation *r) -{ - p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; - return WERR_NOT_SUPPORTED; -} - -/**************************************************************** -****************************************************************/ - static NTSTATUS fill_forest_trust_array(TALLOC_CTX *mem_ctx, struct lsa_ForestTrustInformation *info) { struct lsa_ForestTrustRecord *e; struct pdb_domain_info *dom_info; struct lsa_ForestTrustDomainInfo *domain_info; + char **upn_suffixes = NULL; + uint32_t num_suffixes = 0; + uint32_t i = 0; + NTSTATUS status; dom_info = pdb_get_domain_info(mem_ctx); if (dom_info == NULL) { @@ -2332,7 +2326,15 @@ static NTSTATUS fill_forest_trust_array(TALLOC_CTX *mem_ctx, } info->count = 2; - info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2); + + become_root(); + status = pdb_enum_upn_suffixes(info, &num_suffixes, &upn_suffixes); + unbecome_root(); + if (NT_STATUS_IS_OK(status) && (num_suffixes > 0)) { + info->count += num_suffixes; + } + + info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, info->count); if (info->entries == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2350,6 +2352,21 @@ static NTSTATUS fill_forest_trust_array(TALLOC_CTX *mem_ctx, info->entries[0] = e; + if (num_suffixes > 0) { + for (i = 0; i < num_suffixes ; i++) { + e = talloc(info, struct lsa_ForestTrustRecord); + if (e == NULL) { + return NT_STATUS_NO_MEMORY; + } + + e->flags = 0; + e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME; + e->time = 0; /* so far always 0 in traces. */ + e->forest_trust_data.top_level_name.string = upn_suffixes[i]; + info->entries[1 + i] = e; + } + } + e = talloc(info, struct lsa_ForestTrustRecord); if (e == NULL) { return NT_STATUS_NO_MEMORY; @@ -2368,12 +2385,76 @@ static NTSTATUS fill_forest_trust_array(TALLOC_CTX *mem_ctx, domain_info->netbios_domain_name.string = talloc_steal(info, dom_info->name); - info->entries[1] = e; + info->entries[info->count - 1] = e; return NT_STATUS_OK; } /**************************************************************** +****************************************************************/ + +WERROR _netr_DsRGetForestTrustInformation(struct pipes_struct *p, + struct netr_DsRGetForestTrustInformation *r) +{ + NTSTATUS status; + struct lsa_ForestTrustInformation *info, **info_ptr; + + if (!(p->pipe_bound && (p->auth.auth_type != DCERPC_AUTH_TYPE_NONE) + && (p->auth.auth_level != DCERPC_AUTH_LEVEL_NONE))) { + p->fault_state = DCERPC_FAULT_ACCESS_DENIED; + return WERR_ACCESS_DENIED; + } + + if (r->in.flags & (~DS_GFTI_UPDATE_TDO)) { + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return WERR_INVALID_FLAGS; + } + + if ((r->in.flags & DS_GFTI_UPDATE_TDO) && (lp_server_role() != ROLE_DOMAIN_PDC)) { + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return WERR_NERR_NOTPRIMARY; + } + + if ((r->in.trusted_domain_name == NULL) && (r->in.flags & DS_GFTI_UPDATE_TDO)) { + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return WERR_INVALID_PARAMETER; + } + + /* retrieve forest trust information and stop further processing */ + if (r->in.trusted_domain_name == NULL) { + info_ptr = talloc(p->mem_ctx, struct lsa_ForestTrustInformation *); + if (info_ptr == NULL) { + p->fault_state = DCERPC_FAULT_CANT_PERFORM; + return WERR_NOMEM; + } + info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation); + if (info == NULL) { + p->fault_state = DCERPC_FAULT_CANT_PERFORM; + return WERR_NOMEM; + } + + /* Fill forest trust information and expand UPN suffixes list */ + status = fill_forest_trust_array(p->mem_ctx, info); + if (!NT_STATUS_IS_OK(status)) { + p->fault_state = DCERPC_FAULT_CANT_PERFORM; + return WERR_NOMEM; + } + + *info_ptr = info; + r->out.forest_trust_info = info_ptr; + + return WERR_OK; + + } + + /* TODO: implement remaining parts of DsrGetForestTrustInformation (opnum 43) + * when trusted_domain_name is not NULL */ + + p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; + return WERR_NOT_SUPPORTED; +} + +/**************************************************************** _netr_GetForestTrustInformation ****************************************************************/ @@ -2417,6 +2498,7 @@ NTSTATUS _netr_GetForestTrustInformation(struct pipes_struct *p, return NT_STATUS_NO_MEMORY; } + /* Fill forest trust information, do expand UPN suffixes list */ status = fill_forest_trust_array(p->mem_ctx, info); if (!NT_STATUS_IS_OK(status)) { return status; -- 1.8.1.4