From 190000cdb170a45895016cff4f5de6a2768d8a90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 13 Apr 2012 09:58:42 +0200
Subject: [PATCH 3/6] sudo responder: get rid of dctx where possible

---
 src/responder/sudo/sudosrv_cmd.c           |   61 ++++++++-------
 src/responder/sudo/sudosrv_get_sudorules.c |  114 ++++++++++++++-------------
 src/responder/sudo/sudosrv_private.h       |   20 +++--
 3 files changed, 102 insertions(+), 93 deletions(-)

diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index bb9e89e..c75d391 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -93,25 +93,22 @@ 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_dom_ctx *dctx, int ret)
+errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret)
 {
     uint8_t *response_body = NULL;
     size_t response_len = 0;
-    size_t num_rules = dctx->res_count;
-    struct sysdb_attrs **rules = dctx->res;
+    size_t num_rules = cmd_ctx->num_rules;
+    struct sysdb_attrs **rules = cmd_ctx->rules;
 
     switch (ret) {
     case EOK:
         /*
-         * Parent of dctx->res is in-memory cache, we must not talloc_free it!
+         * Parent of cmd_ctx->rules is in-memory cache, we must not talloc_free it!
          */
-        if (!dctx->cmd_ctx->sudo_ctx->timed) {
-            num_rules = dctx->res_count;
-            rules = dctx->res;
-        } else {
+        if (cmd_ctx->sudo_ctx->timed) {
             /* filter rules by time */
-            ret = sysdb_sudo_filter_rules_by_time(dctx, dctx->res_count,
-                                                  dctx->res, 0,
+            ret = sysdb_sudo_filter_rules_by_time(cmd_ctx, cmd_ctx->num_rules,
+                                                  cmd_ctx->rules, 0,
                                                   &num_rules, &rules);
             if (ret != EOK) {
                 return EFAULT;
@@ -119,14 +116,14 @@ errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret)
         }
 
         /* send result */
-        ret = sudosrv_build_response(dctx->cmd_ctx, SSS_SUDO_ERROR_OK,
+        ret = sudosrv_build_response(cmd_ctx, SSS_SUDO_ERROR_OK,
                                      num_rules, rules,
                                      &response_body, &response_len);
         if (ret != EOK) {
             return EFAULT;
         }
 
-        ret = sudosrv_cmd_send_reply(dctx->cmd_ctx, response_body, response_len);
+        ret = sudosrv_cmd_send_reply(cmd_ctx, response_body, response_len);
         break;
 
     case EAGAIN:
@@ -145,13 +142,13 @@ errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret)
 
     default:
         /* send error */
-        ret = sudosrv_cmd_send_error(dctx->cmd_ctx, dctx->cmd_ctx, ret);
+        ret = sudosrv_cmd_send_error(cmd_ctx, cmd_ctx, ret);
         break;
     }
 
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("Fatal error, killing connection!\n"));
-        talloc_free(dctx->cmd_ctx->cli_ctx);
+        talloc_free(cmd_ctx->cli_ctx);
         return EFAULT;
     }
 
@@ -164,14 +161,15 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx)
     struct sudo_dom_ctx *dctx = NULL;
     uint8_t *query_body = NULL;
     size_t query_len = 0;
-    int ret = EOK;
+    errno_t ret = EOK;
 
     cmd_ctx = talloc_zero(cli_ctx, struct sudo_cmd_ctx);
-    if (!cmd_ctx) {
+    if (cmd_ctx == NULL) {
         /* kill the connection here as we have no context for reply */
         DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n"));
         return ENOMEM;
     }
+    cmd_ctx->domain = NULL;
     cmd_ctx->cli_ctx = cli_ctx;
     cmd_ctx->type = type;
     cmd_ctx->username = NULL;
@@ -181,18 +179,17 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx)
     cmd_ctx->sudo_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct sudo_ctx);
     if (!cmd_ctx->sudo_ctx) {
         DEBUG(SSSDBG_FATAL_FAILURE, ("sudo_ctx not set, killing connection!\n"));
-        talloc_free(cmd_ctx);
-        return EFAULT;
+        ret = EFAULT;
+        goto done;
     }
 
     /* create domain ctx */
     dctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx);
