Blame SOURCES/0125-krb5_child-become-user-earlier.patch

905b4d
From 0c7f33bb6b16ef7dd27816489d9ec0b5c758c64f Mon Sep 17 00:00:00 2001
905b4d
From: Sumit Bose <sbose@redhat.com>
905b4d
Date: Mon, 1 Dec 2014 17:36:56 +0100
905b4d
Subject: [PATCH 125/128] krb5_child: become user earlier
905b4d
905b4d
The host keytab and the FAST credential cache are copied into memory
905b4d
early at startup to allow to drop privileges earlier.
905b4d
905b4d
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
905b4d
---
905b4d
 Makefile.am                     |   1 +
905b4d
 src/providers/krb5/krb5_child.c | 131 ++++++++++++++++++++++++++++------------
905b4d
 2 files changed, 94 insertions(+), 38 deletions(-)
905b4d
905b4d
diff --git a/Makefile.am b/Makefile.am
905b4d
index 3d16428856d6cb2e9e190b0df8895ab3f45db39c..6f6db56f5d6229b530cc6f18f66c42f22140bdeb 100644
905b4d
--- a/Makefile.am
905b4d
+++ b/Makefile.am
905b4d
@@ -2531,6 +2531,7 @@ libsss_ad_la_LDFLAGS = \
905b4d
 krb5_child_SOURCES = \
905b4d
     src/providers/krb5/krb5_child.c \
905b4d
     src/providers/krb5/krb5_ccache.c \
905b4d
+    src/providers/krb5/krb5_keytab.c \
905b4d
     src/providers/dp_pam_data_util.c \
905b4d
     src/util/user_info_msg.c \
905b4d
     src/util/sss_krb5.c \
905b4d
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
905b4d
index d828dd550251d70851edcdc6b1eda6f5c051baf2..ce8a9235e1d64bccc91d367bc744cca2b32a40da 100644
905b4d
--- a/src/providers/krb5/krb5_child.c
905b4d
+++ b/src/providers/krb5/krb5_child.c
905b4d
@@ -42,6 +42,12 @@
905b4d
 
905b4d
 #define SSSD_KRB5_CHANGEPW_PRINCIPAL "kadmin/changepw"
905b4d
 
905b4d
+enum k5c_fast_opt {
905b4d
+    K5C_FAST_NEVER,
905b4d
+    K5C_FAST_TRY,
905b4d
+    K5C_FAST_DEMAND,
905b4d
+};
905b4d
+
905b4d
 struct krb5_req {
905b4d
     krb5_context ctx;
905b4d
     krb5_principal princ;
905b4d
@@ -67,6 +73,7 @@ struct krb5_req {
905b4d
     char *old_ccname;
905b4d
     bool old_cc_valid;
905b4d
     bool old_cc_active;
905b4d
+    enum k5c_fast_opt fast_val;
905b4d
 };
905b4d
 
905b4d
 static krb5_context krb5_error_ctx;
905b4d
@@ -1839,6 +1846,7 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
905b4d
     char *fast_principal;
905b4d
     krb5_error_code kerr;
905b4d
     char *tmp_str;
905b4d
+    char *new_ccname;
905b4d
 
905b4d
     tmp_str = getenv(SSSD_KRB5_FAST_PRINCIPAL);
905b4d
     if (tmp_str) {
905b4d
@@ -1881,6 +1889,15 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
905b4d
         return kerr;
905b4d
     }
905b4d
 
905b4d
+    kerr = copy_ccache_into_memory(kr, kr->ctx, kr->fast_ccname, &new_ccname);
905b4d
+    if (kerr != 0) {
905b4d
+        DEBUG(SSSDBG_CRIT_FAILURE, "copy_ccache_into_memory failed.\n");
905b4d
+        return kerr;
905b4d
+    }
905b4d
+
905b4d
+    talloc_free(kr->fast_ccname);
905b4d
+    kr->fast_ccname = new_ccname;
905b4d
+
905b4d
     kerr = sss_krb5_get_init_creds_opt_set_fast_ccache_name(kr->ctx,
905b4d
                                                             kr->options,
905b4d
                                                             kr->fast_ccname);
905b4d
@@ -1908,12 +1925,6 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
905b4d
     return EOK;
905b4d
 }
905b4d
 
905b4d
-enum k5c_fast_opt {
905b4d
-    K5C_FAST_NEVER,
905b4d
-    K5C_FAST_TRY,
905b4d
-    K5C_FAST_DEMAND,
905b4d
-};
905b4d
-
905b4d
 static errno_t check_use_fast(enum k5c_fast_opt *_fast_val)
