summaryrefslogtreecommitdiffstats
path: root/src/responder/common
diff options
context:
space:
mode:
authorFabiano Fidêncio <fidencio@redhat.com>2017-02-24 21:58:45 +0100
committerJakub Hrozek <jhrozek@redhat.com>2017-03-14 12:34:56 +0100
commit9286d0d4143bcb4e36b91022107e307998122bbb (patch)
treead7bd0edd6bb3ef6e0d569b23f6f7420e9d1b6ea /src/responder/common
parent7cd226414c7bcdd32f05416df64ebda3ac869bd7 (diff)
downloadsssd-9286d0d4143bcb4e36b91022107e307998122bbb.tar.gz
sssd-9286d0d4143bcb4e36b91022107e307998122bbb.tar.xz
sssd-9286d0d4143bcb4e36b91022107e307998122bbb.zip
CACHE_REQ: Move cache_req_next_domain() into a new tevent request
This change prepares for the upcoming patch, which will have to support more than one iteration over all domains, leaving us with a better control of the whole logic around this iteration. Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com> Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/responder/common')
-rw-r--r--src/responder/common/cache_req/cache_req.c427
1 files changed, 279 insertions, 148 deletions
diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c
index 2d4c6be10..7a836c93c 100644
--- a/src/responder/common/cache_req/cache_req.c
+++ b/src/responder/common/cache_req/cache_req.c
@@ -307,7 +307,7 @@ cache_req_assume_upn(struct cache_req *cr)
return true;
}
-struct cache_req_state {
+struct cache_req_search_domains_state {
/* input data */
struct tevent_context *ev;
struct cache_req *cr;
@@ -321,6 +321,260 @@ struct cache_req_state {
bool dp_success;
};
+static struct tevent_req *
+cache_req_search_domains_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cache_req *cr,
+ struct sss_domain_info *domain,
+ bool check_next);
+
+static errno_t cache_req_search_domains_next(struct tevent_req *req);
+
+static errno_t cache_req_select_domains(struct tevent_req *req,
+ const char *domain_name);
+
+static void cache_req_search_domains_done(struct tevent_req *subreq);
+
+struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cache_req *cr,
+ struct sss_domain_info *domain,
+ bool check_next)
+{
+ struct tevent_req *req;
+ struct cache_req_search_domains_state *state = NULL;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cache_req_search_domains_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->cr = cr;
+
+ state->domain = domain;
+ state->check_next = check_next;
+ state->dp_success = true;
+
+ ret = cache_req_search_domains_next(req);
+ if (ret == EAGAIN) {
+ return req;
+ }
+
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static errno_t cache_req_search_domains_next(struct tevent_req *req)
+{
+ struct cache_req_search_domains_state *state;
+ struct tevent_req *subreq;
+ struct cache_req *cr;
+ uint32_t next_domain_flag;
+ bool is_domain_valid;
+ bool allow_no_fqn;
+ errno_t ret;
+
+ state = tevent_req_data(req, struct cache_req_search_domains_state);
+ cr = state->cr;
+
+ next_domain_flag = cr->plugin->get_next_domain_flags;
+ allow_no_fqn = cr->plugin->allow_missing_fqn;
+
+ while (state->domain != NULL) {
+ /* Check if this domain is valid for this request. */
+ is_domain_valid = cache_req_validate_domain(cr, state->domain);
+ if (!is_domain_valid) {
+ state->domain = get_next_domain(state->domain, next_domain_flag);
+ continue;
+ }
+
+ /* If not specified otherwise, we skip domains that require fully
+ * qualified names on domain less search. We do not descend into
+ * subdomains here since those are implicitly qualified.
+ */
+ if (state->check_next && !allow_no_fqn && state->domain->fqnames) {
+ state->domain = get_next_domain(state->domain, 0);
+ continue;
+ }
+
+ state->selected_domain = state->domain;
+
+ if (state->domain == NULL) {
+ break;
+ }
+
+ ret = cache_req_set_domain(cr, state->domain);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ subreq = cache_req_search_send(state, state->ev, cr);
+ if (subreq == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, cache_req_search_domains_done, req);
+
+ /* we will continue with the following domain the next time */
+ if (state->check_next) {
+ state->domain = get_next_domain(state->domain,
+ cr->plugin->get_next_domain_flags);
+ }
+
+ return EAGAIN;
+ }
+
+ /* If we've got some result from previous searches we want to return
+ * EOK here so the whole cache request is successfully finished. */
+ if (state->num_results > 0) {
+ return EOK;
+ }
+
+ /* We have searched all available domains and no result was found.
+ *
+ * If the plug-in uses a negative cache which is shared among all domains
+ * (e.g. unique identifiers such as user or group id or sid), we add it
+ * here and return object not found error.
+ *
+ * However, we can only set the negative cache if all data provider
+ * requests succeeded because only then we can be sure that it does
+ * not exist-
+ */
+ if (state->dp_success) {
+ cache_req_global_ncache_add(cr);
+ }
+
+ return ENOENT;
+}
+
+static void cache_req_search_domains_done(struct tevent_req *subreq)
+{
+ struct cache_req_search_domains_state *state;
+ struct ldb_result *result;
+ struct tevent_req *req;
+ struct tevent_req *req_send;
+ bool dp_success;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct cache_req_search_domains_state);
+
+ ret = cache_req_search_recv(state, subreq, &result, &dp_success);
+ talloc_zfree(subreq);
+
+ /* Remember if any DP request fails. */
+ state->dp_success = !dp_success ? false : state->dp_success;
+
+ switch (ret) {
+ case EOK:
+ /* We got some data from this search. Save it. */
+ ret = cache_req_create_and_add_result(state,
+ state->cr,
+ state->selected_domain,
+ result,
+ state->cr->data->name.lookup,
+ &state->results,
+ &state->num_results);
+ if (ret != EOK) {
+ /* We were unable to save data. */
+ goto done;
+ }
+
+ if (!state->check_next || !state->cr->plugin->search_all_domains) {
+ /* We are not interested in more results. */
+ ret = EOK;
+ goto done;
+ }
+
+ break;
+ case ENOENT:
+ if (state->check_next == false) {
+ /* Lookup domain was specified as input.
+ * We don't want to try the next domain,
+ * but we may want to try UPN search. */
+
+ if (cache_req_assume_upn(state->cr)) {
+ /* Here we need to access the request created by cache_req_send()
+ * in order to pass it down to cache_req_select_domains() */
+ req_send = tevent_req_callback_data(req, struct tevent_req);
+
+ /* Try UPN now. */
+ ret = cache_req_select_domains(req_send, NULL);
+ goto done;
+ }
+
+ /* Not found. */
+ ret = ENOENT;
+ goto done;
+ }
+
+ break;
+ default:
+ /* Some serious error has happened. Finish. */
+ goto done;
+ }
+
+ /* This is a domain less search, continue with the next domain. */
+ ret = cache_req_search_domains_next(req);
+
+done:
+ if (ret == ENOENT && state->results != NULL) {
+ /* We have at least one result. */
+ ret = EOK;
+ }
+
+ switch (ret) {
+ case EOK:
+ tevent_req_done(req);
+ break;
+ case EAGAIN:
+ break;
+ default:
+ tevent_req_error(req, ret);
+ break;
+ }
+
+ return;
+}
+
+static errno_t
+cache_req_search_domains_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct cache_req_result ***_results)
+{
+ struct cache_req_search_domains_state *state;
+
+ state = tevent_req_data(req, struct cache_req_search_domains_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_results != NULL) {
+ *_results = talloc_steal(mem_ctx, state->results);
+ }
+
+ return EOK;
+}
+
+struct cache_req_state {
+ /* input data */
+ struct tevent_context *ev;
+ struct cache_req *cr;
+
+ /* work data */
+ struct cache_req_result **results;
+ size_t num_results;
+};
+
static errno_t cache_req_process_input(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
struct cache_req *cr,
@@ -328,10 +582,9 @@ static errno_t cache_req_process_input(TALLOC_CTX *mem_ctx,
static void cache_req_input_parsed(struct tevent_req *subreq);
-static errno_t cache_req_select_domains(struct tevent_req *req,
- const char *domain);
-
-static errno_t cache_req_next_domain(struct tevent_req *req);
+static errno_t cache_req_search_domains(struct tevent_req *req,
+ struct sss_domain_info *domain,
+ bool check_next);
static void cache_req_done(struct tevent_req *subreq);
@@ -356,7 +609,6 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx,
}
state->ev = ev;
- state->dp_success = true;
state->cr = cr = cache_req_create(state, rctx, data, ncache, midpoint);
if (state->cr == NULL) {
ret = ENOMEM;
@@ -475,187 +727,66 @@ static void cache_req_input_parsed(struct tevent_req *subreq)
}
static errno_t cache_req_select_domains(struct tevent_req *req,
- const char *domain)
+ const char *domain_name)
{
struct cache_req_state *state = NULL;
+ struct sss_domain_info *domain;
+ bool check_next;
state = tevent_req_data(req, struct cache_req_state);
- if (domain != NULL) {
+ if (domain_name != NULL) {
CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
"Performing a single domain search\n");
- state->domain = responder_get_domain(state->cr->rctx, domain);
- if (state->domain == NULL) {
+ domain = responder_get_domain(state->cr->rctx, domain_name);
+ if (domain == NULL) {
return ERR_DOMAIN_NOT_FOUND;
}
- state->check_next = false;
+ check_next = false;
} else {
CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr,
"Performing a multi-domain search\n");
- state->domain = state->cr->rctx->domains;
- state->check_next = true;
+ domain = state->cr->rctx->domains;
+ check_next = true;
}
- return cache_req_next_domain(req);
+ return cache_req_search_domains(req, domain, check_next);
}
-static errno_t cache_req_next_domain(struct tevent_req *req)
+static errno_t cache_req_search_domains(struct tevent_req *req,
+ struct sss_domain_info *domain,
+ bool check_next)
{
- struct cache_req_state *state;
struct tevent_req *subreq;
- struct cache_req *cr;
- uint32_t next_domain_flag;
- bool is_domain_valid;
- bool allow_no_fqn;
- errno_t ret;
+ struct cache_req_state *state = NULL;
state = tevent_req_data(req, struct cache_req_state);
- cr = state->cr;
-
- next_domain_flag = cr->plugin->get_next_domain_flags;
- allow_no_fqn = cr->plugin->allow_missing_fqn;
-
- while (state->domain != NULL) {
- /* Check if this domain is valid for this request. */
- is_domain_valid = cache_req_validate_domain(cr, state->domain);
- if (!is_domain_valid) {
- state->domain = get_next_domain(state->domain, next_domain_flag);
- continue;
- }
-
- /* If not specified otherwise, we skip domains that require fully
- * qualified names on domain less search. We do not descend into
- * subdomains here since those are implicitly qualified.
- */
- if (state->check_next && !allow_no_fqn && state->domain->fqnames) {
- state->domain = get_next_domain(state->domain, 0);
- continue;
- }
-
- state->selected_domain = state->domain;
-
- if (state->domain == NULL) {
- break;
- }
-
- ret = cache_req_set_domain(cr, state->domain);
- if (ret != EOK) {
- return ret;
- }
- subreq = cache_req_search_send(state, state->ev, cr);
- if (subreq == NULL) {
- return ENOMEM;
- }
-
- tevent_req_set_callback(subreq, cache_req_done, req);
-
- /* we will continue with the following domain the next time */
- if (state->check_next) {
- state->domain = get_next_domain(state->domain,
- cr->plugin->get_next_domain_flags);
- }
-
- return EAGAIN;
- }
-
- /* If we've got some result from previous searches we want to return
- * EOK here so the whole cache request is successfully finished. */
- if (state->num_results > 0) {
- return EOK;
- }
-
- /* We have searched all available domains and no result was found.
- *
- * If the plug-in uses a negative cache which is shared among all domains
- * (e.g. unique identifiers such as user or group id or sid), we add it
- * here and return object not found error.
- *
- * However, we can only set the negative cache if all data provider
- * requests succeeded because only then we can be sure that it does
- * not exist-
- */
- if (state->dp_success) {
- cache_req_global_ncache_add(cr);
+ subreq = cache_req_search_domains_send(state, state->ev, state->cr, domain,
+ check_next);
+ if (subreq == NULL) {
+ return ENOMEM;
}
- return ENOENT;
+ tevent_req_set_callback(subreq, cache_req_done, req);
+ return EAGAIN;
}
static void cache_req_done(struct tevent_req *subreq)
{
struct cache_req_state *state;
- struct ldb_result *result;
struct tevent_req *req;
- bool dp_success;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct cache_req_state);
- ret = cache_req_search_recv(state, subreq, &result, &dp_success);
+ ret = cache_req_search_domains_recv(state, subreq, &state->results);
talloc_zfree(subreq);
- /* Remember if any DP request fails. */
- state->dp_success = !dp_success ? false : state->dp_success;
-
- switch (ret) {
- case EOK:
- /* We got some data from this search. Save it. */
- ret = cache_req_create_and_add_result(state,
- state->cr,
- state->selected_domain,
- result,
- state->cr->data->name.lookup,
- &state->results,
- &state->num_results);
- if (ret != EOK) {
- /* We were unable to save data. */
- goto done;
- }
-
- if (!state->check_next || !state->cr->plugin->search_all_domains) {
- /* We are not interested in more results. */
- ret = EOK;
- goto done;
- }
-
- break;
- case ENOENT:
- if (state->check_next == false) {
- /* Lookup domain was specified as input.
- * We don't want to try the next domain,
- * but we may want to try UPN search. */
-
- if (cache_req_assume_upn(state->cr)) {
- /* Try UPN now. */
- ret = cache_req_select_domains(req, NULL);
- goto done;
- }
-
- /* Not found. */
- ret = ENOENT;
- goto done;
- }
-
- break;
- default:
- /* Some serious error has happened. Finish. */
- goto done;
- }
-
- /* This is a domain less search, continue with the next domain. */
- ret = cache_req_next_domain(req);
-
-done:
- if (ret == ENOENT && state->results != NULL) {
- /* We have at least one result. */
- ret = EOK;
- }
-
switch (ret) {
case EOK:
CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Finished: Success\n");