diff options
-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, |