Blame SOURCES/0008-krb5_child-fix-permissions-during-SC-auth.patch

836b22
From a61b80d7f10bbdfaa10fde1f868c9fb4b7abe62f Mon Sep 17 00:00:00 2001
836b22
From: Sumit Bose <sbose@redhat.com>
836b22
Date: Mon, 10 Dec 2018 17:44:13 +0100
836b22
Subject: [PATCH] krb5_child: fix permissions during SC auth
836b22
MIME-Version: 1.0
836b22
Content-Type: text/plain; charset=UTF-8
836b22
Content-Transfer-Encoding: 8bit
836b22
836b22
For PKINIT we might need access to the pcscd socket which by default is
836b22
only allowed for authenticated users. Since PKINIT is part of the
836b22
authentication and the user is not authenticated yet, we have to use
836b22
different privileges and can only drop it only after the TGT is
836b22
received. The fast_uid and fast_gid are the IDs the backend is running
836b22
with. This can be either root or the 'sssd' user. Root is allowed by
836b22
default and the 'sssd' user is allowed with the help of the
836b22
sssd-pcsc.rules policy-kit rule. So those IDs are a suitable choice. We
836b22
can only call switch_creds() because after the TGT is returned we have
836b22
to switch to the IDs of the user to store the TGT.
836b22
836b22
The final change to the IDs of the user is not only important for KCM
836b22
type credential caches but for file based ccache types like FILE or DIR
836b22
as well.
836b22
836b22
Related to https://pagure.io/SSSD/sssd/issue/3903
836b22
836b22
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
836b22
(cherry picked from commit e49e9f727e4960c8a0a2ed50488dac6e51ddf284)
836b22
836b22
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
836b22
---
836b22
 src/providers/krb5/krb5_child.c | 64 ++++++++++++++++++++-------------
836b22
 1 file changed, 39 insertions(+), 25 deletions(-)
836b22
836b22
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
836b22
index a86d9a7ae..ae63b14d1 100644
836b22
--- a/src/providers/krb5/krb5_child.c
836b22
+++ b/src/providers/krb5/krb5_child.c
836b22
@@ -108,6 +108,7 @@ struct krb5_req {
836b22
 
836b22
     uid_t fast_uid;
836b22
     gid_t fast_gid;
836b22
+    struct sss_creds *pcsc_saved_creds;
836b22
 
836b22
     struct cli_opts *cli_opts;
836b22
 };
836b22
@@ -1755,6 +1756,22 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
836b22
         goto done;
836b22
     }
836b22
 
836b22
+    kerr = restore_creds(kr->pcsc_saved_creds);
836b22
+    if (kerr != 0)  {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "restore_creds failed.\n");
836b22
+    }
836b22
+    /* Make sure ccache is created and written as the user */
836b22
+    if (geteuid() != kr->uid || getegid() != kr->gid) {
836b22
+        kerr = k5c_become_user(kr->uid, kr->gid, kr->posix_domain);
836b22
+        if (kerr != 0) {
836b22
+            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
836b22
+            goto done;
836b22
+        }
836b22
+    }
836b22
+
836b22
+    DEBUG(SSSDBG_TRACE_INTERNAL,
836b22
+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
836b22
+
836b22
     /* If kr->ccname is cache collection (DIR:/...), we want to work
836b22
      * directly with file ccache (DIR::/...), but cache collection
836b22
      * should be returned back to back end.
836b22
@@ -3011,20 +3028,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
836b22
     krb5_error_code kerr;
836b22
     int parse_flags;
836b22
 
836b22
-    if (offline || (kr->fast_val == K5C_FAST_NEVER && kr->validate == false)) {
836b22
-        /* If krb5_child was started as setuid, but we don't need to
836b22
-         * perform either validation or FAST, just drop privileges to
836b22
-         * the user who is logging in. The same applies to the offline case.
836b22
-         */
836b22
-        kerr = k5c_become_user(kr->uid, kr->gid, kr->posix_domain);
836b22
-        if (kerr != 0) {
836b22
-            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
836b22
-            return kerr;
836b22
-        }
836b22
-    }
836b22
-    DEBUG(SSSDBG_TRACE_INTERNAL,
836b22
-          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
836b22
-
836b22
     /* Set the global error context */
836b22
     krb5_error_ctx = kr->ctx;
836b22
 
836b22
@@ -3218,8 +3221,8 @@ int main(int argc, const char *argv[])
836b22
     const char *opt_logger = NULL;
836b22
     errno_t ret;
836b22
     krb5_error_code kerr;
836b22
-    uid_t fast_uid;
836b22
-    gid_t fast_gid;
836b22
+    uid_t fast_uid = 0;
836b22
+    gid_t fast_gid = 0;
836b22
     struct cli_opts cli_opts = { 0 };
836b22
     int sss_creds_password = 0;
836b22
 
836b22
@@ -3333,20 +3336,31 @@ int main(int argc, const char *argv[])
836b22
         goto done;
836b22
     }
836b22
 
836b22
-    /* pkinit needs access to pcscd */
836b22
-    if ((sss_authtok_get_type(kr->pd->authtok) != SSS_AUTHTOK_TYPE_SC_PIN
836b22
-            && sss_authtok_get_type(kr->pd->authtok)
836b22
-                                        != SSS_AUTHTOK_TYPE_SC_KEYPAD)) {
836b22
+    /* For PKINIT we might need access to the pcscd socket which by default
836b22
+     * is only allowed for authenticated users. Since PKINIT is part of
836b22
+     * the authentication and the user is not authenticated yet, we have
836b22
+     * to use different privileges and can only drop it only after the TGT is
836b22
+     * received. The fast_uid and fast_gid are the IDs the backend is running
836b22
+     * with. This can be either root or the 'sssd' user. Root is allowed by
836b22
+     * default and the 'sssd' user is allowed with the help of the
836b22
+     * sssd-pcsc.rules policy-kit rule. So those IDs are a suitable choice. We
836b22
+     * can only call switch_creds() because after the TGT is returned we have
836b22
+     * to switch to the IDs of the user to store the TGT. */
836b22
+    if (IS_SC_AUTHTOK(kr->pd->authtok)) {
836b22
+        kerr = switch_creds(kr, kr->fast_uid, kr->fast_gid, 0, NULL,
836b22
+                            &kr->pcsc_saved_creds);
836b22
+    } else {
836b22
         kerr = k5c_become_user(kr->uid, kr->gid, kr->posix_domain);
836b22
-        if (kerr != 0) {
836b22
-            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
836b22
-            ret = EFAULT;
836b22
-            goto done;
836b22
-        }
836b22
+    }
836b22
+    if (kerr != 0) {
836b22
+        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
836b22
+        ret = EFAULT;
836b22
+        goto done;
836b22
     }
836b22
 
836b22
     DEBUG(SSSDBG_TRACE_INTERNAL,
836b22
           "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
836b22
+
836b22
     try_open_krb5_conf();
836b22
 
836b22
     ret = k5c_setup(kr, offline);
836b22
-- 
836b22
2.21.1
836b22