diff options
| author | Fabiano Fidêncio <fidencio@redhat.com> | 2017-02-24 21:58:45 +0100 |
|---|---|---|
| committer | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-14 12:34:56 +0100 |
| commit | 9286d0d4143bcb4e36b91022107e307998122bbb (patch) | |
| tree | ad7bd0edd6bb3ef6e0d569b23f6f7420e9d1b6ea /src/responder/common | |
| parent | 7cd226414c7bcdd32f05416df64ebda3ac869bd7 (diff) | |
| download | sssd-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.c | 427 |
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"); |
