dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone

Blame SOURCES/0041-pam_sss-add-option-require_cert_auth.patch

71e593
From f724123e20f8d4a1c85473d917da6c65a10d6d62 Mon Sep 17 00:00:00 2001
71e593
From: Sumit Bose <sbose@redhat.com>
71e593
Date: Tue, 18 Sep 2018 09:53:37 +0200
71e593
Subject: [PATCH 41/47] pam_sss: add option require_cert_auth
71e593
71e593
With this new option pam_sss will wait until a Smartcard is available
71e593
and then try to authenticate with the help of the Smartcard.
71e593
71e593
Related https://pagure.io/SSSD/sssd/issue/3650
71e593
71e593
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
71e593
(cherry picked from commit 49be8974b490c368d349752f3196af0c9ed28dd5)
71e593
---
71e593
 src/man/pam_sss.8.xml          | 25 ++++++++++++
71e593
 src/responder/pam/pamsrv_cmd.c | 12 ++++++
71e593
 src/responder/pam/pamsrv_p11.c |  5 ++-
71e593
 src/sss_client/pam_message.c   |  4 ++
71e593
 src/sss_client/pam_message.h   |  1 +
71e593
 src/sss_client/pam_sss.c       | 92 ++++++++++++++++++++++++++----------------
71e593
 src/sss_client/sss_cli.h       |  2 +
71e593
 src/util/sss_pam_data.c        |  1 +
71e593
 src/util/sss_pam_data.h        |  1 +
71e593
 9 files changed, 107 insertions(+), 36 deletions(-)
71e593
71e593
diff --git a/src/man/pam_sss.8.xml b/src/man/pam_sss.8.xml
71e593
index ca2e8e20678d102525a9252678dd83459c3338ac..9998519f16c934e0d578760a57cc0908db760bfb 100644
71e593
--- a/src/man/pam_sss.8.xml
71e593
+++ b/src/man/pam_sss.8.xml
71e593
@@ -53,6 +53,9 @@
71e593
             <arg choice='opt'>
71e593
                 <replaceable>try_cert_auth</replaceable>
71e593
             </arg>
71e593
+            <arg choice='opt'>
71e593
+                <replaceable>require_cert_auth</replaceable>
71e593
+            </arg>
71e593
         </cmdsynopsis>
71e593
     </refsynopsisdiv>
71e593
 
71e593
@@ -223,6 +226,28 @@ auth sufficient pam_sss.so allow_missing_name
71e593
                     </para>
71e593
                 </listitem>
71e593
             </varlistentry>
71e593
+            <varlistentry>
71e593
+                <term>
71e593
+                    <option>require_cert_auth</option>
71e593
+                </term>
71e593
+                <listitem>
71e593
+                    <para>
71e593
+                        Do certificate based authentication, i.e.
71e593
+                        authentication with a Smartcard or similar devices. If a
71e593
+                        Smartcard is not available the user will be prompted to
71e593
+                        insert one. SSSD will wait for a Smartcard until the
71e593
+                        timeout defined by p11_wait_for_card_timeout passed,
71e593
+                        please see
71e593
+                        <citerefentry><refentrytitle>sssd.conf</refentrytitle>
71e593
+                        <manvolnum>5</manvolnum></citerefentry> for details.
71e593
+                    </para>
71e593
+                    <para>
71e593
+                        If no Smartcard is available after the timeout or
71e593
+                        certificate based authentication is not allowed for the
71e593
+                        current service PAM_AUTHINFO_UNAVAIL is returned.
71e593
+                    </para>
71e593
+                </listitem>
71e593
+            </varlistentry>
71e593
         </variablelist>
71e593
     </refsect1>
71e593
 
71e593
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
71e593
index c8df32de9e72e9f5ce33e26f0a13101a99f01d5f..6e37f831602e4c367176cc14126dbbec72c858cd 100644
71e593
--- a/src/responder/pam/pamsrv_cmd.c
71e593
+++ b/src/responder/pam/pamsrv_cmd.c
71e593
@@ -317,6 +317,11 @@ static int pam_parse_in_data_v2(struct pam_data *pd,
71e593
                                              size, body, blen, &c);
