diff options
author | Michael Adam <obnox@samba.org> | 2012-11-17 02:30:07 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2012-12-03 08:48:21 +0100 |
commit | 8e5ce1e2d53f36fd35eb8efad7da680dcf0b1ce1 (patch) | |
tree | aa270f566a0bc5754582326afa1cec838b5dff27 | |
parent | c58c68d5ba58855098d24c54db9c0cda19db0f4b (diff) | |
download | samba-8e5ce1e2d53f36fd35eb8efad7da680dcf0b1ce1.tar.gz samba-8e5ce1e2d53f36fd35eb8efad7da680dcf0b1ce1.tar.bz2 samba-8e5ce1e2d53f36fd35eb8efad7da680dcf0b1ce1.zip |
s3:winbindd: factor winbindd_sids_to_xids into external and internal part
- 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>
-rw-r--r-- | source3/Makefile.in | 1 | ||||
-rw-r--r-- | source3/winbindd/wb_sids2xids.c | 263 | ||||
-rw-r--r-- | source3/winbindd/winbindd_proto.h | 6 | ||||
-rw-r--r-- | source3/winbindd/winbindd_sids_to_xids.c | 180 | ||||
-rwxr-xr-x | source3/wscript_build | 1 |
5 files changed, 286 insertions, 165 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 35556873ae..bb0861fb38 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 index 0000000000..7a198c18ce --- /dev/null +++ b/source3/winbindd/wb_sids2xids.c @@ -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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index b4f0852ac3..4e5fb7389c 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -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, diff --git a/source3/winbindd/winbindd_sids_to_xids.c b/source3/winbindd/winbindd_sids_to_xids.c index 7456d3a307..e4c7e3f0a9 100644 --- a/source3/winbindd/winbindd_sids_to_xids.c +++ b/source3/winbindd/winbindd_sids_to_xids.c @@ -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 @@ -20,28 +21,15 @@ #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; } diff --git a/source3/wscript_build b/source3/wscript_build index b9984fe98b..039b6b795e 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -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 |