On 04/19/2016 09:59 AM, Lukas Slebodnik wrote:
On (01/03/16 13:53), Pavel Březina wrote:
On 02/25/2016 02:08 PM, Jakub Hrozek wrote:
On Tue, Feb 09, 2016 at 02:07:21PM +0100, Pavel Březina wrote:
First of the responders is converted -)

Sorry for the first delay in review. Before reading the code, I
submitted the patches to automated tests, so far I found:

Error: COMPILER_WARNING:
sssd-1.13.90/src/responder/sudo/sudosrv_get_sudorules.c:29: included_from: 
Included from here.
sssd-1.13.90/src/responder/sudo/sudosrv_get_sudorules.c: scope_hint: In 
function 'sudosrv_get_rules_done'
sssd-1.13.90/src/util/util.h:144:9: warning: 'debug_name' may be used 
uninitialized in this function [-Wmaybe-uninitialized]
#         sss_debug_fn(__FILE__, __LINE__, __FUNCTION__, \
#         ^
sssd-1.13.90/src/responder/sudo/sudosrv_get_sudorules.c:225:17: note: 
'debug_name' was declared here
#     const char *debug_name;
#                 ^
#  142|       int __debug_macro_level = level; \
#  143|       if (DEBUG_IS_SET(__debug_macro_level)) { \
#  144|->         sss_debug_fn(__FILE__, __LINE__, __FUNCTION__, \
#  145|                        __debug_macro_level, \
#  146|                        format, ##__VA_ARGS__); \

But feel free to only fix the issue in your branch for now, at least until
all the automated downstream tests finish.

// snip

+
+static errno_t sudosrv_query_cache(TALLOC_CTX *mem_ctx,
+                                   struct sss_domain_info *domain,
+                                   const char **attrs,
+                                   unsigned int flags,
+                                   const char *username,
+                                   uid_t uid,
+                                   char **groupnames,
+                                   bool inverse_order,
+                                   struct sysdb_attrs ***_rules,
+                                   uint32_t *_count)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *filter;
+    errno_t ret;
+    size_t count;
+    struct sysdb_attrs **rules;
+    struct ldb_message **msgs;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_get_sudo_filter(tmp_ctx, username, uid, groupnames,
+                                flags, &filter);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct the search filter "
+              "[%d]: %s\n", ret, sss_strerror(ret));
+        goto done;
+    }
+
+    DEBUG(SSSDBG_FUNC_DATA, "Searching sysdb with [%s]\n", filter);
+
+    if (IS_SUBDOMAIN(domain)) {
+        /* rules are stored inside parent domain tree */
+        domain = domain->parent;
+    }
+
+    ret = sysdb_search_custom(tmp_ctx, domain, filter, SUDORULE_SUBDIR,
+                              attrs, &count, &msgs);
+    if (ret != EOK && ret != ENOENT) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
+        goto done;
+    } if (ret == ENOENT) {
       ^^^^^^^^^^^^^^^^^^^^^^
I wanted to push these ACK-ed patches but I noticed
this non-standard change :-)

I think you wanted here "else if" or "if" on next line.
I can change it before push If you let me which way you like more.

    ret = sysdb_search_custom(tmp_ctx, domain, filter, SUDORULE_SUBDIR,
                              attrs, &count, &msgs);
    if (ret == ENOENT) {
        *_rules = NULL;
        *_count = 0;
        ret = EOK;
        goto done;
    } else if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
        goto done;
    }

This is how it's supposed to be :-) Thanks.


From 340fb49f9476e9e07330d1e3f70db998bf888418 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Mon, 8 Feb 2016 14:02:59 +0100
Subject: [PATCH 1/4] sudo: remove unused structure sudo_dp_request

---
 src/responder/sudo/sudosrv_private.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index 186ed2cb5114d00524b41b801b5f32bac50f7153..f602f6a83cd52a54ce180d3aaaa1febd1d991f32 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -79,11 +79,6 @@ struct sudo_dom_ctx {
     bool check_provider;
 };
 
-struct sudo_dp_request {
-    struct cli_ctx *cctx;
-    struct sss_domain_info *domain;
-};
-
 struct sss_cmd_table *get_sudo_cmds(void);
 
 errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret);
-- 
2.1.0

From 4367d4140b6be2b421e1e8836d35d4e822c8b22b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Mon, 8 Feb 2016 14:30:16 +0100
Subject: [PATCH 2/4] sudo: use cache_req for initgroups

This is just blind code change, the next patch will improve it so
for example we don't do initgroups during query-parsing phase.

Resolves:
https://fedorahosted.org/sssd/ticket/1126
---
 src/responder/sudo/sudosrv_cmd.c           |  29 +--
 src/responder/sudo/sudosrv_get_sudorules.c | 292 ++---------------------------
 src/responder/sudo/sudosrv_private.h       |  13 +-
 src/responder/sudo/sudosrv_query.c         | 114 ++++-------
 4 files changed, 47 insertions(+), 401 deletions(-)

diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index dd636e949200dd49c1422a5789e9328dc4b25fb0..c68a6980ba817071e3766a0ddf7c158499d47aec 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -221,7 +221,7 @@ static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
         goto done;
     }
 
-    req = sudosrv_parse_query_send(cmd_ctx, cli_ctx->rctx,
+    req = sudosrv_parse_query_send(cmd_ctx, cmd_ctx->sudo_ctx,
                                    query_body, query_len);
     if (req == NULL) {
         ret = ENOMEM;
@@ -239,8 +239,6 @@ done:
 static void sudosrv_cmd_parse_query_done(struct tevent_req *req)
 {
     struct sudo_cmd_ctx *cmd_ctx = NULL;
-    struct sudo_dom_ctx *dom_ctx = NULL;
-    struct sudo_ctx *sudo_ctx = NULL;
     errno_t ret;
 
     cmd_ctx = tevent_req_callback_data(req, struct sudo_cmd_ctx);
@@ -254,8 +252,6 @@ static void sudosrv_cmd_parse_query_done(struct tevent_req *req)
         goto done;
     }
 
-    cmd_ctx->check_next = cmd_ctx->domain == NULL;
-
     switch (cmd_ctx->type) {
         case SSS_SUDO_DEFAULTS:
             DEBUG(SSSDBG_FUNC_DATA, "Requesting default options "
@@ -269,28 +265,7 @@ static void sudosrv_cmd_parse_query_done(struct tevent_req *req)
             break;
     }
 
-    /* create domain ctx */
-
-    dom_ctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx);
-    if (dom_ctx == NULL) {
-        ret = ENOMEM;
-        goto done;
-    }
-    dom_ctx->cmd_ctx = cmd_ctx;
-    dom_ctx->domain = cmd_ctx->domain != NULL ? cmd_ctx->domain
-                                              : cmd_ctx->cli_ctx->rctx->domains;
-
-    sudo_ctx = talloc_get_type(cmd_ctx->cli_ctx->rctx->pvt_ctx, struct sudo_ctx);
-    ret = sss_ncache_check_user(sudo_ctx->ncache, sudo_ctx->neg_timeout,
-                                dom_ctx->domain, cmd_ctx->username);
-    if (ret == EEXIST) {
-        DEBUG(SSSDBG_TRACE_FUNC, "User [%s@%s] filtered out (ncache)\n",
-              cmd_ctx->username, dom_ctx->domain->name);
-        ret = ENOENT;
-        goto done;
-    }
-
-    ret = sudosrv_get_sudorules(dom_ctx);
+    ret = sudosrv_get_sudorules(cmd_ctx);
 
 done:
     sudosrv_cmd_done(cmd_ctx, ret);
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 75d8cac41d57ff65449cdf5ed3b08cf7d46d55c1..13015072e6daf1455b0b8e66a225f84c94280958 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -30,26 +30,12 @@
 #include "responder/sudo/sudosrv_private.h"
 #include "providers/data_provider.h"
 
-static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx);
-
-errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx)
+errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx)
 {
     errno_t ret;
 
-    dctx->check_provider = true;
-    ret = sudosrv_get_user(dctx);
-    if (ret == EAGAIN) {
-        DEBUG(SSSDBG_TRACE_INTERNAL,
-              "Looking up the user info from Data Provider\n");
-        return EAGAIN;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Error looking up user information [%d]: %s\n", ret, strerror(ret));
-        return ret;
-    }
-
     /* OK, got the user from cache. Try to get the rules. */
-    ret = sudosrv_get_rules(dctx->cmd_ctx);
+    ret = sudosrv_get_rules(cmd_ctx);
     if (ret == EAGAIN) {
         DEBUG(SSSDBG_TRACE_INTERNAL,
               "Looking up the sudo rules from Data Provider\n");
@@ -63,262 +49,6 @@ errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx)
     return EOK;
 }
 
