cache_req.c revision 9286d0d4143bcb4e36b91022107e307998122bbb
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen Pavel Březina <pbrezina@redhat.com>
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen Copyright (C) 2016 Red Hat
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen This program is free software; you can redistribute it and/or modify
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen it under the terms of the GNU General Public License as published by
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen the Free Software Foundation; either version 3 of the License, or
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (at your option) any later version.
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen This program is distributed in the hope that it will be useful,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen GNU General Public License for more details.
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen You should have received a copy of the GNU General Public License
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen#include "responder/common/cache_req/cache_req_private.h"
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen#include "responder/common/cache_req/cache_req_plugin.h"
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic const struct cache_req_plugin *
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen static const struct cache_req_plugin *plugins[CACHE_REQ_SENTINEL] = {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Bug: invalid plugin type!");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic errno_t cache_req_set_plugin(struct cache_req *cr,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "Bug: unset plugin!");
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_INTERNAL, cr, "Setting \"%s\" plugin\n",
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenstatic struct cache_req *
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* It is perfectly fine to just overflow here. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainencache_req_set_name(struct cache_req *cr, const char *name)
b8864211b88ed7521e9af514590639344af38910Timo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Setting name [%s]\n", name);
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr, "Unable to set name!\n");
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainencache_req_validate_domain(struct cache_req *cr,
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Domain %s does not support "
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return false;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Domain %s supports enumeration\n",
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainencache_req_is_well_known_object(TALLOC_CTX *mem_ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cr->plugin->is_well_known_fn(mem_ctx, cr, cr->data, _result);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Object is well known!\n");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "Unable to prepare data [%d]: %s\n",
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainencache_req_prepare_domain_data(struct cache_req *cr,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (cr->plugin->prepare_domain_data_fn == NULL) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "Preparing input data for domain [%s] rules\n",
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ret = cr->plugin->prepare_domain_data_fn(cr, cr->data, domain);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "Unable to prepare data [%d]: %s\n",
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainencache_req_create_debug_name(struct cache_req *cr,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (cr->plugin->create_debug_name_fn == NULL) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "Bug: no create debug name function specified!\n");
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen cr->debugobj = cr->plugin->create_debug_name_fn(cr, cr->data, domain);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen "Unable to create debug name!\n");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Using domain [%s]\n", domain->name);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_prepare_domain_data(cr, domain);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_create_debug_name(cr, domain);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void cache_req_global_ncache_add(struct cache_req *cr)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (cr->plugin->global_ncache_add_fn == NULL) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "This request type does not support "
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "global negative cache\n");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Adding [%s] to global "
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cr->plugin->global_ncache_add_fn(cr->ncache, cr->data);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "Cannot set negative cache for [%s] [%d]: %s\n",
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* not fatal */
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen || strchr(cr->data->name.input, '@') == NULL) {
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen return false;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_set_plugin(cr, cr->plugin->upn_equivalent);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return false;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_set_name(cr, cr->data->name.input);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_set_name() failed\n");
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return false;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Assuming UPN [%s]\n",
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* input data */
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen /* work data */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic struct tevent_req *
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainencache_req_search_domains_send(TALLOC_CTX *mem_ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic errno_t cache_req_search_domains_next(struct tevent_req *req);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic errno_t cache_req_select_domains(struct tevent_req *req,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void cache_req_search_domains_done(struct tevent_req *subreq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstruct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct cache_req_search_domains_state *state = NULL;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic errno_t cache_req_search_domains_next(struct tevent_req *req)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen state = tevent_req_data(req, struct cache_req_search_domains_state);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen next_domain_flag = cr->plugin->get_next_domain_flags;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* Check if this domain is valid for this request. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen is_domain_valid = cache_req_validate_domain(cr, state->domain);
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen state->domain = get_next_domain(state->domain, next_domain_flag);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* If not specified otherwise, we skip domains that require fully
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen * qualified names on domain less search. We do not descend into
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen * subdomains here since those are implicitly qualified.
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (state->check_next && !allow_no_fqn && state->domain->fqnames) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen state->domain = get_next_domain(state->domain, 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_set_domain(cr, state->domain);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen subreq = cache_req_search_send(state, state->ev, cr);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen tevent_req_set_callback(subreq, cache_req_search_domains_done, req);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen /* we will continue with the following domain the next time */
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen state->domain = get_next_domain(state->domain,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen /* If we've got some result from previous searches we want to return
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen * EOK here so the whole cache request is successfully finished. */
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* We have searched all available domains and no result was found.
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen * If the plug-in uses a negative cache which is shared among all domains
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen * (e.g. unique identifiers such as user or group id or sid), we add it
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen * here and return object not found error.
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen * However, we can only set the negative cache if all data provider
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen * requests succeeded because only then we can be sure that it does
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainenstatic void cache_req_search_domains_done(struct tevent_req *subreq)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen req = tevent_req_callback_data(subreq, struct tevent_req);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen state = tevent_req_data(req, struct cache_req_search_domains_state);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ret = cache_req_search_recv(state, subreq, &result, &dp_success);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* Remember if any DP request fails. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen state->dp_success = !dp_success ? false : state->dp_success;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* We got some data from this search. Save it. */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* We were unable to save data. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!state->check_next || !state->cr->plugin->search_all_domains) {
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen /* We are not interested in more results. */
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen /* Lookup domain was specified as input.
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen * We don't want to try the next domain,
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen * but we may want to try UPN search. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* Here we need to access the request created by cache_req_send()
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen * in order to pass it down to cache_req_select_domains() */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen req_send = tevent_req_callback_data(req, struct tevent_req);
goto done;
goto done;
goto done;
done:
switch (ret) {
case EOK:
case EAGAIN:
static errno_t
return EOK;
struct cache_req_state {
const char *domain);
bool check_next);
int midpoint,
const char *domain,
return NULL;
goto done;
goto done;
goto done;
goto done;
done:
return req;
const char *domain)
const char *default_domain;
return EOK;
return ENOMEM;
return EAGAIN;
char *name;
char *domain;
bool maybe_upn;
switch (ret) {
case EOK:
case ERR_DOMAIN_NOT_FOUND:
if (!maybe_upn) {
const char *domain_name)
bool check_next;
return ERR_DOMAIN_NOT_FOUND;
check_next = false;
check_next = true;
bool check_next)
return ENOMEM;
return EAGAIN;
switch (ret) {
case EOK:
case EAGAIN:
case ENOENT:
return EOK;
return EOK;
struct tevent_req *
const char *domain,
return NULL;
return req;