summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2015-01-23 14:03:07 +0100
committerJakub Hrozek <jhrozek@redhat.com>2015-03-13 09:56:03 +0100
commit665bc06b1a39c64227de74ecbba3db1c4c104ccf (patch)
tree8b64a9d620951e29800894086c5355c2dfad8702
parentbbc34d5a6e84d6c337bd89a22d33e365eb466226 (diff)
downloadsssd-665bc06b1a39c64227de74ecbba3db1c4c104ccf.tar.gz
sssd-665bc06b1a39c64227de74ecbba3db1c4c104ccf.tar.xz
sssd-665bc06b1a39c64227de74ecbba3db1c4c104ccf.zip
cache_req: preparations for different input type
Currently cache_req takes only user name as an input parameter. However, this is not enough since we will need also UID and GID in the future. This patch creates a structure to hold input parameters so it can be simply extended to support other input types. Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/responder/common/responder_cache_req.c345
-rw-r--r--src/responder/common/responder_cache_req.h41
-rw-r--r--src/responder/ifp/ifpsrv_cmd.c24
3 files changed, 310 insertions, 100 deletions
diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c
index 39f90cfe1..b60f91c2c 100644
--- a/src/responder/common/responder_cache_req.c
+++ b/src/responder/common/responder_cache_req.c
@@ -28,54 +28,177 @@
#include "responder/common/responder_cache_req.h"
#include "providers/data_provider.h"
-static errno_t cache_req_check_ncache(enum sss_dp_acct_type dp_type,
+struct cache_req_input {
+ enum cache_req_type type;
+
+ /* Provided input. */
+ const char *orig_name;
+
+ /* Data Provider request type resolved from @type.
+ * FIXME: This is currently needed for data provider calls. We should
+ * refactor responder_dp.c to get rid of this member. */
+ enum sss_dp_acct_type dp_type;
+
+ /* Domain related informations. */
+ struct sss_domain_info *domain;
+
+ /* Name sanitized according to domain rules such as case sensitivity and
+ * replacement of space character. This needs to be set up for each
+ * domain separately. */
+ const char *dom_objname;
+
+ /* Fully qualified object name used in debug messages. */
+ const char *debug_fqn;
+};
+
+struct cache_req_input *
+cache_req_input_create(TALLOC_CTX *mem_ctx,
+ enum cache_req_type type,
+ const char *name)
+{
+ struct cache_req_input *input;
+
+ input = talloc_zero(mem_ctx, struct cache_req_input);
+ if (input == NULL) {
+ return NULL;
+ }
+
+ input->type = type;
+
+ /* Check that input parameters match selected type. */
+ switch (input->type) {
+ case CACHE_REQ_USER_BY_NAME:
+ case CACHE_REQ_INITGROUPS:
+ if (name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL!\n");
+ goto fail;
+ }
+
+ input->orig_name = talloc_strdup(input, name);
+ if (input->orig_name == NULL) {
+ goto fail;
+ }
+ break;
+ }
+
+ /* Resolve Data Provider request type. */
+ switch (type) {
+ case CACHE_REQ_USER_BY_NAME:
+ input->dp_type = SSS_DP_USER;
+ break;
+
+ case CACHE_REQ_INITGROUPS:
+ input->dp_type = SSS_DP_INITGROUPS;
+ break;
+ }
+
+ return input;
+
+fail:
+ talloc_free(input);
+ return NULL;
+}
+
+static errno_t
+cache_req_input_set_domain(struct cache_req_input *input,
+ struct sss_domain_info *domain,
+ struct resp_ctx *rctx)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ const char *name = NULL;
+ const char *fqn = NULL;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ talloc_zfree(input->dom_objname);
+ talloc_zfree(input->debug_fqn);
+
+ switch (input->type) {
+ case CACHE_REQ_USER_BY_NAME:
+ case CACHE_REQ_INITGROUPS:
+ name = sss_get_cased_name(tmp_ctx, input->orig_name,
+ domain->case_sensitive);
+ if (name == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ name = sss_reverse_replace_space(tmp_ctx, name, rctx->override_space);
+ if (name == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ fqn = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name);
+ if (fqn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ break;
+ }
+
+ input->domain = domain;
+ input->dom_objname = talloc_steal(input, name);
+ input->debug_fqn = talloc_steal(input, fqn);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t cache_req_check_ncache(struct cache_req_input *input,
struct sss_nc_ctx *ncache,
- int neg_timeout,
- struct sss_domain_info *domain,
- const char *name)
+ int neg_timeout)
{
errno_t ret;
- switch (dp_type) {
- case SSS_DP_USER:
- case SSS_DP_INITGROUPS:
- ret = sss_ncache_check_user(ncache, neg_timeout, domain, name);
+ switch (input->type) {
+ case CACHE_REQ_USER_BY_NAME:
+ case CACHE_REQ_INITGROUPS:
+ ret = sss_ncache_check_user(ncache, neg_timeout,
+ input->domain, input->dom_objname);
break;
default:
ret = EINVAL;
- DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported DP request type\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported cache request type\n");
break;
}
if (ret == EEXIST) {
- DEBUG(SSSDBG_TRACE_FUNC, "[%s] does not exist in [%s]! "
- "(negative cache)\n", name, domain->name);
+ DEBUG(SSSDBG_TRACE_FUNC, "[%s] does not exist (negative cache)\n",
+ input->debug_fqn);
}
return ret;
}
-static void cache_req_add_to_ncache(enum sss_dp_acct_type dp_type,
- struct sss_nc_ctx *ncache,
- struct sss_domain_info *domain,
- const char *name)
+static void cache_req_add_to_ncache(struct cache_req_input *input,
+ struct sss_nc_ctx *ncache)
{
errno_t ret;
- switch (dp_type) {
- case SSS_DP_USER:
- case SSS_DP_INITGROUPS:
- ret = sss_ncache_set_user(ncache, false, domain, name);
+ switch (input->type) {
+ case CACHE_REQ_USER_BY_NAME:
+ case CACHE_REQ_INITGROUPS:
+ ret = sss_ncache_set_user(ncache, false, input->domain,
+ input->dom_objname);
break;
default:
ret = EINVAL;
- DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported DP request type\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported cache request type\n");
break;
}
if (ret != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set negcache for %s@%s [%d]: %s\n",
- name, domain->name, ret, sss_strerror(ret));
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set negcache for [%s] [%d]: %s\n",
+ input->debug_fqn, ret, sss_strerror(ret));
/* not fatal */
}
@@ -84,30 +207,29 @@ static void cache_req_add_to_ncache(enum sss_dp_acct_type dp_type,
}
static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx,
- enum sss_dp_acct_type dp_type,
- struct sss_domain_info *domain,
- const char *name,
+ struct cache_req_input *input,
struct ldb_result **_result)
{
struct ldb_result *result = NULL;
bool one_item_only;
errno_t ret;
- DEBUG(SSSDBG_FUNC_DATA, "Requesting info for [%s@%s]\n",
- name, domain->name);
+ DEBUG(SSSDBG_FUNC_DATA, "Requesting info for [%s]\n", input->debug_fqn);
- switch (dp_type) {
- case SSS_DP_USER:
+ switch (input->type) {
+ case CACHE_REQ_USER_BY_NAME:
one_item_only = true;
- ret = sysdb_getpwnam_with_views(mem_ctx, domain, name, &result);
+ ret = sysdb_getpwnam_with_views(mem_ctx, input->domain,
+ input->dom_objname, &result);
break;
- case SSS_DP_INITGROUPS:
+ case CACHE_REQ_INITGROUPS:
one_item_only = false;
- ret = sysdb_initgroups_with_views(mem_ctx, domain, name, &result);
+ ret = sysdb_initgroups_with_views(mem_ctx, input->domain,
+ input->dom_objname, &result);
break;
default:
ret = EINVAL;
- DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported DP request type\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported cache request type\n");
break;
}
@@ -136,9 +258,7 @@ struct cache_req_cache_state {
struct sss_nc_ctx *ncache;
int neg_timeout;
int cache_refresh_percent;
- enum sss_dp_acct_type dp_type;
- struct sss_domain_info *domain;
- const char *name;
+ struct cache_req_input *input;
/* output data */
struct ldb_result *result;
@@ -154,9 +274,7 @@ static struct tevent_req *cache_req_cache_send(TALLOC_CTX *mem_ctx,
struct sss_nc_ctx *ncache,
int neg_timeout,
int cache_refresh_percent,
- enum sss_dp_acct_type dp_type,
- struct sss_domain_info *domain,
- const char *name)
+ struct cache_req_input *input)
{
struct cache_req_cache_state *state = NULL;
struct tevent_req *req = NULL;
@@ -173,28 +291,11 @@ static struct tevent_req *cache_req_cache_send(TALLOC_CTX *mem_ctx,
state->ncache = ncache;
state->neg_timeout = neg_timeout;
state->cache_refresh_percent = cache_refresh_percent;
- state->dp_type = dp_type;
- state->domain = domain;
-
- /* Sanitize input name. */
- state->name = sss_get_cased_name(state, name, domain->case_sensitive);
- if (state->name == NULL) {
- ret = ENOMEM;
- goto immediately;
- }
-
- state->name = sss_reverse_replace_space(state, state->name,
- state->rctx->override_space);
- if (state->name == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sss_reverse_replace_space failed\n");
- ret = ENOMEM;
- goto immediately;
- }
+ state->input = input;
/* Check negative cache first. */
- ret = cache_req_check_ncache(state->dp_type, state->ncache,
- state->neg_timeout, state->domain,
- state->name);
+ ret = cache_req_check_ncache(state->input, state->ncache,
+ state->neg_timeout);
if (ret == EEXIST) {
ret = ENOENT;
goto immediately;
@@ -227,8 +328,7 @@ static errno_t cache_req_cache_search(struct tevent_req *req)
state = tevent_req_data(req, struct cache_req_cache_state);
- ret = cache_req_get_object(state, state->dp_type, state->domain,
- state->name, &state->result);
+ ret = cache_req_get_object(state, state->input, &state->result);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache "
"[%d]: %s\n", ret, sss_strerror(ret));
@@ -242,8 +342,8 @@ static errno_t cache_req_cache_search(struct tevent_req *req)
}
/* One result found */
- DEBUG(SSSDBG_TRACE_FUNC,
- "Returning info for [%s@%s]\n", state->name, state->domain->name);
+ DEBUG(SSSDBG_TRACE_FUNC, "Returning info for [%s]\n",
+ state->input->debug_fqn);
return EOK;
}
@@ -260,7 +360,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
if (state->result == NULL || state->result->count == 0) {
ret = ENOENT;
} else {
- if (state->dp_type == SSS_DP_INITGROUPS) {
+ if (state->input->type == CACHE_REQ_INITGROUPS) {
cache_expire = ldb_msg_find_attr_as_uint64(state->result->msgs[0],
SYSDB_INITGR_EXPIRE, 0);
} else {
@@ -282,9 +382,10 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
DEBUG(SSSDBG_TRACE_FUNC, "Performing midpoint cache update\n");
- subreq = sss_dp_get_account_send(state, state->rctx, state->domain,
- true, state->dp_type, state->name,
- 0, NULL);
+ subreq = sss_dp_get_account_send(state, state->rctx,
+ state->input->domain, true,
+ state->input->dp_type,
+ state->input->dom_objname, 0, NULL);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band "
"data provider request\n");
@@ -298,13 +399,15 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
/* Cache miss or the cache is expired. We need to get the updated
* information before returning it. */
- if (DOM_HAS_VIEWS(state->domain)) {
+ if (DOM_HAS_VIEWS(state->input->domain)) {
extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
}
- subreq = sss_dp_get_account_send(state, state->rctx, state->domain,
- true, state->dp_type, state->name,
- 0, extra_flag);
+ subreq = sss_dp_get_account_send(state, state->rctx,
+ state->input->domain, true,
+ state->input->dp_type,
+ state->input->dom_objname, 0,
+ extra_flag);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Out of memory sending data provider request\n");
@@ -349,11 +452,9 @@ static void cache_req_cache_done(struct tevent_req *subreq)
}
/* Get result from cache again. */
- ret = cache_req_get_object(state, state->dp_type, state->domain,
- state->name, &state->result);
+ ret = cache_req_get_object(state, state->input, &state->result);
if (ret == ENOENT) {
- cache_req_add_to_ncache(state->dp_type, state->ncache,
- state->domain, state->name);
+ cache_req_add_to_ncache(state->input, state->ncache);
ret = ENOENT;
} else if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache "
@@ -366,8 +467,8 @@ static void cache_req_cache_done(struct tevent_req *subreq)
}
/* One result found */
- DEBUG(SSSDBG_TRACE_FUNC,
- "Returning info for [%s@%s]\n", state->name, state->domain->name);
+ DEBUG(SSSDBG_TRACE_FUNC, "Returning info for [%s]\n",
+ state->input->debug_fqn);
tevent_req_done(req);
}
@@ -394,8 +495,7 @@ struct cache_req_state {
struct sss_nc_ctx *ncache;
int neg_timeout;
int cache_refresh_percent;
- const char *name;
- enum sss_dp_acct_type dp_type;
+ struct cache_req_input *input;
/* work data */
struct ldb_result *result;
@@ -413,9 +513,8 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx,
struct sss_nc_ctx *ncache,
int neg_timeout,
int cache_refresh_percent,
- enum sss_dp_acct_type dp_type,
const char *domain,
- const char *name)
+ struct cache_req_input *input)
{
struct cache_req_state *state = NULL;
struct tevent_req *req = NULL;
@@ -432,12 +531,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx,
state->ncache = ncache;
state->neg_timeout = neg_timeout;
state->cache_refresh_percent = cache_refresh_percent;
- state->dp_type = dp_type;
- state->name = talloc_strdup(state, name);
- if (state->name == NULL) {
- ret = ENOMEM;
- goto immediately;
- }
+ state->input = input;
if (domain != NULL) {
/* single-domain search */
@@ -476,6 +570,7 @@ static errno_t cache_req_next_domain(struct tevent_req *req)
{
struct cache_req_state *state = NULL;
struct tevent_req *subreq = NULL;
+ errno_t ret;
state = tevent_req_data(req, struct cache_req_state);
@@ -493,11 +588,16 @@ static errno_t cache_req_next_domain(struct tevent_req *req)
break;
}
+ ret = cache_req_input_set_domain(state->input, state->domain,
+ state->rctx);
+ if (ret != EOK) {
+ return ret;
+ }
+
subreq = cache_req_cache_send(state, state->ev, state->rctx,
state->ncache, state->neg_timeout,
state->cache_refresh_percent,
- state->dp_type, state->domain,
- state->name);
+ state->input);
if (subreq == NULL) {
return ENOMEM;
}
@@ -564,3 +664,70 @@ errno_t cache_req_recv(TALLOC_CTX *mem_ctx,
return EOK;
}
+
+static struct tevent_req *
+cache_req_steal_input_and_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ struct cache_req_input *input)
+{
+ struct tevent_req *req;
+
+ req = cache_req_send(mem_ctx, ev, rctx, ncache, neg_timeout,
+ cache_refresh_percent, domain, input);
+ if (req == NULL) {
+ talloc_zfree(input);
+ }
+
+ talloc_steal(req, input);
+
+ return req;
+}
+
+struct tevent_req *
+cache_req_user_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *name)
+{
+ struct cache_req_input *input;
+
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_NAME, name);
+ if (input == NULL) {
+ return NULL;
+ }
+
+ return cache_req_steal_input_and_send(mem_ctx, ev, rctx, ncache,
+ neg_timeout, cache_refresh_percent,
+ domain, input);
+}
+
+struct tevent_req *
+cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *name)
+{
+ struct cache_req_input *input;
+
+ input = cache_req_input_create(mem_ctx, CACHE_REQ_INITGROUPS, name);
+ if (input == NULL) {
+ return NULL;
+ }
+
+ return cache_req_steal_input_and_send(mem_ctx, ev, rctx, ncache,
+ neg_timeout, cache_refresh_percent,
+ domain, input);
+}
diff --git a/src/responder/common/responder_cache_req.h b/src/responder/common/responder_cache_req.h
index fdad94a13..3d11cd234 100644
--- a/src/responder/common/responder_cache_req.h
+++ b/src/responder/common/responder_cache_req.h
@@ -27,6 +27,18 @@
#include "responder/common/responder.h"
#include "responder/common/negcache.h"
+enum cache_req_type {
+ CACHE_REQ_USER_BY_NAME,
+ CACHE_REQ_INITGROUPS
+};
+
+struct cache_req_input;
+
+struct cache_req_input *
+cache_req_input_create(TALLOC_CTX *mem_ctx,
+ enum cache_req_type type,
+ const char *name);
+
/**
* Currently only SSS_DP_USER and SSS_DP_INITGROUPS are supported.
*
@@ -38,27 +50,36 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx,
struct sss_nc_ctx *ncache,
int neg_timeout,
int cache_refresh_percent,
- enum sss_dp_acct_type dp_type,
const char *domain,
- const char *name);
+ struct cache_req_input *input);
errno_t cache_req_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
struct ldb_result **_result,
struct sss_domain_info **_domain);
-#define cache_req_user_by_name_send(mem_ctx, ev, rctx, ncache, neg_timeout, \
- cache_refresh_percent, domain, name) \
- cache_req_send(mem_ctx, ev, rctx, ncache, neg_timeout, \
- cache_refresh_percent, SSS_DP_USER, domain, name)
+struct tevent_req *
+cache_req_user_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *name);
#define cache_req_user_by_name_recv(mem_ctx, req, _result, _domain) \
cache_req_recv(mem_ctx, req, _result, _domain)
-#define cache_req_initgr_by_name_send(mem_ctx, ev, rctx, ncache, neg_timeout, \
- cache_refresh_percent, domain, name) \
- cache_req_send(mem_ctx, ev, rctx, ncache, neg_timeout, \
- cache_refresh_percent, SSS_DP_INITGROUPS, domain, name)
+struct tevent_req *
+cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resp_ctx *rctx,
+ struct sss_nc_ctx *ncache,
+ int neg_timeout,
+ int cache_refresh_percent,
+ const char *domain,
+ const char *name);
#define cache_req_initgr_by_name_recv(mem_ctx, req, _result, _domain) \
cache_req_recv(mem_ctx, req, _result, _domain)
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index 11a7fb26c..b57a33a8d 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -477,6 +477,7 @@ static void
ifp_user_get_attr_lookup(struct tevent_req *subreq)
{
struct ifp_user_get_attr_state *state = NULL;
+ struct cache_req_input *input = NULL;
struct tevent_req *req = NULL;
errno_t ret;
@@ -490,9 +491,30 @@ ifp_user_get_attr_lookup(struct tevent_req *subreq)
return;
}
+ switch (state->search_type) {
+ case SSS_DP_USER:
+ input = cache_req_input_create(state, CACHE_REQ_USER_BY_NAME,
+ state->name);
+ break;
+ case SSS_DP_INITGROUPS:
+ input = cache_req_input_create(state, CACHE_REQ_INITGROUPS,
+ state->name);
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported search type [%d]!\n",
+ state->search_type);
+ tevent_req_error(req, ERR_INTERNAL);
+ return;
+ }
+
+ if (input == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
subreq = cache_req_send(state, state->rctx->ev, state->rctx,
state->ncache, state->neg_timeout, 0,
- state->search_type, state->domname, state->name);
+ state->domname, input);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;