From 7770270f8ab7d57ec598bff5022a09391fc3a66a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Mon, 23 Jan 2012 15:32:08 +0100
Subject: [PATCH 3/5] SUDO Integration - responder command for cn=defaults

https://fedorahosted.org/sssd/ticket/1143
---
 src/responder/sudo/sudosrv_cmd.c           |   47 ++++++++++++++++++++++++++++
 src/responder/sudo/sudosrv_dp.c            |   15 ++++++++-
 src/responder/sudo/sudosrv_get_sudorules.c |   37 ++++++++++++++--------
 src/responder/sudo/sudosrv_private.h       |   12 +++++--
 src/sss_client/sss_cli.h                   |    1 +
 5 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index 72e608b..3550e8b 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -149,6 +149,7 @@ static int sudosrv_cmd_get_sudorules(struct cli_ctx *cli_ctx)
         goto done;
     }
     cmd_ctx->cli_ctx = cli_ctx;
+    cmd_ctx->type = SSS_DP_SUDO_USER;
 
     dctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx);
     if (!dctx) {
@@ -207,6 +208,51 @@ done:
     return sudosrv_cmd_done(dctx, ret);
 }
 
+static int sudosrv_cmd_get_defaults(struct cli_ctx *cli_ctx)
+{
+    int ret = EOK;
+    struct sudo_cmd_ctx *cmd_ctx = NULL;
+    struct sudo_dom_ctx *dctx = NULL;
+
+    cmd_ctx = talloc_zero(cli_ctx, struct sudo_cmd_ctx);
+    if (!cmd_ctx) {
+        ret = ENOMEM;
+        goto done;
+    }
+    cmd_ctx->cli_ctx = cli_ctx;
+    cmd_ctx->type = SSS_DP_SUDO_DEFAULTS;
+    cmd_ctx->username = NULL;
+    cmd_ctx->check_next = false;
+
+    dctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx);
+    if (!dctx) {
+        ret = ENOMEM;
+        goto done;
+    }
+    dctx->cmd_ctx = cmd_ctx;
+
+    DEBUG(SSSDBG_FUNC_DATA, ("Requesting cn=defaults\n"));
+
+    /* sudo currently does not support domain selection
+     * so find first available domain
+     * TODO - support domain selection */
+    dctx->domain = cli_ctx->rctx->domains;
+    while (dctx->domain && dctx->domain->fqnames) {
+        dctx->domain = dctx->domain->next;
+    }
+    if (!dctx->domain) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("No valid domain found\n"));
+        ret = ENOENT;
+        goto done;
+    }
+
+    /* ok, find it ! */
+    ret = sudosrv_get_rules(dctx);
+
+done:
+    return sudosrv_cmd_done(dctx, ret);
+}
+
 struct cli_protocol_version *register_cli_protocol_version(void)
 {
     static struct cli_protocol_version sudo_cli_protocol_version[] = {
@@ -220,6 +266,7 @@ struct sss_cmd_table *get_sudo_cmds(void) {
     static struct sss_cmd_table sudo_cmds[] = {
         {SSS_GET_VERSION, sss_cmd_get_version},
         {SSS_SUDO_GET_SUDORULES, sudosrv_cmd_get_sudorules},
+        {SSS_SUDO_GET_DEFAULTS, sudosrv_cmd_get_defaults},
         {SSS_CLI_NULL, NULL}
     };
 
diff --git a/src/responder/sudo/sudosrv_dp.c b/src/responder/sudo/sudosrv_dp.c
index 4002955..4d0082f 100644
--- a/src/responder/sudo/sudosrv_dp.c
+++ b/src/responder/sudo/sudosrv_dp.c
@@ -107,11 +107,24 @@ sss_dp_get_sudoers_msg(void *pvt)
 
     info = talloc_get_type(pvt, struct sss_dp_get_sudoers_info);
 
+    switch (info->type) {
+        case SSS_DP_SUDO_DEFAULTS:
+            be_type = BE_REQ_SUDO_DEFAULTS;
+            break;
+        case SSS_DP_SUDO_USER:
+            be_type = BE_REQ_SUDO_USER;
+            break;
+    }
+
     if (info->fast_reply) {
         be_type |= BE_REQ_FAST;
     }
 
-    filter = talloc_asprintf(info, "name=%s", info->name);
+    if (info->name != NULL) {
+        filter = talloc_asprintf(info, "name=%s", info->name);
+    } else {
+        filter = talloc_strdup(info, "");
+    }
     if (!filter) {
         DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory?!\n"));
         return NULL;
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 0b3b81e..b7e1705 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -28,7 +28,6 @@
 #include "responder/sudo/sudosrv_private.h"
 
 static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx);
-static errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx);
 
 errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx)
 {
@@ -243,7 +242,7 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
 static void
 sudosrv_dp_req_done(struct tevent_req *req);
 
-static errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
+errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
 {
     struct tevent_req *dpreq;
     struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
@@ -254,7 +253,7 @@ static 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,
-                                    SSS_DP_SUDO,
+                                    cmd_ctx->type,
                                     cmd_ctx->username);
     if (dpreq == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -341,6 +340,7 @@ sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
 
 static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
                                                  struct sysdb_ctx *sysdb,
+                                                 enum sss_dp_sudo_type type,
                                                  const char *username,
                                                  uid_t uid,
                                                  char **groupnames,
@@ -368,15 +368,20 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx)
         goto done;
     }
 
-    ret = sysdb_get_sudo_user_info(tmp_ctx, dctx->cmd_ctx->username,
-                                   sysdb, &uid, &groupnames);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-             ("Unable to retrieve user info [%d]: %s\n", strerror(ret)));
-        goto done;
+    if (dctx->cmd_ctx->type == SSS_DP_SUDO_USER) {
+        ret = sysdb_get_sudo_user_info(tmp_ctx, dctx->cmd_ctx->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;
     }
 
-    ret = sudosrv_get_sudorules_query_cache(dctx, sysdb,
+    ret = sudosrv_get_sudorules_query_cache(dctx, sysdb, dctx->cmd_ctx->type,
                                             dctx->cmd_ctx->username,
                                             uid, groupnames,
                                             &dctx->res, &dctx->res_count);
@@ -400,6 +405,7 @@ sort_sudo_rules(struct sysdb_attrs **rules, size_t count);
 
 static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
                                                  struct sysdb_ctx *sysdb,
+                                                 enum sss_dp_sudo_type type,
                                                  const char *username,
                                                  uid_t uid,
                                                  char **groupnames,
@@ -430,9 +436,14 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) return ENOMEM;
 
-    flags =   SYSDB_SUDO_FILTER_USERINFO
-            | SYSDB_SUDO_FILTER_INCLUDE_ALL
-            | SYSDB_SUDO_FILTER_INCLUDE_DFL;
+    switch (type) {
+    case SSS_DP_SUDO_DEFAULTS:
+        flags = SYSDB_SUDO_FILTER_INCLUDE_DFL;
+        break;
+    case SSS_DP_SUDO_USER:
+        flags =   SYSDB_SUDO_FILTER_USERINFO | SYSDB_SUDO_FILTER_INCLUDE_ALL;
+        break;
+    }
     ret = sysdb_get_sudo_filter(tmp_ctx, username, uid, groupnames,
                                 flags, &filter);
     if (ret != EOK) {
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index 23b421b..b59aca4 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -31,12 +31,18 @@
 #define SSS_SUDO_SBUS_SERVICE_VERSION 0x0001
 #define SSS_SUDO_SBUS_SERVICE_NAME "sudo"
 
+enum sss_dp_sudo_type {
+    SSS_DP_SUDO_DEFAULTS,
+    SSS_DP_SUDO_USER
+};
+
 struct sudo_ctx {
     struct resp_ctx *rctx;
 };
 
 struct sudo_cmd_ctx {
     struct cli_ctx *cli_ctx;
+    enum sss_dp_sudo_type type;
     char *username;
     bool check_next;
 };
@@ -63,6 +69,8 @@ errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret);
 
 errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx);
 
+errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx);
+
 char * sudosrv_get_sudorules_parse_query(TALLOC_CTX *mem_ctx,
                                          const char *query_body,
                                          int query_len);
@@ -98,10 +106,6 @@ int sudosrv_response_append_attr(TALLOC_CTX *mem_ctx,
                                  uint8_t **_response_body,
                                  size_t *_response_len);
 
-enum sss_dp_sudo_type {
-    SSS_DP_SUDO
-};
-
 struct tevent_req *
 sss_dp_get_sudoers_send(TALLOC_CTX *mem_ctx,
                         struct resp_ctx *rctx,
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index c17e376..8bba729 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -160,6 +160,7 @@ enum sss_cli_command {
 
 /* SUDO */
     SSS_SUDO_GET_SUDORULES = 0x00C1,
+    SSS_SUDO_GET_DEFAULTS  = 0x00C2,
 
 /* PAM related calls */
     SSS_PAM_AUTHENTICATE     = 0x00F1, /**< see pam_sm_authenticate(3) for
-- 
1.7.6.4
