>From 084e515f0a0ec0c7275ff968fd2612d7ccf37516 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Sun, 19 Oct 2014 19:15:52 +0200 Subject: [PATCH 4/6] LDAP: Drop privileges after kinit in ldap_child After ldap_child initializes privileges using root-owned keytab, it drops privileges to the SSSD user, minimizing the amount of code that runs as root. --- Makefile.am | 4 +- src/providers/ldap/ldap_child.c | 79 ++++++++++++++++++++------------- src/providers/ldap/sdap_child_helpers.c | 8 +++- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/Makefile.am b/Makefile.am index 083837e4894c0bf3875ab09893cdc69903c10e06..9eabc4e5f91b8473f4fb90358f7666b752a68250 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2479,7 +2479,9 @@ ldap_child_SOURCES = \ src/util/atomic_io.c \ src/util/authtok.c \ src/util/util.c \ - src/util/signal.c + src/util/signal.c \ + src/util/become_user.c \ + $(NULL) ldap_child_CFLAGS = \ $(AM_CFLAGS) \ $(POPT_CFLAGS) \ diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c index 6195d503ca6503dc754ed9d2c840210ed5c8a492..5eced9dae1694b2adafafb13441e8a7368b136e0 100644 --- a/src/providers/ldap/ldap_child.c +++ b/src/providers/ldap/ldap_child.c @@ -49,6 +49,8 @@ struct input_buffer { const char *princ_str; const char *keytab_name; krb5_deltat lifetime; + uid_t uid; + gid_t gid; }; static errno_t unpack_buffer(uint8_t *buf, size_t size, @@ -99,6 +101,12 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, SAFEALIGN_COPY_UINT32_CHECK(&ibuf->lifetime, buf + p, size, &p); DEBUG(SSSDBG_TRACE_LIBS, "lifetime: %d\n", ibuf->lifetime); + /* UID and GID to run as */ + SAFEALIGN_COPY_UINT32_CHECK(&ibuf->uid, buf + p, size, &p); + SAFEALIGN_COPY_UINT32_CHECK(&ibuf->gid, buf + p, size, &p); + DEBUG(SSSDBG_FUNC_DATA, + "Will run as [%"SPRIuid"][%"SPRIgid"].\n", ibuf->uid, ibuf->gid); + return EOK; } @@ -243,6 +251,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, const char *princ_str, const char *keytab_name, const krb5_deltat lifetime, + uid_t uid, + gid_t gid, const char **ccname_out, time_t *expire_time_out) { @@ -373,6 +383,44 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, goto done; } + memset(&my_creds, 0, sizeof(my_creds)); + memset(&options, 0, sizeof(options)); + + krb5_get_init_creds_opt_set_address_list(&options, NULL); + krb5_get_init_creds_opt_set_forwardable(&options, 0); + krb5_get_init_creds_opt_set_proxiable(&options, 0); + krb5_get_init_creds_opt_set_tkt_life(&options, lifetime); + + tmp_str = getenv("KRB5_CANONICALIZE"); + if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) { + DEBUG(SSSDBG_CONF_SETTINGS, "Will canonicalize principals\n"); + canonicalize = 1; + } + sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize); + + krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc, + keytab, 0, NULL, &options); + krb5_kt_close(context, keytab); + keytab = NULL; + if (krberr) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to init credentials: %s\n", + sss_krb5_get_error_message(context, krberr)); + sss_log(SSS_LOG_ERR, + "Failed to initialize credentials using keytab [%s]: %s. " + "Unable to create GSSAPI-encrypted LDAP connection.", + KEYTAB_CLEAN_NAME, + sss_krb5_get_error_message(context, krberr)); + goto done; + } + DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n"); + + krberr = become_user(uid, gid); + if (krberr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n"); + goto done; + } + ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX", DB_PATH, realm_name); ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s", @@ -409,36 +457,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, goto done; } - memset(&my_creds, 0, sizeof(my_creds)); - memset(&options, 0, sizeof(options)); - - krb5_get_init_creds_opt_set_address_list(&options, NULL); - krb5_get_init_creds_opt_set_forwardable(&options, 0); - krb5_get_init_creds_opt_set_proxiable(&options, 0); - krb5_get_init_creds_opt_set_tkt_life(&options, lifetime); - - tmp_str = getenv("KRB5_CANONICALIZE"); - if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) { - DEBUG(SSSDBG_CONF_SETTINGS, "Will canonicalize principals\n"); - canonicalize = 1; - } - sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize); - - krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc, - keytab, 0, NULL, &options); - if (krberr) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Failed to init credentials: %s\n", - sss_krb5_get_error_message(context, krberr)); - sss_log(SSS_LOG_ERR, - "Failed to initialize credentials using keytab [%s]: %s. " - "Unable to create GSSAPI-encrypted LDAP connection.", - KEYTAB_CLEAN_NAME, - sss_krb5_get_error_message(context, krberr)); - goto done; - } - DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n"); - /* Use updated principal if changed due to canonicalization. */ krberr = krb5_cc_initialize(context, ccache, my_creds.client); if (krberr) { @@ -644,6 +662,7 @@ int main(int argc, const char *argv[]) kerr = ldap_child_get_tgt_sync(main_ctx, ibuf->realm_str, ibuf->princ_str, ibuf->keytab_name, ibuf->lifetime, + ibuf->uid, ibuf->gid, &ccname, &expire_time); if (kerr != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n"); diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c index 448c5af10e9da8949bcaa39d8a3fa05ec309e16f..e5d46b9b756cd50fadb212da72ad1cc9bdd93330 100644 --- a/src/providers/ldap/sdap_child_helpers.c +++ b/src/providers/ldap/sdap_child_helpers.c @@ -152,7 +152,7 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx, return ENOMEM; } - buf->size = 4 * sizeof(uint32_t); + buf->size = 6 * sizeof(uint32_t); if (realm_str) { buf->size += strlen(realm_str); } @@ -201,6 +201,12 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx, /* lifetime */ SAFEALIGN_SET_UINT32(&buf->data[rp], lifetime, &rp); + /* UID and GID to drop privileges to, if needed. The ldap_child process runs as + * setuid if the back end runs unprivileged as it needs to access the keytab + */ + SAFEALIGN_SET_UINT32(&buf->data[rp], geteuid(), &rp); + SAFEALIGN_SET_UINT32(&buf->data[rp], getegid(), &rp); + *io_buf = buf; return EOK; } -- 1.9.3