URL: https://github.com/SSSD/sssd/pull/187 Author: fidencio Title: #187: Add support to lookup for users/groups in subdomains just by the user shortname Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/187/head:pr187 git checkout pr187
From 87a447bb7c101eda7a44c3b280208d4ca5362689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Fri, 24 Feb 2017 21:58:45 +0100 Subject: [PATCH 1/7] CACHE_REQ: Move cache_req_next_domain() into a new tevent request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 <[email protected]> --- src/responder/common/cache_req/cache_req.c | 504 +++++++++++++++++++---------- 1 file changed, 334 insertions(+), 170 deletions(-) diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c index 16429c6..a88ee22 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,312 @@ 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); + +static errno_t +cache_req_search_domains_add_result( + struct cache_req_search_domains_state *state, + struct cache_req_result *new) +{ + struct cache_req_result **results = state->results; + size_t index; + size_t count; + + /* Make space for new results. */ + index = state->num_results; + count = state->num_results + 1; + + results = talloc_realloc(state, results, struct cache_req_result *, count + 1); + if (results == NULL) { + return ENOMEM; + } + + results[index] = talloc_steal(results, new); + results[index + 1] = NULL; + state->results = results; + state->num_results = count; + + return EOK; +} + +static errno_t +cache_req_search_domains_create_and_add_result( + struct cache_req_search_domains_state *state, + struct sss_domain_info *domain, + struct ldb_result *ldb_result, + const char *name) +{ + struct cache_req_result *item; + errno_t ret; + + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, + "Found %u entries in domain %s\n", + ldb_result->count, domain->name); + + item = cache_req_create_result(state, domain, ldb_result, name, NULL); + if (item == NULL) { + return ENOMEM; + } + + ret = cache_req_search_domains_add_result(state, item); + if (ret != EOK) { + talloc_free(item); + } + + return ret; +} + +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_search_domains_create_and_add_result( + state, + state->selected_domain, + result, + state->cr->data->name.lookup); + 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_add_result(struct cache_req_state *state, struct cache_req_result *new); @@ -331,10 +637,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); @@ -359,7 +664,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; @@ -477,114 +781,55 @@ 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 errno_t @@ -612,99 +857,18 @@ cache_req_add_result(struct cache_req_state *state, return EOK; } -static errno_t -cache_req_create_and_add_result(struct cache_req_state *state, - struct sss_domain_info *domain, - struct ldb_result *ldb_result, - const char *name) -{ - struct cache_req_result *item; - errno_t ret; - - CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, - "Found %u entries in domain %s\n", - ldb_result->count, domain->name); - - item = cache_req_create_result(state, domain, ldb_result, name, NULL); - if (item == NULL) { - return ENOMEM; - } - - ret = cache_req_add_result(state, item); - if (ret != EOK) { - talloc_free(item); - } - - return ret; -} - 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->selected_domain, - result, - state->cr->data->name.lookup); - 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"); From bd9bcb78e4fbdad1da13b00312eaa091a63bf69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Wed, 22 Feb 2017 08:07:45 +0100 Subject: [PATCH 2/7] CACHE_REQ: Confront caches first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces a new configurable option to define whether the responder should query all domains' caches before querying the Data Providers. This new option is called confront_caches_first and, by default, it's disabled, meaning that, for each provider, the responder may contact the cache and the data provider in the same iteration. Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <[email protected]> --- src/confdb/confdb.h | 1 + src/config/SSSDConfig/__init__.py.in | 1 + src/config/SSSDConfigTest.py | 1 + src/config/cfg_rules.ini | 7 ++++ src/config/etc/sssd.api.conf | 1 + src/man/sssd.conf.5.xml | 12 ++++++ src/responder/common/cache_req/cache_req.c | 44 ++++++++++++++++++++-- src/responder/common/cache_req/cache_req_private.h | 6 ++- src/responder/common/cache_req/cache_req_search.c | 21 +++++++++-- src/responder/common/responder.h | 1 + src/responder/common/responder_common.c | 11 ++++++ 11 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 89b89bf..6e54b72 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -88,6 +88,7 @@ #define CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT "local_negative_timeout" #define CONFDB_RESPONDER_IDLE_TIMEOUT "responder_idle_timeout" #define CONFDB_RESPONDER_IDLE_DEFAULT_TIMEOUT 300 +#define CONFDB_RESPONDER_CONFRONT_CACHES_FIRST "confront_caches_first" /* NSS */ #define CONFDB_NSS_CONF_ENTRY "config/nss" diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 44fb777..0cb8ef3 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -51,6 +51,7 @@ option_strings = { 'fd_limit' : _('The number of file descriptors that may be opened by this responder'), 'client_idle_timeout' : _('Idle time before automatic disconnection of a client'), 'responder_idle_timeout' : _('Idle time before automatic shutdown of the responder'), + 'confront_caches_first': _('Always query all the caches before querying the Data Providers'), # [sssd] 'services' : _('SSSD Services to start'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 8cb03ad..b6d3a18 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -309,6 +309,7 @@ def testListOptions(self): 'fd_limit', 'client_idle_timeout', 'responder_idle_timeout', + 'confront_caches_first', 'description', 'certificate_verification', 'override_space', diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index c01aa85..78e62b3 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -59,6 +59,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # Name service option = user_attributes @@ -97,6 +98,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # Authentication service option = offline_credentials_expiration @@ -131,6 +133,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # sudo service option = sudo_timed @@ -152,6 +155,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # autofs service option = autofs_negative_timeout @@ -172,6 +176,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # ssh service option = ssh_hash_known_hosts @@ -194,6 +199,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # PAC responder option = allowed_uids @@ -215,6 +221,7 @@ option = fd_limit option = client_idle_timeout option = description option = responder_idle_timeout +option = confront_caches_first # InfoPipe responder option = allowed_uids diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index 7d21d6b..a786483 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -14,6 +14,7 @@ reconnection_retries = int, None, false fd_limit = int, None, false client_idle_timeout = int, None, false responder_idle_timeout = int, None, false +confront_caches_first = int, None, false description = str, None, false [sssd] diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 2a2ef69..429d896 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -662,6 +662,18 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term>confront_caches_first</term> + <listitem> + <para> + This option specifies whether the responder should + query all caches before querying the Data Providers. + </para> + <para> + Default: false + </para> + </listitem> + </varlistentry> </variablelist> </refsect2> diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c index a88ee22..613a937 100644 --- a/src/responder/common/cache_req/cache_req.c +++ b/src/responder/common/cache_req/cache_req.c @@ -118,6 +118,9 @@ cache_req_create(TALLOC_CTX *mem_ctx, return NULL; } + cr->confront_caches_first = rctx->confront_caches_first; + cr->bypass_cache = cr->plugin->bypass_cache || cr->data->bypass_cache; + return cr; } @@ -319,6 +322,8 @@ struct cache_req_search_domains_state { size_t num_results; bool check_next; bool dp_success; + bool bypass_cache; + bool bypass_dp; }; static struct tevent_req * @@ -326,7 +331,9 @@ 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); + bool check_next, + bool bypass_cache, + bool bypass_dp); static errno_t cache_req_search_domains_next(struct tevent_req *req); @@ -392,7 +399,9 @@ 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) + bool check_next, + bool bypass_cache, + bool bypass_dp) { struct tevent_req *req; struct cache_req_search_domains_state *state = NULL; @@ -412,6 +421,8 @@ struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx, state->domain = domain; state->check_next = check_next; state->dp_success = true; + state->bypass_cache = bypass_cache; + state->bypass_dp = bypass_dp; ret = cache_req_search_domains_next(req); if (ret == EAGAIN) { @@ -472,7 +483,8 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) return ret; } - subreq = cache_req_search_send(state, state->ev, cr); + subreq = cache_req_search_send(state, state->ev, cr, + state->bypass_cache, state->bypass_dp); if (subreq == NULL) { return ENOMEM; } @@ -621,10 +633,12 @@ struct cache_req_state { /* input data */ struct tevent_context *ev; struct cache_req *cr; + const char *domain_name; /* work data */ struct cache_req_result **results; size_t num_results; + bool bypass_cache; }; static errno_t cache_req_add_result(struct cache_req_state *state, @@ -685,6 +699,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, goto done; } + state->domain_name = domain; ret = cache_req_select_domains(req, domain); done: @@ -773,6 +788,7 @@ static void cache_req_input_parsed(struct tevent_req *subreq) return; } + state->domain_name = domain; ret = cache_req_select_domains(req, domain); if (ret != EAGAIN) { tevent_req_error(req, ret); @@ -816,14 +832,27 @@ static errno_t cache_req_search_domains(struct tevent_req *req, { struct tevent_req *subreq; struct cache_req_state *state = NULL; + bool bypass_dp; state = tevent_req_data(req, struct cache_req_state); + bypass_dp = false; + if (state->cr->confront_caches_first) { + bypass_dp = !state->bypass_cache; + } + + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, + "Search will %s the cache and %s the data provider\n", + state->bypass_cache ? "bypass" : "confront", + bypass_dp ? "bypass" : "confront"); + subreq = cache_req_search_domains_send(state, state->ev, state->cr, domain, - check_next); + check_next, + state->bypass_cache, + bypass_dp); if (subreq == NULL) { return ENOMEM; } @@ -869,6 +898,13 @@ static void cache_req_done(struct tevent_req *subreq) ret = cache_req_search_domains_recv(state, subreq, &state->results); talloc_zfree(subreq); + if (state->cr->confront_caches_first && !state->bypass_cache) { + if (ret == ENOENT) { + state->bypass_cache = true; + ret = cache_req_select_domains(req, state->domain_name); + } + } + switch (ret) { case EOK: CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, "Finished: Success\n"); diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h index 3839f5a..8af2bdf 100644 --- a/src/responder/common/cache_req/cache_req_private.h +++ b/src/responder/common/cache_req/cache_req_private.h @@ -40,6 +40,8 @@ struct cache_req { /* Domain related informations. */ struct sss_domain_info *domain; + bool confront_caches_first; + bool bypass_cache; /* Debug information */ uint32_t reqid; @@ -91,7 +93,9 @@ struct cache_req_data { struct tevent_req * cache_req_search_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct cache_req *cr); + struct cache_req *cr, + bool bypass_cache, + bool bypass_dp); errno_t cache_req_search_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, diff --git a/src/responder/common/cache_req/cache_req_search.c b/src/responder/common/cache_req/cache_req_search.c index 612f194..f80ed00 100644 --- a/src/responder/common/cache_req/cache_req_search.c +++ b/src/responder/common/cache_req/cache_req_search.c @@ -181,7 +181,9 @@ static void cache_req_search_done(struct tevent_req *subreq); struct tevent_req * cache_req_search_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct cache_req *cr) + struct cache_req *cr, + bool bypass_cache, + bool bypass_dp) { struct cache_req_search_state *state; enum cache_object_status status; @@ -214,12 +216,18 @@ cache_req_search_send(TALLOC_CTX *mem_ctx, */ state->result = NULL; status = CACHE_OBJECT_MISSING; - if (!cr->plugin->bypass_cache && !cr->data->bypass_cache) { + if (!bypass_cache) { ret = cache_req_search_cache(state, cr, &state->result); if (ret != EOK && ret != ENOENT) { goto done; } + if (cr->confront_caches_first && ret == EOK) { + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, + "Returning [%s] from cache\n", cr->debugobj); + goto done; + } + status = cache_req_expiration_status(cr, state->result); if (status == CACHE_OBJECT_VALID) { CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, @@ -227,9 +235,16 @@ cache_req_search_send(TALLOC_CTX *mem_ctx, ret = EOK; goto done; } + + if (cr->confront_caches_first && ret == ENOENT) { + goto done; + } + } + + if (!bypass_dp) { + ret = cache_req_search_dp(req, status); } - ret = cache_req_search_dp(req, status); if (ret != EAGAIN) { goto done; } diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 5717d6a..a22de7d 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -138,6 +138,7 @@ struct resp_ctx { bool shutting_down; bool socket_activated; bool dbus_activated; + bool confront_caches_first; }; struct cli_creds; diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index 5c59f0d..006853b 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -1101,6 +1101,17 @@ int sss_process_init(TALLOC_CTX *mem_ctx, } } + ret = confdb_get_bool(rctx->cdb, rctx->confdb_service_path, + CONFDB_RESPONDER_CONFRONT_CACHES_FIRST, + false, &rctx->confront_caches_first); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot get \"confront_caches_option\".\n" + "Querying the caches first before querying the " + "Data Providers will not be enforced [%d]: %s.\n", + ret, sss_strerror(ret)); + } + ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path, CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT, GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout); From 3a4623df16ba6cc6312b4a85ddb00ae1aa9ba438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Wed, 1 Mar 2017 08:34:57 +0000 Subject: [PATCH 3/7] CACHE_REQ: Descend into subdomains on lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's make all plugins, but the "host_by_name", to descend into the subdomains on lookups. This patch basically prepares the field for the coming up patches that will allow group/user resolution in all domains (or a subset of the domains) to be possible by only using the short names without the domain component. The "host_by_name" plugin was not changed as it's a specific IPA plugin and won't find anything on its subdomains. Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <[email protected]> --- src/responder/common/cache_req/plugins/cache_req_enum_svc.c | 2 +- src/responder/common/cache_req/plugins/cache_req_group_by_filter.c | 2 +- src/responder/common/cache_req/plugins/cache_req_group_by_name.c | 2 +- src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c | 2 +- src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c | 2 +- src/responder/common/cache_req/plugins/cache_req_object_by_name.c | 2 +- src/responder/common/cache_req/plugins/cache_req_svc_by_name.c | 2 +- src/responder/common/cache_req/plugins/cache_req_svc_by_port.c | 2 +- src/responder/common/cache_req/plugins/cache_req_user_by_filter.c | 2 +- src/responder/common/cache_req/plugins/cache_req_user_by_name.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c index 2c4917c..28dea33 100644 --- a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c +++ b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c @@ -68,7 +68,7 @@ const struct cache_req_plugin cache_req_enum_svc = { .allow_missing_fqn = true, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = NULL, diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c index 88e1137..6ce6ae0 100644 --- a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c @@ -123,7 +123,7 @@ const struct cache_req_plugin cache_req_group_by_filter = { .allow_missing_fqn = false, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_group_by_filter_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c index be1eb9b..af6f23c 100644 --- a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c @@ -186,7 +186,7 @@ const struct cache_req_plugin cache_req_group_by_name = { .allow_missing_fqn = false, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_group_by_name_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c index 10fb67c..307b65a 100644 --- a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c @@ -201,7 +201,7 @@ const struct cache_req_plugin cache_req_initgroups_by_name = { .allow_missing_fqn = false, .allow_switch_to_upn = true, .upn_equivalent = CACHE_REQ_INITGROUPS_BY_UPN, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_initgroups_by_name_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c index bc6fc9a..e49d6d8 100644 --- a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c @@ -120,7 +120,7 @@ const struct cache_req_plugin cache_req_netgroup_by_name = { .allow_missing_fqn = true, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_netgroup_by_name_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c index 2b2caee..74d2b3d 100644 --- a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c @@ -196,7 +196,7 @@ const struct cache_req_plugin cache_req_object_by_name = { .allow_missing_fqn = false, .allow_switch_to_upn = true, .upn_equivalent = CACHE_REQ_USER_BY_UPN, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = cache_req_object_by_name_well_known, .prepare_domain_data_fn = cache_req_object_by_name_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c index cbb186d..ef13f09 100644 --- a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c @@ -144,7 +144,7 @@ const struct cache_req_plugin cache_req_svc_by_name = { .allow_missing_fqn = false, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_svc_by_name_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c index 1da23d4..afa2eee 100644 --- a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c +++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c @@ -117,7 +117,7 @@ const struct cache_req_plugin cache_req_svc_by_port = { .allow_missing_fqn = false, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_svc_by_port_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c index ee7e693..eb71b42 100644 --- a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c @@ -123,7 +123,7 @@ const struct cache_req_plugin cache_req_user_by_filter = { .allow_missing_fqn = false, .allow_switch_to_upn = false, .upn_equivalent = CACHE_REQ_SENTINEL, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_user_by_filter_prepare_domain_data, diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c index 4289f5f..0670feb 100644 --- a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c @@ -191,7 +191,7 @@ const struct cache_req_plugin cache_req_user_by_name = { .allow_missing_fqn = false, .allow_switch_to_upn = true, .upn_equivalent = CACHE_REQ_USER_BY_UPN, - .get_next_domain_flags = 0, + .get_next_domain_flags = SSS_GND_DESCEND, .is_well_known_fn = NULL, .prepare_domain_data_fn = cache_req_user_by_name_prepare_domain_data, From dbc1bf20ac0845b23ce6ff22b5c6255c5b663480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Mon, 27 Feb 2017 16:50:41 +0000 Subject: [PATCH 4/7] Allow subdomains to inherit "use_fully_qualified_names" option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces the possibility to have subdomains inheriting the "use_fully_qualified_names" option from its parent domain. The intention behind this change is to allow user and group resolution and user authentication in all the domains or a subset of the domains to be possible by using only the short names without the domain component. Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <[email protected]> --- src/db/sysdb_subdomains.c | 7 ++++++- src/man/sssd.conf.5.xml | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c index 01f4976..6b501e8 100644 --- a/src/db/sysdb_subdomains.c +++ b/src/db/sysdb_subdomains.c @@ -118,7 +118,6 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, } dom->enumerate = enumerate; - dom->fqnames = true; dom->mpg = mpg; dom->state = DOM_ACTIVE; @@ -147,6 +146,12 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, dom->service_timeout = parent->service_timeout; dom->names = parent->names; + /* If the parent domain requires fully-qualified names, the subdomain should + * do as well */ + inherit_option = string_in_list(CONFDB_DOMAIN_FQ, + parent->sd_inherit, false); + dom->fqnames = inherit_option ? parent->fqnames : true; + dom->override_homedir = parent->override_homedir; dom->fallback_homedir = parent->fallback_homedir; dom->subdomain_homedir = parent->subdomain_homedir; diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 429d896..6c30580 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -2491,6 +2491,9 @@ pam_account_locked_message = Account locked, please contact help desk. ldap_user_principal </para> <para> + use_fully_qualified_names + </para> + <para> ldap_krb5_keytab (the value of krb5_keytab will be used if ldap_krb5_keytab is not set explicitly) </para> From 81b17d8e167ed9b391bb7f8f2cac0e47ab9279a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]> Date: Wed, 1 Mar 2017 13:21:19 +0000 Subject: [PATCH 5/7] NSS/TESTS: Fix subdomains attribution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related: https://pagure.io/SSSD/sssd/issue/3001 Reviewed-by: Fabiano Fidêncio <[email protected]> --- src/tests/cmocka/test_nss_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index 72bbaf9..d06326e 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -3217,7 +3217,7 @@ static int nss_subdom_test_setup(void **state) ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom); assert_int_equal(ret, EOK); - nss_test_ctx->subdom = subdomain; + nss_test_ctx->subdom = nss_test_ctx->tctx->dom->subdomains; return 0; } From 7a9efa7a3a24efd7fdb74790a568be0153463c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Wed, 1 Mar 2017 20:46:10 +0000 Subject: [PATCH 6/7] NSS/TESTS: Improve setup/teardown for subdomains tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch basically makes the getgrnam_members_subdom(), getgrnam_mix_dom(), getgrnam_mix_dom_fqdn() and getgrnam_mix_subdom() more independent of each other. Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <[email protected]> --- src/tests/cmocka/test_nss_srv.c | 182 +++++++++++++++++++++++++++++++++------- 1 file changed, 150 insertions(+), 32 deletions(-) diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index d06326e..ff740c7 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -418,6 +418,26 @@ static errno_t store_user(struct nss_test_ctx *ctx, return ret; } +static errno_t delete_user(struct nss_test_ctx *ctx, + struct sss_domain_info *dom, + struct passwd *user) +{ + errno_t ret; + char *fqname; + + fqname = sss_create_internal_fqname(ctx, + user->pw_name, + dom->name); + if (fqname == NULL) { + return ENOMEM; + } + + ret = sysdb_delete_user(dom, fqname, user->pw_uid); + + talloc_free(fqname); + return ret; +} + static errno_t set_user_attr(struct nss_test_ctx *ctx, struct sss_domain_info *dom, struct passwd *user, @@ -491,6 +511,27 @@ static errno_t store_group(struct nss_test_ctx *ctx, return ret; } +static errno_t delete_group(struct nss_test_ctx *ctx, + struct sss_domain_info *dom, + struct group *group) +{ + errno_t ret; + char *fqname; + + fqname = sss_create_internal_fqname(ctx, + group->gr_name, + dom->name); + + if (fqname == NULL) { + return ENOMEM; + } + + ret = sysdb_delete_group(dom, fqname, group->gr_gid); + + talloc_free(fqname); + return ret; +} + static void assert_groups_equal(struct group *expected, struct group *gr, const int nmem) { @@ -540,6 +581,42 @@ static errno_t store_group_member(struct nss_test_ctx *ctx, return ret; } +static errno_t remove_group_member(struct nss_test_ctx *ctx, + const char *shortname_group, + struct sss_domain_info *group_dom, + const char *shortname_member, + struct sss_domain_info *member_dom, + enum sysdb_member_type type) +{ + errno_t ret; + char *group_fqname = NULL; + char *member_fqname = NULL; + + group_fqname = sss_create_internal_fqname(ctx, + shortname_group, + group_dom->name); + if (group_fqname == NULL) { + return ENOMEM; + } + + member_fqname = sss_create_internal_fqname(ctx, + shortname_member, + member_dom->name); + if (member_fqname == NULL) { + talloc_free(group_fqname); + return ENOMEM; + } + + ret = sysdb_remove_group_member(group_dom, + group_fqname, + member_fqname, + type, + false); + + talloc_free(group_fqname); + talloc_free(member_fqname); + return ret; +} /* ====================== The tests =============================== */ struct passwd getpwnam_usr = { @@ -1599,34 +1676,6 @@ void test_nss_getgrnam_members_subdom(void **state) { errno_t ret; - ret = store_group(nss_test_ctx, nss_test_ctx->subdom, - &testsubdomgroup, 0); - assert_int_equal(ret, EOK); - - ret = store_user(nss_test_ctx, nss_test_ctx->subdom, - &submember1, NULL, 0); - assert_int_equal(ret, EOK); - - ret = store_user(nss_test_ctx, nss_test_ctx->subdom, - &submember2, NULL, 0); - assert_int_equal(ret, EOK); - - ret = store_group_member(nss_test_ctx, - testsubdomgroup.gr_name, - nss_test_ctx->subdom, - submember1.pw_name, - nss_test_ctx->subdom, - SYSDB_MEMBER_USER); - assert_int_equal(ret, EOK); - - ret = store_group_member(nss_test_ctx, - testsubdomgroup.gr_name, - nss_test_ctx->subdom, - submember2.pw_name, - nss_test_ctx->subdom, - SYSDB_MEMBER_USER); - assert_int_equal(ret, EOK); - mock_input_user_or_group("testsubdomgroup@"TEST_SUBDOM_NAME); will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); @@ -1757,6 +1806,14 @@ void test_nss_getgrnam_mix_dom_fqdn(void **state) { errno_t ret; + ret = store_group_member(nss_test_ctx, + testgroup_members.gr_name, + nss_test_ctx->tctx->dom, + submember1.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + nss_test_ctx->tctx->dom->fqnames = true; mock_input_user_or_group("testgroup_members@"TEST_DOM_NAME); @@ -3218,6 +3275,35 @@ static int nss_subdom_test_setup(void **state) assert_int_equal(ret, EOK); nss_test_ctx->subdom = nss_test_ctx->tctx->dom->subdomains; + + ret = store_group(nss_test_ctx, nss_test_ctx->subdom, + &testsubdomgroup, 0); + assert_int_equal(ret, EOK); + + ret = store_user(nss_test_ctx, nss_test_ctx->subdom, + &submember1, NULL, 0); + assert_int_equal(ret, EOK); + + ret = store_user(nss_test_ctx, nss_test_ctx->subdom, + &submember2, NULL, 0); + assert_int_equal(ret, EOK); + + ret = store_group_member(nss_test_ctx, + testsubdomgroup.gr_name, + nss_test_ctx->subdom, + submember1.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + ret = store_group_member(nss_test_ctx, + testsubdomgroup.gr_name, + nss_test_ctx->subdom, + submember2.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + return 0; } @@ -3239,6 +3325,38 @@ static int nss_test_teardown(void **state) return 0; } +static int nss_subdom_test_teardown(void **state) +{ + errno_t ret; + + ret = remove_group_member(nss_test_ctx, + testsubdomgroup.gr_name, + nss_test_ctx->subdom, + submember2.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + ret = remove_group_member(nss_test_ctx, + testsubdomgroup.gr_name, + nss_test_ctx->subdom, + submember1.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + ret = delete_user(nss_test_ctx, nss_test_ctx->subdom, &submember2); + assert_int_equal(ret, EOK); + + ret = delete_user(nss_test_ctx, nss_test_ctx->subdom, &submember1); + assert_int_equal(ret, EOK); + + ret = delete_group(nss_test_ctx, nss_test_ctx->subdom, &testsubdomgroup); + assert_int_equal(ret, EOK); + + return nss_test_teardown(state); +} + struct passwd testbysid = { .pw_name = discard_const("testsiduser"), .pw_uid = 12345, @@ -3748,16 +3866,16 @@ int main(int argc, const char *argv[]) nss_fqdn_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom, nss_subdom_test_setup, - nss_test_teardown), + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom, nss_subdom_test_setup, - nss_test_teardown), + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn, nss_subdom_test_setup, - nss_test_teardown), + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom, nss_subdom_test_setup, - nss_test_teardown), + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_space, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_space_sub, From d2a1c9bc0bad05f2e1a253f386e14e65126e9c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <[email protected]> Date: Wed, 1 Mar 2017 08:33:06 +0000 Subject: [PATCH 7/7] NSS/TESTS: Include searches for non-fqnames members of a subdomain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's extend the NSS tests in order to also test looking up users, from a subdomain, by their short names (non fully qualified names). Related: https://pagure.io/SSSD/sssd/issue/3001 Signed-off-by: Fabiano Fidêncio <[email protected]> --- src/tests/cmocka/test_nss_srv.c | 250 ++++++++++++++++++++++++++++++++++------ 1 file changed, 213 insertions(+), 37 deletions(-) diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index ff740c7..f065ac3 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -1648,16 +1648,29 @@ static int test_nss_getgrnam_members_check_subdom(uint32_t status, tmp_ctx = talloc_new(nss_test_ctx); assert_non_null(tmp_ctx); - exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember1.pw_name); - assert_non_null(exp_members[0]); - exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember2.pw_name); - assert_non_null(exp_members[1]); - - expected.gr_name = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, testsubdomgroup.gr_name); - assert_non_null(expected.gr_name); + if (nss_test_ctx->subdom->fqnames) { + exp_members[0] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember1.pw_name); + assert_non_null(exp_members[0]); + + exp_members[1] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember2.pw_name); + assert_non_null(exp_members[1]); + + expected.gr_name = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + testsubdomgroup.gr_name); + assert_non_null(expected.gr_name); + } else { + exp_members[0] = submember1.pw_name; + exp_members[1] = submember2.pw_name; + expected.gr_name = testsubdomgroup.gr_name; + } assert_int_equal(status, EOK); @@ -1692,6 +1705,29 @@ void test_nss_getgrnam_members_subdom(void **state) assert_int_equal(ret, EOK); } +void test_nss_getgrnam_members_subdom_nonfqnames(void **state) +{ + errno_t ret; + + nss_test_ctx->subdom->fqnames = false; + + mock_input_user_or_group("testsubdomgroup"); + mock_account_recv_simple(); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); + will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + /* Query for that group, call a callback when command finishes */ + set_cmd_cb(test_nss_getgrnam_members_check_subdom); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + + assert_int_equal(ret, EOK); +} + static int test_nss_getgrnam_check_mix_dom(uint32_t status, uint8_t *body, size_t blen) { @@ -1710,9 +1746,15 @@ static int test_nss_getgrnam_check_mix_dom(uint32_t status, tmp_ctx = talloc_new(nss_test_ctx); assert_non_null(tmp_ctx); - exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember1.pw_name); - assert_non_null(exp_members[0]); + if (nss_test_ctx->subdom->fqnames) { + exp_members[0] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember1.pw_name); + assert_non_null(exp_members[0]); + } else { + exp_members[0] = submember1.pw_name; + } exp_members[1] = testmember1.pw_name; exp_members[2] = testmember2.pw_name; @@ -1756,6 +1798,35 @@ void test_nss_getgrnam_mix_dom(void **state) assert_int_equal(ret, EOK); } +void test_nss_getgrnam_mix_dom_nonfqnames(void **state) +{ + errno_t ret; + + nss_test_ctx->subdom->fqnames = false; + + ret = store_group_member(nss_test_ctx, + testgroup_members.gr_name, + nss_test_ctx->tctx->dom, + submember1.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testgroup_members"); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); + will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + /* Query for that group, call a callback when command finishes */ + set_cmd_cb(test_nss_getgrnam_check_mix_dom); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + assert_int_equal(ret, EOK); +} + static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status, uint8_t *body, size_t blen) { @@ -1773,21 +1844,33 @@ static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status, tmp_ctx = talloc_new(nss_test_ctx); assert_non_null(tmp_ctx); - exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember1.pw_name); - assert_non_null(exp_members[0]); - exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, - nss_test_ctx->tctx->dom, testmember1.pw_name); - assert_non_null(exp_members[1]); - exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, - nss_test_ctx->tctx->dom, testmember2.pw_name); - assert_non_null(exp_members[2]); - - expected.gr_name = sss_tc_fqname(tmp_ctx, - nss_test_ctx->tctx->dom->names, - nss_test_ctx->tctx->dom, - testgroup_members.gr_name); - assert_non_null(expected.gr_name); + if (nss_test_ctx->subdom->fqnames) { + exp_members[0] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember1.pw_name); + assert_non_null(exp_members[0]); + } else { + exp_members[0] = submember1.pw_name; + } + if (nss_test_ctx->tctx->dom->fqnames) { + exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, + nss_test_ctx->tctx->dom, testmember1.pw_name); + assert_non_null(exp_members[1]); + exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, + nss_test_ctx->tctx->dom, testmember2.pw_name); + assert_non_null(exp_members[2]); + + expected.gr_name = sss_tc_fqname(tmp_ctx, + nss_test_ctx->tctx->dom->names, + nss_test_ctx->tctx->dom, + testgroup_members.gr_name); + assert_non_null(expected.gr_name); + } else { + exp_members[1] = testmember1.pw_name; + exp_members[2] = testmember2.pw_name; + expected.gr_name = testgroup_members.gr_name; + } assert_int_equal(status, EOK); @@ -1834,6 +1917,40 @@ void test_nss_getgrnam_mix_dom_fqdn(void **state) assert_int_equal(ret, EOK); } +void test_nss_getgrnam_mix_dom_fqdn_nonfqnames(void **state) +{ + errno_t ret; + + ret = store_group_member(nss_test_ctx, + testgroup_members.gr_name, + nss_test_ctx->tctx->dom, + submember1.pw_name, + nss_test_ctx->subdom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + nss_test_ctx->tctx->dom->fqnames = false; + nss_test_ctx->subdom->fqnames = false; + + + mock_input_user_or_group("testgroup_members"); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); + will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + /* Query for that group, call a callback when command finishes */ + set_cmd_cb(test_nss_getgrnam_check_mix_dom_fqdn); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + + /* Restore FQDN settings */ + nss_test_ctx->tctx->dom->fqnames = false; + assert_int_equal(ret, EOK); +} + static int test_nss_getgrnam_check_mix_subdom(uint32_t status, uint8_t *body, size_t blen) { @@ -1851,20 +1968,37 @@ static int test_nss_getgrnam_check_mix_subdom(uint32_t status, tmp_ctx = talloc_new(nss_test_ctx); assert_non_null(tmp_ctx); - exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember1.pw_name); - assert_non_null(exp_members[0]); - exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, submember2.pw_name); - assert_non_null(exp_members[1]); + if (nss_test_ctx->subdom->fqnames) { + exp_members[0] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember1.pw_name); + assert_non_null(exp_members[0]); + + exp_members[1] = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + submember2.pw_name); + assert_non_null(exp_members[1]); + } else { + exp_members[0] = submember1.pw_name; + exp_members[1] = submember2.pw_name; + } + /* Important: this member is from a non-qualified domain, so his name will * not be qualified either */ exp_members[2] = testmember1.pw_name; - expected.gr_name = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, - nss_test_ctx->subdom, testsubdomgroup.gr_name); - assert_non_null(expected.gr_name); + if (nss_test_ctx->subdom->fqnames) { + expected.gr_name = sss_tc_fqname(tmp_ctx, + nss_test_ctx->subdom->names, + nss_test_ctx->subdom, + testsubdomgroup.gr_name); + assert_non_null(expected.gr_name); + } else { + expected.gr_name = testsubdomgroup.gr_name; + } assert_int_equal(status, EOK); @@ -1906,6 +2040,36 @@ void test_nss_getgrnam_mix_subdom(void **state) assert_int_equal(ret, EOK); } +void test_nss_getgrnam_mix_subdom_nonfqnames(void **state) +{ + errno_t ret; + + nss_test_ctx->subdom->fqnames = false; + + ret = store_group_member(nss_test_ctx, + testsubdomgroup.gr_name, + nss_test_ctx->subdom, + testmember1.pw_name, + nss_test_ctx->tctx->dom, + SYSDB_MEMBER_USER); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testsubdomgroup"); + mock_account_recv_simple(); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); + will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + /* Query for that group, call a callback when command finishes */ + set_cmd_cb(test_nss_getgrnam_check_mix_subdom); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + assert_int_equal(ret, EOK); +} + struct group space_group = { .gr_gid = 2123, .gr_name = discard_const("space group"), @@ -3867,15 +4031,27 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom, nss_subdom_test_setup, nss_subdom_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom_nonfqnames, + nss_subdom_test_setup, + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom, nss_subdom_test_setup, nss_subdom_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_nonfqnames, + nss_subdom_test_setup, + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn, nss_subdom_test_setup, nss_subdom_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn_nonfqnames, + nss_subdom_test_setup, + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom, nss_subdom_test_setup, nss_subdom_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom_nonfqnames, + nss_subdom_test_setup, + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_space, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getgrnam_space_sub,
_______________________________________________ sssd-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
