summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2014-11-25 12:58:24 +0100
committerJakub Hrozek <jhrozek@redhat.com>2015-01-09 15:16:15 +0100
commitfaae3d55e5cf416f16158d3b9f8c8fd475ac6acf (patch)
tree36b256cf48ea0cfa1e2eaa5e14502b50f836d53e
parent96faa5ca7e395991885f3c354dfe543749b900a7 (diff)
downloadsssd-faae3d55e5cf416f16158d3b9f8c8fd475ac6acf.tar.gz
sssd-faae3d55e5cf416f16158d3b9f8c8fd475ac6acf.tar.xz
sssd-faae3d55e5cf416f16158d3b9f8c8fd475ac6acf.zip
IFP: use new cache interface
Reviewed-by: Michal Židek <mzidek@redhat.com>
-rw-r--r--src/responder/ifp/ifpsrv_cmd.c365
1 files changed, 45 insertions, 320 deletions
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index 49792f53c..41b354367 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -23,6 +23,7 @@
#include "db/sysdb.h"
#include "responder/ifp/ifp_private.h"
+#include "responder/common/responder_cache_req.h"
struct ifp_attr_req {
const char *name;
@@ -433,15 +434,8 @@ struct ifp_user_get_attr_state {
int neg_timeout;
};
-static void ifp_user_get_attr_dom(struct tevent_req *subreq);
-static errno_t ifp_user_get_attr_search(struct tevent_req *req);
-int ifp_cache_check(struct ifp_user_get_attr_state *state,
- enum sss_dp_acct_type search_type,
- sss_dp_callback_t callback,
- unsigned int cache_refresh_percent,
- const char *extra_flag,
- void *pvt);
-void ifp_user_get_attr_done(struct tevent_req *req);
+static void ifp_user_get_attr_lookup(struct tevent_req *subreq);
+static void ifp_user_get_attr_done(struct tevent_req *subreq);
static struct tevent_req *
ifp_user_get_attr_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
@@ -470,7 +464,7 @@ ifp_user_get_attr_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
ret = ENOMEM;
goto done;
}
- tevent_req_set_callback(subreq, ifp_user_get_attr_dom, req);
+ tevent_req_set_callback(subreq, ifp_user_get_attr_lookup, req);
ret = EOK;
done:
@@ -481,338 +475,69 @@ done:
}
static void
-ifp_user_get_attr_dom(struct tevent_req *subreq)
+ifp_user_get_attr_lookup(struct tevent_req *subreq)
{
+ struct ifp_user_get_attr_state *state = NULL;
+ struct tevent_req *req = NULL;
errno_t ret;
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct ifp_user_get_attr_state *state = tevent_req_data(req,
- struct ifp_user_get_attr_state);
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_user_get_attr_state);
ret = sss_parse_inp_recv(subreq, state, &state->name, &state->domname);
- talloc_free(subreq);
+ talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- if (state->domname) {
- /* this is a search in one domain */
- state->dom = responder_get_domain(state->rctx, state->domname);
- if (state->dom == NULL) {
- tevent_req_error(req, EINVAL);
- return;
- }
- state->check_next = false;
- } else {
- /* this is a multidomain search */
- state->dom = state->rctx->domains;
- state->check_next = true;
- }
-
- state->check_provider = NEED_CHECK_PROVIDER(state->dom->provider);
-
- /* All set up, do the search! */
- ret = ifp_user_get_attr_search(req);
- if (ret == EOK) {
- /* The data was cached. Just quit */
- tevent_req_done(req);
- return;
- } else if (ret != EAGAIN) {
- tevent_req_error(req, ret);
+ subreq = cache_req_send(state, state->rctx->ev, state->rctx,
+ state->ncache, state->neg_timeout, 0,
+ state->search_type, state->domname, state->name);
+ if (subreq == NULL) {
+ tevent_req_error(req, ENOMEM);
return;
}
- /* Execution will resume in ifp_dp_callback */
+ tevent_req_set_callback(subreq, ifp_user_get_attr_done, req);
}
-static void ifp_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static errno_t ifp_user_get_attr_search(struct tevent_req *req)
+static void ifp_user_get_attr_done(struct tevent_req *subreq)
{
- struct ifp_user_get_attr_state *state = tevent_req_data(req,
- struct ifp_user_get_attr_state);
- struct sss_domain_info *dom = state->dom;
- const char *extra_flag = NULL;
- char *name = NULL;
+ struct ifp_user_get_attr_state *state = NULL;
+ struct tevent_req *req = NULL;
errno_t ret;
- while (dom) {
- /* if it is a domainless search, skip domains that require fully
- * qualified names instead */
- while (dom && state->check_next && dom->fqnames) {
- dom = get_next_domain(dom, false);
- }
-
- if (!dom) break;
-
- if (dom != state->dom) {
- /* make sure we reset the check_provider flag when we check
- * a new domain */
- state->check_provider = NEED_CHECK_PROVIDER(dom->provider);
- }
-
- /* make sure to update the cache_req if we changed domain */
- state->dom = dom;
-
- talloc_free(name);
- name = sss_get_cased_name(state, state->name, dom->case_sensitive);
- if (!name) return ENOMEM;
-
- state->name = sss_reverse_replace_space(state, name,
- state->rctx->override_space);
- if (state->name == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sss_reverse_replace_space failed\n");
- return ENOMEM;
- }
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ret = sss_ncache_check_user(state->ncache,
- state->neg_timeout,
- dom, name);
- /* if neg cached, return we didn't find it */
- if (ret == EEXIST) {
- DEBUG(SSSDBG_TRACE_FUNC,
- "User [%s] does not exist in [%s]! (negative cache)\n",
- name, dom->name);
- /* if a multidomain search, try with next */
- if (state->check_next) {
- dom = get_next_domain(dom, false);
- continue;
- }
-
- /* There are no further domains or this was a
- * fully-qualified user request.
- */
- return ENOENT;
- }
-
- DEBUG(SSSDBG_FUNC_DATA,
- "Requesting info for [%s@%s]\n", name, dom->name);
-
- switch (state->search_type) {
- case SSS_DP_USER:
- ret = sysdb_get_user_attr_with_views(state, dom, name,
- state->attrs, &state->res);
- break;
- case SSS_DP_INITGROUPS:
- ret = sysdb_initgroups_with_views(state, dom, name,
- &state->res);
- break;
- default:
- DEBUG(SSSDBG_OP_FAILURE, "Unsupported operation\n");
- return EIO;
- }
-
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Failed to make request to our cache!\n");
- return EIO;
- }
-
- if (state->search_type == SSS_DP_USER) {
- if (state->res->count > 1) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "getpwnam call returned more than one result !?!\n");
- return ENOENT;
- }
- }
-
- if (state->res->count == 0 && state->check_provider == false) {
- /* set negative cache only if not result of cache check */
- ret = sss_ncache_set_user(state->ncache, false, dom, name);
- if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set negcache for %s@%s\n",
- name, dom->name);
- /* Not fatal */
- }
-
- /* if a multidomain search, try with next */
- if (state->check_next) {
- dom = get_next_domain(dom, false);
- if (dom) continue;
- }
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_user_get_attr_state);
- DEBUG(SSSDBG_TRACE_FUNC, "No results for getpwnam call\n");
- return ENOENT;
- }
-
- /* if this is a caching provider (or if we haven't checked the cache
- * yet) then verify that the cache is uptodate */
- if (state->check_provider) {
- if (DOM_HAS_VIEWS(dom) && state->res->count == 0) {
- extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
- }
-
- ret = ifp_cache_check(state, state->search_type,
- ifp_dp_callback, 0, extra_flag, req);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return ret;
- }
- }
-
- /* One result found */
- DEBUG(SSSDBG_TRACE_FUNC,
- "Returning info for user [%s@%s]\n", name, dom->name);
- return EOK;
- }
-
- DEBUG(SSSDBG_MINOR_FAILURE,
- "No matching domain found for [%s], fail!\n", state->inp);
- return ENOENT;
-}
-
-int ifp_cache_check(struct ifp_user_get_attr_state *state,
- enum sss_dp_acct_type search_type,
- sss_dp_callback_t callback,
- unsigned int cache_refresh_percent,
- const char *extra_flag,
- void *pvt)
-{
- uint64_t cache_expire = 0;
- int ret;
- struct tevent_req *req;
- struct dp_callback_ctx *cb_ctx = NULL;
-
- if (search_type == SSS_DP_USER && state->res->count > 1) {
- DEBUG(SSSDBG_OP_FAILURE,
- "cache search call returned more than one result! "
- "DB Corrupted?\n");
- return ENOENT;
- }
-
- if (state->res->count > 0) {
- if (search_type == SSS_DP_USER) {
- cache_expire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
- } else {
- cache_expire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
- SYSDB_INITGR_EXPIRE, 0);
- }
-
- /* if we have any reply let's check cache validity */
- ret = sss_cmd_check_cache(state->res->msgs[0], cache_refresh_percent,
- cache_expire);
- if (ret == EOK) {
- DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning..\n");
- return EOK;
- } else if (ret != EAGAIN && ret != ENOENT) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Error checking cache: %d\n", ret);
- return ret;
- }
- } else {
- /* No replies */
- ret = ENOENT;
- }
-
- /* EAGAIN (off band) or ENOENT (cache miss) -> check cache */
- if (ret == EAGAIN) {
- /* No callback required
- * This was an out-of-band update. We'll return EOK
- * so the calling function can return the cached entry
- * immediately.
- */
- DEBUG(SSSDBG_TRACE_FUNC, "Performing midpoint cache update\n");
-
- req = sss_dp_get_account_send(state, state->rctx, state->dom, true,
- search_type, state->name, 0,
- extra_flag);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Out of memory sending out-of-band data provider "
- "request\n");
- /* This is non-fatal, so we'll continue here */
- } else {
- DEBUG(SSSDBG_TRACE_FUNC, "Updating cache out-of-band\n");
- }
-
- /* We don't need to listen for a reply, so we will free the
- * request here.
- */
- talloc_zfree(req);
- } else {
- /* This is a cache miss. Or the cache is expired.
- * We need to get the updated user information before returning it.
- */
-
- /* dont loop forever; mark the provider as checked */
- state->check_provider = false;
-
- req = sss_dp_get_account_send(state, state->rctx, state->dom, true,
- search_type, state->name, 0, extra_flag);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Out of memory sending data provider request\n");
- return ENOMEM;
- }
-
- cb_ctx = talloc_zero(state, struct dp_callback_ctx);
- if (cb_ctx == NULL) {
- talloc_zfree(req);
- return ENOMEM;
- }
- cb_ctx->callback = callback;
- cb_ctx->ptr = pvt;
- cb_ctx->cctx = NULL; /* There is no client in ifp */
- cb_ctx->mem_ctx = state;
-
- tevent_req_set_callback(req, ifp_user_get_attr_done, cb_ctx);
- return EAGAIN;
- }
-
- return EOK;
-}
-
-void ifp_user_get_attr_done(struct tevent_req *req)
-{
- struct dp_callback_ctx *cb_ctx =
- tevent_req_callback_data(req, struct dp_callback_ctx);
-
- errno_t ret;
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
- char *err_msg;
-
- ret = sss_dp_get_account_recv(cb_ctx->mem_ctx, req,
- &err_maj, &err_min,
- &err_msg);
- talloc_zfree(req);
+ ret = cache_req_recv(state, subreq, &state->res, &state->dom);
+ talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Could not get account info: %d\n", ret);
- /* report error with callback */
+ tevent_req_error(req, ret);
+ return;
}
- cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
-}
+ if (state->search_type == SSS_DP_USER) {
+ /* throw away the result and perform attr search */
+ talloc_zfree(state->res);
-static void ifp_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- errno_t ret;
- struct tevent_req *req = talloc_get_type(ptr, struct tevent_req);
-
- if (err_maj) {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg);
- }
-
- /* Backend was updated successfully. Check again */
- ret = ifp_user_get_attr_search(req);
- if (ret == EAGAIN) {
- /* Another search in progress */
- return;
- } else if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
+ ret = sysdb_get_user_attr_with_views(state, state->dom, state->name,
+ state->attrs, &state->res);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_get_user_attr_with_views() "
+ "failed [%d]: %s\n", ret, sss_strerror(ret));
+ tevent_req_error(req, ret);
+ return;
+ } else if (state->res->count == 0) {
+ tevent_req_error(req, ENOENT);
+ return;
+ } else if (state->res->count != 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_get_user_attr_with_views() "
+ "returned more than one result!\n");
+ tevent_req_error(req, ENOENT);
+ return;
+ }
}
tevent_req_done(req);