diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2013-08-24 15:45:57 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-09-18 19:06:36 +0200 |
commit | 74802794554e0f87d1354b6788f1719cd7d80a6c (patch) | |
tree | ff10cc4446f6fff980c955b8c50d659b87f0d8c0 /src | |
parent | 21f749c9300a1a51f3eb83d7f1483ec2fe15b3cc (diff) | |
download | sssd-74802794554e0f87d1354b6788f1719cd7d80a6c.tar.gz sssd-74802794554e0f87d1354b6788f1719cd7d80a6c.tar.xz sssd-74802794554e0f87d1354b6788f1719cd7d80a6c.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/ad/ad_id.c | 185 | ||||
-rw-r--r-- | src/providers/ad/ad_id.h | 10 | ||||
-rw-r--r-- | src/providers/ad/ad_init.c | 6 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.h | 11 | ||||
-rw-r--r-- | 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 48ad84259..1d45440e1 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 1fd6b599a..74b85645c 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 992881951..c829cc861 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 b21de0024..0d565fc63 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 2a42fdafb..8cccaa916 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, |