s3-netlogon: enumerate UPN suffixes from PASSDB when available
authorAlexander Bokovoy <ab@samba.org>
Wed, 3 Apr 2013 13:52:45 +0000 (16:52 +0300)
committerAndreas Schneider <asn@cryptomilk.org>
Tue, 9 Apr 2013 20:19:34 +0000 (22:19 +0200)
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 <asn@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Tue Apr  9 22:19:34 CEST 2013 on sn-devel-104

source3/rpc_server/netlogon/srv_netlog_nt.c

index e5da138491ba206d567e697e9aa7c3aa9ec3a1f0..6a6c125da9a28e45b69635c50a70cd08ca1625d5 100644 (file)
@@ -2292,22 +2292,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) {
@@ -2315,7 +2309,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;
        }
@@ -2333,6 +2335,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;
@@ -2351,11 +2368,75 @@ 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
 ****************************************************************/
@@ -2400,6 +2481,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;