winbindd: in wb_lookupsids return domain name if we have it
authorRalph Boehme <slow@samba.org>
Fri, 24 Jun 2016 13:16:42 +0000 (15:16 +0200)
committerRalph Boehme <slow@samba.org>
Tue, 28 Jun 2016 05:27:18 +0000 (07:27 +0200)
When doing a SID to xid mapping for an unknown SID, the idmap child gets
passed a lsa_RefDomainList with an empty domain name (ie ""). This is
coming from LsaLookupSids() and causes the mapping request to end up in
the default idmap domain.

Example request with domain name "":

  wbint_Sids2UnixIDs: struct wbint_Sids2UnixIDs
     in: struct wbint_Sids2UnixIDs
         domains                  : *
             domains: struct lsa_RefDomainList
                 count                    : 0x00000001 (1)
                 domains                  : *
                     domains: ARRAY(1)
                         domains: struct lsa_DomainInfo
                             name: struct lsa_StringLarge
                                 length                   : 0x0000 (0)
                                 size                     : 0x0002 (2)
                                 string                   : *
                                     string                   : ''
                             sid                      : *
                                 sid                      : S-1-5-21-3152989960-574718769-2188965058
                 max_size                 : 0x00000020 (32)
         ids                      : *
             ids: struct wbint_TransIDArray
                 num_ids                  : 0x00000001 (1)
                 ids: ARRAY(1)
                     ids: struct wbint_TransID
                         type                     : ID_TYPE_NOT_SPECIFIED (0)
                         domain_index             : 0x00000000 (0)
                         rid                      : 0x000029aa (66666)
                         xid: struct unixid
                             id                       : 0xffffffff (4294967295)
                             type                     : ID_TYPE_NOT_SPECIFIED (0)

In _wbint_Sids2UnixIDs() we call idmap_find_domain_with_sid() with the
domain name "" and this triggers use of the default idmap domain which
in case of idmap_autorid will allocate an id from a idmap_autorid range.

If we know the domain, ensure we return it for SIDs were the SID was not
found but the domain of the SID was found. Callers like sids2xids depend
on the domain name and returning an empty string "" for valid domain can
trigger unwanted idmap range allocations.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11961

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source3/winbindd/wb_lookupsids.c

index 8c5f9dbbb48af6af63973deabd2413d1609cbbae..248054750ff61146185054fd35e94579bc686831 100644 (file)
@@ -72,6 +72,8 @@ struct wb_lookupsids_state {
         * wbint_LookupSid. Preallocated with num_sids.
         */
        uint32_t *single_sids;
+       /* Pointer into the "domains" array above*/
+       struct wb_lookupsids_domain **single_domains;
        uint32_t num_single_sids;
        uint32_t single_sids_done;
 
@@ -127,6 +129,12 @@ struct tevent_req *wb_lookupsids_send(TALLOC_CTX *mem_ctx,
        if (tevent_req_nomem(state->single_sids, req)) {
                return tevent_req_post(req, ev);
        }
+       state->single_domains = talloc_zero_array(state,
+                                                 struct wb_lookupsids_domain *,
+                                                 num_sids);
+       if (tevent_req_nomem(state->single_domains, req)) {
+               return tevent_req_post(req, ev);
+       }
 
        state->res_domains = talloc_zero(state, struct lsa_RefDomainList);
        if (tevent_req_nomem(state->res_domains, req)) {
@@ -455,6 +463,7 @@ static void wb_lookupsids_done(struct tevent_req *subreq)
 
                        state->single_sids[state->num_single_sids] =
                                res_sid_index;
+                       state->single_domains[state->num_single_sids] = d;
                        state->num_single_sids += 1;
                }
                state->domains_done += 1;
@@ -514,9 +523,28 @@ static void wb_lookupsids_single_done(struct tevent_req *subreq)
                                   &domain_name, &name);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               struct wb_lookupsids_domain *wb_domain;
+               const char *tmpname;
+
                type = SID_NAME_UNKNOWN;
 
-               domain_name = talloc_strdup(talloc_tos(), "");
+               wb_domain = state->single_domains[state->single_sids_done];
+               if (wb_domain != NULL) {
+                       /*
+                        * If the lookupsid failed because the rid not
+                        * found in a domain and we have a reference
+                        * to the lookup domain, use the name from
+                        * there.
+                        *
+                        * Callers like sid2xid will use the domain
+                        * name in the idmap backend to figure out
+                        * which domain to use in processing.
+                        */
+                       tmpname = wb_domain->domain->name;
+               } else {
+                       tmpname = "";
+               }
+               domain_name = talloc_strdup(talloc_tos(), tmpname);
                if (tevent_req_nomem(domain_name, req)) {
                        return;
                }