-    if (!dctx) {
-        return sudosrv_cmd_send_error(cmd_ctx, cmd_ctx, ENOMEM);
+    if (dctx == NULL) {
+        ret = ENOMEM;
+        goto done;
     }
     dctx->cmd_ctx = cmd_ctx;
-    dctx->orig_username = NULL;
-    dctx->cased_username = NULL;
 
     switch (cmd_ctx->type) {
     case SSS_DP_SUDO_USER:
@@ -206,25 +203,28 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx)
 
         ret = sudosrv_parse_query(cmd_ctx, cli_ctx->rctx->domains,
                                   cli_ctx->rctx->names, query_body, query_len,
-                                  &cmd_ctx->username, &dctx->domain);
+                                  &cmd_ctx->username, &cmd_ctx->domain);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query: %s\n", strerror(ret)));
             goto done;
         }
 
         DEBUG(SSSDBG_FUNC_DATA, ("Requesting sudo rules for [%s] from [%s]\n",
-              cmd_ctx->username, dctx->domain ? dctx->domain->name : "<ALL>"));
+              cmd_ctx->username, cmd_ctx->domain ? cmd_ctx->domain->name : "<ALL>"));
 
-        if (dctx->domain == NULL) {
+        if (cmd_ctx->domain == NULL) {
             /* this is a multidomain search */
             dctx->domain = cli_ctx->rctx->domains;
             cmd_ctx->check_next = true;
+        } else {
+            dctx->domain = cmd_ctx->domain;
+            cmd_ctx->check_next = false;
         }
 
         /* try to find rules in in-memory cache */
         ret = sudosrv_cache_lookup(cmd_ctx->sudo_ctx->cache, dctx,
                                    cmd_ctx->check_next, cmd_ctx->username,
-                                   &dctx->res_count, &dctx->res);
+                                   &cmd_ctx->num_rules, &cmd_ctx->rules);
         if (ret == EOK) {
             /* cache hit */
             DEBUG(SSSDBG_FUNC_DATA, ("Returning rules for [%s@%s] "
@@ -252,8 +252,8 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx)
         }
 
         ret = sudosrv_cache_lookup(cmd_ctx->sudo_ctx->cache, dctx,
-                                       cmd_ctx->check_next, cmd_ctx->username,
-                                       &dctx->res_count, &dctx->res);
+                                   cmd_ctx->check_next, cmd_ctx->username,
+                                   &cmd_ctx->num_rules, &cmd_ctx->rules);
 
         if (ret == EOK) {
             /* cache hit */
@@ -261,14 +261,15 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx)
                                      "from in-memory cache\n", dctx->domain->name));
         } else if (ret == ENOENT) {
             /* cache expired or missed */
-            ret = sudosrv_get_rules(dctx);
+            cmd_ctx->domain = dctx->domain;
+            ret = sudosrv_get_rules(cmd_ctx);
         } /* else error */
 
         break;
     }
 
 done:
-    return sudosrv_cmd_done(dctx, ret);
+    return sudosrv_cmd_done(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 e92e807..c392027 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -48,7 +48,7 @@ errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx)
     }
 
     /* OK, got the user from cache. Try to get the rules. */
-    ret = sudosrv_get_rules(dctx);
+    ret = sudosrv_get_rules(dctx->cmd_ctx);
     if (ret == EAGAIN) {
         DEBUG(SSSDBG_TRACE_INTERNAL,
               ("Looking up the sudo rules from Data Provider\n"));
@@ -195,14 +195,17 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
             goto done;
         }
 
-        dctx->cased_username = talloc_move(dctx, &name);
-        dctx->orig_username = talloc_strdup(dctx, original_name);
-        if (dctx->orig_username== NULL) {
+        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;
@@ -262,37 +265,36 @@ static void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
         DEBUG(SSSDBG_OP_FAILURE,
               ("Could not look up the user [%d]: %s\n",
               ret, strerror(ret)));
-        sudosrv_cmd_done(dctx, EIO);
+        sudosrv_cmd_done(dctx->cmd_ctx, EIO);
         return;
     }
 
     DEBUG(SSSDBG_TRACE_INTERNAL, ("Looking up sudo rules..\n"));
-    ret = sudosrv_get_rules(dctx);
+    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, EIO);
+        sudosrv_cmd_done(dctx->cmd_ctx, EIO);
         return;
     }
 
 done:
