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

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