From: Volker Lendecke Date: Tue, 12 Jan 2016 20:21:17 +0000 (+0100) Subject: winbind: handle DC_NOT_FOUND in wb_sids2xids X-Git-Tag: talloc-2.1.7~236 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f00af55ece7eaf1ba2b906fd040807177d296f15;p=thirdparty%2Fsamba.git winbind: handle DC_NOT_FOUND in wb_sids2xids The idmap_ad child is designed to connect to domain controllers on its own. Finding a DC is a nontrivial task that the child should not do on its own, in particular it should not have to connect to "our" DC's NETLOGON pipe separately. So when idmap_ad finds that it needs to connect to a DC, it returns NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND. The parent then asynchronously does the lookup and stores the DC info in gencache. After that the parent re-does the idmap child call, during which the child will find the DC-info in gencache. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c index 7cb7ec489b7..e16917f1545 100644 --- a/source3/winbindd/wb_sids2xids.c +++ b/source3/winbindd/wb_sids2xids.c @@ -23,6 +23,7 @@ #include "../libcli/security/security.h" #include "idmap_cache.h" #include "librpc/gen_ndr/ndr_winbind_c.h" +#include "librpc/gen_ndr/ndr_netlogon.h" #include "lsa.h" struct wb_sids2xids_state { @@ -52,6 +53,7 @@ struct wb_sids2xids_state { uint32_t dom_index; struct wbint_TransIDArray *dom_ids; struct lsa_RefDomainList idmap_dom; + bool tried_dclookup; struct wbint_TransIDArray ids; }; @@ -60,6 +62,7 @@ struct wb_sids2xids_state { 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); +static void wb_sids2xids_gotdc(struct tevent_req *subreq); struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -254,7 +257,6 @@ static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type) return type; } - static void wb_sids2xids_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( @@ -270,6 +272,27 @@ static void wb_sids2xids_done(struct tevent_req *subreq) status = dcerpc_wbint_Sids2UnixIDs_recv(subreq, state, &result); TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) && + !state->tried_dclookup) { + + struct lsa_DomainInfo *d; + + d = &state->idmap_doms.domains[state->dom_index]; + + subreq = wb_dsgetdcname_send( + state, state->ev, d->name.string, NULL, NULL, + DS_RETURN_DNS_NAME); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_sids2xids_gotdc, req); + return; + } + src = state->dom_ids; src_idx = 0; dst = &state->ids; @@ -297,6 +320,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq) TALLOC_FREE(state->dom_ids); state->dom_index += 1; + state->tried_dclookup = false; if (state->dom_index == state->idmap_doms.count) { tevent_req_done(req); @@ -326,6 +350,44 @@ static void wb_sids2xids_done(struct tevent_req *subreq) tevent_req_set_callback(subreq, wb_sids2xids_done, req); } +static void wb_sids2xids_gotdc(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 = idmap_child(); + struct netr_DsRGetDCNameInfo *dcinfo; + NTSTATUS status; + + status = wb_dsgetdcname_recv(subreq, state, &dcinfo); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + state->tried_dclookup = true; + + { + struct lsa_DomainInfo *d = + &state->idmap_doms.domains[state->dom_index]; + const char *dom_name = d->name.string; + + status = wb_dsgetdcname_gencache_set(dom_name, dcinfo); + if (tevent_req_nterror(req, status)) { + return; + } + } + + subreq = dcerpc_wbint_Sids2UnixIDs_send( + state, state->ev, child->binding_handle, &state->idmap_dom, + state->dom_ids); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, wb_sids2xids_done, req); +} + NTSTATUS wb_sids2xids_recv(struct tevent_req *req, struct unixid xids[], uint32_t num_xids) {