905b4d
 {
905b4d
     char *use_fast_str;
905b4d
@@ -2064,19 +2075,8 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
905b4d
 {
905b4d
     krb5_error_code kerr;
905b4d
     int parse_flags;
905b4d
-    enum k5c_fast_opt fast_val;
905b4d
 
905b4d
-    kerr = check_use_fast(&fast_val);
905b4d
-    if (kerr != EOK) {
905b4d
-        return kerr;
905b4d
-    }
905b4d
-
905b4d
-    kerr = k5c_ccache_setup(kr, offline);
905b4d
-    if (kerr != EOK) {
905b4d
-        return kerr;
905b4d
-    }
905b4d
-
905b4d
-    if (offline || (fast_val == K5C_FAST_NEVER && kr->validate == false)) {
905b4d
+    if (offline || (kr->fast_val == K5C_FAST_NEVER && kr->validate == false)) {
905b4d
         /* If krb5_child was started as setuid, but we don't need to
905b4d
          * perform either validation or FAST, just drop privileges to
905b4d
          * the user who is logging in. The same applies to the offline case
905b4d
@@ -2097,12 +2097,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
905b4d
               "Cannot read [%s] from environment.\n", SSSD_KRB5_REALM);
905b4d
     }
905b4d
 
905b4d
-    kerr = krb5_init_context(&kr->ctx);
905b4d
-    if (kerr != 0) {
905b4d
-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
905b4d
-        return kerr;
905b4d
-    }
905b4d
-
905b4d
     /* Set the global error context */
905b4d
     krb5_error_ctx = kr->ctx;
905b4d
 
905b4d
@@ -2145,12 +2139,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
905b4d
         return ENOMEM;
905b4d
     }
905b4d
 
905b4d
-    kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
905b4d
-    if (kerr != 0) {
905b4d
-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
905b4d
-        return kerr;
905b4d
-    }
905b4d
-
905b4d
 #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER
905b4d
     kerr = krb5_get_init_creds_opt_set_responder(kr->ctx, kr->options,
905b4d
                                                  sss_krb5_responder, kr);
905b4d
@@ -2175,14 +2163,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
905b4d
 
905b4d
     if (!offline) {
905b4d
         set_canonicalize_option(kr->options);
905b4d
-
905b4d
-        if (fast_val != K5C_FAST_NEVER) {
905b4d
-            kerr = k5c_setup_fast(kr, fast_val == K5C_FAST_DEMAND);
905b4d
-            if (kerr != EOK) {
905b4d
-                DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n");
905b4d
-                return kerr;
905b4d
-            }
905b4d
-        }
905b4d
     }
905b4d
 
905b4d
 /* TODO: set options, e.g.
905b4d
@@ -2199,6 +2179,63 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
905b4d
     return kerr;
905b4d
 }
905b4d
 
905b4d
+static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
905b4d
+                                             uint32_t offline)
905b4d
+{
905b4d
+    krb5_error_code kerr;
905b4d
+    int ret;
905b4d
+    char *mem_keytab;
905b4d
+
905b4d
+    kerr = krb5_init_context(&kr->ctx);
905b4d
+    if (kerr != 0) {
905b4d
+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
905b4d
+        return kerr;
905b4d
+    }
905b4d
+
905b4d
+    kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
905b4d
+    if (kerr != 0) {
905b4d
+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
905b4d
+        return kerr;
905b4d
+    }
905b4d
+
905b4d
+    ret = check_use_fast(&kr->fast_val);
905b4d
+    if (ret != EOK) {
905b4d
+        DEBUG(SSSDBG_CRIT_FAILURE, "check_use_fast failed.\n");
905b4d
+        return ret;;
905b4d
+    }
905b4d
+
905b4d
+    /* For ccache types FILE: and DIR: we might need to create some directory
905b4d
+     * components as root */
905b4d
+    ret = k5c_ccache_setup(kr, offline);
905b4d
+    if (ret != EOK) {
905b4d
+        DEBUG(SSSDBG_CRIT_FAILURE, "k5c_ccache_setup failed.\n");
905b4d
+        return ret;
905b4d
+    }
905b4d
+
905b4d
+    if (!(offline ||
905b4d
+            (kr->fast_val == K5C_FAST_NEVER && kr->validate == false))) {
905b4d
+        kerr = copy_keytab_into_memory(kr, kr->ctx, kr->keytab, &mem_keytab,
905b4d
+                                       NULL);
905b4d
+        if (kerr != 0) {
905b4d
+            DEBUG(SSSDBG_OP_FAILURE, "copy_keytab_into_memory failed.\n");
905b4d
+            return kerr;
905b4d
+        }
905b4d
+
905b4d
+        talloc_free(kr->keytab);
905b4d
+        kr->keytab = mem_keytab;
905b4d
+
905b4d
+        if (kr->fast_val != K5C_FAST_NEVER) {
905b4d
+            kerr = k5c_setup_fast(kr, kr->fast_val == K5C_FAST_DEMAND);
905b4d
+            if (kerr != EOK) {
905b4d
+                DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n");
905b4d
+                return kerr;
905b4d
+            }
905b4d
+        }
905b4d
+    }
905b4d
+
905b4d
+    return 0;
905b4d
+}
905b4d
+
905b4d
 int main(int argc, const char *argv[])
905b4d
 {
905b4d
     struct krb5_req *kr = NULL;
905b4d
@@ -2207,6 +2244,7 @@ int main(int argc, const char *argv[])
905b4d
     poptContext pc;
905b4d
     int debug_fd = -1;
905b4d
     errno_t ret;
905b4d
+    krb5_error_code kerr;
905b4d
 
905b4d
     struct poptOption long_options[] = {
905b4d
         POPT_AUTOHELP
905b4d
@@ -2274,6 +2312,23 @@ int main(int argc, const char *argv[])
905b4d
 
905b4d
     close(STDIN_FILENO);
905b4d
 
905b4d
+    kerr = privileged_krb5_setup(kr, offline);
905b4d
+    if (kerr != 0) {
905b4d
+        DEBUG(SSSDBG_CRIT_FAILURE, "privileged_krb5_setup failed.\n");
905b4d
+        ret = EFAULT;
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    kerr = become_user(kr->uid, kr->gid);
905b4d
+    if (kerr != 0) {
905b4d
+        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
905b4d
+        ret = EFAULT;
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    DEBUG(SSSDBG_TRACE_INTERNAL,
905b4d
+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
905b4d
+
905b4d
     ret = k5c_setup(kr, offline);
905b4d
     if (ret != EOK) {
905b4d
         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_child_setup failed.\n");
905b4d
-- 
905b4d
1.9.3
905b4d