diff options
Diffstat (limited to 'source3/winbindd/wb_xids2sids.c')
-rw-r--r-- | source3/winbindd/wb_xids2sids.c | 162 |
1 files changed, 147 insertions, 15 deletions
diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c index 15e94c4203f..8850e63c8b4 100644 --- a/source3/winbindd/wb_xids2sids.c +++ b/source3/winbindd/wb_xids2sids.c @@ -23,11 +23,13 @@ #include "idmap_cache.h" #include "librpc/gen_ndr/ndr_winbind_c.h" #include "librpc/gen_ndr/ndr_netlogon.h" +#include "passdb/lookup_sid.h" struct wb_xids2sids_dom_map { unsigned low_id; unsigned high_id; const char *name; + struct dom_sid sid; }; /* @@ -93,6 +95,7 @@ static bool wb_xids2sids_add_dom(const char *domname, dom_maps = tmp; map = &dom_maps[num_maps]; + ZERO_STRUCTP(map); map->name = talloc_move(dom_maps, &name); } @@ -102,30 +105,138 @@ static bool wb_xids2sids_add_dom(const char *domname, return false; } -static void wb_xids2sids_init_dom_maps(void) +struct wb_xids2sids_init_dom_maps_state { + struct tevent_context *ev; + struct tevent_req *req; + size_t dom_idx; +}; + +static void wb_xids2sids_init_dom_maps_lookupname_next( + struct wb_xids2sids_init_dom_maps_state *state); + +static void wb_xids2sids_init_dom_maps_lookupname_done( + struct tevent_req *subreq); + +static struct tevent_req *wb_xids2sids_init_dom_maps_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev) { - if (dom_maps != NULL) { - return; + struct tevent_req *req = NULL; + struct wb_xids2sids_init_dom_maps_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct wb_xids2sids_init_dom_maps_state); + if (req == NULL) { + return NULL; } + *state = (struct wb_xids2sids_init_dom_maps_state) { + .ev = ev, + .req = req, + .dom_idx = 0, + }; + if (dom_maps != NULL) { + tevent_req_done(req); + return tevent_req_post(req, ev); + } /* * Put the passdb idmap domain first. We always need to try * there first. */ - dom_maps = talloc_array(NULL, struct wb_xids2sids_dom_map, 1); - if (dom_maps == NULL) { - return; + dom_maps = talloc_zero_array(NULL, struct wb_xids2sids_dom_map, 1); + if (tevent_req_nomem(dom_maps, req)) { + return tevent_req_post(req, ev); } dom_maps[0].low_id = 0; dom_maps[0].high_id = UINT_MAX; dom_maps[0].name = talloc_strdup(dom_maps, get_global_sam_name()); - if (dom_maps[0].name == NULL) { + if (tevent_req_nomem(dom_maps[0].name, req)) { TALLOC_FREE(dom_maps); - return; + return tevent_req_post(req, ev); } lp_scan_idmap_domains(wb_xids2sids_add_dom, NULL); + + wb_xids2sids_init_dom_maps_lookupname_next(state); + if (!tevent_req_is_in_progress(req)) { + tevent_req_post(req, ev); + } + return req; +} + +static void wb_xids2sids_init_dom_maps_lookupname_next( + struct wb_xids2sids_init_dom_maps_state *state) +{ + struct tevent_req *subreq = NULL; + + if (state->dom_idx == talloc_array_length(dom_maps)) { + tevent_req_done(state->req); + return; + } + + if (strequal(dom_maps[state->dom_idx].name, "*")) { + state->dom_idx++; + if (state->dom_idx == talloc_array_length(dom_maps)) { + tevent_req_done(state->req); + return; + } + } + + subreq = wb_lookupname_send(state, + state->ev, + dom_maps[state->dom_idx].name, + "", + LOOKUP_NAME_NO_NSS); + if (tevent_req_nomem(subreq, state->req)) { + return; + } + tevent_req_set_callback(subreq, + wb_xids2sids_init_dom_maps_lookupname_done, + state->req); +} + +static void wb_xids2sids_init_dom_maps_lookupname_done( + struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_xids2sids_init_dom_maps_state *state = tevent_req_data( + req, struct wb_xids2sids_init_dom_maps_state); + enum lsa_SidType type; + NTSTATUS status; + + status = wb_lookupname_recv(subreq, + &dom_maps[state->dom_idx].sid, + &type); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("Lookup domain name '%s' failed '%s'\n", + dom_maps[state->dom_idx].name, + nt_errstr(status)); + + state->dom_idx++; + wb_xids2sids_init_dom_maps_lookupname_next(state); + return; + } + + if (type != SID_NAME_DOMAIN) { + DBG_WARNING("SID %s for idmap domain name '%s' " + "not a domain SID\n", + sid_string_dbg(&dom_maps[state->dom_idx].sid), + dom_maps[state->dom_idx].name); + + ZERO_STRUCT(dom_maps[state->dom_idx].sid); + } + + state->dom_idx++; + wb_xids2sids_init_dom_maps_lookupname_next(state); + + return; +} + +static NTSTATUS wb_xids2sids_init_dom_maps_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } struct wb_xids2sids_dom_state { @@ -185,7 +296,6 @@ static struct tevent_req *wb_xids2sids_dom_send( /* already mapped */ continue; } - state->dom_xids[state->num_dom_xids++] = id; } @@ -321,6 +431,7 @@ struct wb_xids2sids_state { }; static void wb_xids2sids_done(struct tevent_req *subreq); +static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq); struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -329,7 +440,6 @@ struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct wb_xids2sids_state *state; - size_t num_domains; req = tevent_req_create(mem_ctx, &state, struct wb_xids2sids_state); @@ -371,22 +481,44 @@ struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx, } } - wb_xids2sids_init_dom_maps(); - num_domains = talloc_array_length(dom_maps); + subreq = wb_xids2sids_init_dom_maps_send( + state, state->ev); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, wb_xids2sids_init_dom_maps_done, req); + return req; +} + +static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct wb_xids2sids_state *state = tevent_req_data( + req, struct wb_xids2sids_state); + size_t num_domains; + NTSTATUS status; + + status = wb_xids2sids_init_dom_maps_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + num_domains = talloc_array_length(dom_maps); if (num_domains == 0) { tevent_req_done(req); - return tevent_req_post(req, ev); + return; } subreq = wb_xids2sids_dom_send( state, state->ev, &dom_maps[state->dom_idx], state->xids, state->num_xids, state->sids); if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + return; } tevent_req_set_callback(subreq, wb_xids2sids_done, req); - return req; + return; } static void wb_xids2sids_done(struct tevent_req *subreq) |