-static void sudosrv_dp_send_acct_req_done(struct tevent_req *req);
-static void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
-                                           const char *err_msg, void *ptr);
-
-static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
-{
-    TALLOC_CTX *tmp_ctx = NULL;
-    struct sss_domain_info *dom = dctx->domain;
-    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
-    struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
-    struct ldb_result *user;
-    time_t cache_expire = 0;
-    struct tevent_req *dpreq;
-    struct dp_callback_ctx *cb_ctx;
-    const char *original_name = NULL;
-    const char *extra_flag = NULL;
-    const char *search_name = NULL;
-    char *name = NULL;
-    uid_t uid = 0;
-    errno_t ret;
-
-    tmp_ctx = talloc_new(NULL);
-    if (tmp_ctx == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
-        return ENOMEM;
-    }
-
-    while (dom) {
-       /* if it is a domainless search, skip domains that require fully
-        * qualified names instead */
-        while (dom && cmd_ctx->check_next && dom->fqnames) {
-            dom = get_next_domain(dom, 0);
-        }
-
-        if (!dom) break;
-
-        /* make sure to update the dctx if we changed domain */
-        dctx->domain = dom;
-
-        talloc_free(name);
-        name = sss_get_cased_name(tmp_ctx, cmd_ctx->username,
-                                  dom->case_sensitive);
-        if (name == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
-            ret = ENOMEM;
-            goto done;
-        }
-
-        name = sss_reverse_replace_space(tmp_ctx, name,
-                                         cmd_ctx->sudo_ctx->rctx->override_space);
-        if (name == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_reverse_replace_whitespaces failed\n");
-            return ENOMEM;
-        }
-
-        DEBUG(SSSDBG_FUNC_DATA, "Requesting info about [%s@%s]\n",
-              name, dom->name);
-
-        ret = sysdb_getpwnam_with_views(dctx, dctx->domain, name, &user);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                  "Failed to make request to our cache!\n");
-            ret = EIO;
-            goto done;
-        }
-
-        if (user->count > 1) {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "getpwnam call returned more than one result !?!\n");
-            ret = EIO;
-            goto done;
-        }
-
-        if (user->count == 0 && !dctx->check_provider) {
-            /* if a multidomain search, try with next */
-            if (cmd_ctx->check_next) {
-                dctx->check_provider = true;
-                dom = get_next_domain(dom, 0);
-                if (dom) continue;
-            }
-
-            DEBUG(SSSDBG_MINOR_FAILURE, "No results for getpwnam call\n");
-            ret = ENOENT;
-            goto done;
-        }
-
-        /* One result found, check cache expiry */
-        if (user->count == 1) {
-            cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0],
-                                                       SYSDB_CACHE_EXPIRE, 0);
-        }
-
-        /* If cache miss and we haven't checked DP yet OR the entry is
-         * outdated, go to DP */
-        if ((user->count == 0 || cache_expire < time(NULL))
-            && dctx->check_provider) {
-
-            search_name = cmd_ctx->username;
-            if (is_local_view(dom->view_name)) {
-                /* Search with original name in case of local view. */
-                if (user->count != 0) {
-                    search_name = ldb_msg_find_attr_as_string(user->msgs[0],
-                                                              SYSDB_NAME, NULL);
-                }
-            } else if (DOM_HAS_VIEWS(dom) && (user->count == 0
-                || ldb_msg_find_attr_as_string(user->msgs[0],
-                                               OVERRIDE_PREFIX SYSDB_NAME,
-                                               NULL) != NULL)) {
-                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
-            }
-
-            dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
-                                            dom, false, SSS_DP_INITGROUPS,
-                                            search_name, 0, extra_flag);
-            if (!dpreq) {
-                DEBUG(SSSDBG_CRIT_FAILURE,
-                      "Out of memory sending data provider request\n");
-                ret = ENOMEM;
-                goto done;
-            }
-
-            cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
-            if(!cb_ctx) {
-                talloc_zfree(dpreq);
-                ret = ENOMEM;
-                goto done;
-            }
-
-            cb_ctx->callback = sudosrv_check_user_dp_callback;
-            cb_ctx->ptr = dctx;
-            cb_ctx->cctx = cli_ctx;
-            cb_ctx->mem_ctx = cli_ctx;
-
-            tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);
-
-            /* tell caller we are in an async call */
-            ret = EAGAIN;
-            goto done;
-        }
-
-        /* check uid */
-        uid = sss_view_ldb_msg_find_attr_as_uint64(dom, user->msgs[0],
-                                                   SYSDB_UIDNUM, 0);
-        if (uid != cmd_ctx->uid) {
-            /* if a multidomain search, try with next */
-            if (cmd_ctx->check_next) {
-                dctx->check_provider = true;
-                dom = get_next_domain(dom, 0);
-                if (dom) continue;
-            }
-
-            DEBUG(SSSDBG_MINOR_FAILURE, "UID does not match\n");
-            ret = ENOENT;
-            goto done;
-        }
-
-        /* user is stored in cache, remember cased and original name */
-        original_name = ldb_msg_find_attr_as_string(user->msgs[0],
-                                                    SYSDB_NAME, NULL);
-        if (original_name == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
-            ret = EFAULT;
-            goto done;
-        }
-
-        cmd_ctx->cased_username = talloc_move(cmd_ctx, &name);
-        cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name);
-        if (cmd_ctx->orig_username == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
-            ret = ENOMEM;
-            goto done;
-        }
-
-        /* and set domain */
-        cmd_ctx->domain = dom;
-
-        DEBUG(SSSDBG_TRACE_FUNC, "Returning info for user [%s@%s]\n",
-              cmd_ctx->username, dctx->domain->name);
-        ret = EOK;
-        goto done;
-    }
-
-    ret = ENOENT;
-done:
-    talloc_free(tmp_ctx);
-    return ret;
-}
-
-static void sudosrv_dp_send_acct_req_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);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Fatal error, killing connection!\n");
-        talloc_free(cb_ctx->cctx);
-        return;
-    }
-
-    cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
-}
-
-static void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
-                                           const char *err_msg, void *ptr)
-{
-    errno_t ret;
-    struct sudo_dom_ctx *dctx = talloc_get_type(ptr, struct sudo_dom_ctx);
-
-    if (err_maj) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-             "Unable to get information from Data Provider\n"
-              "Error: %u, %u, %s\n",
-              (unsigned int)err_maj, (unsigned int)err_min, err_msg);
-    }
-
-    DEBUG(SSSDBG_TRACE_INTERNAL,
-          "Data Provider returned, check the cache again\n");
-    dctx->check_provider = false;
-    ret = sudosrv_get_user(dctx);
-    if (ret == EAGAIN) {
-        goto done;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Could not look up the user [%d]: %s\n",
-              ret, strerror(ret));
-        sudosrv_cmd_done(dctx->cmd_ctx, ret);
-        return;
-    }
-
-    DEBUG(SSSDBG_TRACE_INTERNAL, "Looking up sudo rules..\n");
-    ret = sudosrv_get_rules(dctx->cmd_ctx);
-    if (ret == EAGAIN) {
-        goto done;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Error getting sudo rules [%d]: %s\n",
-              ret, strerror(ret));
-        sudosrv_cmd_done(dctx->cmd_ctx, EIO);
-        return;
-    }
-
-done:
-    sudosrv_cmd_done(dctx->cmd_ctx, ret);
-}
-
 static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
                                                 struct sudo_cmd_ctx *cmd_ctx,
                                                 struct sysdb_attrs ***_rules,
@@ -367,12 +97,12 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
     switch (cmd_ctx->type) {
         case SSS_SUDO_DEFAULTS:
             DEBUG(SSSDBG_TRACE_FUNC, "Retrieving default options "
-                  "for [%s] from [%s]\n", cmd_ctx->orig_username,
+                  "for [%s] from [%s]\n", cmd_ctx->username,
                   cmd_ctx->domain->name);
             break;
         case SSS_SUDO_USER:
             DEBUG(SSSDBG_TRACE_FUNC, "Retrieving rules "
-                  "for [%s] from [%s]\n", cmd_ctx->orig_username,
+                  "for [%s] from [%s]\n", cmd_ctx->username,
                   cmd_ctx->domain->name);
             break;
     }
