|
|
905b4d |
From 954637494fc8453f71e2b5d93b3d1ea97e31d646 Mon Sep 17 00:00:00 2001
|
|
|
905b4d |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
Date: Sun, 19 Oct 2014 19:15:52 +0200
|
|
|
905b4d |
Subject: [PATCH 68/71] LDAP: Drop privileges after kinit in ldap_child
|
|
|
905b4d |
MIME-Version: 1.0
|
|
|
905b4d |
Content-Type: text/plain; charset=UTF-8
|
|
|
905b4d |
Content-Transfer-Encoding: 8bit
|
|
|
905b4d |
|
|
|
905b4d |
After ldap_child initializes privileges using root-owned keytab, it
|
|
|
905b4d |
drops privileges to the SSSD user, minimizing the amount of code that
|
|
|
905b4d |
runs as root.
|
|
|
905b4d |
|
|
|
905b4d |
Reviewed-by: Michal Židek <mzidek@redhat.com>
|
|
|
905b4d |
---
|
|
|
905b4d |
Makefile.am | 4 +-
|
|
|
905b4d |
src/providers/ldap/ldap_child.c | 96 ++++++++++++++++++++-------------
|
|
|
905b4d |
src/providers/ldap/sdap_child_helpers.c | 8 ++-
|
|
|
905b4d |
3 files changed, 70 insertions(+), 38 deletions(-)
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/Makefile.am b/Makefile.am
|
|
|
905b4d |
index 02b087ea37b4e55da7eeb7fb199d282d72129e40..ea296c40f89c552d5825cbce8e95afdc517e8bb5 100644
|
|
|
905b4d |
--- a/Makefile.am
|
|
|
905b4d |
+++ b/Makefile.am
|
|
|
905b4d |
@@ -2517,7 +2517,9 @@ ldap_child_SOURCES = \
|
|
|
905b4d |
src/util/atomic_io.c \
|
|
|
905b4d |
src/util/authtok.c \
|
|
|
905b4d |
src/util/util.c \
|
|
|
905b4d |
- src/util/signal.c
|
|
|
905b4d |
+ src/util/signal.c \
|
|
|
905b4d |
+ src/util/become_user.c \
|
|
|
905b4d |
+ $(NULL)
|
|
|
905b4d |
ldap_child_CFLAGS = \
|
|
|
905b4d |
$(AM_CFLAGS) \
|
|
|
905b4d |
$(POPT_CFLAGS) \
|
|
|
905b4d |
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
|
|
|
905b4d |
index e1abc9fd73f2ae95f0a0c28159589ebd36d2cf06..a922b181715c5e89301e9f50bdb81723d1ff2a6a 100644
|
|
|
905b4d |
--- a/src/providers/ldap/ldap_child.c
|
|
|
905b4d |
+++ b/src/providers/ldap/ldap_child.c
|
|
|
905b4d |
@@ -49,6 +49,8 @@ struct input_buffer {
|
|
|
905b4d |
const char *princ_str;
|
|
|
905b4d |
const char *keytab_name;
|
|
|
905b4d |
krb5_deltat lifetime;
|
|
|
905b4d |
+ uid_t uid;
|
|
|
905b4d |
+ gid_t gid;
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
static errno_t unpack_buffer(uint8_t *buf, size_t size,
|
|
|
905b4d |
@@ -99,6 +101,12 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
|
|
|
905b4d |
SAFEALIGN_COPY_UINT32_CHECK(&ibuf->lifetime, buf + p, size, &p);
|
|
|
905b4d |
DEBUG(SSSDBG_TRACE_LIBS, "lifetime: %u\n", ibuf->lifetime);
|
|
|
905b4d |
|
|
|
905b4d |
+ /* UID and GID to run as */
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&ibuf->uid, buf + p, size, &p);
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&ibuf->gid, buf + p, size, &p);
|
|
|
905b4d |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
905b4d |
+ "Will run as [%"SPRIuid"][%"SPRIgid"].\n", ibuf->uid, ibuf->gid);
|
|
|
905b4d |
+
|
|
|
905b4d |
return EOK;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
@@ -242,6 +250,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
|
|
|
905b4d |
const char *princ_str,
|
|
|
905b4d |
const char *keytab_name,
|
|
|
905b4d |
const krb5_deltat lifetime,
|
|
|
905b4d |
+ uid_t uid,
|
|
|
905b4d |
+ gid_t gid,
|
|
|
905b4d |
const char **ccname_out,
|
|
|
905b4d |
time_t *expire_time_out)
|
|
|
905b4d |
{
|
|
|
905b4d |
@@ -372,42 +382,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
|
|
|
905b4d |
goto done;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
|
|
|
905b4d |
- DB_PATH, realm_name);
|
|
|
905b4d |
- ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s",
|
|
|
905b4d |
- DB_PATH, realm_name);
|
|
|
905b4d |
- if (ccname_file_dummy == NULL || ccname_file == NULL) {
|
|
|
905b4d |
- ret = ENOMEM;
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
- }
|
|
|
905b4d |
-
|
|
|
905b4d |
- old_umask = umask(077);
|
|
|
905b4d |
- fd = mkstemp(ccname_file_dummy);
|
|
|
905b4d |
- umask(old_umask);
|
|
|
905b4d |
- if (fd == -1) {
|
|
|
905b4d |
- ret = errno;
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
- }
|
|
|
905b4d |
- /* We only care about creating a unique file name here, we don't
|
|
|
905b4d |
- * need the fd
|
|
|
905b4d |
- */
|
|
|
905b4d |
- close(fd);
|
|
|
905b4d |
-
|
|
|
905b4d |
- ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
|
|
|
905b4d |
- ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
|
|
|
905b4d |
- if (ccname_dummy == NULL || ccname == NULL) {
|
|
|
905b4d |
- krberr = ENOMEM;
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
- }
|
|
|
905b4d |
- DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
|
|
|
905b4d |
-
|
|
|
905b4d |
- krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
|
|
|
905b4d |
- if (krberr) {
|
|
|
905b4d |
- DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
|
|
|
905b4d |
- sss_krb5_get_error_message(context, krberr));
|
|
|
905b4d |
- goto done;
|
|
|
905b4d |
- }
|
|
|
905b4d |
-
|
|
|
905b4d |
memset(&my_creds, 0, sizeof(my_creds));
|
|
|
905b4d |
memset(&options, 0, sizeof(options));
|
|
|
905b4d |
|
|
|
905b4d |
@@ -423,8 +397,36 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
|
|
|
905b4d |
}
|
|
|
905b4d |
sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize);
|
|
|
905b4d |
|
|
|
905b4d |
+ ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s",
|
|
|
905b4d |
+ DB_PATH, realm_name);
|
|
|
905b4d |
+ if (ccname_file == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
|
|
|
905b4d |
+ DB_PATH, realm_name);
|
|
|
905b4d |
+ if (ccname_file_dummy == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ old_umask = umask(077);
|
|
|
905b4d |
+ fd = mkstemp(ccname_file_dummy);
|
|
|
905b4d |
+ umask(old_umask);
|
|
|
905b4d |
+ if (fd == -1) {
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ /* We only care about creating a unique file name here, we don't
|
|
|
905b4d |
+ * need the fd
|
|
|
905b4d |
+ */
|
|
|
905b4d |
+ close(fd);
|
|
|
905b4d |
+
|
|
|
905b4d |
krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc,
|
|
|
905b4d |
keytab, 0, NULL, &options);
|
|
|
905b4d |
+ krb5_kt_close(context, keytab);
|
|
|
905b4d |
+ keytab = NULL;
|
|
|
905b4d |
if (krberr) {
|
|
|
905b4d |
DEBUG(SSSDBG_FATAL_FAILURE,
|
|
|
905b4d |
"Failed to init credentials: %s\n",
|
|
|
905b4d |
@@ -438,6 +440,27 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
|
|
|
905b4d |
}
|
|
|
905b4d |
DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n");
|
|
|
905b4d |
|
|
|
905b4d |
+ krberr = become_user(uid, gid);
|
|
|
905b4d |
+ if (krberr != 0) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
|
|
|
905b4d |
+ ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
|
|
|
905b4d |
+ if (ccname_dummy == NULL || ccname == NULL) {
|
|
|
905b4d |
+ krberr = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
|
|
|
905b4d |
+ if (krberr) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
|
|
|
905b4d |
+ sss_krb5_get_error_message(context, krberr));
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
/* Use updated principal if changed due to canonicalization. */
|
|
|
905b4d |
krberr = krb5_cc_initialize(context, ccache, my_creds.client);
|
|
|
905b4d |
if (krberr) {
|
|
|
905b4d |
@@ -643,6 +666,7 @@ int main(int argc, const char *argv[])
|
|
|
905b4d |
kerr = ldap_child_get_tgt_sync(main_ctx,
|
|
|
905b4d |
ibuf->realm_str, ibuf->princ_str,
|
|
|
905b4d |
ibuf->keytab_name, ibuf->lifetime,
|
|
|
905b4d |
+ ibuf->uid, ibuf->gid,
|
|
|
905b4d |
&ccname, &expire_time);
|
|
|
905b4d |
if (kerr != EOK) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n");
|
|
|
905b4d |
diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
index 448c5af10e9da8949bcaa39d8a3fa05ec309e16f..e5d46b9b756cd50fadb212da72ad1cc9bdd93330 100644
|
|
|
905b4d |
--- a/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
+++ b/src/providers/ldap/sdap_child_helpers.c
|
|
|
905b4d |
@@ -152,7 +152,7 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
return ENOMEM;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- buf->size = 4 * sizeof(uint32_t);
|
|
|
905b4d |
+ buf->size = 6 * sizeof(uint32_t);
|
|
|
905b4d |
if (realm_str) {
|
|
|
905b4d |
buf->size += strlen(realm_str);
|
|
|
905b4d |
}
|
|
|
905b4d |
@@ -201,6 +201,12 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
/* lifetime */
|
|
|
905b4d |
SAFEALIGN_SET_UINT32(&buf->data[rp], lifetime, &rp);
|
|
|
905b4d |
|
|
|
905b4d |
+ /* UID and GID to drop privileges to, if needed. The ldap_child process runs as
|
|
|
905b4d |
+ * setuid if the back end runs unprivileged as it needs to access the keytab
|
|
|
905b4d |
+ */
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&buf->data[rp], geteuid(), &rp);
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&buf->data[rp], getegid(), &rp);
|
|
|
905b4d |
+
|
|
|
905b4d |
*io_buf = buf;
|
|
|
905b4d |
return EOK;
|
|
|
905b4d |
}
|
|
|
905b4d |
--
|
|
|
905b4d |
1.9.3
|
|
|
905b4d |
|