summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2014-10-19 19:15:52 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-11-05 19:55:05 +0100
commit936940720b1b0e701a2317abc4c2d05a78338f33 (patch)
treeb7958988dedffefe1b1aba53b989cb51f1f23746 /src
parent5eef3da14cb34e4cb6356f0b291c066db946f936 (diff)
downloadsssd-936940720b1b0e701a2317abc4c2d05a78338f33.tar.gz
sssd-936940720b1b0e701a2317abc4c2d05a78338f33.tar.xz
sssd-936940720b1b0e701a2317abc4c2d05a78338f33.zip
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. Reviewed-by: Michal Židek <mzidek@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/providers/ldap/ldap_child.c90
-rw-r--r--src/providers/ldap/sdap_child_helpers.c8
2 files changed, 64 insertions, 34 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index e1abc9fd7..a922b1817 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: %u\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;
}
@@ -242,6 +250,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)
{
@@ -372,11 +382,31 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
goto done;
}
- ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
- DB_PATH, realm_name);
+ 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);
+
ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s",
DB_PATH, realm_name);
- if (ccname_file_dummy == NULL || ccname_file == NULL) {
+ if (ccname_file == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
+ DB_PATH, realm_name);
+ if (ccname_file_dummy == NULL) {
ret = ENOMEM;
goto done;
}
@@ -393,38 +423,10 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
*/
close(fd);
- ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
- ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
- if (ccname_dummy == NULL || ccname == NULL) {
- krberr = ENOMEM;
- goto done;
- }
- DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
-
- krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
- if (krberr) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
- sss_krb5_get_error_message(context, krberr));
- 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",
@@ -438,6 +440,27 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
}
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_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
+ ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
+ if (ccname_dummy == NULL || ccname == NULL) {
+ krberr = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
+
+ krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
+ if (krberr) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
+ sss_krb5_get_error_message(context, krberr));
+ goto done;
+ }
+
/* Use updated principal if changed due to canonicalization. */
krberr = krb5_cc_initialize(context, ccache, my_creds.client);
if (krberr) {
@@ -643,6 +666,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 448c5af10..e5d46b9b7 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;
}