@@ -383,7 +113,7 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
      * provider call
      */
     ret = sysdb_get_sudo_user_info(tmp_ctx, cmd_ctx->domain,
-                                   cmd_ctx->orig_username, NULL, &groupnames);
+                                   cmd_ctx->username, NULL, &groupnames);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
              "Unable to retrieve user info [%d]: %s\n", ret, strerror(ret));
@@ -396,7 +126,7 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
             | SYSDB_SUDO_FILTER_USERINFO;
     ret = sudosrv_get_sudorules_query_cache(tmp_ctx,
                                             cmd_ctx->domain, attrs, flags,
-                                            cmd_ctx->orig_username,
+                                            cmd_ctx->username,
                                             cmd_ctx->uid, groupnames,
                                             cmd_ctx->sudo_ctx->inverse_order,
                                             &expired_rules, &expired_rules_num);
@@ -414,7 +144,7 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
         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,
+                                        cmd_ctx->username,
                                         expired_rules_num, expired_rules);
         if (dpreq == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
@@ -535,7 +265,7 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
                                         cmd_ctx->cli_ctx->rctx,
                                         cmd_ctx->domain, false,
                                         SSS_DP_SUDO_FULL_REFRESH,
-                                        cmd_ctx->orig_username,
+                                        cmd_ctx->username,
                                         0, NULL);
         if (dpreq == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
@@ -587,10 +317,10 @@ static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
 
     switch (cmd_ctx->type) {
     case SSS_SUDO_USER:
-        debug_name = cmd_ctx->cased_username;
+        debug_name = cmd_ctx->username;
         ret = sysdb_get_sudo_user_info(tmp_ctx,
                                        cmd_ctx->domain,
-                                       cmd_ctx->orig_username,
+                                       cmd_ctx->username,
                                        NULL, &groupnames);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
@@ -608,7 +338,7 @@ static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
 
     ret = sudosrv_get_sudorules_query_cache(tmp_ctx,
                                             cmd_ctx->domain, attrs, flags,
-                                            cmd_ctx->orig_username,
+                                            cmd_ctx->username,
                                             cmd_ctx->uid, groupnames,
                                             cmd_ctx->sudo_ctx->inverse_order,
                                             &rules, &num_rules);
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index f602f6a83cd52a54ce180d3aaaa1febd1d991f32..dceb113b530c8adfdb361cafff95b49d7dc323b5 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -61,10 +61,7 @@ struct sudo_cmd_ctx {
     /* input data */
     uid_t uid;
     char *username;
-    const char *orig_username;
-    const char *cased_username;
     struct sss_domain_info *domain;
-    bool check_next;
 
     uint32_t expired_rules_num;
 
@@ -73,22 +70,16 @@ struct sudo_cmd_ctx {
     uint32_t num_rules;
 };
 
-struct sudo_dom_ctx {
-    struct sudo_cmd_ctx *cmd_ctx;
-    struct sss_domain_info *domain;
-    bool check_provider;
-};
-
 struct sss_cmd_table *get_sudo_cmds(void);
 
 errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret);
 
-errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx);
+errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx);
 
 errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx);
 
 struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
-                                            struct resp_ctx *rctx,
+                                            struct sudo_ctx *sudo_ctx,
                                             uint8_t *query_body,
                                             size_t query_len);
 
diff --git a/src/responder/sudo/sudosrv_query.c b/src/responder/sudo/sudosrv_query.c
index 4cb07e32b3d7f2897dcd7f4941aa44bf8928d5c2..08b359c0464f1cc00866e46634e571562910018d 100644
--- a/src/responder/sudo/sudosrv_query.c
+++ b/src/responder/sudo/sudosrv_query.c
@@ -25,6 +25,7 @@
 #include <tevent.h>
 
 #include "util/util.h"
+#include "responder/common/responder_cache_req.h"
 #include "responder/sudo/sudosrv_private.h"
 
 static int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
@@ -252,15 +253,15 @@ fail:
 }
 
 struct sudosrv_parse_query_state {
-    struct resp_ctx *rctx;
     uid_t uid;
-    char *rawname;
+    char *username;
+    struct sss_domain_info *domain;
 };
 
 static void sudosrv_parse_query_done(struct tevent_req *subreq);
 
 struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
-                                            struct resp_ctx *rctx,
+                                            struct sudo_ctx *sudo_ctx,
                                             uint8_t *query_body,
                                             size_t query_len)
 {
@@ -270,7 +271,6 @@ struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
     size_t offset = 0;
     size_t rawname_len = 0;
     char *rawname = NULL;
-    char *domainname = NULL;
     errno_t ret;
 
     /* create request */
@@ -281,14 +281,12 @@ struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
-    state->rctx = rctx;
-
     /* uid */
 
     if (query_len < sizeof(uid_t)) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Query is too small\n");
         ret = EINVAL;
-        goto done;
+        goto immediately;
     }
     safealign_memcpy(&state->uid, query_body, sizeof(uid_t), &offset);
 
@@ -300,68 +298,59 @@ struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
     if (rawname[rawname_len - 1] != '\0') {
         DEBUG(SSSDBG_CRIT_FAILURE, "Username is not zero terminated\n");
         ret = EINVAL;
-        goto done;
+        goto immediately;
     }
 
     if (rawname_len < 2) { /* at least one character and zero */
         DEBUG(SSSDBG_CRIT_FAILURE, "Query does not contain username\n");
         ret = EINVAL;
-        goto done;
+        goto immediately;
     }
 
     if (!sss_utf8_check((uint8_t*)rawname, rawname_len - 1)) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Supplied data is not valid UTF-8 string\n");
         ret = EINVAL;
-        goto done;
+        goto immediately;
     }
 
     /* parse username */
 
-    state->rawname = rawname;
-    ret = sss_parse_name_for_domains(state, rctx->domains,
-                                     rctx->default_domain, state->rawname,
-                                     &domainname, NULL);
-    if (ret == EAGAIN) {
-        DEBUG(SSSDBG_TRACE_FUNC, "Domain [%s] not found, "
-              "sending subdomain request\n", domainname);
-
-        subreq = sss_dp_get_domains_send(state, rctx, true, domainname);
-        if (subreq == NULL) {
-            ret = ENOMEM;
-        } else {
-            tevent_req_set_callback(subreq, sudosrv_parse_query_done, req);
-            ret = EAGAIN;
-        }
-        goto done;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid name received [%s]\n", rawname);
-        goto done;
+    subreq = cache_req_initgr_by_name_send(state, sudo_ctx->rctx->ev,
+                                           sudo_ctx->rctx, sudo_ctx->ncache,
+                                           sudo_ctx->neg_timeout, 0,
+                                           NULL, rawname);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto immediately;
     }
 
-    ret = EOK;
+    tevent_req_set_callback(subreq, sudosrv_parse_query_done, req);
+
+    return req;
 
-done:
-    if (ret != EAGAIN) {
-        if (ret == EOK) {
-            tevent_req_done(req);
-        } else {
-            tevent_req_error(req, ret);
-        }
-        tevent_req_post(req, rctx->ev);
+immediately:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
     }
+    tevent_req_post(req, sudo_ctx->rctx->ev);
 
     return req;
 }
 
 static void sudosrv_parse_query_done(struct tevent_req *subreq)
 {
-    struct tevent_req *req = NULL;
+    struct sudosrv_parse_query_state *state;
+    struct tevent_req *req;
     errno_t ret;
 
     req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sudosrv_parse_query_state);
 
