From f840cfd6c2ad61045160f301d6ae7276e3e33f54 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Jan 28 2016 13:46:09 +0000 Subject: cache_req: do not lookup views if possible This is needed for LOCAL view but also creates a shortcut for server side overrides. Resolves: https://fedorahosted.org/sssd/ticket/2849 Reviewed-by: Jakub Hrozek (cherry picked from commit 5f2b1986a16a394ecbecd16f82c7265b5b47b546) --- diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c index 3a436d8..2344b0f 100644 --- a/src/responder/common/responder_cache_req.c +++ b/src/responder/common/responder_cache_req.c @@ -589,24 +589,101 @@ static errno_t cache_req_expiration_status(struct cache_req_input *input, return sss_cmd_check_cache(result->msgs[0], cache_refresh_percent, expire); } -static void cache_req_dpreq_params(struct cache_req_input *input, +static void cache_req_dpreq_params(TALLOC_CTX *mem_ctx, + struct cache_req_input *input, + struct ldb_result *result, const char **_string, uint32_t *_id, const char **_flag) { + struct ldb_result *user = NULL; + const char *name = NULL; + uint32_t id = 0; + errno_t ret; + *_id = input->id; *_string = input->dom_objname; + *_flag = NULL; + + if (cache_req_input_is_upn(input)) { + *_flag = EXTRA_NAME_IS_UPN; + return; + } if (input->type == CACHE_REQ_USER_BY_CERT) { *_string = input->cert; + return; } - *_flag = NULL; - if (DOM_HAS_VIEWS(input->domain)) { + if (!DOM_HAS_VIEWS(input->domain)) { + return; + } + + /* We must search with views. */ + if (result == NULL || result->count == 0) { *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; - } else if (cache_req_input_is_upn(input)) { - *_flag = EXTRA_NAME_IS_UPN; + return; } + + /* If domain has views we will try to user original values instead of the + * overridden ones. This is a must for the LOCAL view since we can't look + * it up otherwise. But it is also a shortcut for non-local views where + * we will not fail over to the overridden value. */ + + switch (input->type) { + case CACHE_REQ_USER_BY_NAME: + case CACHE_REQ_GROUP_BY_NAME: + name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); + } + break; + case CACHE_REQ_USER_BY_ID: + id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_UIDNUM, 0); + if (id == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); + } + break; + case CACHE_REQ_GROUP_BY_ID: + id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_GIDNUM, 0); + if (id == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); + } + break; + case CACHE_REQ_INITGROUPS: + ret = sysdb_getpwnam_with_views(NULL, input->domain, + input->dom_objname, &user); + if (ret != EOK || user == NULL || user->count != 1) { + /* Case where the user is not found has been already handled. If + * this is not OK, it is an error. */ + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to match initgroups user " + "[%d]: %s\n", ret, sss_strerror(ret)); + break; + } + + name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME, + NULL); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); + break; + } + + talloc_steal(mem_ctx, name); + talloc_free(user); + break; + default: + return; + } + + /* Now we have the original name and id. We don't have to search with + * views unless some error occurred. */ + if (name == NULL && id == 0) { + *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; + return; + } + + *_string = talloc_steal(mem_ctx, name); + *_id = id; } struct cache_req_cache_state { @@ -716,7 +793,8 @@ static errno_t cache_req_cache_check(struct tevent_req *req) state = tevent_req_data(req, struct cache_req_cache_state); - cache_req_dpreq_params(state->input, &search_str, &search_id, &extra_flag); + cache_req_dpreq_params(state, state->input, state->result, + &search_str, &search_id, &extra_flag); ret = cache_req_expiration_status(state->input, state->result, state->cache_refresh_percent);