diff options
Diffstat (limited to 'src/providers/simple/simple_access.c')
-rw-r--r-- | src/providers/simple/simple_access.c | 269 |
1 files changed, 146 insertions, 123 deletions
diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c index d4fa615f2..ca6d49db4 100644 --- a/src/providers/simple/simple_access.c +++ b/src/providers/simple/simple_access.c @@ -34,13 +34,80 @@ #define TIMEOUT_OF_REFRESH_FILTER_LISTS 5 -static void simple_access_check(struct tevent_req *req); static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, char **list, - char ***_out); + char ***_out) +{ + TALLOC_CTX *tmp_ctx = NULL; + char **out = NULL; + char *domain = NULL; + char *name = NULL; + size_t size; + size_t i; + errno_t ret; + + if (list == NULL) { + *_out = NULL; + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + ret = ENOMEM; + goto done; + } + + for (size = 0; list[size] != NULL; size++) { + /* count size */ + } + + out = talloc_zero_array(tmp_ctx, char*, size + 1); + if (out == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); + ret = ENOMEM; + goto done; + } + + /* Since this is access provider, we should fail on any error so we don't + * allow unauthorized access. */ + for (i = 0; i < size; i++) { + ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i], + &domain, &name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n", + list[i], ret, sss_strerror(ret)); + goto done; + } + + if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 || + (be_ctx->domain->flat_name != NULL && + strcasecmp(domain, be_ctx->domain->flat_name) == 0)) { + /* This object belongs to main SSSD domain. Those users and groups + * are stored without domain part, so we will strip it off. + * */ + out[i] = talloc_move(out, &name); + } else { + /* Subdomain users and groups are stored as fully qualified names, + * thus we will remember the domain part. + * + * Since subdomains may come and go, we will look for their + * existence later, during each access check. + */ + out[i] = talloc_move(out, &list[i]); + } + } + + *_out = talloc_steal(mem_ctx, out); + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} -static int simple_access_obtain_filter_lists(struct simple_ctx *ctx) +int simple_access_obtain_filter_lists(struct simple_ctx *ctx) { struct be_ctx *bectx = ctx->be_ctx; int ret; @@ -103,185 +170,141 @@ failed: return ret; } -void simple_access_handler(struct be_req *be_req) -{ - struct be_ctx *be_ctx = be_req_get_be_ctx(be_req); +struct simple_access_handler_state { struct pam_data *pd; +}; + +static void simple_access_handler_done(struct tevent_req *subreq); + +static struct tevent_req * +simple_access_handler_send(TALLOC_CTX *mem_ctx, + struct simple_ctx *simple_ctx, + struct pam_data *pd, + struct dp_req_params *params) +{ + struct simple_access_handler_state *state; + struct tevent_req *subreq; struct tevent_req *req; - struct simple_ctx *ctx; - int ret; + errno_t ret; time_t now; - pd = talloc_get_type(be_req_get_data(be_req), struct pam_data); + req = tevent_req_create(mem_ctx, &state, + struct simple_access_handler_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } - pd->pam_status = PAM_SYSTEM_ERR; + state->pd = pd; + pd->pam_status = PAM_SYSTEM_ERR; if (pd->cmd != SSS_PAM_ACCT_MGMT) { DEBUG(SSSDBG_CONF_SETTINGS, "simple access does not handle pam task %d.\n", pd->cmd); pd->pam_status = PAM_MODULE_UNKNOWN; - goto done; + goto immediately; } - ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data, - struct simple_ctx); - - now = time(NULL); - if ((now - ctx->last_refresh_of_filter_lists) + if ((now - simple_ctx->last_refresh_of_filter_lists) > TIMEOUT_OF_REFRESH_FILTER_LISTS) { - ret = simple_access_obtain_filter_lists(ctx); + ret = simple_access_obtain_filter_lists(simple_ctx); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Failed to refresh filter lists\n"); } - ctx->last_refresh_of_filter_lists = now; + simple_ctx->last_refresh_of_filter_lists = now; } - req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user); - if (!req) { + subreq = simple_access_check_send(state, params->ev, simple_ctx, pd->user); + if (subreq == NULL) { pd->pam_status = PAM_SYSTEM_ERR; - goto done; + goto immediately; } - tevent_req_set_callback(req, simple_access_check, be_req); - return; -done: - be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL); + tevent_req_set_callback(subreq, simple_access_handler_done, req); + + return req; + +immediately: + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); + tevent_req_post(req, params->ev); + + return req; } -static void simple_access_check(struct tevent_req *req) +static void simple_access_handler_done(struct tevent_req *subreq) { - bool access_granted = false; + struct simple_access_handler_state *state; + struct tevent_req *req; + bool access_granted; errno_t ret; - struct pam_data *pd; - struct be_req *be_req; - be_req = tevent_req_callback_data(req, struct be_req); - pd = talloc_get_type(be_req_get_data(be_req), struct pam_data); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct simple_access_handler_state); - ret = simple_access_check_recv(req, &access_granted); - talloc_free(req); + ret = simple_access_check_recv(subreq, &access_granted); + talloc_free(subreq); if (ret != EOK) { - pd->pam_status = PAM_SYSTEM_ERR; + state->pd->pam_status = PAM_SYSTEM_ERR; goto done; } if (access_granted) { - pd->pam_status = PAM_SUCCESS; + state->pd->pam_status = PAM_SUCCESS; } else { - pd->pam_status = PAM_PERM_DENIED; + state->pd->pam_status = PAM_PERM_DENIED; } done: - be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL); + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); } -static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx, - struct be_ctx *be_ctx, - char **list, - char ***_out) +static errno_t +simple_access_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data) { - TALLOC_CTX *tmp_ctx = NULL; - char **out = NULL; - char *domain = NULL; - char *name = NULL; - size_t size; - size_t i; - errno_t ret; - - if (list == NULL) { - *_out = NULL; - return EOK; - } + struct simple_access_handler_state *state = NULL; - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); - ret = ENOMEM; - goto done; - } + state = tevent_req_data(req, struct simple_access_handler_state); - for (size = 0; list[size] != NULL; size++) { - /* count size */ - } + TEVENT_REQ_RETURN_ON_ERROR(req); - out = talloc_zero_array(tmp_ctx, char*, size + 1); - if (out == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); - ret = ENOMEM; - goto done; - } + *_data = talloc_steal(mem_ctx, state->pd); - /* Since this is access provider, we should fail on any error so we don't - * allow unauthorized access. */ - for (i = 0; i < size; i++) { - ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i], - &domain, &name); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n", - list[i], ret, sss_strerror(ret)); - goto done; - } - - if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 || - (be_ctx->domain->flat_name != NULL && - strcasecmp(domain, be_ctx->domain->flat_name) == 0)) { - /* This object belongs to main SSSD domain. Those users and groups - * are stored without domain part, so we will strip it off. - * */ - out[i] = talloc_move(out, &name); - } else { - /* Subdomain users and groups are stored as fully qualified names, - * thus we will remember the domain part. - * - * Since subdomains may come and go, we will look for their - * existence later, during each access check. - */ - out[i] = talloc_move(out, &list[i]); - } - } - - *_out = talloc_steal(mem_ctx, out); - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; + return EOK; } -struct bet_ops simple_access_ops = { - .handler = simple_access_handler, - .finalize = NULL -}; - -int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops, - void **pvt_data) +errno_t sssm_simple_access_init(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + void *module_data, + struct dp_method *dp_methods) { - int ret = EINVAL; struct simple_ctx *ctx; - ctx = talloc_zero(bectx, struct simple_ctx); + errno_t ret; + + ctx = talloc_zero(mem_ctx, struct simple_ctx); if (ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed.\n"); return ENOMEM; } - ctx->domain = bectx->domain; - ctx->be_ctx = bectx; + ctx->domain = be_ctx->domain; + ctx->be_ctx = be_ctx; ctx->last_refresh_of_filter_lists = 0; ret = simple_access_obtain_filter_lists(ctx); if (ret != EOK) { - goto failed; + talloc_free(ctx); + return ret; } - *ops = &simple_access_ops; - *pvt_data = ctx; + dp_set_method(dp_methods, DPM_ACCESS_HANDLER, + simple_access_handler_send, simple_access_handler_recv, ctx, + struct simple_ctx, struct pam_data, struct pam_data *); return EOK; - -failed: - talloc_free(ctx); - return ret; } - |