-    ret = sss_dp_get_domains_recv(subreq);
-    talloc_free(subreq);
+    ret = cache_req_initgr_by_name_recv(state, subreq, NULL,
+                                        &state->domain, &state->username);
+    talloc_zfree(subreq);
     if (ret != EOK) {
         tevent_req_error(req, ret);
         return;
@@ -377,53 +366,14 @@ errno_t sudosrv_parse_query_recv(TALLOC_CTX *mem_ctx,
                                  struct sss_domain_info **_domain)
 {
     struct sudosrv_parse_query_state *state = NULL;
-    struct sss_domain_info *domain = NULL;
-    char *username = NULL;
-    char *domainname = NULL;
-    errno_t ret;
 
     state = tevent_req_data(req, struct sudosrv_parse_query_state);
 
     TEVENT_REQ_RETURN_ON_ERROR(req);
 
-    if (state->rawname == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "No query specified?!\n");
-        return EINVAL;
-    }
-
-    /* Try to parse username@domain again because if the first call
-     * returned EAGAIN, then username is unset. If we get EAGAIN again,
-     * we will not search for it again.
-     */
-    ret = sss_parse_name_for_domains(state, state->rctx->domains,
-                                     state->rctx->default_domain,
-                                     state->rawname,
-                                     &domainname, &username);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_TRACE_FUNC, "Unable to parse domain [%d]: %s\n",
-                                  ret, strerror(ret));
-        return ret;
-    }
-
-    if (username == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "No username specified!\n");
-        return EINVAL;
-    }
-
-    if (domainname != NULL) {
-        /* mem_ctx because it duplicates only subdomains not domains
-         * so I cannot easily steal it */
-        domain = responder_get_domain(state->rctx, domainname);
-        if (domain == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, "Corresponding domain [%s] has not been "
-                                      "found\n", domainname);
-            return ENOENT;
-        }
-    }
-
     *_uid = state->uid;
-    *_username = talloc_steal(mem_ctx, username);
-    *_domain = domain; /* do not steal on mem_ctx */
+    *_username = talloc_steal(mem_ctx, state->username);
+    *_domain = state->domain; /* do not steal on mem_ctx */
 
     return EOK;
 }
-- 
2.1.0

From c3b3141d5898ce1cd8b5dee43b297c8b49f525cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Tue, 9 Feb 2016 10:52:51 +0100
Subject: [PATCH 3/4] sudo: do not use tevent when parsing query

---
 src/responder/sudo/sudosrv_cmd.c           |  30 +++++---
 src/responder/sudo/sudosrv_get_sudorules.c |   2 +-
 src/responder/sudo/sudosrv_private.h       |  16 ++--
 src/responder/sudo/sudosrv_query.c         | 115 +++++------------------------
 4 files changed, 45 insertions(+), 118 deletions(-)

diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index c68a6980ba817071e3766a0ddf7c158499d47aec..bdf01fac73886ed91507f318575c4af546ad7528 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -25,6 +25,7 @@
 #include "util/util.h"
 #include "responder/common/responder.h"
 #include "responder/common/responder_packet.h"
+#include "responder/common/responder_cache_req.h"
 #include "responder/sudo/sudosrv_private.h"
 #include "db/sysdb_sudo.h"
 #include "sss_client/sss_cli.h"
@@ -164,7 +165,7 @@ errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret)
     return EOK;
 }
 
-static void sudosrv_cmd_parse_query_done(struct tevent_req *req);
+static void sudosrv_cmd_initgr_done(struct tevent_req *req);
 
 static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
 {
@@ -213,7 +214,6 @@ static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
     }
 
     /* parse query */
-
     sss_packet_get_body(cli_ctx->creq->in, &query_body, &query_len);
     if (query_len <= 0 || query_body == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Query is empty\n");
@@ -221,14 +221,24 @@ static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
         goto done;
     }
 
-    req = sudosrv_parse_query_send(cmd_ctx, cmd_ctx->sudo_ctx,
-                                   query_body, query_len);
+    ret = sudosrv_parse_query(cmd_ctx, query_body, query_len,
+                              &cmd_ctx->rawname, &cmd_ctx->uid);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse sudo query [%d]: %s\n",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+
+    req = cache_req_initgr_by_name_send(cmd_ctx, cli_ctx->ev, cli_ctx->rctx,
+                                        cmd_ctx->sudo_ctx->ncache,
+                                        cmd_ctx->sudo_ctx->neg_timeout,
+                                        0, NULL, cmd_ctx->rawname);
     if (req == NULL) {
         ret = ENOMEM;
         goto done;
     }
 
-    tevent_req_set_callback(req, sudosrv_cmd_parse_query_done, cmd_ctx);
+    tevent_req_set_callback(req, sudosrv_cmd_initgr_done, cmd_ctx);
 
     ret = EAGAIN;
 
@@ -236,19 +246,19 @@ done:
     return sudosrv_cmd_done(cmd_ctx, ret);
 }
 
-static void sudosrv_cmd_parse_query_done(struct tevent_req *req)
+static void sudosrv_cmd_initgr_done(struct tevent_req *req)
 {
     struct sudo_cmd_ctx *cmd_ctx = NULL;
     errno_t ret;
 
     cmd_ctx = tevent_req_callback_data(req, struct sudo_cmd_ctx);
 
-    ret = sudosrv_parse_query_recv(cmd_ctx, req, &cmd_ctx->uid,
-                                   &cmd_ctx->username, &cmd_ctx->domain);
+    ret = cache_req_initgr_by_name_recv(cmd_ctx, req, NULL, &cmd_ctx->domain,
+                                        &cmd_ctx->username);
     talloc_zfree(req);
     if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid query [%d]: %s\n",
-                                    ret, strerror(ret));
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform initgroups [%d]: %s\n",
+              ret, strerror(ret));
         goto done;
     }
 
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 13015072e6daf1455b0b8e66a225f84c94280958..c81c990ac07d949ade47bbaf5b26f56117b5bfe7 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <talloc.h>
+#include <tevent.h>
 
 #include "util/util.h"
 #include "db/sysdb_sudo.h"
@@ -34,7 +35,6 @@ errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx)
 {
     errno_t ret;
 
-    /* OK, got the user from cache. Try to get the rules. */
     ret = sudosrv_get_rules(cmd_ctx);
     if (ret == EAGAIN) {
         DEBUG(SSSDBG_TRACE_INTERNAL,
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index dceb113b530c8adfdb361cafff95b49d7dc323b5..38de16960d9eaff38b92cddb859fcb8ef2c90c5d 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -60,6 +60,7 @@ struct sudo_cmd_ctx {
 
     /* input data */
     uid_t uid;
+    char *rawname;
     char *username;
     struct sss_domain_info *domain;
 
@@ -78,16 +79,11 @@ errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx);
 
 errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx);
 
-struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
-                                            struct sudo_ctx *sudo_ctx,
-                                            uint8_t *query_body,
-                                            size_t query_len);
-
-errno_t sudosrv_parse_query_recv(TALLOC_CTX *mem_ctx,
-                                 struct tevent_req *req,
-                                 uid_t *_uid,
-                                 char **_username,
-                                 struct sss_domain_info **_domain);
+errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx,
+                            uint8_t *query_body,
+                            size_t query_len,
+                            char **_rawname,
+                            uid_t *_uid);
 
 errno_t sudosrv_build_response(TALLOC_CTX *mem_ctx,
                                uint32_t error,
diff --git a/src/responder/sudo/sudosrv_query.c b/src/responder/sudo/sudosrv_query.c
index 08b359c0464f1cc00866e46634e571562910018d..36d777eb52e8fa7f1d366433b56d37431bf0bb7c 100644
--- a/src/responder/sudo/sudosrv_query.c
+++ b/src/responder/sudo/sudosrv_query.c
@@ -25,7 +25,6 @@
 #include <tevent.h>
 
 #include "util/util.h"
-#include "responder/common/responder_cache_req.h"
 #include "responder/sudo/sudosrv_private.h"
 
 static int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
@@ -252,128 +251,50 @@ fail:
     return ret;
 }
 
-struct sudosrv_parse_query_state {
-    uid_t uid;
-    char *username;
-    struct sss_domain_info *domain;
-};
-
-static void sudosrv_parse_query_done(struct tevent_req *subreq);
-
-struct tevent_req *sudosrv_parse_query_send(TALLOC_CTX *mem_ctx,
-                                            struct sudo_ctx *sudo_ctx,
-                                            uint8_t *query_body,
-                                            size_t query_len)
+errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx,
+                            uint8_t *query_body,
+                            size_t query_len,
+                            char **_rawname,
+                            uid_t *_uid)
 {
-    struct tevent_req *req = NULL;
-    struct tevent_req *subreq = NULL;
-    struct sudosrv_parse_query_state *state = NULL;
     size_t offset = 0;
-    size_t rawname_len = 0;
-    char *rawname = NULL;
-    errno_t ret;
-
-    /* create request */
-    req = tevent_req_create(mem_ctx, &state,
-                            struct sudosrv_parse_query_state);
-    if (req == NULL) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "tevent_req_create() failed\n");
-        return NULL;
-    }
+    size_t rawname_len;
+    char *rawname;
+    uid_t uid;
 
     /* uid */