-    sudosrv_cmd_done(dctx, ret);
+    sudosrv_cmd_done(dctx->cmd_ctx, ret);
 }
 
-static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx);
+static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx);
 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);
 
-errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
+errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
 {
     struct tevent_req *dpreq;
-    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
     struct dp_callback_ctx *cb_ctx = NULL;
 
     DEBUG(SSSDBG_TRACE_FUNC, ("getting rules for %s\n",
@@ -300,25 +302,25 @@ errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
 
     dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx,
                                     cmd_ctx->cli_ctx->rctx,
-                                    dctx->domain, false,
+                                    cmd_ctx->domain, false,
                                     cmd_ctx->type,
-                                    dctx->orig_username);
+                                    cmd_ctx->orig_username);
     if (dpreq == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               ("Cannot issue DP request.\n"));
         return EIO;
     }
 
-    cb_ctx = talloc_zero(dctx, struct dp_callback_ctx);
+    cb_ctx = talloc_zero(cmd_ctx, struct dp_callback_ctx);
     if (!cb_ctx) {
         talloc_zfree(dpreq);
         return ENOMEM;
     }
 
     cb_ctx->callback = sudosrv_get_sudorules_dp_callback;
-    cb_ctx->ptr = dctx;
-    cb_ctx->cctx = dctx->cmd_ctx->cli_ctx;
-    cb_ctx->mem_ctx = dctx;
+    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);
     return EAGAIN;
@@ -329,8 +331,7 @@ sudosrv_dp_req_done(struct tevent_req *req)
 {
     struct dp_callback_ctx *cb_ctx =
         tevent_req_callback_data(req, struct dp_callback_ctx);
-    struct sudo_dom_ctx *dctx =
-        talloc_get_type(cb_ctx->ptr, struct sudo_dom_ctx);
+    struct cli_ctx *cli_ctx = talloc_get_type(cb_ctx->cctx, struct cli_ctx);
 
     errno_t ret;
     dbus_uint16_t err_maj;
@@ -343,7 +344,7 @@ sudosrv_dp_req_done(struct tevent_req *req)
     talloc_free(req);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("Fatal error, killing connection!\n"));
-        talloc_free(dctx->cmd_ctx->cli_ctx);
+        talloc_free(cli_ctx);
         return;
     }
 
@@ -354,8 +355,7 @@ static void
 sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
                                   const char *err_msg, void *ptr)
 {
-    struct sudo_dom_ctx *dctx =
-        talloc_get_type(ptr, struct sudo_dom_ctx);
+    struct sudo_cmd_ctx *cmd_ctx = talloc_get_type(ptr, struct sudo_cmd_ctx);
     errno_t ret;
 
     if (err_maj) {
@@ -364,25 +364,19 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
                "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));
-
-        /* Loop to the next domain if possible */
-        if (dctx->domain->next && dctx->cmd_ctx->check_next) {
-            dctx->domain = dctx->domain->next;
-            dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-        }
     }
 
     DEBUG(SSSDBG_TRACE_INTERNAL, ("About to get sudo rules from cache\n"));
-    ret = sudosrv_get_sudorules_from_cache(dctx);
+    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)));
-        sudosrv_cmd_done(dctx, EIO);
+        sudosrv_cmd_done(cmd_ctx, EIO);
         return;
     }
 
-    sudosrv_cmd_done(dctx, ret);
+    sudosrv_cmd_done(cmd_ctx, ret);
 }
 
 static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
@@ -394,21 +388,28 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
                                                  struct sysdb_attrs ***_rules,
                                                  size_t *_count);
 
-static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx)
+static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx)
 {
     TALLOC_CTX *tmp_ctx;
     errno_t ret;
     struct sysdb_ctx *sysdb;
-    struct sudo_ctx *sudo_ctx = dctx->cmd_ctx->sudo_ctx;
-    uid_t uid;
-    char **groupnames;
-    const char *safe_name = dctx->cmd_ctx->username ?
-                            dctx->cmd_ctx->username : "default rules";
+    struct sudo_ctx *sudo_ctx = cmd_ctx->sudo_ctx;
+    uid_t uid = 0;
+    char **groupnames = NULL;
+    const char *debug_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) return ENOMEM;
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+        return ENOMEM;
+    }
 
