>From e4cd0b96faf10fa81251f7b48d14a60f352153a4 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 13 Oct 2014 21:13:38 +0200 Subject: [PATCH 2/6] KRB5: Drop privileges in the child, not the back end In future patches, sssd_be will be running as a non-privileged user, who will execute the setuid krb5_child. In this case, the child will start as root and drop the privileges as soon as possible. However, we need to also remove the privilege drop in sssd_be, because if we dropped to the user who is authenticating, we wouldn't be even allowed to execute krb5_child. The krb5_child permissions should be 4750, owned by root.sssd, to make sure only root and sssd can execute the child and if executed by sssd, the child will run as root. --- src/providers/krb5/krb5_child.c | 71 ++++++++++++++++++++++++++------- src/providers/krb5/krb5_child_handler.c | 8 ---- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index 3234a4e6c740db5e05f7db8eb7f4ea0cc126e7ce..15dc316fab32934cd422368c1556c2f724fbd8ab 100644 --- a/src/providers/krb5/krb5_child.c +++ b/src/providers/krb5/krb5_child.c @@ -1840,11 +1840,60 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand) return EOK; } -static int k5c_setup(struct krb5_req *kr, uint32_t offline) +enum k5c_fast_opt { + K5C_FAST_NEVER, + K5C_FAST_TRY, + K5C_FAST_DEMAND, +}; + +static errno_t check_use_fast(enum k5c_fast_opt *_fast_val) { - krb5_error_code kerr; char *use_fast_str; + enum k5c_fast_opt fast_val; + + use_fast_str = getenv(SSSD_KRB5_USE_FAST); + if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) { + DEBUG(SSSDBG_CONF_SETTINGS, "Not using FAST.\n"); + fast_val = K5C_FAST_NEVER; + } else if (strcasecmp(use_fast_str, "try") == 0) { + fast_val = K5C_FAST_TRY; + } else if (strcasecmp(use_fast_str, "demand") == 0) { + fast_val = K5C_FAST_DEMAND; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unsupported value [%s] for krb5_use_fast.\n", + use_fast_str); + return EINVAL; + } + + *_fast_val = fast_val; + return EOK; +} + +static int k5c_setup(struct krb5_req *kr, uint32_t offline) +{ + krb5_error_code kerr; int parse_flags; + enum k5c_fast_opt fast_val; + + kerr = check_use_fast(&fast_val); + if (kerr != EOK) { + return kerr; + } + + if (offline || (fast_val == K5C_FAST_NEVER && kr->validate == false)) { + /* If krb5_child was started as setuid, but we don't need to + * perform either validation or FAST, just drop privileges to + * the user who is logging in. The same applies to the offline case + */ + kerr = become_user(kr->uid, kr->gid); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n"); + return kerr; + } + } + DEBUG(SSSDBG_TRACE_INTERNAL, + "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid()); kr->realm = getenv(SSSD_KRB5_REALM); if (kr->realm == NULL) { @@ -1931,18 +1980,12 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) if (!offline) { set_canonicalize_option(kr->options); - use_fast_str = getenv(SSSD_KRB5_USE_FAST); - if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) { - DEBUG(SSSDBG_CONF_SETTINGS, "Not using FAST.\n"); - } else if (strcasecmp(use_fast_str, "try") == 0) { - kerr = k5c_setup_fast(kr, false); - } else if (strcasecmp(use_fast_str, "demand") == 0) { - kerr = k5c_setup_fast(kr, true); - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - "Unsupported value [%s] for krb5_use_fast.\n", - use_fast_str); - return EINVAL; + if (fast_val > K5C_FAST_NEVER) { + kerr = k5c_setup_fast(kr, fast_val == K5C_FAST_DEMAND); + if (kerr != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n"); + return kerr; + } } } diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c index 4ba939deb3e0e282b3ca9b2b21226ea7e64e311b..71c7f9c9f662e16b94afda0c8c0ae24666f0ba15 100644 --- a/src/providers/krb5/krb5_child_handler.c +++ b/src/providers/krb5/krb5_child_handler.c @@ -284,14 +284,6 @@ static errno_t fork_child(struct tevent_req *req) pid = fork(); if (pid == 0) { /* child */ - if (state->kr->run_as_user) { - ret = become_user(state->kr->uid, state->kr->gid); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n"); - return ret; - } - } - err = exec_child(state, pipefd_to_child, pipefd_from_child, KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd); -- 1.9.3