-
     if (query_len < sizeof(uid_t)) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Query is too small\n");
-        ret = EINVAL;
-        goto immediately;
+        return EINVAL;
     }
-    safealign_memcpy(&state->uid, query_body, sizeof(uid_t), &offset);
+    safealign_memcpy(&uid, query_body, sizeof(uid_t), &offset);
 
     /* username[@domain] */
-
     rawname = (char*)(query_body + offset);
     rawname_len = query_len - offset; /* strlen + zero */
 
     if (rawname[rawname_len - 1] != '\0') {
         DEBUG(SSSDBG_CRIT_FAILURE, "Username is not zero terminated\n");
-        ret = EINVAL;
-        goto immediately;
+        return EINVAL;
     }
 
     if (rawname_len < 2) { /* at least one character and zero */
         DEBUG(SSSDBG_CRIT_FAILURE, "Query does not contain username\n");
-        ret = EINVAL;
-        goto immediately;
+        return EINVAL;
     }
 
     if (!sss_utf8_check((uint8_t*)rawname, rawname_len - 1)) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Supplied data is not valid UTF-8 string\n");
-        ret = EINVAL;
-        goto immediately;
+        return EINVAL;
     }
 
-    /* parse username */
-
-    subreq = cache_req_initgr_by_name_send(state, sudo_ctx->rctx->ev,
-                                           sudo_ctx->rctx, sudo_ctx->ncache,
-                                           sudo_ctx->neg_timeout, 0,
-                                           NULL, rawname);
-    if (subreq == NULL) {
-        ret = ENOMEM;
-        goto immediately;
-    }
-
-    tevent_req_set_callback(subreq, sudosrv_parse_query_done, req);
-
-    return req;
-
-immediately:
-    if (ret == EOK) {
-        tevent_req_done(req);
-    } else {
-        tevent_req_error(req, ret);
-    }
-    tevent_req_post(req, sudo_ctx->rctx->ev);
-
-    return req;
-}
-
-static void sudosrv_parse_query_done(struct tevent_req *subreq)
-{
-    struct sudosrv_parse_query_state *state;
-    struct tevent_req *req;
-    errno_t ret;
-
-    req = tevent_req_callback_data(subreq, struct tevent_req);
-    state = tevent_req_data(req, struct sudosrv_parse_query_state);
-
-    ret = cache_req_initgr_by_name_recv(state, subreq, NULL,
-                                        &state->domain, &state->username);
-    talloc_zfree(subreq);
-    if (ret != EOK) {
-        tevent_req_error(req, ret);
-        return;
+    rawname = talloc_strdup(mem_ctx, rawname);
+    if (rawname == NULL) {
+        return ENOMEM;
     }
 
-    tevent_req_done(req);
-}
-
-errno_t sudosrv_parse_query_recv(TALLOC_CTX *mem_ctx,
-                                 struct tevent_req *req,
-                                 uid_t *_uid,
-                                 char **_username,
-                                 struct sss_domain_info **_domain)
-{
-    struct sudosrv_parse_query_state *state = NULL;
-
-    state = tevent_req_data(req, struct sudosrv_parse_query_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *_uid = state->uid;
-    *_username = talloc_steal(mem_ctx, state->username);
-    *_domain = state->domain; /* do not steal on mem_ctx */
+    *_uid = uid;
+    *_rawname = rawname;
 
     return EOK;
 }
-- 
2.1.0

From 1136ba4578bdac002ed43a12a369e52e43433ba4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Tue, 9 Feb 2016 12:57:59 +0100
Subject: [PATCH 4/4] sudo: convert get_sudorules to tevent

There was a lot of confusion with different error codes
and where to call sudosrv_cmd_done to finish the client
request. Converting it whole to tevent makes it much
more simpler to read and follow the request logic.
---
 src/responder/sudo/sudosrv_cmd.c           |  46 +-
 src/responder/sudo/sudosrv_get_sudorules.c | 867 +++++++++++++++--------------
 src/responder/sudo/sudosrv_private.h       |  18 +-
 3 files changed, 481 insertions(+), 450 deletions(-)

diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index bdf01fac73886ed91507f318575c4af546ad7528..eeb388c48e6255959ad4afd0f10a358d1fab44bc 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -25,7 +25,6 @@
 #include "util/util.h"
 #include "responder/common/responder.h"
 #include "responder/common/responder_packet.h"
-#include "responder/common/responder_cache_req.h"
 #include "responder/sudo/sudosrv_private.h"
 #include "db/sysdb_sudo.h"
 #include "sss_client/sss_cli.h"
@@ -96,7 +95,7 @@ static errno_t sudosrv_cmd_send_error(TALLOC_CTX *mem_ctx,
     return sudosrv_cmd_send_reply(cmd_ctx, response_body, response_len);
 }
 
-errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret)
+errno_t sudosrv_cmd_reply(struct sudo_cmd_ctx *cmd_ctx, int ret)
 {
     uint8_t *response_body = NULL;
     size_t response_len = 0;
@@ -165,7 +164,7 @@ errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret)
     return EOK;
 }
 
-static void sudosrv_cmd_initgr_done(struct tevent_req *req);
+static void sudosrv_cmd_done(struct tevent_req *req);
 
 static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
 {
@@ -185,7 +184,6 @@ static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
         return ENOMEM;
     }
 
-    cmd_ctx->domain = NULL;
     cmd_ctx->cli_ctx = cli_ctx;
     cmd_ctx->type = type;
     cmd_ctx->sudo_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct sudo_ctx);
@@ -229,56 +227,40 @@ static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
         goto done;
     }
 
-    req = cache_req_initgr_by_name_send(cmd_ctx, cli_ctx->ev, cli_ctx->rctx,
-                                        cmd_ctx->sudo_ctx->ncache,
-                                        cmd_ctx->sudo_ctx->neg_timeout,
-                                        0, NULL, cmd_ctx->rawname);
+    req = sudosrv_get_rules_send(cmd_ctx, cli_ctx->ev, cmd_ctx->sudo_ctx,
+                                 cmd_ctx->type, cmd_ctx->uid,
+                                 cmd_ctx->rawname);
     if (req == NULL) {
         ret = ENOMEM;
         goto done;
     }
 
-    tevent_req_set_callback(req, sudosrv_cmd_initgr_done, cmd_ctx);
+    tevent_req_set_callback(req, sudosrv_cmd_done, cmd_ctx);
 
     ret = EAGAIN;
 
 done:
-    return sudosrv_cmd_done(cmd_ctx, ret);
+    return sudosrv_cmd_reply(cmd_ctx, ret);
 }
 
-static void sudosrv_cmd_initgr_done(struct tevent_req *req)
+static void sudosrv_cmd_done(struct tevent_req *req)
 {
-    struct sudo_cmd_ctx *cmd_ctx = NULL;
+    struct sudo_cmd_ctx *cmd_ctx;
     errno_t ret;
 
     cmd_ctx = tevent_req_callback_data(req, struct sudo_cmd_ctx);
 
-    ret = cache_req_initgr_by_name_recv(cmd_ctx, req, NULL, &cmd_ctx->domain,
-                                        &cmd_ctx->username);
+    ret = sudosrv_get_rules_recv(cmd_ctx, req, &cmd_ctx->rules,
+                                 &cmd_ctx->num_rules);
     talloc_zfree(req);
     if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform initgroups [%d]: %s\n",
-              ret, strerror(ret));
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain cached rules [%d]: %s\n",
+              ret, sss_strerror(ret));
         goto done;
     }
 
-    switch (cmd_ctx->type) {
-        case SSS_SUDO_DEFAULTS:
-            DEBUG(SSSDBG_FUNC_DATA, "Requesting default options "
-                  "for [%s] from [%s]\n", cmd_ctx->username,
-                  cmd_ctx->domain ? cmd_ctx->domain->name : "<ALL>");
-            break;
-        case SSS_SUDO_USER:
-            DEBUG(SSSDBG_FUNC_DATA, "Requesting rules "
-                  "for [%s] from [%s]\n", cmd_ctx->username,
-                  cmd_ctx->domain ? cmd_ctx->domain->name : "<ALL>");
-            break;
-    }
-
-    ret = sudosrv_get_sudorules(cmd_ctx);
-
 done:
-    sudosrv_cmd_done(cmd_ctx, ret);
+    sudosrv_cmd_reply(cmd_ctx, ret);
 }
 
 static int sudosrv_cmd_get_sudorules(struct cli_ctx *cli_ctx)
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index c81c990ac07d949ade47bbaf5b26f56117b5bfe7..31163c42b83a0491a7f89504e1e6907ed1b14feb 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -28,419 +28,10 @@
 
 #include "util/util.h"
 #include "db/sysdb_sudo.h"
+#include "responder/common/responder_cache_req.h"
 #include "responder/sudo/sudosrv_private.h"
 #include "providers/data_provider.h"
 
-errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx)
-{
-    errno_t ret;
-
-    ret = sudosrv_get_rules(cmd_ctx);
-    if (ret == EAGAIN) {
-        DEBUG(SSSDBG_TRACE_INTERNAL,
-              "Looking up the sudo rules from Data Provider\n");
-        return EAGAIN;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Error looking up sudo rules [%d]: %s\n", ret, strerror(ret));
-        return ret;
-    }
-
-    return EOK;
-}
-
-static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
-                                                struct sudo_cmd_ctx *cmd_ctx,
-                                                struct sysdb_attrs ***_rules,
-                                                uint32_t *_num_rules);
-static void
-sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
-                                  const char *err_msg, void *ptr);
-static void
-sudosrv_dp_req_done(struct tevent_req *req);
-
-static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
-                                                 struct sss_domain_info *domain,
-                                                 const char **attrs,
-                                                 unsigned int flags,
-                                                 const char *username,
-                                                 uid_t uid,
-                                                 char **groupnames,
-                                                 bool inverse_order,
-                                                 struct sysdb_attrs ***_rules,
-                                                 uint32_t *_count);
-
-errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
-{
-    TALLOC_CTX *tmp_ctx = NULL;
-    struct tevent_req *dpreq = NULL;
-    struct dp_callback_ctx *cb_ctx = NULL;
-    char **groupnames = NULL;
-    uint32_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:
-            DEBUG(SSSDBG_TRACE_FUNC, "Retrieving default options "
-                  "for [%s] from [%s]\n", cmd_ctx->username,
-                  cmd_ctx->domain->name);
-            break;
-        case SSS_SUDO_USER:
-            DEBUG(SSSDBG_TRACE_FUNC, "Retrieving rules "
-                  "for [%s] from [%s]\n", cmd_ctx->username,
-                  cmd_ctx->domain->name);
-            break;
-    }
-
-    /* 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->domain,
-                                   cmd_ctx->username, NULL, &groupnames);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-             "Unable to retrieve user info [%d]: %s\n", ret, strerror(ret));
-        goto done;
-    }
-
-    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,
-                                            cmd_ctx->domain, attrs, flags,
-                                            cmd_ctx->username,
-                                            cmd_ctx->uid, groupnames,
-                                            cmd_ctx->sudo_ctx->inverse_order,
-                                            &expired_rules, &expired_rules_num);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve expired sudo rules "
-                                    "[%d]: %s\n", ret, strerror(ret));
-        goto done;
-    }
-
-    cmd_ctx->expired_rules_num = expired_rules_num;
-    if (expired_rules_num > 0) {
-        /* refresh expired rules then continue */
-        DEBUG(SSSDBG_TRACE_INTERNAL, "Refreshing %d expired rules\n",
-                                      expired_rules_num);
-        dpreq = sss_dp_get_sudoers_send(tmp_ctx, cmd_ctx->cli_ctx->rctx,
-                                        cmd_ctx->domain, false,
-                                        SSS_DP_SUDO_REFRESH_RULES,
-                                        cmd_ctx->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;
-
-    } 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, cmd_ctx,
-                                               &cmd_ctx->rules,
-                                               &cmd_ctx->num_rules);
-        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
-sudosrv_dp_req_done(struct tevent_req *req)
-{
-    struct dp_callback_ctx *cb_ctx =
-        tevent_req_callback_data(req, struct dp_callback_ctx);
-    struct cli_ctx *cli_ctx;
-
-    errno_t ret;
-    dbus_uint16_t err_maj;
-    dbus_uint32_t err_min;
-    char *err_msg;
-
-    cli_ctx = talloc_get_type(cb_ctx->cctx, struct cli_ctx);
-
-    ret = sss_dp_get_sudoers_recv(cb_ctx->mem_ctx, req,
-                                  &err_maj, &err_min,
-                                  &err_msg);
-    talloc_free(req);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
-        talloc_free(cli_ctx);
-        return;
-    }
-
-    cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
-}
-
-static void
-sudosrv_dp_oob_req_done(struct tevent_req *req)
-{
-    DEBUG(SSSDBG_TRACE_FUNC, "Out of band refresh finished\n");
-    talloc_free(req);
-}
-
-static void
-sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
-                                  const char *err_msg, void *ptr)
-{
-    struct sudo_cmd_ctx *cmd_ctx = talloc_get_type(ptr, struct sudo_cmd_ctx);
-    struct tevent_req *dpreq = NULL;
-    errno_t ret;
-
-    if (err_maj) {
-        DEBUG(SSSDBG_CRIT_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);
-    }
-
-    DEBUG(SSSDBG_TRACE_INTERNAL, "About to get sudo rules from cache\n");
-    ret = sudosrv_get_sudorules_from_cache(cmd_ctx, cmd_ctx, &cmd_ctx->rules,
-                                           &cmd_ctx->num_rules);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Failed to make a request to our cache [%d]: %s\n",
-              ret, strerror(ret));
-        sudosrv_cmd_done(cmd_ctx, EIO);
-        return;
-    }
-
-    if (cmd_ctx->expired_rules_num > 0
-        && err_min == ENOENT) {
-        DEBUG(SSSDBG_TRACE_INTERNAL,
-              "Some expired rules were removed from the server, "
-               "scheduling full refresh out of band\n");
-        dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx->rctx,
-                                        cmd_ctx->cli_ctx->rctx,
-                                        cmd_ctx->domain, false,
-                                        SSS_DP_SUDO_FULL_REFRESH,
-                                        cmd_ctx->username,
-                                        0, NULL);
-        if (dpreq == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Cannot issue DP request.\n");
-        } else {
-            tevent_req_set_callback(dpreq, sudosrv_dp_oob_req_done, NULL);
-        }
-    }
-
-    sudosrv_cmd_done(cmd_ctx, ret);
-}
-
-static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
-                                                struct sudo_cmd_ctx *cmd_ctx,
-                                                struct sysdb_attrs ***_rules,
-                                                uint32_t *_num_rules)
-{
-    TALLOC_CTX *tmp_ctx;
-    errno_t ret;
-    char **groupnames = NULL;
-    const char *debug_name = NULL;
-    unsigned int flags = SYSDB_SUDO_FILTER_NONE;
-    struct sysdb_attrs **rules = NULL;
-    uint32_t num_rules = 0;
-    const char *attrs[] = { SYSDB_OBJECTCLASS,
-                            SYSDB_SUDO_CACHE_AT_CN,
-                            SYSDB_SUDO_CACHE_AT_USER,
-                            SYSDB_SUDO_CACHE_AT_HOST,
-                            SYSDB_SUDO_CACHE_AT_COMMAND,
-                            SYSDB_SUDO_CACHE_AT_OPTION,
-                            SYSDB_SUDO_CACHE_AT_RUNAS,
-                            SYSDB_SUDO_CACHE_AT_RUNASUSER,
-                            SYSDB_SUDO_CACHE_AT_RUNASGROUP,
-                            SYSDB_SUDO_CACHE_AT_NOTBEFORE,
-                            SYSDB_SUDO_CACHE_AT_NOTAFTER,
-                            SYSDB_SUDO_CACHE_AT_ORDER,
-                            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_USER:
-        debug_name = cmd_ctx->username;
-        ret = sysdb_get_sudo_user_info(tmp_ctx,
-                                       cmd_ctx->domain,
-                                       cmd_ctx->username,
-                                       NULL, &groupnames);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                 "Unable to retrieve user info [%d]: %s\n",
-                  ret, strerror(ret));
-            goto done;
-        }
-        flags = SYSDB_SUDO_FILTER_USERINFO | SYSDB_SUDO_FILTER_INCLUDE_ALL;
-        break;
-    case SSS_SUDO_DEFAULTS:
-        debug_name = "<default options>";
-        flags = SYSDB_SUDO_FILTER_INCLUDE_DFL;
-        break;
-    }
-
-    ret = sudosrv_get_sudorules_query_cache(tmp_ctx,
-                                            cmd_ctx->domain, attrs, flags,
-                                            cmd_ctx->username,
-                                            cmd_ctx->uid, groupnames,
-                                            cmd_ctx->sudo_ctx->inverse_order,
-                                            &rules, &num_rules);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-             "Unable to retrieve sudo rules [%d]: %s\n", ret, strerror(ret));
-        goto done;
-    }
-
-    DEBUG(SSSDBG_TRACE_FUNC, "Returning %d rules for [%s@%s]\n",
-                              num_rules, debug_name, cmd_ctx->domain->name);
-
-    if (_rules != NULL) {
-        *_rules = talloc_steal(mem_ctx, rules);
-    }
-
-    if (_num_rules != NULL) {
-        *_num_rules = num_rules;
-    }
-
-    ret = EOK;
-done:
-    talloc_free(tmp_ctx);
-    return ret;
-}
-
-static errno_t
-sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool higher_wins);
-
-static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
-                                                 struct sss_domain_info *domain,
-                                                 const char **attrs,
-                                                 unsigned int flags,
-                                                 const char *username,
-                                                 uid_t uid,
-                                                 char **groupnames,
-                                                 bool inverse_order,
-                                                 struct sysdb_attrs ***_rules,
-                                                 uint32_t *_count)
-{
-    TALLOC_CTX *tmp_ctx;
-    char *filter;
-    errno_t ret;
-    size_t count;
-    struct sysdb_attrs **rules;
-    struct ldb_message **msgs;
-
-    tmp_ctx = talloc_new(NULL);
-    if (tmp_ctx == NULL) return ENOMEM;
-
-    ret = sysdb_get_sudo_filter(tmp_ctx, username, uid, groupnames,
-                                flags, &filter);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Could not construct the search filter [%d]: %s\n",
-               ret, strerror(ret));
-        goto done;
-    }
-
-    DEBUG(SSSDBG_FUNC_DATA, "Searching sysdb with [%s]\n", filter);
-
-    if (IS_SUBDOMAIN(domain)) {
-        /* rules are stored inside parent domain tree */
-        domain = domain->parent;
-    }
-
-    ret = sysdb_search_custom(tmp_ctx, domain, filter,
-                              SUDORULE_SUBDIR, attrs,
-                              &count, &msgs);
-    if (ret != EOK && ret != ENOENT) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
-        goto done;
-    } if (ret == ENOENT) {
-       *_rules = NULL;
-       *_count = 0;
-       ret = EOK;
-       goto done;
-    }
-
-    ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Could not convert ldb message to sysdb_attrs\n");
-        goto done;
-    }
-
-    ret = sort_sudo_rules(rules, count, inverse_order);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "Could not sort rules by sudoOrder\n");
-        goto done;
-    }
-
-    *_rules = talloc_steal(mem_ctx, rules);
-    *_count = (uint32_t)count;
-
-    ret = EOK;
-done:
-    talloc_free(tmp_ctx);
-    return ret;
-}
-
 static int
 sudo_order_cmp(const void *a, const void *b, bool lower_wins)
 {
@@ -521,3 +112,459 @@ sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool lower_wins)
 
     return EOK;
 }
