[SSSD] [PATCH] PAM: Add domains= option to pam_sss

Daniel Gollub dgollub at brocade.com
Tue Jul 29 14:15:16 UTC 2014


Fixes:
https://fedorahosted.org/sssd/ticket/1021

Signed-off-by: Daniel Gollub <dgollub at brocade.com>
Reviewed-by: Sven-Thorsten Dietrich <sven at brocade.com>
---
 src/providers/data_provider.h  |  1 +
 src/responder/pam/pamsrv_cmd.c | 44 +++++++++++++++++++++++++++++++++++++++++-
 src/sss_client/pam_sss.c       | 29 ++++++++++++++++++++++++++--
 src/sss_client/sss_cli.h       |  1 +
 4 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index ebb4fad..0abfd0f 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -170,6 +170,7 @@ struct pam_data {
     char *tty;
     char *ruser;
     char *rhost;
+    char **requested_domains;
     struct sss_auth_token *authtok;
     struct sss_auth_token *newauthtok;
     uint32_t cli_pid;
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 140d541..c6539e5 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -44,6 +44,26 @@ enum pam_verbosity {
 
 static void pam_reply(struct pam_auth_req *preq);
 
+static bool is_domain_requested(struct pam_data *pd, const char *domain_name)
+{
+    int i;
+
+    /* If none specific domains got requested via pam, all domains are allowed.
+     * Which mimics the default/original behaviour.
+     */
+    if (!pd->requested_domains)
+	    return true;
+
+    for (i = 0; pd->requested_domains[i]; i++) {
+       if (strcmp(domain_name, pd->requested_domains[i]))
+           continue;
+
+       return true;
+    }
+
+    return false;
+}
+
 static int extract_authtok_v2(struct sss_auth_token *tok,
                               size_t data_size, uint8_t *body, size_t blen,
                               size_t *c)
@@ -146,6 +166,7 @@ static int pam_parse_in_data_v2(struct sss_domain_info *domains,
     int ret;
     uint32_t start;
     uint32_t terminator;
+    char *requested_domains;
 
     if (blen < 4*sizeof(uint32_t)+2) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
@@ -202,6 +223,16 @@ static int pam_parse_in_data_v2(struct sss_domain_info *domains,
                     ret = extract_string(&pd->rhost, size, body, blen, &c);
                     if (ret != EOK) return ret;
                     break;
+                case SSS_PAM_ITEM_REQUESTED_DOMAINS:
+                    ret = extract_string(&requested_domains, size, body, blen, &c);
+                    if (ret != EOK) return ret;
+                    ret = split_on_separator(pd, requested_domains, ',', true, true,
+				             &pd->requested_domains, NULL);
+                    if (ret != EOK) {
+                        DEBUG(1, ("Failed to parse requested_domains list!\n"));
+                        return ret;
+                    }
+                    break;
                 case SSS_PAM_ITEM_CLI_PID:
                     ret = extract_uint32_t(&pd->cli_pid, size,
                                            body, blen, &c);
@@ -836,12 +867,22 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
             ret = ENOENT;
             goto done;
         }
+
+        /* skip this domain if not requested */
+        if (!is_domain_requested(pd, dom->name)) {
+	    ret = ENOENT;
+	    goto done;
+	}
     } else {
         for (dom = preq->cctx->rctx->domains;
              dom;
              dom = get_next_domain(dom, false)) {
             if (dom->fqnames) continue;
 
+            /* skip this domain if not requested */
+            if (!is_domain_requested(pd, dom->name))
+                continue;
+
             ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
                                           dom, pd->user);
             if (ncret == ENOENT) {
@@ -856,7 +897,8 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
                   "User [%s@%s] filtered out (negative cache). "
                    "Trying next domain.\n", pd->user, dom->name);
         }
-        if (!dom) {
+
+        if (!dom || !is_domain_requested(pd, dom->name)) {
             ret = ENOENT;
             goto done;
         }
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index d2502d1..4d76bd2 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -58,6 +58,7 @@
 #define PW_RESET_MSG_MAX_SIZE 4096
 
 #define OPT_RETRY_KEY "retry="
+#define OPT_DOMAINS_KEY "domains="
 
 struct pam_items {
     const char* pam_service;
@@ -81,6 +82,8 @@ struct pam_items {
     pid_t cli_pid;
     const char *login_name;
     char *domain_name;
+    const char *requested_domains;
+    size_t requested_domains_size;
 };
 
 #define DEBUG_MGS_LEN 1024
@@ -246,6 +249,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size,
     len += pi->pam_newauthtok != NULL ?
                 3*sizeof(uint32_t) + pi->pam_newauthtok_size : 0;
     len += 3*sizeof(uint32_t); /* cli_pid */
+    len += *pi->requested_domains != '\0' ?
+                2*sizeof(uint32_t) + pi->requested_domains_size : 0;
+
 
     buf = malloc(len);
     if (buf == NULL) {
@@ -271,6 +277,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size,
     rp += add_string_item(SSS_PAM_ITEM_RHOST, pi->pam_rhost, pi->pam_rhost_size,
                           &buf[rp]);
 
+    rp += add_string_item(SSS_PAM_ITEM_REQUESTED_DOMAINS, pi->requested_domains, pi->requested_domains_size,
+                          &buf[rp]);
+
     rp += add_uint32_t_item(SSS_PAM_ITEM_CLI_PID, (uint32_t) pi->cli_pid,
                             &buf[rp]);
 
@@ -1061,6 +1070,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
 
     pi->domain_name = NULL;
 
+    if (pi->requested_domains == NULL) pi->requested_domains="";
+    pi->requested_domains_size=strlen(pi->requested_domains)+1;
+
     return PAM_SUCCESS;
 }
 
@@ -1080,6 +1092,7 @@ static void print_pam_items(struct pam_items *pi)
     D(("Authtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_authtok)));
     D(("Newauthtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_newauthtok)));
     D(("Cli_PID: %d", pi->cli_pid));
+    D(("Requested domains: %s", pi->requested_domains));
 }
 
 static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
@@ -1271,7 +1284,8 @@ static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi)
 }
 
 static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
-                      uint32_t *flags, int *retries, bool *quiet_mode)
+                      uint32_t *flags, int *retries, bool *quiet_mode,
+                      const char **domains)
 {
     char *ep;
 
@@ -1284,6 +1298,14 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
             *flags |= FLAGS_USE_FIRST_PASS;
         } else if (strcmp(*argv, "use_authtok") == 0) {
             *flags |= FLAGS_USE_AUTHTOK;
+        } else if (strncmp(*argv, OPT_DOMAINS_KEY, strlen(OPT_DOMAINS_KEY)) == 0) {
+            if (*(*argv+strlen(OPT_DOMAINS_KEY)) == '\0') {
+                logger(pamh, LOG_ERR, "Missing argument to option domains.");
+                *domains = '\0';
+            } else {
+                *domains = *argv+strlen(OPT_DOMAINS_KEY);
+            }
+
         } else if (strncmp(*argv, OPT_RETRY_KEY, strlen(OPT_RETRY_KEY)) == 0) {
             if (*(*argv+6) == '\0') {
                 logger(pamh, LOG_ERR, "Missing argument to option retry.");
@@ -1443,12 +1465,15 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
     bool retry = false;
     bool quiet_mode = false;
     int retries = 0;
+    const char *domains = NULL;
 
     bindtextdomain(PACKAGE, LOCALEDIR);
 
     D(("Hello pam_sssd: %d", task));
 
-    eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode);
+    eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode, &domains);
+
+    pi.requested_domains = domains;
 
     ret = get_pam_items(pamh, &pi);
     if (ret != PAM_SUCCESS) {
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index 16a08e1..15f8322 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -314,6 +314,7 @@ enum pam_item_type {
     SSS_PAM_ITEM_NEWAUTHTOK,
     SSS_PAM_ITEM_CLI_LOCALE,
     SSS_PAM_ITEM_CLI_PID,
+    SSS_PAM_ITEM_REQUESTED_DOMAINS,
 };
 
 #define SSS_NSS_MAX_ENTRIES 256
-- 
1.9.1




More information about the sssd-devel mailing list