s3:winbindd: factor winbindd_sids_to_xids into external and internal part
authorMichael Adam <obnox@samba.org>
Sat, 17 Nov 2012 01:30:07 +0000 (02:30 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 3 Dec 2012 07:48:21 +0000 (08:48 +0100)
- external part takes winbindd request/reponse structs (with sid strings)
- internal part takes sid lists

The new internal part implements functions wb_sids2xids_* that are
moved into the new module wb_sids2xids.c.

The purpose of this change is to use wb_sids2xids in winbindd_sid_to_uid
and winbindd_sid_to_gid instead of the currently used wb_sid2uid and wb_sid2gid.
We should just have one code path into id mapping and not several that behave
differently.

Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source3/Makefile.in
source3/winbindd/wb_sids2xids.c [new file with mode: 0644]
source3/winbindd/winbindd_proto.h
source3/winbindd/winbindd_sids_to_xids.c
source3/wscript_build

index 35556873ae167b2f746592d385a438846d3addef..bb0861fb38fe35291a207312d95775fea34f1203 100644 (file)
@@ -1400,6 +1400,7 @@ WINBINDD_OBJ1 = \
                winbindd/wb_sid2gid.o \
                winbindd/wb_uid2sid.o \
                winbindd/wb_gid2sid.o \
+               winbindd/wb_sids2xids.o \
                winbindd/wb_queryuser.o \
                winbindd/wb_lookupuseraliases.o \
                winbindd/wb_lookupusergroups.o \
diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
new file mode 100644 (file)
index 0000000..7a198c1
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+   Unix SMB/CIFS implementation.
+   async sids2xids
+   Copyright (C) Volker Lendecke 2011
+   Copyright (C) Michael Adam 2012
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "../libcli/security/security.h"
+#include "idmap_cache.h"
+#include "librpc/gen_ndr/ndr_wbint_c.h"
+
+struct wb_sids2xids_state {
+       struct tevent_context *ev;
+
+       struct dom_sid *sids;
+       uint32_t num_sids;
+
+       struct id_map *cached;
+
+       struct dom_sid *non_cached;
+       uint32_t num_non_cached;
+
+       struct lsa_RefDomainList *domains;
+       struct lsa_TransNameArray *names;
+
+       struct wbint_TransIDArray ids;
+};
+
+
+static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map);
+static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq);
+static void wb_sids2xids_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const struct dom_sid *sids,
+                                    const uint32_t num_sids)
+{
+       struct tevent_req *req, *subreq;
+       struct wb_sids2xids_state *state;
+       uint32_t i;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct wb_sids2xids_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->ev = ev;
+
+       state->num_sids = num_sids;
+
+       state->sids = talloc_zero_array(state, struct dom_sid, num_sids);
+       if (tevent_req_nomem(state->sids, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       for (i = 0; i < num_sids; i++) {
+               sid_copy(&state->sids[i], &sids[i]);
+       }
+
+       state->cached = talloc_zero_array(state, struct id_map, num_sids);
+       if (tevent_req_nomem(state->cached, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       state->non_cached = talloc_array(state, struct dom_sid, num_sids);
+       if (tevent_req_nomem(state->non_cached, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       /*
+        * Extract those sids that can not be resolved from cache
+        * into a separate list to be handed to id mapping, keeping
+        * the same index.
+        */
+       for (i=0; i<state->num_sids; i++) {
+
+               DEBUG(10, ("SID %d: %s\n", (int)i,
+                          sid_string_dbg(&state->sids[i])));
+
+               if (wb_sids2xids_in_cache(&state->sids[i], &state->cached[i])) {
+                       continue;
+               }
+               sid_copy(&state->non_cached[state->num_non_cached],
+                        &state->sids[i]);
+               state->num_non_cached += 1;
+       }
+
+       if (state->num_non_cached == 0) {
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = wb_lookupsids_send(state, ev, state->non_cached,
+                                   state->num_non_cached);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req);
+       return req;
+}
+
+static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map)
+{
+       struct unixid id;
+       bool expired;
+
+       if (!winbindd_use_idmap_cache()) {
+               return false;
+       }
+       if (idmap_cache_find_sid2unixid(sid, &id, &expired)) {
+               if (expired && is_domain_online(find_our_domain())) {
+                       return false;
+               }
+               map->sid = sid;
+               map->xid = id;
+               map->status = ID_MAPPED;
+               return true;
+       }
+       return false;
+}
+
+static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type);
+
+static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct wb_sids2xids_state *state = tevent_req_data(
+               req, struct wb_sids2xids_state);
+       struct winbindd_child *child;
+       NTSTATUS status;
+       int i;
+
+       status = wb_lookupsids_recv(subreq, state, &state->domains,
+                                   &state->names);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       state->ids.num_ids = state->num_non_cached;
+       state->ids.ids = talloc_array(state, struct wbint_TransID,
+                                     state->num_non_cached);
+       if (tevent_req_nomem(state->ids.ids, req)) {
+               return;
+       }
+
+       for (i=0; i<state->num_non_cached; i++) {
+               struct lsa_TranslatedName *n = &state->names->names[i];
+               struct wbint_TransID *t = &state->ids.ids[i];
+
+               t->type = lsa_SidType_to_id_type(n->sid_type);
+               t->domain_index = n->sid_index;
+               sid_peek_rid(&state->non_cached[i], &t->rid);
+               t->unix_id = (uint64_t)-1;
+       }
+
+       child = idmap_child();
+
+       subreq = dcerpc_wbint_Sids2UnixIDs_send(
+               state, state->ev, child->binding_handle, state->domains,
+               &state->ids);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, wb_sids2xids_done, req);
+}
+
+static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type)
+{
+       enum id_type type;
+
+       switch(sid_type) {
+       case SID_NAME_COMPUTER:
+       case SID_NAME_USER:
+               type = ID_TYPE_UID;
+               break;
+       case SID_NAME_DOM_GRP:
+       case SID_NAME_ALIAS:
+       case SID_NAME_WKN_GRP:
+               type = ID_TYPE_GID;
+               break;
+       default:
+               type = ID_TYPE_NOT_SPECIFIED;
+               break;
+       }
+
+       return type;
+}
+
+
+static void wb_sids2xids_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct wb_sids2xids_state *state = tevent_req_data(
+               req, struct wb_sids2xids_state);
+       NTSTATUS status, result;
+
+       status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result);
+       TALLOC_FREE(subreq);
+       if (any_nt_status_not_ok(status, result, &status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+NTSTATUS wb_sids2xids_recv(struct tevent_req *req,
+                          struct unixid *xids)
+{
+       struct wb_sids2xids_state *state = tevent_req_data(
+               req, struct wb_sids2xids_state);
+       NTSTATUS status;
+       uint32_t i, num_non_cached;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               DEBUG(5, ("wb_sids_to_xids failed: %s\n", nt_errstr(status)));
+               return status;
+       }
+
+       num_non_cached = 0;
+
+       for (i=0; i<state->num_sids; i++) {
+               struct unixid xid;
+
+               xid.id = UINT32_MAX;
+
+               if (state->cached[i].sid != NULL) {
+                       xid = state->cached[i].xid;
+               } else {
+                       xid.id = state->ids.ids[num_non_cached].unix_id;
+                       xid.type = state->ids.ids[num_non_cached].type;
+
+                       idmap_cache_set_sid2unixid(
+                               &state->non_cached[num_non_cached],
+                               &xid);
+
+                       num_non_cached += 1;
+               }
+
+               xids[i] = xid;
+       }
+
+       return NT_STATUS_OK;
+}
index b4f0852ac3f14da5b3fd9360c2deafbfb8774811..4e5fb7389cc49de193b18bfee01f5131492f6257 100644 (file)
@@ -860,6 +860,12 @@ NTSTATUS wb_lookupsids_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                            struct lsa_RefDomainList **domains,
                            struct lsa_TransNameArray **names);
 
+struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const struct dom_sid *sids,
+                                    const uint32_t num_sids);
+NTSTATUS wb_sids2xids_recv(struct tevent_req *req,
+                          struct unixid *xids);
 struct tevent_req *winbindd_sids_to_xids_send(TALLOC_CTX *mem_ctx,
                                              struct tevent_context *ev,
                                              struct winbindd_cli_state *cli,
index 7456d3a307156342c228a1700d37896e86486745..e4c7e3f0a9f0d3183954b0c9ca1d725ddb723554 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    async implementation of WINBINDD_SIDS_TO_XIDS
    Copyright (C) Volker Lendecke 2011
+   Copyright (C) Michael Adam 2012
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "includes.h"
 #include "winbindd.h"
 #include "../libcli/security/security.h"
-#include "librpc/gen_ndr/ndr_wbint_c.h"
-#include "idmap_cache.h"
+
 
 struct winbindd_sids_to_xids_state {
        struct tevent_context *ev;
        struct dom_sid *sids;
        uint32_t num_sids;
-
-       struct id_map *cached;
-
-       struct dom_sid *non_cached;
-       uint32_t num_non_cached;
-
-       struct lsa_RefDomainList *domains;
-       struct lsa_TransNameArray *names;
-
-       struct wbint_TransIDArray ids;
+       struct unixid *xids;
 };
 
-static bool winbindd_sids_to_xids_in_cache(struct dom_sid *sid,
-                                          struct id_map *map);
-static void winbindd_sids_to_xids_lookupsids_done(struct tevent_req *subreq);
 static void winbindd_sids_to_xids_done(struct tevent_req *subreq);
 
 struct tevent_req *winbindd_sids_to_xids_send(TALLOC_CTX *mem_ctx,
@@ -51,7 +39,6 @@ struct tevent_req *winbindd_sids_to_xids_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req, *subreq;
        struct winbindd_sids_to_xids_state *state;
-       uint32_t i;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct winbindd_sids_to_xids_state);
@@ -80,154 +67,31 @@ struct tevent_req *winbindd_sids_to_xids_send(TALLOC_CTX *mem_ctx,
 
        DEBUG(10, ("num_sids: %d\n", (int)state->num_sids));
 
-       state->cached = talloc_zero_array(state, struct id_map,
-                                         state->num_sids);
-       if (tevent_req_nomem(state->cached, req)) {
-               return tevent_req_post(req, ev);
-       }
-       state->non_cached = talloc_array(state, struct dom_sid,
-                                        state->num_sids);
-       if (tevent_req_nomem(state->non_cached, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       /*
-        * Extract those sids that can not be resolved from cache
-        * into a separate list to be handed to id mapping, keeping
-        * the same index.
-        */
-       for (i=0; i<state->num_sids; i++) {
-
-               DEBUG(10, ("SID %d: %s\n", (int)i,
-                          sid_string_dbg(&state->sids[i])));
-
-               if (winbindd_sids_to_xids_in_cache(&state->sids[i],
-                                                  &state->cached[i])) {
-                       continue;
-               }
-               sid_copy(&state->non_cached[state->num_non_cached],
-                        &state->sids[i]);
-               state->num_non_cached += 1;
-       }
-
-       if (state->num_non_cached == 0) {
-               tevent_req_done(req);
-               return tevent_req_post(req, ev);
-       }
-
-       subreq = wb_lookupsids_send(state, ev, state->non_cached,
-                                   state->num_non_cached);
+       subreq = wb_sids2xids_send(state, ev, state->sids, state->num_sids);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       tevent_req_set_callback(subreq, winbindd_sids_to_xids_lookupsids_done,
-                               req);
-       return req;
-}
 
-static bool winbindd_sids_to_xids_in_cache(struct dom_sid *sid,
-                                          struct id_map *map)
-{
-       struct unixid id;
-       bool expired;
-
-       if (!winbindd_use_idmap_cache()) {
-               return false;
-       }
-       if (idmap_cache_find_sid2unixid(sid, &id, &expired)) {
-               if (expired && is_domain_online(find_our_domain())) {
-                       return false;
-               }
-               map->sid = sid;
-               map->xid = id;
-               map->status = ID_MAPPED;
-               return true;
-       }
-       return false;
+       tevent_req_set_callback(subreq, winbindd_sids_to_xids_done, req);
+       return req;
 }
 
-static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type);
-
-static void winbindd_sids_to_xids_lookupsids_done(struct tevent_req *subreq)
+static void winbindd_sids_to_xids_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
        struct winbindd_sids_to_xids_state *state = tevent_req_data(
                req, struct winbindd_sids_to_xids_state);
-       struct winbindd_child *child;
        NTSTATUS status;
-       int i;
-
-       status = wb_lookupsids_recv(subreq, state, &state->domains,
-                                   &state->names);
-       TALLOC_FREE(subreq);
-       if (tevent_req_nterror(req, status)) {
-               return;
-       }
-
-       state->ids.num_ids = state->num_non_cached;
-       state->ids.ids = talloc_array(state, struct wbint_TransID,
-                                     state->num_non_cached);
-       if (tevent_req_nomem(state->ids.ids, req)) {
-               return;
-       }
-
-       for (i=0; i<state->num_non_cached; i++) {
-               struct lsa_TranslatedName *n = &state->names->names[i];
-               struct wbint_TransID *t = &state->ids.ids[i];
-
-               t->type = lsa_SidType_to_id_type(n->sid_type);
-               t->domain_index = n->sid_index;
-               sid_peek_rid(&state->non_cached[i], &t->rid);
-               t->unix_id = (uint64_t)-1;
-       }
-
-       child = idmap_child();
 
-       subreq = dcerpc_wbint_Sids2UnixIDs_send(
-               state, state->ev, child->binding_handle, state->domains,
-               &state->ids);
-       if (tevent_req_nomem(subreq, req)) {
+       state->xids = talloc_zero_array(state, struct unixid, state->num_sids);
+       if (tevent_req_nomem(state->xids, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, winbindd_sids_to_xids_done, req);
-}
-
-static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type)
-{
-       enum id_type type;
-
-       switch(sid_type) {
-       case SID_NAME_COMPUTER:
-       case SID_NAME_USER:
-               type = ID_TYPE_UID;
-               break;
-       case SID_NAME_DOM_GRP:
-       case SID_NAME_ALIAS:
-       case SID_NAME_WKN_GRP:
-               type = ID_TYPE_GID;
-               break;
-       default:
-               type = ID_TYPE_NOT_SPECIFIED;
-               break;
-       }
-
-       return type;
-}
 
-
-static void winbindd_sids_to_xids_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct winbindd_sids_to_xids_state *state = tevent_req_data(
-               req, struct winbindd_sids_to_xids_state);
-       NTSTATUS status, result;
-
-       status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result);
+       status = wb_sids2xids_recv(subreq, state->xids);
        TALLOC_FREE(subreq);
-       if (any_nt_status_not_ok(status, result, &status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
        tevent_req_done(req);
@@ -240,10 +104,10 @@ NTSTATUS winbindd_sids_to_xids_recv(struct tevent_req *req,
                req, struct winbindd_sids_to_xids_state);
        NTSTATUS status;
        char *result = NULL;
-       uint32_t i, num_non_cached;
+       uint32_t i;
 
        if (tevent_req_is_nterror(req, &status)) {
-               DEBUG(5, ("wb_sids_to_xids failed: %s\n", nt_errstr(status)));
+               DEBUG(5, ("Could not convert sids: %s\n", nt_errstr(status)));
                return status;
        }
 
@@ -252,27 +116,12 @@ NTSTATUS winbindd_sids_to_xids_recv(struct tevent_req *req,
                return NT_STATUS_NO_MEMORY;
        }
 
-       num_non_cached = 0;
-
        for (i=0; i<state->num_sids; i++) {
                char type = '\0';
                bool found = true;
                struct unixid xid;
 
-               xid.id = UINT32_MAX;
-
-               if (state->cached[i].sid != NULL) {
-                       xid = state->cached[i].xid;
-               } else {
-                       xid.id = state->ids.ids[num_non_cached].unix_id;
-                       xid.type = state->ids.ids[num_non_cached].type;
-
-                       idmap_cache_set_sid2unixid(
-                               &state->non_cached[num_non_cached],
-                               &xid);
-
-                       num_non_cached += 1;
-               }
+               xid = state->xids[i];
 
                switch (xid.type) {
                case ID_TYPE_UID:
@@ -307,5 +156,6 @@ NTSTATUS winbindd_sids_to_xids_recv(struct tevent_req *req,
 
        response->extra_data.data = result;
        response->length += talloc_get_size(result);
+
        return NT_STATUS_OK;
 }
index b9984fe98bd71762b0142a87fc1d0fbf0666ea61..039b6b795e29ce52a6a3ba013b61a72bba60240f 100755 (executable)
@@ -269,6 +269,7 @@ WINBINDD_SRC1 = '''winbindd/winbindd.c
                    winbindd/wb_sid2gid.c
                    winbindd/wb_uid2sid.c
                    winbindd/wb_gid2sid.c
+                   winbindd/wb_sids2xids.c
                    winbindd/wb_queryuser.c
                    winbindd/wb_lookupuseraliases.c
                    winbindd/wb_lookupusergroups.c