+
+static errno_t sudosrv_query_cache(TALLOC_CTX *mem_ctx,
+                                   struct sss_domain_info *domain,
+                                   const char **attrs,
+                                   unsigned int flags,
+                                   const char *username,
+                                   uid_t uid,
+                                   char **groupnames,
+                                   bool inverse_order,
+                                   struct sysdb_attrs ***_rules,
+                                   uint32_t *_count)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *filter;
+    errno_t ret;
+    size_t count;
+    struct sysdb_attrs **rules;
+    struct ldb_message **msgs;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_get_sudo_filter(tmp_ctx, username, uid, groupnames,
+                                flags, &filter);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct the search filter "
+              "[%d]: %s\n", ret, sss_strerror(ret));
+        goto done;
+    }
+
+    DEBUG(SSSDBG_FUNC_DATA, "Searching sysdb with [%s]\n", filter);
+
+    if (IS_SUBDOMAIN(domain)) {
+        /* rules are stored inside parent domain tree */
+        domain = domain->parent;
+    }
+
+    ret = sysdb_search_custom(tmp_ctx, domain, filter, SUDORULE_SUBDIR,
+                              attrs, &count, &msgs);
+    if (ret == ENOENT) {
+        *_rules = NULL;
+        *_count = 0;
+        ret = EOK;
+        goto done;
+    } else if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
+        goto done;
+    }
+
+    ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Could not convert ldb message to sysdb_attrs\n");
+        goto done;
+    }
+
+    ret = sort_sudo_rules(rules, count, inverse_order);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "Could not sort rules by sudoOrder\n");
+        goto done;
+    }
+
+    *_rules = talloc_steal(mem_ctx, rules);
+    *_count = (uint32_t)count;
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+static errno_t sudosrv_expired_rules(TALLOC_CTX *mem_ctx,
+                                     struct sss_domain_info *domain,
+                                     uid_t uid,
+                                     const char *username,
+                                     char **groups,
+                                     struct sysdb_attrs ***_rules,
+                                     uint32_t *_num_rules)
+{
+    unsigned int flags = SYSDB_SUDO_FILTER_NONE;
+    const char *attrs[] = {SYSDB_NAME, NULL};
+    errno_t ret;
+
+    flags =   SYSDB_SUDO_FILTER_INCLUDE_ALL
+            | SYSDB_SUDO_FILTER_INCLUDE_DFL
+            | SYSDB_SUDO_FILTER_ONLY_EXPIRED
+            | SYSDB_SUDO_FILTER_USERINFO;
+
+    ret = sudosrv_query_cache(mem_ctx, domain, attrs, flags,
+                              username, uid, groups, false,
+                              _rules, _num_rules);
+
+    return ret;
+}
+
+static errno_t sudosrv_cached_rules(TALLOC_CTX *mem_ctx,
+                                    enum sss_sudo_type type,
+                                    struct sss_domain_info *domain,
+                                    uid_t uid,
+                                    const char *username,
+                                    char **groups,
+                                    bool inverse_order,
+                                    struct sysdb_attrs ***_rules,
+                                    uint32_t *_num_rules)
+{
+    unsigned int flags = SYSDB_SUDO_FILTER_NONE;
+    struct sysdb_attrs **rules;
+    const char *debug_name = "unknown";
+    uint32_t num_rules;
+    errno_t ret;
+    const char *attrs[] = {SYSDB_OBJECTCLASS,
+                           SYSDB_SUDO_CACHE_AT_CN,
+                           SYSDB_SUDO_CACHE_AT_USER,
+                           SYSDB_SUDO_CACHE_AT_HOST,
+                           SYSDB_SUDO_CACHE_AT_COMMAND,
+                           SYSDB_SUDO_CACHE_AT_OPTION,
+                           SYSDB_SUDO_CACHE_AT_RUNAS,
+                           SYSDB_SUDO_CACHE_AT_RUNASUSER,
+                           SYSDB_SUDO_CACHE_AT_RUNASGROUP,
+                           SYSDB_SUDO_CACHE_AT_NOTBEFORE,
+                           SYSDB_SUDO_CACHE_AT_NOTAFTER,
+                           SYSDB_SUDO_CACHE_AT_ORDER,
+                           NULL };
+
+
+    switch (type) {
+    case SSS_SUDO_USER:
+        DEBUG(SSSDBG_TRACE_FUNC, "Retrieving rules for [%s@%s]\n",
+              username, domain->name);
+        debug_name = "rules";
+        flags = SYSDB_SUDO_FILTER_USERINFO | SYSDB_SUDO_FILTER_INCLUDE_ALL;
+        break;
+    case SSS_SUDO_DEFAULTS:
+        debug_name = "default options";
+        DEBUG(SSSDBG_TRACE_FUNC, "Retrieving default options for [%s@%s]\n",
+              username, domain->name);
+        flags = SYSDB_SUDO_FILTER_INCLUDE_DFL;
+        break;
+    }
+
+    ret = sudosrv_query_cache(mem_ctx, domain, attrs, flags,
+                              username, uid, groups,
+                              inverse_order, &rules, &num_rules);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+             "Unable to retrieve sudo rules [%d]: %s\n", ret, strerror(ret));
+        return ret;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Returning %d %s for [%s@%s]\n",
+          num_rules, debug_name, username, domain->name);
+
+    *_rules = rules;
+    *_num_rules = num_rules;
+
+    return EOK;
+}
+
+static void
+sudosrv_dp_oob_req_done(struct tevent_req *req)
+{
+    DEBUG(SSSDBG_TRACE_FUNC, "Out of band refresh finished\n");
+    talloc_free(req);
+}
+
+struct sudosrv_refresh_rules_state {
+    struct resp_ctx *rctx;
+    struct sss_domain_info *domain;
+    const char *username;
+};
+
+static void sudosrv_refresh_rules_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sudosrv_refresh_rules_send(TALLOC_CTX *mem_ctx,
+                           struct tevent_context *ev,
+                           struct resp_ctx *rctx,
+                           struct sss_domain_info *domain,
+                           uid_t uid,
+                           const char *username,
+                           char **groups)
+{
+    struct sudosrv_refresh_rules_state *state;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct sysdb_attrs **rules;
+    uint32_t num_rules;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct sudosrv_refresh_rules_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
+        return NULL;
+    }
+
+    state->rctx = rctx;
+    state->domain = domain;
+    state->username = username;
+
+    ret = sudosrv_expired_rules(state, domain, uid, username, groups,
+                                &rules, &num_rules);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve expired sudo rules "
+                                    "[%d]: %s\n", ret, strerror(ret));
+        goto immediately;
+    }
+
+    if (num_rules == 0) {
+        DEBUG(SSSDBG_TRACE_FUNC, "No expired rules were found for [%s@%s].\n",
+              username, domain->name);
+        ret = EOK;
+        goto immediately;
+    }
+
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Refreshing %d expired rules of [%s@%s]\n",
+          num_rules, username, domain->name);
+
+    subreq = sss_dp_get_sudoers_send(state, rctx, domain, false,
+                                     SSS_DP_SUDO_REFRESH_RULES,
+                                     username, num_rules, rules);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    tevent_req_set_callback(subreq, sudosrv_refresh_rules_done, req);
+
+    return req;
+
+immediately:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
+    }
+    tevent_req_post(req, ev);
+
+    return req;
+}
+
+static void sudosrv_refresh_rules_done(struct tevent_req *subreq)
+{
+    struct sudosrv_refresh_rules_state *state;
+    struct tevent_req *req;
+    dbus_uint16_t err_maj;
+    dbus_uint32_t err_min;
+    char *err_msg;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sudosrv_refresh_rules_state);
+
+    ret = sss_dp_get_sudoers_recv(state, subreq, &err_maj, &err_min, &err_msg);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Unable to get information from Data Provider, "
+              "Error: %u, %u, %s\n",
+              (unsigned int)err_maj, (unsigned int)err_min, err_msg);
+        goto done;
+    }
+
+    if (err_min == ENOENT) {
+        DEBUG(SSSDBG_TRACE_INTERNAL, "Some expired rules were removed from "
+              "the server, scheduling full refresh out of band\n");
+        subreq = sss_dp_get_sudoers_send(state->rctx, state->rctx,
+                                         state->domain, false,
+                                         SSS_DP_SUDO_FULL_REFRESH,
+                                         state->username, 0, NULL);
+        if (subreq == NULL) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot issue DP request.\n");
+            ret = EOK; /* We don't care. */
+            goto done;
+        }
+
+        tevent_req_set_callback(subreq, sudosrv_dp_oob_req_done, NULL);
+    }
+
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    tevent_req_done(req);
+}
+
+static errno_t sudosrv_refresh_rules_recv(struct tevent_req *req)
+{
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    return EOK;
+}
+
+struct sudosrv_get_rules_state {
+    struct tevent_context *ev;
+    struct resp_ctx *rctx;
+    enum sss_sudo_type type;
+    uid_t uid;
+    char *username;
+    struct sss_domain_info *domain;
+    char **groups;
+    bool inverse_order;
+
+    struct sysdb_attrs **rules;
+    uint32_t num_rules;
+};
+
+static void sudosrv_get_rules_initgr_done(struct tevent_req *subreq);
+static void sudosrv_get_rules_done(struct tevent_req *subreq);
+
+struct tevent_req *sudosrv_get_rules_send(TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev,
+                                          struct sudo_ctx *sudo_ctx,
+                                          enum sss_sudo_type type,
+                                          uid_t uid,
+                                          const char *username)
+{
+    struct sudosrv_get_rules_state *state;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state, struct sudosrv_get_rules_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
+        return NULL;
+    }
+
+    state->ev = ev;
+    state->rctx = sudo_ctx->rctx;
+    state->type = type;
+    state->uid = uid;
+    state->inverse_order = sudo_ctx->inverse_order;
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Running initgroups for [%s]\n", username);
+
+    subreq = cache_req_initgr_by_name_send(state, ev, sudo_ctx->rctx,
+                                           sudo_ctx->ncache,
+                                           sudo_ctx->neg_timeout,
+                                           0, NULL, username);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    tevent_req_set_callback(subreq, sudosrv_get_rules_initgr_done, req);
+
+    return req;
+
+immediately:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
+    }
+    tevent_req_post(req, ev);
+
+    return req;
+}
+
+static void sudosrv_get_rules_initgr_done(struct tevent_req *subreq)
+{
+    struct sudosrv_get_rules_state *state;
+    struct tevent_req *req;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sudosrv_get_rules_state);
+
+    ret = cache_req_initgr_by_name_recv(state, subreq, NULL,
+                                        &state->domain, &state->username);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    ret = sysdb_get_sudo_user_info(state, state->domain, state->username,
+                                   NULL, &state->groups);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain user groups [%d]: %s\n",
+              ret, sss_strerror(ret));
+        goto done;
+    }
+
+    subreq = sudosrv_refresh_rules_send(state, state->ev, state->rctx,
+                                        state->domain, state->uid,
+                                        state->username, state->groups);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    tevent_req_set_callback(subreq, sudosrv_get_rules_done, req);
+
+    ret = EAGAIN;
+
+done:
+    if (ret != EOK && ret != EAGAIN) {
+        tevent_req_error(req, ret);
+        return;
+    } else if (ret != EAGAIN) {
+        tevent_req_done(req);
+    }
+}
+
+static void sudosrv_get_rules_done(struct tevent_req *subreq)
+{
+    struct sudosrv_get_rules_state *state = NULL;
+    struct tevent_req *req = NULL;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sudosrv_get_rules_state);
+
+    ret = sudosrv_refresh_rules_recv(subreq);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh expired rules, "
+              "we will return what is in cache.\n");
+    }
+
+    ret = sudosrv_cached_rules(state, state->type, state->domain, state->uid,
+                               state->username, state->groups,
+                               state->inverse_order,
+                               &state->rules, &state->num_rules);
+
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t sudosrv_get_rules_recv(TALLOC_CTX *mem_ctx,
+                               struct tevent_req *req,
+                               struct sysdb_attrs ***_rules,
+                               uint32_t *_num_rules)
+{
+    struct sudosrv_get_rules_state *state = NULL;
+    state = tevent_req_data(req, struct sudosrv_get_rules_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *_rules = talloc_steal(mem_ctx, state->rules);
+    *_num_rules = state->num_rules;
+
+    return EOK;
+}
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index 38de16960d9eaff38b92cddb859fcb8ef2c90c5d..99eef03e950f88d9296dbf33e66c68f100523cc9 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -61,10 +61,6 @@ struct sudo_cmd_ctx {
     /* input data */
     uid_t uid;
     char *rawname;
-    char *username;
-    struct sss_domain_info *domain;
-
-    uint32_t expired_rules_num;
 
     /* output data */
     struct sysdb_attrs **rules;
@@ -73,11 +69,17 @@ struct sudo_cmd_ctx {
 
 struct sss_cmd_table *get_sudo_cmds(void);
 
-errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret);
+struct tevent_req *sudosrv_get_rules_send(TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev,
+                                          struct sudo_ctx *sudo_ctx,
+                                          enum sss_sudo_type type,
+                                          uid_t uid,
+                                          const char *username);
 
-errno_t sudosrv_get_sudorules(struct sudo_cmd_ctx *cmd_ctx);
-
-errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx);
+errno_t sudosrv_get_rules_recv(TALLOC_CTX *mem_ctx,
+                               struct tevent_req *req,
+                               struct sysdb_attrs ***_rules,
+                               uint32_t *_num_rules);
 
 errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx,
                             uint8_t *query_body,
-- 
2.1.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to