From 010c35e66398bbeb82fb1b31fc619b1a9eaf2d3d Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Fri, 11 May 2012 14:15:38 +0200 Subject: sudo responder: refresh expired rules --- src/responder/sudo/sudosrv_get_sudorules.c | 137 ++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 31 deletions(-) diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c index 6b8ee3692..c38c4da41 100644 --- a/src/responder/sudo/sudosrv_get_sudorules.c +++ b/src/responder/sudo/sudosrv_get_sudorules.c @@ -308,10 +308,41 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min, static void sudosrv_dp_req_done(struct tevent_req *req); +static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + enum sss_dp_sudo_type type, + const char **attrs, + unsigned int flags, + const char *username, + uid_t uid, + char **groupnames, + struct sysdb_attrs ***_rules, + size_t *_count); + errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx) { - struct tevent_req *dpreq; + TALLOC_CTX *tmp_ctx = NULL; + struct tevent_req *dpreq = NULL; struct dp_callback_ctx *cb_ctx = NULL; + struct sysdb_ctx *sysdb = cmd_ctx->domain->sysdb; + char **groupnames = NULL; + size_t expired_rules_num = 0; + struct sysdb_attrs **expired_rules = NULL; + errno_t ret; + unsigned int flags = SYSDB_SUDO_FILTER_NONE; + const char *attrs[] = { SYSDB_NAME, + NULL }; + + if (cmd_ctx->domain == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Domain is not set!\n")); + return EFAULT; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n")); + return ENOMEM; + } switch (cmd_ctx->type) { case SSS_SUDO_DEFAULTS: @@ -326,31 +357,86 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx) break; } - dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx, - cmd_ctx->cli_ctx->rctx, - cmd_ctx->domain, false, - cmd_ctx->type, - cmd_ctx->orig_username, - 0, NULL); - if (dpreq == NULL) { + /* Fetch all expired rules: + * sudo asks sssd twice - for defaults and for rules. If we refresh all + * expired rules for this user and defaults at once we will save one + * provider call + */ + ret = sysdb_get_sudo_user_info(tmp_ctx, cmd_ctx->orig_username, sysdb, + NULL, &groupnames); + if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - ("Cannot issue DP request.\n")); - return EIO; + ("Unable to retrieve user info [%d]: %s\n", strerror(ret))); + goto done; } - cb_ctx = talloc_zero(cmd_ctx, struct dp_callback_ctx); - if (!cb_ctx) { - talloc_zfree(dpreq); - return ENOMEM; + flags = SYSDB_SUDO_FILTER_INCLUDE_ALL + | SYSDB_SUDO_FILTER_INCLUDE_DFL + | SYSDB_SUDO_FILTER_ONLY_EXPIRED + | SYSDB_SUDO_FILTER_USERINFO; + ret = sudosrv_get_sudorules_query_cache(tmp_ctx, sysdb, cmd_ctx->type, + attrs, flags, cmd_ctx->orig_username, + cmd_ctx->uid, groupnames, + &expired_rules, &expired_rules_num); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Unable to retrieve expired sudo rules [%d]: %s\n", strerror(ret))); + goto done; } - cb_ctx->callback = sudosrv_get_sudorules_dp_callback; - cb_ctx->ptr = cmd_ctx; - cb_ctx->cctx = cmd_ctx->cli_ctx; - cb_ctx->mem_ctx = cmd_ctx; + if (expired_rules_num > 0) { + /* refresh expired rules then continue */ + DEBUG(SSSDBG_TRACE_INTERNAL, ("Refreshing expired rules\n")); + dpreq = sss_dp_get_sudoers_send(tmp_ctx, cmd_ctx->cli_ctx->rctx, + cmd_ctx->domain, false, + SSS_DP_SUDO_REFRESH_RULES, + cmd_ctx->orig_username, + expired_rules_num, expired_rules); + if (dpreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Cannot issue DP request.\n")); + ret = EIO; + goto done; + } + + cb_ctx = talloc_zero(tmp_ctx, struct dp_callback_ctx); + if (!cb_ctx) { + talloc_zfree(dpreq); + ret = ENOMEM; + goto done; + } + + cb_ctx->callback = sudosrv_get_sudorules_dp_callback; + cb_ctx->ptr = cmd_ctx; + cb_ctx->cctx = cmd_ctx->cli_ctx; + cb_ctx->mem_ctx = cmd_ctx; + + tevent_req_set_callback(dpreq, sudosrv_dp_req_done, cb_ctx); + ret = EAGAIN; - tevent_req_set_callback(dpreq, sudosrv_dp_req_done, cb_ctx); - return EAGAIN; + } else { + /* nothing is expired return what we have in the cache */ + DEBUG(SSSDBG_TRACE_INTERNAL, ("About to get sudo rules from cache\n")); + ret = sudosrv_get_sudorules_from_cache(cmd_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to make a request to our cache [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + } + + if (dpreq != NULL) { + talloc_steal(cmd_ctx->cli_ctx, dpreq); + } + + if (cb_ctx != NULL) { + talloc_steal(cmd_ctx, cb_ctx); + } + +done: + talloc_free(tmp_ctx); + return ret; } static void @@ -406,17 +492,6 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min, sudosrv_cmd_done(cmd_ctx, ret); } -static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - enum sss_dp_sudo_type type, - const char **attrs, - unsigned int flags, - const char *username, - uid_t uid, - char **groupnames, - struct sysdb_attrs ***_rules, - size_t *_count); - static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx) { TALLOC_CTX *tmp_ctx; -- cgit