-    sysdb = dctx->domain->sysdb;
+    sysdb = cmd_ctx->domain->sysdb;
     if (sysdb == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               ("sysdb context not found for this domain!\n"));
@@ -416,23 +417,26 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx)
         goto done;
     }
 
-    if (dctx->cmd_ctx->type == SSS_DP_SUDO_USER) {
-        ret = sysdb_get_sudo_user_info(tmp_ctx, dctx->orig_username,
-                                       sysdb, &uid, &groupnames);
+    switch (cmd_ctx->type) {
+    case SSS_DP_SUDO_USER:
+        debug_name = cmd_ctx->cased_username;
+        ret = sysdb_get_sudo_user_info(tmp_ctx, cmd_ctx->orig_username, sysdb,
+                                       &uid, &groupnames);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                  ("Unable to retrieve user info [%d]: %s\n", strerror(ret)));
             goto done;
         }
-    } else {
-        uid = 0;
-        groupnames = NULL;
+        break;
+    case SSS_DP_SUDO_DEFAULTS:
+        debug_name = "<default options>";
+        break;
     }
 
-    ret = sudosrv_get_sudorules_query_cache(dctx, sysdb, dctx->cmd_ctx->type,
-                                            dctx->orig_username,
+    ret = sudosrv_get_sudorules_query_cache(cmd_ctx, sysdb, cmd_ctx->type,
+                                            cmd_ctx->orig_username,
                                             uid, groupnames,
-                                            &dctx->res, &dctx->res_count);
+                                            &cmd_ctx->rules, &cmd_ctx->num_rules);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
              ("Unable to retrieve sudo rules [%d]: %s\n", strerror(ret)));
@@ -440,20 +444,20 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx)
     }
 
     /* Store result in in-memory cache */
-    ret = sudosrv_cache_set_entry(sudo_ctx->rctx->ev, sudo_ctx,
-                                  sudo_ctx->cache, dctx->domain,
-                                  dctx->cased_username, dctx->res_count,
-                                  dctx->res, sudo_ctx->cache_timeout);
+    ret = sudosrv_cache_set_entry(sudo_ctx->rctx->ev, sudo_ctx, sudo_ctx->cache,
+                                  cmd_ctx->domain, cmd_ctx->cased_username,
+                                  cmd_ctx->num_rules, cmd_ctx->rules,
+                                  sudo_ctx->cache_timeout);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE, ("Unable to store rules in cache for "
-              "[%s@%s]\n", safe_name, dctx->domain->name));
+              "[%s@%s]\n", debug_name, cmd_ctx->domain->name));
     } else {
         DEBUG(SSSDBG_FUNC_DATA, ("Rules for [%s@%s] stored in in-memory cache\n",
-                                 safe_name, dctx->domain->name));
+                                 debug_name, cmd_ctx->domain->name));
     }
 
     DEBUG(SSSDBG_TRACE_FUNC, ("Returning rules for [%s@%s]\n",
-          safe_name, dctx->domain->name));
+          debug_name, cmd_ctx->domain->name));
 
     ret = EOK;
 done:
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index e83532e..dee8e06 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include <talloc.h>
+#include <sys/types.h>
 
 #include "src/db/sysdb.h"
 #include "responder/common/responder.h"
@@ -57,20 +58,23 @@ struct sudo_cmd_ctx {
     struct cli_ctx *cli_ctx;
     struct sudo_ctx *sudo_ctx;
     enum sss_dp_sudo_type type;
+
+    /* input data */
     char *username;
+    const char *orig_username;
+    const char *cased_username;
+    struct sss_domain_info *domain;
     bool check_next;
+
+    /* output data */
+    struct sysdb_attrs **rules;
+    size_t num_rules;
 };
 
 struct sudo_dom_ctx {
     struct sudo_cmd_ctx *cmd_ctx;
     struct sss_domain_info *domain;
     bool check_provider;
-    const char *orig_username;
-    const char *cased_username;
-
-    /* cache results */
-    struct sysdb_attrs **res;
-    size_t res_count;
 };
 
 struct sudo_dp_request {
@@ -80,11 +84,11 @@ struct sudo_dp_request {
 
 struct sss_cmd_table *get_sudo_cmds(void);
 
-errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret);
+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_rules(struct sudo_dom_ctx *dctx);
+errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx);
 
 errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx,
                             struct sss_domain_info *domains,
-- 
1.7.6.5