71e593
                     if (ret != EOK) return ret;
71e593
                     break;
71e593
+                case SSS_PAM_ITEM_FLAGS:
71e593
+                    ret = extract_uint32_t(&pd->cli_flags, size,
71e593
+                                           body, blen, &c);
71e593
+                    if (ret != EOK) return ret;
71e593
+                    break;
71e593
                 default:
71e593
                     DEBUG(SSSDBG_CRIT_FAILURE,
71e593
                           "Ignoring unknown data type [%d].\n", type);
71e593
@@ -1447,6 +1452,13 @@ static void pam_forwarder_cert_cb(struct tevent_req *req)
71e593
                   "No certificate found and no logon name given, " \
71e593
                   "authentication not possible.\n");
71e593
             ret = ENOENT;
71e593
+        } else if (pd->cli_flags & PAM_CLI_FLAGS_TRY_CERT_AUTH) {
71e593
+            DEBUG(SSSDBG_TRACE_ALL,
71e593
+                  "try_cert_auth flag set but no certificate available, "
71e593
+                  "request finished.\n");
71e593
+            preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
71e593
+            pam_reply(preq);
71e593
+            return;
71e593
         } else {
71e593
             if (pd->cmd == SSS_PAM_AUTHENTICATE) {
71e593
                 DEBUG(SSSDBG_CRIT_FAILURE,
71e593
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
71e593
index ffa6787e967488ac408ce0f0a11b96066c29b630..8b8859d9d335aec6d310201256522fa8afdd3694 100644
71e593
--- a/src/responder/pam/pamsrv_p11.c
71e593
+++ b/src/responder/pam/pamsrv_p11.c
71e593
@@ -721,7 +721,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
71e593
     struct timeval tv;
71e593
     int pipefd_to_child[2] = PIPE_INIT;
71e593
     int pipefd_from_child[2] = PIPE_INIT;
71e593
-    const char *extra_args[13] = { NULL };
71e593
+    const char *extra_args[14] = { NULL };
71e593
     uint8_t *write_buf = NULL;
71e593
     size_t write_buf_len = 0;
71e593
     size_t arg_c;
71e593
@@ -748,6 +748,9 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
71e593
 
71e593
     /* extra_args are added in revers order */
71e593
     arg_c = 0;
71e593
+    if ((pd->cli_flags & PAM_CLI_FLAGS_REQUIRE_CERT_AUTH) && pd->priv == 1) {
71e593
+        extra_args[arg_c++] = "--wait_for_card";
71e593
+    }
71e593
     extra_args[arg_c++] = nss_db;
71e593
     extra_args[arg_c++] = "--nssdb";
71e593
     if (verify_opts != NULL) {
71e593
diff --git a/src/sss_client/pam_message.c b/src/sss_client/pam_message.c
71e593
index b239f6f53da54054c52e484bdd076193709cb003..036ae2ad17742c123ba59e39a122ea605b7b95a6 100644
71e593
--- a/src/sss_client/pam_message.c
71e593
+++ b/src/sss_client/pam_message.c
71e593
@@ -126,6 +126,7 @@ int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer)
71e593
     len += 3*sizeof(uint32_t); /* cli_pid */
71e593
     len += *pi->requested_domains != '\0' ?
71e593
                 2*sizeof(uint32_t) + pi->requested_domains_size : 0;
71e593
+    len += 3*sizeof(uint32_t); /* flags */
71e593
 
71e593
     buf = malloc(len);
71e593
     if (buf == NULL) {
71e593
@@ -164,6 +165,9 @@ int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer)
71e593
                            pi->pam_newauthtok, pi->pam_newauthtok_size,
71e593
                            &buf[rp]);
71e593
 
71e593
+    rp += add_uint32_t_item(SSS_PAM_ITEM_FLAGS, (uint32_t) pi->flags,
71e593
+                            &buf[rp]);
71e593
+
71e593
     SAFEALIGN_SETMEM_UINT32(buf + rp, SSS_END_OF_PAM_REQUEST, &rp);
71e593
 
71e593
     if (rp != len) {
71e593
diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h
71e593
index 11526a80a767ff5602b194d14765ff261e8f9707..50fedcd82d8ace520d0360d85d163f91df0cb100 100644
71e593
--- a/src/sss_client/pam_message.h
71e593
+++ b/src/sss_client/pam_message.h
71e593
@@ -51,6 +51,7 @@ struct pam_items {
71e593
     enum sss_authtok_type pam_newauthtok_type;
71e593
     size_t pam_newauthtok_size;
71e593
     pid_t cli_pid;
71e593
+    uint32_t flags;
71e593
     const char *login_name;
71e593
     char *domain_name;
71e593
     const char *requested_domains;
71e593
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
71e593
index 96ff15adad867aceae17431cd5256ae52e4b9306..b4c1036ad68a97821f5d0aee873fa18fe5e72683 100644
71e593
--- a/src/sss_client/pam_sss.c
71e593
+++ b/src/sss_client/pam_sss.c
71e593
@@ -134,6 +134,7 @@ static void free_cai(struct cert_auth_info *cai)
71e593
         free(cai->cert_user);
71e593
         free(cai->cert);
71e593
         free(cai->token_name);
71e593
+        free(cai->module_name);
71e593
         free(cai->key_id);
71e593
         free(cai->prompt_str);
71e593
         free(cai);
71e593
@@ -1247,6 +1248,8 @@ static int get_pam_items(pam_handle_t *pamh, uint32_t flags,
71e593
     pi->cert_list = NULL;
71e593
     pi->selected_cert = NULL;
71e593
 
71e593
+    pi->flags = flags;
71e593
+
71e593
     return PAM_SUCCESS;
71e593
 }
71e593
 
71e593
@@ -1267,6 +1270,7 @@ static void print_pam_items(struct pam_items *pi)
71e593
     D(("Newauthtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_newauthtok)));
71e593
     D(("Cli_PID: %d", pi->cli_pid));
71e593
     D(("Requested domains: %s", pi->requested_domains));
71e593
+    D(("Flags: %d", pi->flags));
71e593
 }
71e593
 
71e593
 static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
71e593
@@ -1999,6 +2003,8 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
71e593
             *flags |= PAM_CLI_FLAGS_PROMPT_ALWAYS;
71e593
         } else if (strcmp(*argv, "try_cert_auth") == 0) {
71e593
             *flags |= PAM_CLI_FLAGS_TRY_CERT_AUTH;
71e593
+        } else if (strcmp(*argv, "require_cert_auth") == 0) {
71e593
+            *flags |= PAM_CLI_FLAGS_REQUIRE_CERT_AUTH;
71e593
         } else {
71e593
             logger(pamh, LOG_WARNING, "unknown option: %s", *argv);
71e593
         }
71e593
@@ -2274,55 +2280,51 @@ static int get_authtok_for_password_change(pam_handle_t *pamh,
71e593
     return PAM_SUCCESS;
71e593
 }
71e593
 
71e593
-#define SC_ENTER_FMT "Please enter smart card labeled\n %s\nand press enter"
71e593
+#define SC_ENTER_LABEL_FMT "Please enter smart card labeled\n %s"
71e593
+#define SC_ENTER_FMT "Please enter smart card"
71e593
 
71e593
 static int check_login_token_name(pam_handle_t *pamh, struct pam_items *pi,
71e593
-                                  bool quiet_mode)
71e593
+                                  int retries, bool quiet_mode)
71e593
 {
71e593
     int ret;
71e593
     int pam_status;
71e593
     char *login_token_name;
71e593
     char *prompt = NULL;
71e593
-    size_t size;
71e593
-    char *answer = NULL;
71e593
-    /* TODO: check multiple cert case */
71e593
-    struct cert_auth_info *cai = pi->cert_list;
71e593
-
71e593
-    if (cai == NULL) {
71e593
-        D(("No certificate information available"));
71e593
-        return EINVAL;
71e593
-    }
71e593
+    uint32_t orig_flags = pi->flags;
71e593
 
71e593
     login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME");
71e593
+    if (login_token_name == NULL
71e593
+            && !(pi->flags & PAM_CLI_FLAGS_REQUIRE_CERT_AUTH)) {
71e593
+        return PAM_SUCCESS;
71e593
+    }
71e593
+
71e593
     if (login_token_name == NULL) {
71e593
-        return PAM_SUCCESS;
71e593
+        ret = asprintf(&prompt, SC_ENTER_FMT);
71e593
+    } else {
71e593
+        ret = asprintf(&prompt, SC_ENTER_LABEL_FMT, login_token_name);
71e593
+    }
71e593
+    if (ret == -1) {
71e593
+        return ENOMEM;
71e593
     }
71e593
 
71e593
-    while (cai->token_name == NULL
71e593
-               || strcmp(login_token_name, cai->token_name) != 0) {
71e593
-        size = sizeof(SC_ENTER_FMT) + strlen(login_token_name);
71e593
-        prompt = malloc(size);
71e593
-        if (prompt == NULL) {
71e593
-            D(("malloc failed."));
71e593
-            return ENOMEM;
71e593
-        }
71e593
+    pi->flags |= PAM_CLI_FLAGS_REQUIRE_CERT_AUTH;
71e593
+
71e593
+    /* TODO: check multiple cert case */
71e593
+    while (pi->cert_list == NULL || pi->cert_list->token_name == NULL
71e593
+                || (login_token_name != NULL
71e593
+                        && strcmp(login_token_name,
71e593
+                                  pi->cert_list->token_name) != 0)) {
71e593
 
71e593
-        ret = snprintf(prompt, size, SC_ENTER_FMT,
71e593
-                       login_token_name);
71e593
-        if (ret < 0 || ret >= size) {
71e593
-            D(("snprintf failed."));
71e593
-            free(prompt);
71e593
-            return EFAULT;
71e593
+        if (retries < 0) {
71e593
+            ret = PAM_AUTHINFO_UNAVAIL;
71e593
+            goto done;
71e593
         }
71e593
+        retries--;
71e593
 
71e593
-        ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt,
71e593
-                                  NULL, &answer);
71e593
-        free(prompt);
71e593
+        ret = do_pam_conversation(pamh, PAM_TEXT_INFO, prompt, NULL, NULL);
71e593
         if (ret != PAM_SUCCESS) {
71e593
             D(("do_pam_conversation failed."));
71e593
-            return ret;
71e593
-        } else {
71e593
-            free(answer);
71e593
+            goto done;
71e593
         }
71e593
 
71e593
         pam_status = send_and_receive(pamh, pi, SSS_PAM_PREAUTH, quiet_mode);
71e593
@@ -2335,7 +2337,14 @@ static int check_login_token_name(pam_handle_t *pamh, struct pam_items *pi,
71e593
         }
71e593
     }
71e593
 
71e593
-    return PAM_SUCCESS;
71e593
+    ret = PAM_SUCCESS;
71e593
+
71e593
+done:
71e593
+
71e593
+    pi->flags = orig_flags;
71e593
+    free(prompt);
71e593
+
71e593
+    return ret;
71e593
 }
71e593
 
71e593
 static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
71e593
@@ -2394,8 +2403,19 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
71e593
                         && (pi.pam_authtok == NULL
71e593
                                 || (flags & PAM_CLI_FLAGS_PROMPT_ALWAYS))
71e593
                         && access(PAM_PREAUTH_INDICATOR, F_OK) == 0) {
71e593
+
71e593
+                    if (flags & PAM_CLI_FLAGS_REQUIRE_CERT_AUTH) {
71e593
+                        /* Do not use PAM_CLI_FLAGS_REQUIRE_CERT_AUTH in the first
71e593
+                         * SSS_PAM_PREAUTH run. In case a card is already inserted
71e593
+                         * we do not have to prompt to insert a card. */
71e593
+                        pi.flags &= ~PAM_CLI_FLAGS_REQUIRE_CERT_AUTH;
71e593
+                        pi.flags |= PAM_CLI_FLAGS_TRY_CERT_AUTH;
71e593
+                    }
71e593
+
71e593
                     pam_status = send_and_receive(pamh, &pi, SSS_PAM_PREAUTH,
71e593
                                                   quiet_mode);
71e593
+
71e593
+                    pi.flags = flags;
71e593
                     if (pam_status != PAM_SUCCESS) {
71e593
                         D(("send_and_receive returned [%d] during pre-auth",
71e593
                            pam_status));
71e593
@@ -2414,8 +2434,10 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
71e593
                     return PAM_AUTHINFO_UNAVAIL;
71e593
                 }
71e593
 
71e593
-                if (strcmp(pi.pam_service, "gdm-smartcard") == 0) {
71e593
-                    ret = check_login_token_name(pamh, &pi, quiet_mode);
71e593
+                if (strcmp(pi.pam_service, "gdm-smartcard") == 0
71e593
+                        || (flags & PAM_CLI_FLAGS_REQUIRE_CERT_AUTH)) {
71e593
+                    ret = check_login_token_name(pamh, &pi, retries,
71e593
+                                                 quiet_mode);
71e593
                     if (ret != PAM_SUCCESS) {
71e593
                         D(("check_login_token_name failed.\n"));
71e593
                         return ret;
71e593
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
71e593
index 38e3f999d799556a56ac08f0f3a6b538b8cde9f3..af8a43916d43b631092941fed13c520273a1acc5 100644
71e593
--- a/src/sss_client/sss_cli.h
71e593
+++ b/src/sss_client/sss_cli.h
71e593
@@ -363,6 +363,7 @@ enum pam_item_type {
71e593
     SSS_PAM_ITEM_CLI_LOCALE,
71e593
     SSS_PAM_ITEM_CLI_PID,
71e593
     SSS_PAM_ITEM_REQUESTED_DOMAINS,
71e593
+    SSS_PAM_ITEM_FLAGS,
71e593
 };
71e593
 
71e593
 #define PAM_CLI_FLAGS_USE_FIRST_PASS (1 << 0)
71e593
@@ -374,6 +375,7 @@ enum pam_item_type {
71e593
 #define PAM_CLI_FLAGS_ALLOW_MISSING_NAME (1 << 6)
71e593
 #define PAM_CLI_FLAGS_PROMPT_ALWAYS (1 << 7)
71e593
 #define PAM_CLI_FLAGS_TRY_CERT_AUTH (1 << 8)
71e593
+#define PAM_CLI_FLAGS_REQUIRE_CERT_AUTH (1 << 9)
71e593
 
71e593
 #define SSS_NSS_MAX_ENTRIES 256
71e593
 #define SSS_NSS_HEADER_SIZE (sizeof(uint32_t) * 4)
71e593
diff --git a/src/util/sss_pam_data.c b/src/util/sss_pam_data.c
71e593
index 5e41349b9e98974563bf55c41ce36c26b897ac99..cb8779c1dff04832f623eb518d2b010107d4b045 100644
71e593
--- a/src/util/sss_pam_data.c
71e593
+++ b/src/util/sss_pam_data.c
71e593
@@ -176,6 +176,7 @@ void pam_print_data(int l, struct pam_data *pd)
71e593
     DEBUG(l, "priv: %d\n", pd->priv);
71e593
     DEBUG(l, "cli_pid: %d\n", pd->cli_pid);
71e593
     DEBUG(l, "logon name: %s\n", PAM_SAFE_ITEM(pd->logon_name));
71e593
+    DEBUG(l, "flags: %d\n", pd->cli_flags);
71e593
 }
71e593
 
71e593
 int pam_add_response(struct pam_data *pd, enum response_type type,
71e593
diff --git a/src/util/sss_pam_data.h b/src/util/sss_pam_data.h
71e593
index 7d74fa6a0026d3964f33c8529063b1dceae45688..c9898105418fc76b45d78883a0520f37d0ae1c05 100644
71e593
--- a/src/util/sss_pam_data.h
71e593
+++ b/src/util/sss_pam_data.h
71e593
@@ -58,6 +58,7 @@ struct pam_data {
71e593
     struct sss_auth_token *newauthtok;
71e593
     uint32_t cli_pid;
71e593
     char *logon_name;
71e593
+    uint32_t cli_flags;
71e593
 
71e593
     int pam_status;
71e593
     int response_delay;
71e593
-- 
71e593
2.14.4
71e593