>From 5acc47c2aa196a2f8137f9cc40e0702421ad1cba Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 20 Aug 2013 16:13:56 +0200 Subject: [PATCH 03/11] LDAP: Move the ldap enum request to its own reusable module The LDAP enumeration was too closely tied to the LDAP identity provider. Because some providers might need special handling such as refresh the master domain record before proceeding with the enumeration itself, this patch splits the request itself to a separate async request and lets the ldap_id_enum.c module only configure this new request. Also move the enum timestamp to sdap_domain to make the enum tracking per sdap domain. The cleanup timestamp will be moved in another patch. --- Makefile.am | 2 + src/providers/ldap/ldap_common.h | 5 - src/providers/ldap/ldap_id_enum.c | 628 +-------------------- src/providers/ldap/sdap.h | 3 + .../ldap/{ldap_id_enum.c => sdap_async_enum.c} | 346 ++++-------- src/providers/ldap/sdap_async_enum.h | 38 ++ src/providers/ldap/sdap_reinit.c | 13 +- 7 files changed, 171 insertions(+), 864 deletions(-) copy src/providers/ldap/{ldap_id_enum.c => sdap_async_enum.c} (64%) create mode 100644 src/providers/ldap/sdap_async_enum.h diff --git a/Makefile.am b/Makefile.am index 4dd8ed352179211dcbbc19a61936d1041ab08408..8de2e0fbb01a8abe2739d0985daec9a97a2c586d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -460,6 +460,7 @@ dist_noinst_HEADERS = \ src/providers/ldap/sdap_range.h \ src/providers/ldap/sdap_users.h \ src/providers/ldap/sdap_dyndns.h \ + src/providers/ldap/sdap_async_enum.h \ src/providers/ipa/ipa_common.h \ src/providers/ipa/ipa_config.h \ src/providers/ipa/ipa_access.h \ @@ -1428,6 +1429,7 @@ pkglib_LTLIBRARIES += libsss_ldap_common.la libsss_ldap_common_la_SOURCES = \ src/providers/ldap/ldap_id.c \ src/providers/ldap/ldap_id_enum.c \ + src/providers/ldap/sdap_async_enum.c \ src/providers/ldap/ldap_id_cleanup.c \ src/providers/ldap/ldap_id_netgroup.c \ src/providers/ldap/ldap_id_services.c \ diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index db2466ad832d7867d9244a835cde1adab39d347d..c9b2f663b72658c9cdcd4d54ec32b1dd74f31326 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -63,8 +63,6 @@ struct sdap_id_ctx { /* connection to a server */ struct sdap_id_conn_ctx *conn; - /* enumeration loop timer */ - struct timeval last_enum; /* cleanup loop timer */ struct timeval last_purge; @@ -170,9 +168,6 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); -struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev, - struct sdap_id_ctx *ctx); - void sdap_mark_offline(struct sdap_id_ctx *ctx); struct tevent_req *groups_get_send(TALLOC_CTX *memctx, diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index c9cb23b72ded08800bee8adf9f7b69a05032a30b..4e0e1d06eb4e1fe8b93b9d6e35f5843c0861d5ba 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/ldap_id_enum.c @@ -31,6 +31,7 @@ #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" #include "providers/ldap/sdap_idmap.h" +#include "providers/ldap/sdap_async_enum.h" extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -38,9 +39,6 @@ extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, /* ==Enumeration-Task===================================================== */ -static int ldap_id_enumerate_retry(struct tevent_req *req); -static void ldap_id_enumerate_connect_done(struct tevent_req *req); - static void ldap_id_enumerate_reschedule(struct tevent_req *req); static void ldap_id_enumerate_timeout(struct tevent_context *ev, @@ -66,7 +64,7 @@ static void ldap_id_enumerate_timer(struct tevent_context *ev, return; } - req = ldap_id_enumerate_send(ev, ctx); + req = sdap_dom_enum_send(ctx, ev, ctx, ctx->opts->sdom, ctx->conn); if (!req) { DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); /* schedule starting from now, not the last run */ @@ -129,17 +127,17 @@ static void ldap_id_enumerate_reschedule(struct tevent_req *req) { struct sdap_id_ctx *ctx = tevent_req_callback_data(req, struct sdap_id_ctx); - enum tevent_req_state tstate; - uint64_t err; struct timeval tv; int delay; errno_t ret; - if (tevent_req_is_error(req, &tstate, &err)) { + ret = sdap_dom_enum_recv(req); + talloc_zfree(req); + if (ret != EOK) { /* On error schedule starting from now, not the last run */ tv = tevent_timeval_current(); } else { - tv = ctx->last_enum; + tv = ctx->opts->sdom->last_enum; /* Ok, we've completed an enumeration. Save this to the * sysdb so we can postpone starting up the enumeration @@ -152,7 +150,6 @@ static void ldap_id_enumerate_reschedule(struct tevent_req *req) /* This error is non-fatal, so continue */ } } - talloc_zfree(req); delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_add(&tv, delay, 0); @@ -175,616 +172,3 @@ int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) return EOK; } - -struct global_enum_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sdap_id_op *op; - - bool purge; -}; - -static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_op *op, - bool purge); -static errno_t enum_users_recv(struct tevent_req *req); -static void ldap_id_enum_users_done(struct tevent_req *subreq); -static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_op *op, - bool purge); -static errno_t enum_groups_recv(struct tevent_req *req); -static void ldap_id_enum_groups_done(struct tevent_req *subreq); -static void ldap_id_enum_services_done(struct tevent_req *subreq); -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq); - -struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct global_enum_state *state; - struct tevent_req *req; - int t; - - req = tevent_req_create(ctx, &state, struct global_enum_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); - if (!state->op) { - DEBUG(2, ("sdap_id_op_create failed\n")); - talloc_zfree(req); - return NULL; - } - - ctx->last_enum = tevent_timeval_current(); - - t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - if ((ctx->last_purge.tv_sec + t) < ctx->last_enum.tv_sec) { - state->purge = true; - } else { - state->purge = false; - } - - int ret = ldap_id_enumerate_retry(req); - if (ret != EOK) { - DEBUG(2, ("ldap_id_enumerate_retry failed\n")); - talloc_zfree(req); - return NULL; - } - - return req; -} - -static int ldap_id_enumerate_retry(struct tevent_req *req) -{ - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - struct tevent_req *subreq; - int ret; - - subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { - return ret; - } - - tevent_req_set_callback(subreq, ldap_id_enumerate_connect_done, req); - return EOK; -} - -static void ldap_id_enumerate_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_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) { - tevent_req_done(req); - } else { - DEBUG(9, ("User enumeration failed to connect to LDAP server: (%d)[%s]\n", - ret, strerror(ret))); - tevent_req_error(req, ret); - } - - return; - } - - subreq = enum_users_send(state, state->ev, - state->ctx, state->ctx->opts->sdom, - state->op, state->purge); - if(!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, ldap_id_enum_users_done, req); -} - -static void ldap_id_enum_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - uint64_t err = 0; - int ret, dp_error = DP_ERR_FATAL; - - err = enum_users_recv(subreq); - talloc_zfree(subreq); - if (err != EOK && err != ENOENT) { - /* We call sdap_id_op_done only on error - * as the connection is reused by groups enumeration */ - ret = sdap_id_op_done(state->op, (int)err, &dp_error); - if (dp_error == DP_ERR_OK) { - /* retry */ - ret = ldap_id_enumerate_retry(req); - if (ret == EOK) { - return; - } - - dp_error = DP_ERR_FATAL; - } - - if (dp_error == DP_ERR_OFFLINE) { - tevent_req_done(req); - } else { - DEBUG(9, ("User enumeration failed with: (%d)[%s]\n", - ret, strerror(ret))); - tevent_req_error(req, ret); - } - return; - } - - subreq = enum_groups_send(state, state->ev, state->ctx, - state->ctx->opts->sdom, - state->op, state->purge); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req); -} - -static void ldap_id_enum_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - uint64_t err = 0; - int ret, dp_error = DP_ERR_FATAL; - - err = enum_groups_recv(subreq); - talloc_zfree(subreq); - if (err != EOK) { - /* We call sdap_id_op_done only on error - * as the connection is reused by services enumeration */ - ret = sdap_id_op_done(state->op, (int)err, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ldap_id_enumerate_retry(req); - if (ret == EOK) { - return; - } - - dp_error = DP_ERR_FATAL; - } - - if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - tevent_req_done(req); - } else { - DEBUG(9, ("Group enumeration failed with: (%d)[%s]\n", - ret, strerror(ret))); - tevent_req_error(req, ret); - } - - return; - } - } - - subreq = enum_services_send(state, state->ev, state->ctx, - state->op, state->purge); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, ldap_id_enum_services_done, req); -} - -static void ldap_id_enum_services_done(struct tevent_req *subreq) -{ - errno_t ret; - int dp_error = DP_ERR_FATAL; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - - ret = enum_services_recv(subreq); - talloc_zfree(subreq); - if (ret == ENOENT) ret = EOK; - - /* All enumerations are complete, so conclude the - * id_op - */ - ret = sdap_id_op_done(state->op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ldap_id_enumerate_retry(req); - if (ret == EOK) { - return; - } - - dp_error = DP_ERR_FATAL; - } - - if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - tevent_req_done(req); - } else { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Service enumeration failed with: (%d)[%s]\n", - ret, strerror(ret))); - tevent_req_error(req, ret); - } - - return; - } - - if (state->purge) { - - subreq = ldap_id_cleanup_send(state, state->ev, state->ctx); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req); - return; - } - - tevent_req_done(req); -} - -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - talloc_zfree(subreq); - tevent_req_done(req); -} - -/* ==User-Enumeration===================================================== */ - -struct enum_users_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sdap_domain *sdom; - struct sdap_id_op *op; - - char *filter; - const char **attrs; -}; - -static void enum_users_op_done(struct tevent_req *subreq); - -static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_op *op, - bool purge) -{ - struct tevent_req *req, *subreq; - struct enum_users_state *state; - int ret; - bool use_mapping; - - req = tevent_req_create(memctx, &state, struct enum_users_state); - if (!req) return NULL; - - state->ev = ev; - state->sdom = sdom; - state->ctx = ctx; - state->op = op; - - use_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->domain_id); - - /* We always want to filter on objectclass and an available name */ - state->filter = talloc_asprintf(state, - "(&(objectclass=%s)(%s=*)", - ctx->opts->user_map[SDAP_OC_USER].name, - ctx->opts->user_map[SDAP_AT_USER_NAME].name); - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - if (use_mapping) { - /* If we're ID-mapping, check for the objectSID as well */ - state->filter = talloc_asprintf_append_buffer( - state->filter, "(%s=*)", - ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); - } else { - /* We're not ID-mapping, so make sure to only get entries - * that have UID and GID - */ - state->filter = talloc_asprintf_append_buffer( - state->filter, "(%s=*)(%s=*)", - ctx->opts->user_map[SDAP_AT_USER_UID].name, - ctx->opts->user_map[SDAP_AT_USER_GID].name); - } - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) { - /* If we have lastUSN available and we're not doing a full - * refresh, limit to changes with a higher entryUSN value. - */ - state->filter = talloc_asprintf_append_buffer( - state->filter, - "(%s>=%s)(!(%s=%s))", - ctx->opts->user_map[SDAP_AT_USER_USN].name, - ctx->srv_opts->max_user_value, - ctx->opts->user_map[SDAP_AT_USER_USN].name, - ctx->srv_opts->max_user_value); - - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - } - - /* Terminate the search filter */ - state->filter = talloc_asprintf_append_buffer(state->filter, ")"); - if (!state->filter) { - DEBUG(2, ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->user_map, SDAP_OPTS_USER, - NULL, &state->attrs, NULL); - if (ret != EOK) goto fail; - - /* TODO: restrict the enumerations to using a single - * search base at a time. - */ - - subreq = sdap_get_users_send(state, state->ev, - state->sdom->dom, - state->sdom->dom->sysdb, - state->ctx->opts, - state->sdom->user_search_bases, - sdap_id_op_handle(state->op), - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT), - true); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, enum_users_op_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void enum_users_op_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_users_state *state = tevent_req_data(req, - struct enum_users_state); - char *usn_value; - char *endptr = NULL; - unsigned usn_number; - int ret; - - ret = sdap_get_users_recv(subreq, state, &usn_value); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (usn_value) { - talloc_zfree(state->ctx->srv_opts->max_user_value); - state->ctx->srv_opts->max_user_value = talloc_steal(state->ctx, usn_value); - - usn_number = strtoul(usn_value, &endptr, 10); - if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value)) - && (usn_number > state->ctx->srv_opts->last_usn)) { - state->ctx->srv_opts->last_usn = usn_number; - } - } - - DEBUG(4, ("Users higher USN value: [%s]\n", - state->ctx->srv_opts->max_user_value)); - - tevent_req_done(req); -} - -static errno_t enum_users_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -/* =Group-Enumeration===================================================== */ - -struct enum_groups_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sdap_domain *sdom; - struct sdap_id_op *op; - - char *filter; - const char **attrs; -}; - -static void enum_groups_op_done(struct tevent_req *subreq); - -static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - struct sdap_id_op *op, - bool purge) -{ - struct tevent_req *req, *subreq; - struct enum_groups_state *state; - int ret; - bool use_mapping; - - req = tevent_req_create(memctx, &state, struct enum_groups_state); - if (!req) return NULL; - - state->ev = ev; - state->sdom = sdom; - state->ctx = ctx; - state->op = op; - - use_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->domain_id); - - /* We always want to filter on objectclass and an available name */ - state->filter = talloc_asprintf(state, - "(&(objectclass=%s)(%s=*)", - ctx->opts->group_map[SDAP_OC_GROUP].name, - ctx->opts->group_map[SDAP_AT_GROUP_NAME].name); - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - if (use_mapping) { - /* If we're ID-mapping, check for the objectSID as well */ - state->filter = talloc_asprintf_append_buffer( - state->filter, "(%s=*)", - ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name); - } else { - /* We're not ID-mapping, so make sure to only get entries - * that have a non-zero GID. - */ - state->filter = talloc_asprintf_append_buffer( - state->filter, "(&(%s=*)(!(%s=0)))", - ctx->opts->group_map[SDAP_AT_GROUP_GID].name, - ctx->opts->group_map[SDAP_AT_GROUP_GID].name); - } - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) { - state->filter = talloc_asprintf_append_buffer( - state->filter, - "(%s>=%s)(!(%s=%s))", - ctx->opts->group_map[SDAP_AT_GROUP_USN].name, - ctx->srv_opts->max_group_value, - ctx->opts->group_map[SDAP_AT_GROUP_USN].name, - ctx->srv_opts->max_group_value); - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - } - - /* Terminate the search filter */ - state->filter = talloc_asprintf_append_buffer(state->filter, ")"); - if (!state->filter) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to build base filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP, - NULL, &state->attrs, NULL); - if (ret != EOK) goto fail; - - /* TODO: restrict the enumerations to using a single - * search base at a time. - */ - - subreq = sdap_get_groups_send(state, state->ev, - state->sdom, - state->ctx->opts, - sdap_id_op_handle(state->op), - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT), - true); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, enum_groups_op_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void enum_groups_op_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_groups_state *state = tevent_req_data(req, - struct enum_groups_state); - char *usn_value; - char *endptr = NULL; - unsigned usn_number; - int ret; - - ret = sdap_get_groups_recv(subreq, state, &usn_value); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (usn_value) { - talloc_zfree(state->ctx->srv_opts->max_group_value); - state->ctx->srv_opts->max_group_value = - talloc_steal(state->ctx, usn_value); - usn_number = strtoul(usn_value, &endptr, 10); - if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value)) - && (usn_number > state->ctx->srv_opts->last_usn)) { - state->ctx->srv_opts->last_usn = usn_number; - } - } - - DEBUG(4, ("Groups higher USN value: [%s]\n", - state->ctx->srv_opts->max_group_value)); - - tevent_req_done(req); -} - -static errno_t enum_groups_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 6d24982b7759f7d4679d1be3030d0de0a3b9a607..f5f6d90aa075b5e7cffa4445cda87b1757dd3ca3 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -383,6 +383,9 @@ struct sdap_domain { struct sdap_domain *next, *prev; /* Need to modify the list from a talloc destructor */ struct sdap_domain **head; + + /* enumeration loop timer */ + struct timeval last_enum; }; struct sdap_options { diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/sdap_async_enum.c similarity index 64% copy from src/providers/ldap/ldap_id_enum.c copy to src/providers/ldap/sdap_async_enum.c index c9cb23b72ded08800bee8adf9f7b69a05032a30b..c99c64f9f2a35a809aed1787447ab37ae8c7198c 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -1,12 +1,13 @@ /* SSSD - LDAP Identity Enumeration + LDAP Enumeration Module Authors: Simo Sorce + Jakub Hrozek - Copyright (C) 2009 Red Hat + Copyright (C) 2013 Red Hat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,8 +24,6 @@ */ #include -#include -#include #include "util/util.h" #include "db/sysdb.h" @@ -36,154 +35,6 @@ extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx); -/* ==Enumeration-Task===================================================== */ - -static int ldap_id_enumerate_retry(struct tevent_req *req); -static void ldap_id_enumerate_connect_done(struct tevent_req *req); - -static void ldap_id_enumerate_reschedule(struct tevent_req *req); - -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); - -static void ldap_id_enumerate_timer(struct tevent_context *ev, - struct tevent_timer *tt, - struct timeval tv, void *pvt) -{ - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); - struct tevent_timer *timeout; - struct tevent_req *req; - int delay; - errno_t ret; - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - return; - } - - req = ldap_id_enumerate_send(ev, ctx); - if (!req) { - DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ret = ldap_id_enumerate_set_timer(ctx, tv); - if (ret != EOK) { - DEBUG(1, ("Error setting up enumerate timer\n")); - } - return; - } - tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx); - - /* if enumeration takes so long, either we try to enumerate too - * frequently, or something went seriously wrong */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - timeout = tevent_add_timer(ctx->be->ev, req, tv, - ldap_id_enumerate_timeout, req); - if (timeout == NULL) { - /* If we can't guarantee a timeout, we - * need to cancel the request, to avoid - * the possibility of starting another - * concurrently - */ - talloc_zfree(req); - - DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ret = ldap_id_enumerate_set_timer(ctx, tv); - if (ret != EOK) { - DEBUG(1, ("Error setting up enumerate timer\n")); - } - return; - } - return; -} - -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - int delay; - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay)); - - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - - talloc_zfree(req); -} - -static void ldap_id_enumerate_reschedule(struct tevent_req *req) -{ - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - enum tevent_req_state tstate; - uint64_t err; - struct timeval tv; - int delay; - errno_t ret; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* On error schedule starting from now, not the last run */ - tv = tevent_timeval_current(); - } else { - tv = ctx->last_enum; - - /* 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(ctx->be->domain->sysdb, ctx->be->domain, true); - if (ret != EOK) { - DEBUG(1, ("Could not mark domain as having enumerated.\n")); - /* This error is non-fatal, so continue */ - } - } - talloc_zfree(req); - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); -} - -int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) -{ - struct tevent_timer *enum_task; - - DEBUG(6, ("Scheduling next enumeration at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - enum_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_enumerate_timer, ctx); - if (!enum_task) { - DEBUG(0, ("FATAL: failed to setup enumeration task!\n")); - return EFAULT; - } - - return EOK; -} - -struct global_enum_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sdap_id_op *op; - - bool purge; -}; - static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, @@ -191,7 +42,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, struct sdap_id_op *op, bool purge); static errno_t enum_users_recv(struct tevent_req *req); -static void ldap_id_enum_users_done(struct tevent_req *subreq); + static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_id_ctx *ctx, @@ -199,115 +50,142 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct sdap_id_op *op, bool purge); static errno_t enum_groups_recv(struct tevent_req *req); -static void ldap_id_enum_groups_done(struct tevent_req *subreq); -static void ldap_id_enum_services_done(struct tevent_req *subreq); -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq); -struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev, - struct sdap_id_ctx *ctx) +/* ==Enumeration-Request==================================================== */ +struct sdap_dom_enum_state { + struct tevent_context *ev; + struct sdap_id_ctx *ctx; + struct sdap_domain *sdom; + struct sdap_id_conn_ctx *conn; + struct sdap_id_op *op; + + bool purge; +}; + +static errno_t sdap_dom_enum_retry(struct tevent_req *req); +static void sdap_dom_enum_conn_done(struct tevent_req *subreq); +static void sdap_dom_enum_users_done(struct tevent_req *subreq); +static void sdap_dom_enum_groups_done(struct tevent_req *subreq); +static void sdap_dom_enum_services_done(struct tevent_req *subreq); +static void sdap_dom_enum_cleanup_done(struct tevent_req *subreq); + +struct tevent_req * +sdap_dom_enum_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn) { - struct global_enum_state *state; struct tevent_req *req; + struct sdap_dom_enum_state *state; int t; + errno_t ret; - req = tevent_req_create(ctx, &state, struct global_enum_state); + req = tevent_req_create(ctx, &state, struct sdap_dom_enum_state); if (!req) return NULL; state->ev = ev; state->ctx = ctx; + state->sdom = sdom; + state->conn = conn; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); if (!state->op) { - DEBUG(2, ("sdap_id_op_create failed\n")); - talloc_zfree(req); - return NULL; + DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create failed\n")); + ret = EIO; + goto fail; } - ctx->last_enum = tevent_timeval_current(); + sdom->last_enum = tevent_timeval_current(); t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - if ((ctx->last_purge.tv_sec + t) < ctx->last_enum.tv_sec) { + if ((ctx->last_purge.tv_sec + t) < sdom->last_enum.tv_sec) { state->purge = true; - } else { - state->purge = false; } - int ret = ldap_id_enumerate_retry(req); + ret = sdap_dom_enum_retry(req); if (ret != EOK) { - DEBUG(2, ("ldap_id_enumerate_retry failed\n")); - talloc_zfree(req); - return NULL; + DEBUG(SSSDBG_OP_FAILURE, ("ldap_id_enumerate_retry failed\n")); + goto fail; } return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; } -static int ldap_id_enumerate_retry(struct tevent_req *req) +static errno_t sdap_dom_enum_retry(struct tevent_req *req) { - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); + struct sdap_dom_enum_state *state = tevent_req_data(req, + struct sdap_dom_enum_state); struct tevent_req *subreq; - int ret; + errno_t ret; subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (!subreq) { + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, + ("sdap_id_op_connect_send failed: %d\n", ret)); return ret; } - tevent_req_set_callback(subreq, ldap_id_enumerate_connect_done, req); + tevent_req_set_callback(subreq, sdap_dom_enum_conn_done, req); return EOK; } -static void ldap_id_enumerate_connect_done(struct tevent_req *subreq) +static void sdap_dom_enum_conn_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); + struct sdap_dom_enum_state *state = tevent_req_data(req, + struct sdap_dom_enum_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(9, ("User enumeration failed to connect to LDAP server: (%d)[%s]\n", - ret, strerror(ret))); + 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 = enum_users_send(state, state->ev, - state->ctx, state->ctx->opts->sdom, + state->ctx, state->sdom, state->op, state->purge); - if(!subreq) { + if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; } - - tevent_req_set_callback(subreq, ldap_id_enum_users_done, req); + tevent_req_set_callback(subreq, sdap_dom_enum_users_done, req); } -static void ldap_id_enum_users_done(struct tevent_req *subreq) +static void sdap_dom_enum_users_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); + struct sdap_dom_enum_state *state = tevent_req_data(req, + struct sdap_dom_enum_state); uint64_t err = 0; int ret, dp_error = DP_ERR_FATAL; err = enum_users_recv(subreq); talloc_zfree(subreq); - if (err != EOK && err != ENOENT) { + if (err != EOK) { /* We call sdap_id_op_done only on error * as the connection is reused by groups enumeration */ ret = sdap_id_op_done(state->op, (int)err, &dp_error); if (dp_error == DP_ERR_OK) { /* retry */ - ret = ldap_id_enumerate_retry(req); + ret = sdap_dom_enum_retry(req); if (ret == EOK) { return; } @@ -318,29 +196,30 @@ static void ldap_id_enum_users_done(struct tevent_req *subreq) if (dp_error == DP_ERR_OFFLINE) { tevent_req_done(req); } else { - DEBUG(9, ("User enumeration failed with: (%d)[%s]\n", - ret, strerror(ret))); + DEBUG(SSSDBG_OP_FAILURE, + ("User enumeration failed with: (%d)[%s]\n", + ret, strerror(ret))); tevent_req_error(req, ret); } return; } subreq = enum_groups_send(state, state->ev, state->ctx, - state->ctx->opts->sdom, + state->sdom, state->op, state->purge); - if (!subreq) { + if (subreq == NULL) { tevent_req_error(req, ENOMEM); return; } - tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req); + tevent_req_set_callback(subreq, sdap_dom_enum_groups_done, req); } -static void ldap_id_enum_groups_done(struct tevent_req *subreq) +static void sdap_dom_enum_groups_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); + struct sdap_dom_enum_state *state = tevent_req_data(req, + struct sdap_dom_enum_state); uint64_t err = 0; int ret, dp_error = DP_ERR_FATAL; @@ -352,7 +231,7 @@ static void ldap_id_enum_groups_done(struct tevent_req *subreq) ret = sdap_id_op_done(state->op, (int)err, &dp_error); if (dp_error == DP_ERR_OK && ret != EOK) { /* retry */ - ret = ldap_id_enumerate_retry(req); + ret = sdap_dom_enum_retry(req); if (ret == EOK) { return; } @@ -364,8 +243,9 @@ static void ldap_id_enum_groups_done(struct tevent_req *subreq) if (dp_error == DP_ERR_OFFLINE) { tevent_req_done(req); } else { - DEBUG(9, ("Group enumeration failed with: (%d)[%s]\n", - ret, strerror(ret))); + DEBUG(SSSDBG_OP_FAILURE, + ("Group enumeration failed with: (%d)[%s]\n", + ret, strerror(ret))); tevent_req_error(req, ret); } @@ -379,17 +259,17 @@ static void ldap_id_enum_groups_done(struct tevent_req *subreq) tevent_req_error(req, ENOMEM); return; } - tevent_req_set_callback(subreq, ldap_id_enum_services_done, req); + tevent_req_set_callback(subreq, sdap_dom_enum_services_done, req); } -static void ldap_id_enum_services_done(struct tevent_req *subreq) +static void sdap_dom_enum_services_done(struct tevent_req *subreq) { errno_t ret; int dp_error = DP_ERR_FATAL; struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); + struct sdap_dom_enum_state *state = tevent_req_data(req, + struct sdap_dom_enum_state); ret = enum_services_recv(subreq); talloc_zfree(subreq); @@ -401,7 +281,7 @@ static void ldap_id_enum_services_done(struct tevent_req *subreq) ret = sdap_id_op_done(state->op, ret, &dp_error); if (dp_error == DP_ERR_OK && ret != EOK) { /* retry */ - ret = ldap_id_enumerate_retry(req); + ret = sdap_dom_enum_retry(req); if (ret == EOK) { return; } @@ -423,21 +303,20 @@ static void ldap_id_enum_services_done(struct tevent_req *subreq) } if (state->purge) { - subreq = ldap_id_cleanup_send(state, state->ev, state->ctx); if (!subreq) { tevent_req_error(req, ENOMEM); return; } - tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req); + tevent_req_set_callback(subreq, sdap_dom_enum_cleanup_done, req); return; } tevent_req_done(req); } -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq) +static void sdap_dom_enum_cleanup_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); @@ -445,8 +324,14 @@ static void ldap_id_enum_cleanup_done(struct tevent_req *subreq) tevent_req_done(req); } +errno_t sdap_dom_enum_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + /* ==User-Enumeration===================================================== */ - struct enum_users_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; @@ -457,7 +342,7 @@ struct enum_users_state { const char **attrs; }; -static void enum_users_op_done(struct tevent_req *subreq); +static void enum_users_done(struct tevent_req *subreq); static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -480,14 +365,14 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, state->op = op; use_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->domain_id); + ctx->opts->idmap_ctx, + sdom->dom->domain_id); /* We always want to filter on objectclass and an available name */ state->filter = talloc_asprintf(state, - "(&(objectclass=%s)(%s=*)", - ctx->opts->user_map[SDAP_OC_USER].name, - ctx->opts->user_map[SDAP_AT_USER_NAME].name); + "(&(objectclass=%s)(%s=*)", + ctx->opts->user_map[SDAP_OC_USER].name, + ctx->opts->user_map[SDAP_AT_USER_NAME].name); if (!state->filter) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to build base filter\n")); @@ -567,7 +452,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, ret = ENOMEM; goto fail; } - tevent_req_set_callback(subreq, enum_users_op_done, req); + tevent_req_set_callback(subreq, enum_users_done, req); return req; @@ -577,7 +462,7 @@ fail: return req; } -static void enum_users_op_done(struct tevent_req *subreq) +static void enum_users_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); @@ -597,7 +482,8 @@ static void enum_users_op_done(struct tevent_req *subreq) if (usn_value) { talloc_zfree(state->ctx->srv_opts->max_user_value); - state->ctx->srv_opts->max_user_value = talloc_steal(state->ctx, usn_value); + state->ctx->srv_opts->max_user_value = + talloc_steal(state->ctx, usn_value); usn_number = strtoul(usn_value, &endptr, 10); if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value)) @@ -620,7 +506,6 @@ static errno_t enum_users_recv(struct tevent_req *req) } /* =Group-Enumeration===================================================== */ - struct enum_groups_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; @@ -631,7 +516,7 @@ struct enum_groups_state { const char **attrs; }; -static void enum_groups_op_done(struct tevent_req *subreq); +static void enum_groups_done(struct tevent_req *subreq); static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -654,14 +539,14 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, state->op = op; use_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->domain_id); + ctx->opts->idmap_ctx, + sdom->dom->domain_id); /* We always want to filter on objectclass and an available name */ state->filter = talloc_asprintf(state, - "(&(objectclass=%s)(%s=*)", - ctx->opts->group_map[SDAP_OC_GROUP].name, - ctx->opts->group_map[SDAP_AT_GROUP_NAME].name); + "(&(objectclass=%s)(%s=*)", + ctx->opts->group_map[SDAP_OC_GROUP].name, + ctx->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->filter) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to build base filter\n")); @@ -736,7 +621,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, ret = ENOMEM; goto fail; } - tevent_req_set_callback(subreq, enum_groups_op_done, req); + tevent_req_set_callback(subreq, enum_groups_done, req); return req; @@ -746,7 +631,7 @@ fail: return req; } -static void enum_groups_op_done(struct tevent_req *subreq) +static void enum_groups_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); @@ -787,4 +672,3 @@ static errno_t enum_groups_recv(struct tevent_req *req) return EOK; } - diff --git a/src/providers/ldap/sdap_async_enum.h b/src/providers/ldap/sdap_async_enum.h new file mode 100644 index 0000000000000000000000000000000000000000..04ec8c6dcbec4bcce0de67b9e10acc857c9e9416 --- /dev/null +++ b/src/providers/ldap/sdap_async_enum.h @@ -0,0 +1,38 @@ +/* + SSSD + + LDAP Enumeration Module + + Authors: + Simo Sorce + Jakub Hrozek + + Copyright (C) 2013 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SDAP_ASYNC_ENUM_H_ +#define _SDAP_ASYNC_ENUM_H_ + +struct tevent_req * +sdap_dom_enum_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn); + +errno_t sdap_dom_enum_recv(struct tevent_req *req); + +#endif /* _SDAP_ASYNC_ENUM_H_ */ diff --git a/src/providers/ldap/sdap_reinit.c b/src/providers/ldap/sdap_reinit.c index b273c1a66cca5e78ab3c281c684feab93f476471..d7b50bbbd61b98abd6a7c50d237544df32a991c3 100644 --- a/src/providers/ldap/sdap_reinit.c +++ b/src/providers/ldap/sdap_reinit.c @@ -25,6 +25,7 @@ #include "util/util.h" #include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_async_enum.h" #include "db/sysdb.h" #include "db/sysdb_services.h" @@ -79,7 +80,8 @@ struct tevent_req* sdap_reinit_cleanup_send(TALLOC_CTX *mem_ctx, goto immediately; } - subreq = ldap_id_enumerate_send(be_ctx->ev, id_ctx); + subreq = sdap_dom_enum_send(id_ctx, be_ctx->ev, id_ctx, + id_ctx->opts->sdom, id_ctx->conn); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to issue enumeration request\n")); ret = ENOMEM; @@ -199,17 +201,16 @@ static void sdap_reinit_cleanup_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_reinit_cleanup_state *state = NULL; - enum tevent_req_state tstate; - uint64_t err; errno_t ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_reinit_cleanup_state); - if (tevent_req_is_error(subreq, &tstate, &err)) { - ret = err; + ret = sdap_dom_enum_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Domain enumeration failed [%d]: %s\n", - err, strerror(err))); + ret, strerror(ret))); goto fail; } -- 1.8.3.1