|
|
905b4d |
From c32ceaed108c86305d5862430225be636fd7532b Mon Sep 17 00:00:00 2001
|
|
|
905b4d |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
Date: Fri, 28 Nov 2014 13:04:42 +0100
|
|
|
905b4d |
Subject: [PATCH 128/128] KRB5: Create the fast ccache in a child process
|
|
|
905b4d |
|
|
|
905b4d |
Related:
|
|
|
905b4d |
https://fedorahosted.org/sssd/ticket/2503
|
|
|
905b4d |
|
|
|
905b4d |
In order to avoid calling Kerberos library calls as root, the krb5_child
|
|
|
905b4d |
forks itself and recreates the FAST ccache as the SSSD user.
|
|
|
905b4d |
|
|
|
905b4d |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
905b4d |
---
|
|
|
905b4d |
src/providers/krb5/krb5_child.c | 118 ++++++++++++++++++++++++--------
|
|
|
905b4d |
src/providers/krb5/krb5_child_handler.c | 10 ++-
|
|
|
905b4d |
2 files changed, 100 insertions(+), 28 deletions(-)
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
|
|
|
905b4d |
index ce8a9235e1d64bccc91d367bc744cca2b32a40da..1ce1220751a338cb2a2e5f204107b376000a4e3e 100644
|
|
|
905b4d |
--- a/src/providers/krb5/krb5_child.c
|
|
|
905b4d |
+++ b/src/providers/krb5/krb5_child.c
|
|
|
905b4d |
@@ -74,6 +74,9 @@ struct krb5_req {
|
|
|
905b4d |
bool old_cc_valid;
|
|
|
905b4d |
bool old_cc_active;
|
|
|
905b4d |
enum k5c_fast_opt fast_val;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ uid_t fast_uid;
|
|
|
905b4d |
+ gid_t fast_gid;
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
static krb5_context krb5_error_ctx;
|
|
|
905b4d |
@@ -1005,17 +1008,6 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
|
|
|
905b4d |
DEBUG(SSSDBG_CONF_SETTINGS, "TGT validation is disabled.\n");
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- if (kr->validate || kr->fast_ccname != NULL) {
|
|
|
905b4d |
- /* We drop root privileges which were needed to read the keytab file
|
|
|
905b4d |
- * for the validation of the credentials or for FAST here to run the
|
|
|
905b4d |
- * ccache I/O operations with user privileges. */
|
|
|
905b4d |
- kerr = become_user(kr->uid, kr->gid);
|
|
|
905b4d |
- if (kerr != 0) {
|
|
|
905b4d |
- DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
|
|
|
905b4d |
- return kerr;
|
|
|
905b4d |
- }
|
|
|
905b4d |
- }
|
|
|
905b4d |
-
|
|
|
905b4d |
/* If kr->ccname is cache collection (DIR:/...), we want to work
|
|
|
905b4d |
* directly with file ccache (DIR::/...), but cache collection
|
|
|
905b4d |
* should be returned back to back end.
|
|
|
905b4d |
@@ -1432,17 +1424,6 @@ static errno_t renew_tgt_child(struct krb5_req *kr)
|
|
|
905b4d |
DEBUG(SSSDBG_CONF_SETTINGS, "TGT validation is disabled.\n");
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- if (kr->validate || kr->fast_ccname != NULL) {
|
|
|
905b4d |
- /* We drop root privileges which were needed to read the keytab file
|
|
|
905b4d |
- * for the validation of the credentials or for FAST here to run the
|
|
|
905b4d |
- * ccache I/O operations with user privileges. */
|
|
|
905b4d |
- kerr = become_user(kr->uid, kr->gid);
|
|
|
905b4d |
- if (kerr != 0) {
|
|
|
905b4d |
- DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
- }
|
|
|
905b4d |
- }
|
|
|
905b4d |
-
|
|
|
905b4d |
kerr = krb5_cc_initialize(kr->ctx, ccache, kr->princ);
|
|
|
905b4d |
if (kerr != 0) {
|
|
|
905b4d |
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
|
|
|
905b4d |
@@ -1716,6 +1697,8 @@ done:
|
|
|
905b4d |
|
|
|
905b4d |
static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
krb5_context ctx,
|
|
|
905b4d |
+ uid_t fast_uid,
|
|
|
905b4d |
+ gid_t fast_gid,
|
|
|
905b4d |
const char *primary,
|
|
|
905b4d |
const char *realm,
|
|
|
905b4d |
const char *keytab_name,
|
|
|
905b4d |
@@ -1729,6 +1712,8 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
krb5_keytab keytab = NULL;
|
|
|
905b4d |
krb5_principal client_princ = NULL;
|
|
|
905b4d |
krb5_principal server_princ = NULL;
|
|
|
905b4d |
+ pid_t fchild_pid;
|
|
|
905b4d |
+ int status;
|
|
|
905b4d |
|
|
|
905b4d |
tmp_ctx = talloc_new(NULL);
|
|
|
905b4d |
if (tmp_ctx == NULL) {
|
|
|
905b4d |
@@ -1786,10 +1771,79 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
}
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- kerr = get_and_save_tgt_with_keytab(ctx, client_princ, keytab, ccname);
|
|
|
905b4d |
- if (kerr != 0) {
|
|
|
905b4d |
- DEBUG(SSSDBG_CRIT_FAILURE, "get_and_save_tgt_with_keytab failed.\n");
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
+ /* Need to recreate the FAST ccache */
|
|
|
905b4d |
+ fchild_pid = fork();
|
|
|
905b4d |
+ switch (fchild_pid) {
|
|
|
905b4d |
+ case -1:
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "fork failed\n");
|
|
|
905b4d |
+ kerr = EIO;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ case 0:
|
|
|
905b4d |
+ /* Child */
|
|
|
905b4d |
+ debug_prg_name = talloc_asprintf(NULL, "[sssd[krb5_child[%d]]]", getpid());
|
|
|
905b4d |
+ if (debug_prg_name == NULL) {
|
|
|
905b4d |
+ debug_prg_name = "[sssd[krb5_child]]";
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
|
|
|
905b4d |
+ /* Try to carry on */
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ kerr = become_user(fast_uid, fast_gid);
|
|
|
905b4d |
+ if (kerr != 0) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed: %d\n", kerr);
|
|
|
905b4d |
+ exit(1);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
905b4d |
+ "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
|
|
|
905b4d |
+
|
|
|
905b4d |
+ kerr = get_and_save_tgt_with_keytab(ctx, client_princ,
|
|
|
905b4d |
+ keytab, ccname);
|
|
|
905b4d |
+ if (kerr != 0) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "get_and_save_tgt_with_keytab failed: %d\n", kerr);
|
|
|
905b4d |
+ exit(2);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ exit(0);
|
|
|
905b4d |
+ default:
|
|
|
905b4d |
+ /* Parent */
|
|
|
905b4d |
+ do {
|
|
|
905b4d |
+ errno = 0;
|
|
|
905b4d |
+ kerr = waitpid(fchild_pid, &status, 0);
|
|
|
905b4d |
+ } while (kerr == -1 && errno == EINTR);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (kerr > 0) {
|
|
|
905b4d |
+ kerr = EIO;
|
|
|
905b4d |
+ if (WIFEXITED(status)) {
|
|
|
905b4d |
+ kerr = WEXITSTATUS(status);
|
|
|
905b4d |
+ /* Don't blindly fail if the child fails, but check
|
|
|
905b4d |
+ * the ccache again */
|
|
|
905b4d |
+ if (kerr != 0) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
|
|
905b4d |
+ "Creating FAST ccache failed, krb5_child will "
|
|
|
905b4d |
+ "likely fail!\n");
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "krb5_child subprocess %d terminated unexpectedly\n",
|
|
|
905b4d |
+ fchild_pid);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
905b4d |
+ "Failed to wait for children %d\n", fchild_pid);
|
|
|
905b4d |
+ kerr = EIO;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* Check the ccache times again. Should be updated ... */
|
|
|
905b4d |
+ memset(&tgtt, 0, sizeof(tgtt));
|
|
|
905b4d |
+ kerr = get_tgt_times(ctx, ccname, server_princ, client_princ, &tgtt);
|
|
|
905b4d |
+ if (kerr == 0) {
|
|
|
905b4d |
+ if (tgtt.endtime > time(NULL)) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_FUNC_DATA, "FAST TGT was successfully recreated!\n");
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ kerr = ERR_CREDS_EXPIRED;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
kerr = 0;
|
|
|
905b4d |
@@ -1881,7 +1935,8 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
|
|
|
905b4d |
fast_principal = NULL;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- kerr = check_fast_ccache(kr, kr->ctx, fast_principal, fast_principal_realm,
|
|
|
905b4d |
+ kerr = check_fast_ccache(kr, kr->ctx, kr->fast_uid, kr->fast_gid,
|
|
|
905b4d |
+ fast_principal, fast_principal_realm,
|
|
|
905b4d |
kr->keytab, &kr->fast_ccname);
|
|
|
905b4d |
if (kerr != 0) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "check_fast_ccache failed.\n");
|
|
|
905b4d |
@@ -2245,6 +2300,8 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
int debug_fd = -1;
|
|
|
905b4d |
errno_t ret;
|
|
|
905b4d |
krb5_error_code kerr;
|
|
|
905b4d |
+ uid_t fast_uid;
|
|
|
905b4d |
+ gid_t fast_gid;
|
|
|
905b4d |
|
|
|
905b4d |
struct poptOption long_options[] = {
|
|
|
905b4d |
POPT_AUTOHELP
|
|
|
905b4d |
@@ -2259,6 +2316,10 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
{"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
|
|
|
905b4d |
&debug_to_stderr, 0,
|
|
|
905b4d |
_("Send the debug output to stderr directly."), NULL },
|
|
|
905b4d |
+ {"fast-ccache-uid", 0, POPT_ARG_INT, &fast_uid, 0,
|
|
|
905b4d |
+ _("The user to create FAST ccache as"), NULL},
|
|
|
905b4d |
+ {"fast-ccache-gid", 0, POPT_ARG_INT, &fast_gid, 0,
|
|
|
905b4d |
+ _("The group to create FAST ccache as"), NULL},
|
|
|
905b4d |
POPT_TABLEEND
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
@@ -2305,6 +2366,9 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
}
|
|
|
905b4d |
talloc_steal(kr, debug_prg_name);
|
|
|
905b4d |
|
|
|
905b4d |
+ kr->fast_uid = fast_uid;
|
|
|
905b4d |
+ kr->fast_gid = fast_gid;
|
|
|
905b4d |
+
|
|
|
905b4d |
ret = k5c_recv_data(kr, STDIN_FILENO, &offline);
|
|
|
905b4d |
if (ret != EOK) {
|
|
|
905b4d |
goto done;
|
|
|
905b4d |
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
index 9bb61f65437694d8aa2109513b5f061dfc9ee21c..1454d220fb294abc339df6e862154012a03fdca0 100644
|
|
|
905b4d |
--- a/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
+++ b/src/providers/krb5/krb5_child_handler.c
|
|
|
905b4d |
@@ -278,6 +278,14 @@ static errno_t fork_child(struct tevent_req *req)
|
|
|
905b4d |
errno_t err;
|
|
|
905b4d |
struct handle_child_state *state = tevent_req_data(req,
|
|
|
905b4d |
struct handle_child_state);
|
|
|
905b4d |
+ const char *k5c_extra_args[3];
|
|
|
905b4d |
+
|
|
|
905b4d |
+ k5c_extra_args[0] = talloc_asprintf(state, "--fast-ccache-uid=%"SPRIuid, getuid());
|
|
|
905b4d |
+ k5c_extra_args[1] = talloc_asprintf(state, "--fast-ccache-gid=%"SPRIgid, getgid());
|
|
|
905b4d |
+ k5c_extra_args[2] = NULL;
|
|
|
905b4d |
+ if (k5c_extra_args[0] == NULL || k5c_extra_args[1] == NULL) {
|
|
|
905b4d |
+ return ENOMEM;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
|
|
|
905b4d |
ret = pipe(pipefd_from_child);
|
|
|
905b4d |
if (ret == -1) {
|
|
|
905b4d |
@@ -300,7 +308,7 @@ static errno_t fork_child(struct tevent_req *req)
|
|
|
905b4d |
err = exec_child(state,
|
|
|
905b4d |
pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
|
|
|
905b4d |
- NULL);
|
|
|
905b4d |
+ k5c_extra_args);
|
|
|
905b4d |
if (err != EOK) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec KRB5 child: [%d][%s].\n",
|
|
|
905b4d |
err, strerror(err));
|
|
|
905b4d |
--
|
|
|
905b4d |
1.9.3
|
|
|
905b4d |
|