>From 354d31598d63409dad59f789db38f0c48bb46117 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Sat, 24 Aug 2013 15:45:57 +0200 Subject: [PATCH 3/3] AD: Download master domain info when enumerating https://fedorahosted.org/sssd/ticket/2068 With the current design, downloading master domain data was tied to subdomains refresh, triggered by responders. But because enumeration is a background task that can't be triggered on its own, we can't rely on responders to download the master domain data and we need to check the master domain on each enumeration request. --- src/providers/ad/ad_id.c | 185 ++++++++++++++++++++++++++++++++++++++ src/providers/ad/ad_id.h | 10 +++ src/providers/ad/ad_init.c | 6 +- src/providers/ldap/ldap_common.h | 11 +++ src/providers/ldap/ldap_id_enum.c | 6 -- 5 files changed, 211 insertions(+), 7 deletions(-) diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 48ad842590d0a8904744cd5518ac511205416f28..1d45440e197e79a60dbc038d2b0c0c8ffe823642 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -22,6 +22,8 @@ #include "util/util.h" #include "providers/ad/ad_common.h" #include "providers/ad/ad_id.h" +#include "providers/ad/ad_domain_info.h" +#include "providers/ldap/sdap_async_enum.h" struct ad_handle_acct_info_state { struct be_req *breq; @@ -309,3 +311,186 @@ ad_check_online(struct be_req *be_req) return sdap_do_online_check(be_req, ad_ctx->sdap_id_ctx); } + +struct ad_enumeration_state { + struct ldap_enum_ctx *ectx; + struct sdap_id_op *sdap_op; + struct tevent_context *ev; + + struct sdap_domain *sdom; +}; + +static void ad_enumeration_conn_done(struct tevent_req *subreq); +static void ad_enumeration_master_done(struct tevent_req *subreq); +static void ad_enumeration_done(struct tevent_req *subreq); + +struct tevent_req * +ad_enumeration_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct ad_enumeration_state *state; + struct ldap_enum_ctx *ectx; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, struct ad_enumeration_state); + if (req == NULL) return NULL; + + ectx = talloc_get_type(pvt, struct ldap_enum_ctx); + if (ectx == NULL) { + ret = EFAULT; + goto fail; + } + + state->ectx = ectx; + state->ev = ev; + state->sdom = ectx->sdom; + + state->sdap_op = sdap_id_op_create(state, ectx->conn->conn_cache); + if (state->sdap_op == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n")); + ret = ENOMEM; + goto fail; + } + + subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: %d(%s).\n", + ret, strerror(ret))); + goto fail; + } + tevent_req_set_callback(subreq, ad_enumeration_conn_done, req); + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void +ad_enumeration_conn_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ad_enumeration_state *state = tevent_req_data(req, + struct ad_enumeration_state); + int ret, dp_error; + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + if (ret != EOK) { + if (dp_error == DP_ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, + ("Backend is marked offline, retry later!\n")); + tevent_req_done(req); + } else { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Domain enumeration failed to connect to " \ + "LDAP server: (%d)[%s]\n", ret, strerror(ret))); + tevent_req_error(req, ret); + } + return; + } + + subreq = ad_master_domain_send(state, state->ev, + state->ectx->conn, + state->sdap_op, + state->sdom->dom->name); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("ad_master_domain_send failed.\n")); + tevent_req_error(req, ret); + return; + } + tevent_req_set_callback(subreq, ad_enumeration_master_done, req); +} + +static void +ad_enumeration_master_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ad_enumeration_state *state = tevent_req_data(req, + struct ad_enumeration_state); + char *flat_name; + char *master_sid; + + ret = ad_master_domain_recv(subreq, state, + &flat_name, &master_sid); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n")); + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", flat_name)); + DEBUG(SSSDBG_TRACE_FUNC, ("Found master SID [%s].\n", master_sid)); + + ret = sysdb_master_domain_add_info(state->sdom->dom, + flat_name, master_sid); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n")); + tevent_req_error(req, ret); + return; + } + + subreq = sdap_dom_enum_send(state, state->ev, state->ectx->ctx, + state->sdom, state->ectx->conn); + if (subreq == NULL) { + /* The ptask API will reschedule the enumeration on its own on + * failure */ + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to schedule enumeration, retrying later!\n")); + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, ad_enumeration_done, req); +} + +static void +ad_enumeration_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ad_enumeration_state *state = tevent_req_data(req, + struct ad_enumeration_state); + + ret = sdap_dom_enum_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Could not enumerate domain %s\n", state->sdom->dom->name)); + tevent_req_error(req, ret); + return; + } + + /* Ok, we've completed an enumeration. Save this to the + * sysdb so we can postpone starting up the enumeration + * process on the next SSSD service restart (to avoid + * slowing down system boot-up + */ + ret = sysdb_set_enumerated(state->sdom->dom->sysdb, + state->sdom->dom, true); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Could not mark domain as having enumerated.\n")); + /* This error is non-fatal, so continue */ + } + + tevent_req_done(req); +} + +errno_t +ad_enumeration_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h index 1fd6b599a8c42ccf9b68cec6b450a01c5ad80796..74b85645c2d6458617a4064fe3fb3f99696c3741 100644 --- a/src/providers/ad/ad_id.h +++ b/src/providers/ad/ad_id.h @@ -37,6 +37,16 @@ errno_t ad_handle_acct_info_recv(struct tevent_req *req, int *_dp_error, const char **_err); +struct tevent_req * +ad_enumeration_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt); + +errno_t +ad_enumeration_recv(struct tevent_req *req); + void ad_check_online(struct be_req *be_req); #endif /* AD_ID_H_ */ diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index 992881951edc215c9ad6b94efcab905abb3812f5..c829cc861a421db35b1e5f7a91941e20a3684ee6 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -205,7 +205,11 @@ sssm_ad_id_init(struct be_ctx *bectx, goto done; } - ret = ldap_id_setup_tasks(ad_ctx->sdap_id_ctx); + ret = sdap_id_setup_tasks(ad_ctx->sdap_id_ctx, + ad_ctx->sdap_id_ctx->conn, + ad_ctx->sdap_id_ctx->opts->sdom, + ad_enumeration_send, + ad_enumeration_recv); if (ret != EOK) { goto done; } diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index b21de0024c90ae7a62e5461091e0eeaad1526601..0d565fc63b7e949e628ae5cf079e54c134464e77 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -169,6 +169,17 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, const char *conf_path, struct sdap_options *opts); +/* Calling ldap_setup_enumeration will set up a periodic task + * that would periodically call send_fn/recv_fn request. The + * send_fn's pvt parameter will be a pointer to ldap_enum_ctx + * structure that contains the request data + */ +struct ldap_enum_ctx { + struct sdap_id_ctx *ctx; + struct sdap_domain *sdom; + struct sdap_id_conn_ctx *conn; +}; + errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, struct sdap_id_conn_ctx *conn, struct sdap_domain *sdom, diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index 2a42fdafb66eff9640b30c1f21b8c6470f5abc4f..8cccaa916a24beb10fe692d9a0e09f5f47ceb6f7 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/ldap_id_enum.c @@ -27,12 +27,6 @@ #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async_enum.h" -struct ldap_enum_ctx { - struct sdap_id_ctx *ctx; - struct sdap_domain *sdom; - struct sdap_id_conn_ctx *conn; -}; - errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, struct sdap_id_conn_ctx *conn, struct sdap_domain *sdom, -- 1.8.3.1