|
|
905b4d |
From e08eb3e3b0586b331a688a4eded2d7f13611016c Mon Sep 17 00:00:00 2001
|
|
|
905b4d |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
Date: Mon, 20 Oct 2014 23:16:40 +0200
|
|
|
905b4d |
Subject: [PATCH 71/71] IPA: Move setting the SELinux context to a child
|
|
|
905b4d |
process
|
|
|
905b4d |
MIME-Version: 1.0
|
|
|
905b4d |
Content-Type: text/plain; charset=UTF-8
|
|
|
905b4d |
Content-Transfer-Encoding: 8bit
|
|
|
905b4d |
|
|
|
905b4d |
In order for the sssd_be process to run as unprivileged user, we need to
|
|
|
905b4d |
move the semanage processing to a process that runs as the root user
|
|
|
905b4d |
using setuid privileges.
|
|
|
905b4d |
|
|
|
905b4d |
Reviewed-by: Michal Židek <mzidek@redhat.com>
|
|
|
905b4d |
---
|
|
|
905b4d |
Makefile.am | 27 +++
|
|
|
905b4d |
contrib/sssd.spec.in | 1 +
|
|
|
905b4d |
src/providers/ipa/ipa_selinux.c | 425 +++++++++++++++++++++++++++++++++++---
|
|
|
905b4d |
src/providers/ipa/selinux_child.c | 272 ++++++++++++++++++++++++
|
|
|
905b4d |
src/util/util_errors.c | 1 +
|
|
|
905b4d |
src/util/util_errors.h | 1 +
|
|
|
905b4d |
6 files changed, 699 insertions(+), 28 deletions(-)
|
|
|
905b4d |
create mode 100644 src/providers/ipa/selinux_child.c
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/Makefile.am b/Makefile.am
|
|
|
905b4d |
index ea296c40f89c552d5825cbce8e95afdc517e8bb5..b85341f5845c3cffab8a2c95b1be1d32517316e8 100644
|
|
|
905b4d |
--- a/Makefile.am
|
|
|
905b4d |
+++ b/Makefile.am
|
|
|
905b4d |
@@ -146,6 +146,9 @@ endif
|
|
|
905b4d |
if BUILD_SAMBA
|
|
|
905b4d |
sssdlibexec_PROGRAMS += gpo_child
|
|
|
905b4d |
endif
|
|
|
905b4d |
+if BUILD_SEMANAGE
|
|
|
905b4d |
+sssdlibexec_PROGRAMS += selinux_child
|
|
|
905b4d |
+endif
|
|
|
905b4d |
|
|
|
905b4d |
|
|
|
905b4d |
if BUILD_PAC_RESPONDER
|
|
|
905b4d |
@@ -2531,6 +2534,26 @@ ldap_child_LDADD = \
|
|
|
905b4d |
$(DHASH_LIBS) \
|
|
|
905b4d |
$(KRB5_LIBS)
|
|
|
905b4d |
|
|
|
905b4d |
+if BUILD_SEMANAGE
|
|
|
905b4d |
+selinux_child_SOURCES = \
|
|
|
905b4d |
+ src/providers/ipa/selinux_child.c \
|
|
|
905b4d |
+ src/util/sss_semanage.c \
|
|
|
905b4d |
+ src/util/atomic_io.c \
|
|
|
905b4d |
+ src/util/util.c \
|
|
|
905b4d |
+ $(NULL)
|
|
|
905b4d |
+selinux_child_CFLAGS = \
|
|
|
905b4d |
+ $(AM_CFLAGS) \
|
|
|
905b4d |
+ $(POPT_CFLAGS) \
|
|
|
905b4d |
+ $(NULL)
|
|
|
905b4d |
+selinux_child_LDADD = \
|
|
|
905b4d |
+ libsss_debug.la \
|
|
|
905b4d |
+ $(TALLOC_LIBS) \
|
|
|
905b4d |
+ $(POPT_LIBS) \
|
|
|
905b4d |
+ $(DHASH_LIBS) \
|
|
|
905b4d |
+ $(SEMANAGE_LIBS) \
|
|
|
905b4d |
+ $(NULL)
|
|
|
905b4d |
+endif
|
|
|
905b4d |
+
|
|
|
905b4d |
gpo_child_SOURCES = \
|
|
|
905b4d |
src/providers/ad/ad_gpo_child.c \
|
|
|
905b4d |
src/util/atomic_io.c \
|
|
|
905b4d |
@@ -2849,6 +2872,10 @@ endif
|
|
|
905b4d |
if SSSD_USER
|
|
|
905b4d |
chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
|
|
|
905b4d |
chmod 4750 $(sssdlibexecdir)/ldap_child
|
|
|
905b4d |
+if BUILD_SEMANAGE
|
|
|
905b4d |
+ chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
|
|
|
905b4d |
+ chmod 4750 $(sssdlibexecdir)/selinux_child
|
|
|
905b4d |
+endif
|
|
|
905b4d |
endif
|
|
|
905b4d |
|
|
|
905b4d |
install-data-hook:
|
|
|
905b4d |
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
|
|
|
905b4d |
index d2e6cec2610e4c00cb376683cf7e64eb5cdafc5c..5bfb16707c22dc65376581c88b8eb898949e726f 100644
|
|
|
905b4d |
--- a/contrib/sssd.spec.in
|
|
|
905b4d |
+++ b/contrib/sssd.spec.in
|
|
|
905b4d |
@@ -665,6 +665,7 @@ rm -rf $RPM_BUILD_ROOT
|
|
|
905b4d |
%doc COPYING
|
|
|
905b4d |
%attr(755,root,root) %dir %{pubconfpath}/krb5.include.d
|
|
|
905b4d |
%{_libdir}/%{name}/libsss_ipa.so
|
|
|
905b4d |
+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/selinux_child
|
|
|
905b4d |
%{_mandir}/man5/sssd-ipa.5*
|
|
|
905b4d |
|
|
|
905b4d |
%files ad -f sssd_ad.lang
|
|
|
905b4d |
diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
index 7db1c6ed2981e4c4a85d892171bbfa60b006980e..b392d82a61cd523cd5e73e5246013bdbc448ddd5 100644
|
|
|
905b4d |
--- a/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
+++ b/src/providers/ipa/ipa_selinux.c
|
|
|
905b4d |
@@ -24,6 +24,7 @@
|
|
|
905b4d |
#include <security/pam_modules.h>
|
|
|
905b4d |
|
|
|
905b4d |
#include "db/sysdb_selinux.h"
|
|
|
905b4d |
+#include "util/child_common.h"
|
|
|
905b4d |
#include "util/sss_selinux.h"
|
|
|
905b4d |
#include "providers/ldap/sdap_async.h"
|
|
|
905b4d |
#include "providers/ipa/ipa_common.h"
|
|
|
905b4d |
@@ -37,8 +38,23 @@
|
|
|
905b4d |
#include "providers/ipa/ipa_subdomains.h"
|
|
|
905b4d |
|
|
|
905b4d |
#if defined HAVE_SELINUX && defined HAVE_SELINUX_LOGIN_DIR
|
|
|
905b4d |
+
|
|
|
905b4d |
+#ifndef SELINUX_CHILD_DIR
|
|
|
905b4d |
+#ifndef SSSD_LIBEXEC_PATH
|
|
|
905b4d |
+#error "SSSD_LIBEXEC_PATH not defined"
|
|
|
905b4d |
+#endif /* SSSD_LIBEXEC_PATH */
|
|
|
905b4d |
+
|
|
|
905b4d |
+#define SELINUX_CHILD_DIR SSSD_LIBEXEC_PATH
|
|
|
905b4d |
+#endif /* SELINUX_CHILD_DIR */
|
|
|
905b4d |
+
|
|
|
905b4d |
+#define SELINUX_CHILD SELINUX_CHILD_DIR"/selinux_child"
|
|
|
905b4d |
+#define SELINUX_CHILD_LOG_FILE "selinux_child"
|
|
|
905b4d |
+
|
|
|
905b4d |
#include <selinux/selinux.h>
|
|
|
905b4d |
|
|
|
905b4d |
+/* fd used by the selinux_child process for logging */
|
|
|
905b4d |
+int selinux_child_debug_fd = -1;
|
|
|
905b4d |
+
|
|
|
905b4d |
static struct tevent_req *
|
|
|
905b4d |
ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
struct be_ctx *be_ctx,
|
|
|
905b4d |
@@ -274,12 +290,27 @@ struct map_order_ctx {
|
|
|
905b4d |
|
|
|
905b4d |
static errno_t init_map_order_ctx(TALLOC_CTX *mem_ctx, const char *map_order,
|
|
|
905b4d |
struct map_order_ctx **_mo_ctx);
|
|
|
905b4d |
-static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
|
|
|
905b4d |
+
|
|
|
905b4d |
+struct selinux_child_input {
|
|
|
905b4d |
+ const char *seuser;
|
|
|
905b4d |
+ const char *mls_range;
|
|
|
905b4d |
+ const char *username;
|
|
|
905b4d |
+};
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ struct sysdb_attrs **usermaps,
|
|
|
905b4d |
struct pam_data *pd,
|
|
|
905b4d |
struct sss_domain_info *user_domain,
|
|
|
905b4d |
struct map_order_ctx *mo_ctx,
|
|
|
905b4d |
- const char *default_user);
|
|
|
905b4d |
+ const char *default_user,
|
|
|
905b4d |
+ struct selinux_child_input **_sci);
|
|
|
905b4d |
|
|
|
905b4d |
+static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ struct tevent_context *ev,
|
|
|
905b4d |
+ struct selinux_child_input *sci);
|
|
|
905b4d |
+static errno_t selinux_child_recv(struct tevent_req *req);
|
|
|
905b4d |
+
|
|
|
905b4d |
+static void ipa_selinux_child_done(struct tevent_req *child_req);
|
|
|
905b4d |
|
|
|
905b4d |
static void ipa_selinux_handler_done(struct tevent_req *req)
|
|
|
905b4d |
{
|
|
|
905b4d |
@@ -299,6 +330,8 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
|
|
|
905b4d |
struct sysdb_attrs **hbac_rules = 0;
|
|
|
905b4d |
struct sysdb_attrs **best_match_maps;
|
|
|
905b4d |
struct map_order_ctx *map_order_ctx;
|
|
|
905b4d |
+ struct selinux_child_input *sci;
|
|
|
905b4d |
+ struct tevent_req *child_req;
|
|
|
905b4d |
|
|
|
905b4d |
ret = ipa_get_selinux_recv(req, breq, &map_count, &maps,
|
|
|
905b4d |
&hbac_count, &hbac_rules,
|
|
|
905b4d |
@@ -360,14 +393,61 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
|
|
|
905b4d |
goto fail;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- ret = choose_best_seuser(best_match_maps, pd, op_ctx->user_domain,
|
|
|
905b4d |
- map_order_ctx, default_user);
|
|
|
905b4d |
+ ret = choose_best_seuser(breq,
|
|
|
905b4d |
+ best_match_maps, pd, op_ctx->user_domain,
|
|
|
905b4d |
+ map_order_ctx, default_user, &sci);
|
|
|
905b4d |
if (ret != EOK) {
|
|
|
905b4d |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
"Failed to evaluate ordered SELinux users array.\n");
|
|
|
905b4d |
goto fail;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
+ /* Update the SELinux context in a privileged child as the back end is
|
|
|
905b4d |
+ * running unprivileged
|
|
|
905b4d |
+ */
|
|
|
905b4d |
+ child_req = selinux_child_send(breq, be_ctx->ev, sci);
|
|
|
905b4d |
+ if (child_req == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "selinux_child_send() failed\n");
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ tevent_req_set_callback(child_req, ipa_selinux_child_done, op_ctx);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+
|
|
|
905b4d |
+fail:
|
|
|
905b4d |
+ if (in_transaction) {
|
|
|
905b4d |
+ sret = sysdb_transaction_cancel(sysdb);
|
|
|
905b4d |
+ if (sret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ if (ret == EAGAIN) {
|
|
|
905b4d |
+ be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static void ipa_selinux_child_done(struct tevent_req *child_req)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+ struct ipa_selinux_op_ctx *op_ctx;
|
|
|
905b4d |
+ struct be_req *breq;
|
|
|
905b4d |
+ struct pam_data *pd;
|
|
|
905b4d |
+ struct be_ctx *be_ctx;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ op_ctx = tevent_req_callback_data(child_req, struct ipa_selinux_op_ctx);
|
|
|
905b4d |
+ breq = op_ctx->be_req;
|
|
|
905b4d |
+ pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
|
|
|
905b4d |
+ be_ctx = be_req_get_be_ctx(breq);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = selinux_child_recv(child_req);
|
|
|
905b4d |
+ talloc_free(child_req);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
/* If we got here in online mode, set last_update to current time */
|
|
|
905b4d |
if (!be_is_offline(be_ctx)) {
|
|
|
905b4d |
op_ctx->selinux_ctx->last_update = time(NULL);
|
|
|
905b4d |
@@ -375,20 +455,6 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
|
|
|
905b4d |
|
|
|
905b4d |
pd->pam_status = PAM_SUCCESS;
|
|
|
905b4d |
be_req_terminate(breq, DP_ERR_OK, EOK, "Success");
|
|
|
905b4d |
- return;
|
|
|
905b4d |
-
|
|
|
905b4d |
-fail:
|
|
|
905b4d |
- if (in_transaction) {
|
|
|
905b4d |
- sret = sysdb_transaction_cancel(sysdb);
|
|
|
905b4d |
- if (sret != EOK) {
|
|
|
905b4d |
- DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
|
|
|
905b4d |
- }
|
|
|
905b4d |
- }
|
|
|
905b4d |
- if (ret == EAGAIN) {
|
|
|
905b4d |
- be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
|
|
|
905b4d |
- } else {
|
|
|
905b4d |
- be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
|
|
|
905b4d |
- }
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
static errno_t
|
|
|
905b4d |
@@ -652,24 +718,28 @@ done:
|
|
|
905b4d |
return ret;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
-static errno_t
|
|
|
905b4d |
-set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
|
|
|
905b4d |
- const char *seuser_mls_string);
|
|
|
905b4d |
-
|
|
|
905b4d |
+static errno_t selinux_child_setup(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ const char *orig_name,
|
|
|
905b4d |
+ struct sss_domain_info *dom,
|
|
|
905b4d |
+ const char *seuser_mls_string,
|
|
|
905b4d |
+ struct selinux_child_input **_sci);
|
|
|
905b4d |
|
|
|
905b4d |
/* Choose best selinux user based on given order and write
|
|
|
905b4d |
* the user to selinux login file. */
|
|
|
905b4d |
-static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
|
|
|
905b4d |
+static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ struct sysdb_attrs **usermaps,
|
|
|
905b4d |
struct pam_data *pd,
|
|
|
905b4d |
struct sss_domain_info *user_domain,
|
|
|
905b4d |
struct map_order_ctx *mo_ctx,
|
|
|
905b4d |
- const char *default_user)
|
|
|
905b4d |
+ const char *default_user,
|
|
|
905b4d |
+ struct selinux_child_input **_sci)
|
|
|
905b4d |
{
|
|
|
905b4d |
TALLOC_CTX *tmp_ctx;
|
|
|
905b4d |
char *seuser_mls_str = NULL;
|
|
|
905b4d |
const char *tmp_str;
|
|
|
905b4d |
errno_t ret;
|
|
|
905b4d |
int i, j;
|
|
|
905b4d |
+ struct selinux_child_input *sci;
|
|
|
905b4d |
|
|
|
905b4d |
tmp_ctx = talloc_new(NULL);
|
|
|
905b4d |
if (tmp_ctx == NULL) {
|
|
|
905b4d |
@@ -716,15 +786,25 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
|
|
|
905b4d |
}
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- ret = set_seuser_helper(pd->user, user_domain, seuser_mls_str);
|
|
|
905b4d |
+ ret = selinux_child_setup(tmp_ctx, pd->user, user_domain, seuser_mls_str, &sci);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot set up child input buffer");
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ *_sci = talloc_steal(mem_ctx, sci);
|
|
|
905b4d |
+ ret = EOK;
|
|
|
905b4d |
done:
|
|
|
905b4d |
talloc_free(tmp_ctx);
|
|
|
905b4d |
return ret;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
static errno_t
|
|
|
905b4d |
-set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
|
|
|
905b4d |
- const char *seuser_mls_string)
|
|
|
905b4d |
+selinux_child_setup(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ const char *orig_name,
|
|
|
905b4d |
+ struct sss_domain_info *dom,
|
|
|
905b4d |
+ const char *seuser_mls_string,
|
|
|
905b4d |
+ struct selinux_child_input **_sci)
|
|
|
905b4d |
{
|
|
|
905b4d |
errno_t ret;
|
|
|
905b4d |
char *seuser;
|
|
|
905b4d |
@@ -733,6 +813,7 @@ set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
|
|
|
905b4d |
char *username;
|
|
|
905b4d |
char *username_final;
|
|
|
905b4d |
TALLOC_CTX *tmp_ctx;
|
|
|
905b4d |
+ struct selinux_child_input *sci;
|
|
|
905b4d |
|
|
|
905b4d |
tmp_ctx = talloc_new(NULL);
|
|
|
905b4d |
if (tmp_ctx == NULL) {
|
|
|
905b4d |
@@ -778,12 +859,300 @@ set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
|
|
|
905b4d |
username_final = username;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
- ret = set_seuser(username_final, seuser, mls_range);
|
|
|
905b4d |
+ sci = talloc(tmp_ctx, struct selinux_child_input);
|
|
|
905b4d |
+ if (sci == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ sci->seuser = talloc_strdup(sci, seuser);
|
|
|
905b4d |
+ sci->mls_range = talloc_strdup(sci, mls_range);
|
|
|
905b4d |
+ sci->username = talloc_strdup(sci, username);
|
|
|
905b4d |
+ if (sci->seuser == NULL || sci->mls_range == NULL
|
|
|
905b4d |
+ || sci->username == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto done;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ *_sci = talloc_steal(mem_ctx, sci);
|
|
|
905b4d |
+ ret = EOK;
|
|
|
905b4d |
done:
|
|
|
905b4d |
talloc_free(tmp_ctx);
|
|
|
905b4d |
return ret;
|
|
|
905b4d |
}
|
|
|
905b4d |
|
|
|
905b4d |
+struct selinux_child_state {
|
|
|
905b4d |
+ struct selinux_child_input *sci;
|
|
|
905b4d |
+ struct tevent_context *ev;
|
|
|
905b4d |
+ struct io_buffer *buf;
|
|
|
905b4d |
+ struct child_io_fds *io;
|
|
|
905b4d |
+};
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_child_init(void);
|
|
|
905b4d |
+static errno_t selinux_child_create_buffer(struct selinux_child_state *state);
|
|
|
905b4d |
+static errno_t selinux_fork_child(struct selinux_child_state *state);
|
|
|
905b4d |
+static void selinux_child_step(struct tevent_req *subreq);
|
|
|
905b4d |
+static void selinux_child_done(struct tevent_req *subreq);
|
|
|
905b4d |
+static errno_t selinux_child_parse_response(uint8_t *buf, ssize_t len,
|
|
|
905b4d |
+ uint32_t *_child_result);
|
|
|
905b4d |
+
|
|
|
905b4d |
+static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ struct tevent_context *ev,
|
|
|
905b4d |
+ struct selinux_child_input *sci)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ struct tevent_req *req;
|
|
|
905b4d |
+ struct tevent_req *subreq;
|
|
|
905b4d |
+ struct selinux_child_state *state;
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ req = tevent_req_create(mem_ctx, &state, struct selinux_child_state);
|
|
|
905b4d |
+ if (req == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
905b4d |
+ return NULL;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ state->sci = sci;
|
|
|
905b4d |
+ state->ev = ev;
|
|
|
905b4d |
+ state->io = talloc(state, struct child_io_fds);
|
|
|
905b4d |
+ state->buf = talloc(state, struct io_buffer);
|
|
|
905b4d |
+ if (state->io == NULL || state->buf == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto immediately;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ state->io->write_to_child_fd = -1;
|
|
|
905b4d |
+ state->io->read_from_child_fd = -1;
|
|
|
905b4d |
+ talloc_set_destructor((void *) state->io, child_io_destructor);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = selinux_child_init();
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to init the child\n");
|
|
|
905b4d |
+ goto immediately;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = selinux_child_create_buffer(state);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to create the send buffer\n");
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto immediately;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = selinux_fork_child(state);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to fork the child\n");
|
|
|
905b4d |
+ goto immediately;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ subreq = write_pipe_send(state, ev, state->buf->data, state->buf->size,
|
|
|
905b4d |
+ state->io->write_to_child_fd);
|
|
|
905b4d |
+ if (subreq == NULL) {
|
|
|
905b4d |
+ ret = ENOMEM;
|
|
|
905b4d |
+ goto immediately;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ tevent_req_set_callback(subreq, selinux_child_step, req);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = EOK;
|
|
|
905b4d |
+immediately:
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ tevent_req_error(req, ret);
|
|
|
905b4d |
+ tevent_req_post(req, ev);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ return req;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_child_init(void)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ return child_debug_init(SELINUX_CHILD_LOG_FILE, &selinux_child_debug_fd);
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_child_create_buffer(struct selinux_child_state *state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ size_t rp;
|
|
|
905b4d |
+ size_t seuser_len;
|
|
|
905b4d |
+ size_t mls_range_len;
|
|
|
905b4d |
+ size_t username_len;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ seuser_len = strlen(state->sci->seuser);
|
|
|
905b4d |
+ mls_range_len = strlen(state->sci->mls_range);
|
|
|
905b4d |
+ username_len = strlen(state->sci->username);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ state->buf->size = 3 * sizeof(uint32_t);
|
|
|
905b4d |
+ state->buf->size += seuser_len + mls_range_len + username_len;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_ALL, "buffer size: %zu\n", state->buf->size);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ state->buf->data = talloc_size(state->buf, state->buf->size);
|
|
|
905b4d |
+ if (state->buf->data == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
|
|
|
905b4d |
+ return ENOMEM;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ rp = 0;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* seuser */
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&state->buf->data[rp], seuser_len, &rp);
|
|
|
905b4d |
+ safealign_memcpy(&state->buf->data[rp], state->sci->seuser,
|
|
|
905b4d |
+ seuser_len, &rp);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* mls_range */
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&state->buf->data[rp], mls_range_len, &rp);
|
|
|
905b4d |
+ safealign_memcpy(&state->buf->data[rp], state->sci->mls_range,
|
|
|
905b4d |
+ mls_range_len, &rp);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* username */
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&state->buf->data[rp], username_len, &rp);
|
|
|
905b4d |
+ safealign_memcpy(&state->buf->data[rp], state->sci->username,
|
|
|
905b4d |
+ username_len, &rp);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_fork_child(struct selinux_child_state *state)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ int pipefd_to_child[2];
|
|
|
905b4d |
+ int pipefd_from_child[2];
|
|
|
905b4d |
+ pid_t pid;
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = pipe(pipefd_from_child);
|
|
|
905b4d |
+ if (ret == -1) {
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = pipe(pipefd_to_child);
|
|
|
905b4d |
+ if (ret == -1) {
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ pid = fork();
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (pid == 0) { /* child */
|
|
|
905b4d |
+ ret = exec_child(state,
|
|
|
905b4d |
+ pipefd_to_child, pipefd_from_child,
|
|
|
905b4d |
+ SELINUX_CHILD, selinux_child_debug_fd);
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
|
|
|
905b4d |
+ ret, sss_strerror(ret));
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ } else if (pid > 0) { /* parent */
|
|
|
905b4d |
+ state->io->read_from_child_fd = pipefd_from_child[0];
|
|
|
905b4d |
+ close(pipefd_from_child[1]);
|
|
|
905b4d |
+ state->io->write_to_child_fd = pipefd_to_child[1];
|
|
|
905b4d |
+ close(pipefd_to_child[0]);
|
|
|
905b4d |
+ fd_nonblocking(state->io->read_from_child_fd);
|
|
|
905b4d |
+ fd_nonblocking(state->io->write_to_child_fd);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = child_handler_setup(state->ev, pid, NULL, NULL, NULL);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "Could not set up child signal handler\n");
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ } else { /* error */
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "fork failed [%d][%s].\n", errno, sss_strerror(errno));
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static void selinux_child_step(struct tevent_req *subreq)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ struct tevent_req *req;
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+ struct selinux_child_state *state;
|
|
|
905b4d |
+
|
|
|
905b4d |
+
|
|
|
905b4d |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
905b4d |
+ state = tevent_req_data(req, struct selinux_child_state);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = write_pipe_recv(subreq);
|
|
|
905b4d |
+ talloc_zfree(subreq);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ tevent_req_error(req, ret);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ close(state->io->write_to_child_fd);
|
|
|
905b4d |
+ state->io->write_to_child_fd = -1;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ subreq = read_pipe_send(state, state->ev, state->io->read_from_child_fd);
|
|
|
905b4d |
+ if (subreq == NULL) {
|
|
|
905b4d |
+ tevent_req_error(req, ENOMEM);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ tevent_req_set_callback(subreq, selinux_child_done, req);
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static void selinux_child_done(struct tevent_req *subreq)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ struct tevent_req *req;
|
|
|
905b4d |
+ struct selinux_child_state *state;
|
|
|
905b4d |
+ uint32_t child_result;
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+ ssize_t len;
|
|
|
905b4d |
+ uint8_t *buf;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
905b4d |
+ state = tevent_req_data(req, struct selinux_child_state);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = read_pipe_recv(subreq, state, &buf, &len;;
|
|
|
905b4d |
+ talloc_zfree(subreq);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ tevent_req_error(req, ret);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ close(state->io->read_from_child_fd);
|
|
|
905b4d |
+ state->io->read_from_child_fd = -1;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = selinux_child_parse_response(buf, len, &child_result);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "selinux_child_parse_response failed: [%d][%s]\n",
|
|
|
905b4d |
+ ret, strerror(ret));
|
|
|
905b4d |
+ tevent_req_error(req, ret);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ } else if (child_result != 0){
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "Error in selinux_child: [%d][%s]\n",
|
|
|
905b4d |
+ child_result, strerror(child_result));
|
|
|
905b4d |
+ tevent_req_error(req, ERR_SELINUX_CONTEXT);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ tevent_req_done(req);
|
|
|
905b4d |
+ return;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_child_parse_response(uint8_t *buf,
|
|
|
905b4d |
+ ssize_t len,
|
|
|
905b4d |
+ uint32_t *_child_result)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ size_t p = 0;
|
|
|
905b4d |
+ uint32_t child_result;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* semanage retval */
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&child_result, buf + p, len, &p);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ *_child_result = child_result;
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t selinux_child_recv(struct tevent_req *req)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
/* A more generic request to gather all SELinux and HBAC rules. Updates
|
|
|
905b4d |
* cache if necessary
|
|
|
905b4d |
*/
|
|
|
905b4d |
diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
|
|
|
905b4d |
new file mode 100644
|
|
|
905b4d |
index 0000000000000000000000000000000000000000..a624cfd30d6795c305b7673d849213c74de95cd8
|
|
|
905b4d |
--- /dev/null
|
|
|
905b4d |
+++ b/src/providers/ipa/selinux_child.c
|
|
|
905b4d |
@@ -0,0 +1,272 @@
|
|
|
905b4d |
+/*
|
|
|
905b4d |
+ SSSD
|
|
|
905b4d |
+
|
|
|
905b4d |
+ IPA back end -- set SELinux context in a child module
|
|
|
905b4d |
+
|
|
|
905b4d |
+ Authors:
|
|
|
905b4d |
+ Jakub Hrozek <jhrozek@redhat.com>
|
|
|
905b4d |
+
|
|
|
905b4d |
+ Copyright (C) 2014 Red Hat
|
|
|
905b4d |
+
|
|
|
905b4d |
+ This program is free software; you can redistribute it and/or modify
|
|
|
905b4d |
+ it under the terms of the GNU General Public License as published by
|
|
|
905b4d |
+ the Free Software Foundation; either version 3 of the License, or
|
|
|
905b4d |
+ (at your option) any later version.
|
|
|
905b4d |
+
|
|
|
905b4d |
+ This program is distributed in the hope that it will be useful,
|
|
|
905b4d |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
905b4d |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
905b4d |
+ GNU General Public License for more details.
|
|
|
905b4d |
+
|
|
|
905b4d |
+ You should have received a copy of the GNU General Public License
|
|
|
905b4d |
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
905b4d |
+*/
|
|
|
905b4d |
+
|
|
|
905b4d |
+
|
|
|
905b4d |
+#include <sys/types.h>
|
|
|
905b4d |
+#include <unistd.h>
|
|
|
905b4d |
+#include <sys/stat.h>
|
|
|
905b4d |
+#include <popt.h>
|
|
|
905b4d |
+
|
|
|
905b4d |
+#include "util/util.h"
|
|
|
905b4d |
+#include "util/child_common.h"
|
|
|
905b4d |
+#include "providers/dp_backend.h"
|
|
|
905b4d |
+
|
|
|
905b4d |
+struct input_buffer {
|
|
|
905b4d |
+ const char *seuser;
|
|
|
905b4d |
+ const char *mls_range;
|
|
|
905b4d |
+ const char *username;
|
|
|
905b4d |
+};
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t unpack_buffer(uint8_t *buf,
|
|
|
905b4d |
+ size_t size,
|
|
|
905b4d |
+ struct input_buffer *ibuf)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ size_t p = 0;
|
|
|
905b4d |
+ uint32_t len;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* seuser */
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "seuser length: %d\n", len);
|
|
|
905b4d |
+ if (len == 0) {
|
|
|
905b4d |
+ return EINVAL;
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ if ((p + len ) > size) return EINVAL;
|
|
|
905b4d |
+ ibuf->seuser = talloc_strndup(ibuf, (char *)(buf + p), len);
|
|
|
905b4d |
+ if (ibuf->seuser == NULL) return ENOMEM;
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "seuser: %s\n", ibuf->seuser);
|
|
|
905b4d |
+ p += len;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* MLS range */
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "mls_range length: %d\n", len);
|
|
|
905b4d |
+ if (len == 0) {
|
|
|
905b4d |
+ return EINVAL;
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ if ((p + len ) > size) return EINVAL;
|
|
|
905b4d |
+ ibuf->mls_range = talloc_strndup(ibuf, (char *)(buf + p), len);
|
|
|
905b4d |
+ if (ibuf->mls_range == NULL) return ENOMEM;
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "mls_range: %s\n", ibuf->mls_range);
|
|
|
905b4d |
+ p += len;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* username */
|
|
|
905b4d |
+ SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "username length: %d\n", len);
|
|
|
905b4d |
+ if (len == 0) {
|
|
|
905b4d |
+ return EINVAL;
|
|
|
905b4d |
+ } else {
|
|
|
905b4d |
+ if ((p + len ) > size) return EINVAL;
|
|
|
905b4d |
+ ibuf->username = talloc_strndup(ibuf, (char *)(buf + p), len);
|
|
|
905b4d |
+ if (ibuf->username == NULL) return ENOMEM;
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "username: %s\n", ibuf->username);
|
|
|
905b4d |
+ p += len;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t pack_buffer(struct response *r, int result)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ size_t p = 0;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* A buffer with the following structure must be created:
|
|
|
905b4d |
+ * uint32_t status of the request (required)
|
|
|
905b4d |
+ */
|
|
|
905b4d |
+ r->size = sizeof(uint32_t);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ r->buf = talloc_array(r, uint8_t, r->size);
|
|
|
905b4d |
+ if(r->buf == NULL) {
|
|
|
905b4d |
+ return ENOMEM;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_FUNC, "result [%d]\n", result);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* result */
|
|
|
905b4d |
+ SAFEALIGN_SET_UINT32(&r->buf[p], result, &p);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+static errno_t prepare_response(TALLOC_CTX *mem_ctx,
|
|
|
905b4d |
+ int result,
|
|
|
905b4d |
+ struct response **rsp)
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ int ret;
|
|
|
905b4d |
+ struct response *r = NULL;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ r = talloc_zero(mem_ctx, struct response);
|
|
|
905b4d |
+ if (r == NULL) {
|
|
|
905b4d |
+ return ENOMEM;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ r->buf = NULL;
|
|
|
905b4d |
+ r->size = 0;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = pack_buffer(r, result);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "pack_buffer failed\n");
|
|
|
905b4d |
+ return ret;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ *rsp = r;
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_ALL, "r->size: %zu\n", r->size);
|
|
|
905b4d |
+ return EOK;
|
|
|
905b4d |
+}
|
|
|
905b4d |
+
|
|
|
905b4d |
+int main(int argc, const char *argv[])
|
|
|
905b4d |
+{
|
|
|
905b4d |
+ int opt;
|
|
|
905b4d |
+ poptContext pc;
|
|
|
905b4d |
+ int debug_fd = -1;
|
|
|
905b4d |
+ errno_t ret;
|
|
|
905b4d |
+ TALLOC_CTX *main_ctx = NULL;
|
|
|
905b4d |
+ uint8_t *buf = NULL;
|
|
|
905b4d |
+ ssize_t len = 0;
|
|
|
905b4d |
+ struct input_buffer *ibuf = NULL;
|
|
|
905b4d |
+ struct response *resp = NULL;
|
|
|
905b4d |
+ size_t written;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ struct poptOption long_options[] = {
|
|
|
905b4d |
+ POPT_AUTOHELP
|
|
|
905b4d |
+ {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
|
|
|
905b4d |
+ _("Debug level"), NULL},
|
|
|
905b4d |
+ {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
|
|
|
905b4d |
+ _("Add debug timestamps"), NULL},
|
|
|
905b4d |
+ {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
|
|
|
905b4d |
+ _("Show timestamps with microseconds"), NULL},
|
|
|
905b4d |
+ {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
|
|
|
905b4d |
+ _("An open file descriptor for the debug logs"), NULL},
|
|
|
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 |
+ POPT_TABLEEND
|
|
|
905b4d |
+ };
|
|
|
905b4d |
+
|
|
|
905b4d |
+ /* Set debug level to invalid value so we can decide if -d 0 was used. */
|
|
|
905b4d |
+ debug_level = SSSDBG_INVALID;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
|
|
|
905b4d |
+ while((opt = poptGetNextOpt(pc)) != -1) {
|
|
|
905b4d |
+ switch(opt) {
|
|
|
905b4d |
+ default:
|
|
|
905b4d |
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
|
|
|
905b4d |
+ poptBadOption(pc, 0), poptStrerror(opt));
|
|
|
905b4d |
+ poptPrintUsage(pc, stderr, 0);
|
|
|
905b4d |
+ _exit(-1);
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ poptFreeContext(pc);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG_INIT(debug_level);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ debug_prg_name = talloc_asprintf(NULL, "[sssd[selinux_child[%d]]]", getpid());
|
|
|
905b4d |
+ if (debug_prg_name == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (debug_fd != -1) {
|
|
|
905b4d |
+ ret = set_debug_file_from_fd(debug_fd);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_FUNC, "selinux_child started.\n");
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
905b4d |
+ "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
|
|
|
905b4d |
+
|
|
|
905b4d |
+ main_ctx = talloc_new(NULL);
|
|
|
905b4d |
+ if (main_ctx == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
|
|
|
905b4d |
+ talloc_free(discard_const(debug_prg_name));
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+ talloc_steal(main_ctx, debug_prg_name);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE);
|
|
|
905b4d |
+ if (buf == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ibuf = talloc_zero(main_ctx, struct input_buffer);
|
|
|
905b4d |
+ if (ibuf == NULL) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_FUNC, "context initialized\n");
|
|
|
905b4d |
+
|
|
|
905b4d |
+ errno = 0;
|
|
|
905b4d |
+ len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE);
|
|
|
905b4d |
+ if (len == -1) {
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret));
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ close(STDIN_FILENO);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = unpack_buffer(buf, len, ibuf);
|
|
|
905b4d |
+ if (ret != EOK) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
905b4d |
+ "unpack_buffer failed.[%d][%s].\n", ret, strerror(ret));
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ ret = prepare_response(main_ctx, ret, &resp);
|
|
|
905b4d |
+
|
|
|
905b4d |
+ errno = 0;
|
|
|
905b4d |
+
|
|
|
905b4d |
+ written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size);
|
|
|
905b4d |
+ if (written == -1) {
|
|
|
905b4d |
+ ret = errno;
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret,
|
|
|
905b4d |
+ strerror(ret));
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ if (written != resp->size) {
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Expected to write %zu bytes, wrote %zu\n",
|
|
|
905b4d |
+ resp->size, written);
|
|
|
905b4d |
+ goto fail;
|
|
|
905b4d |
+ }
|
|
|
905b4d |
+
|
|
|
905b4d |
+ DEBUG(SSSDBG_TRACE_FUNC, "selinux_child completed successfully\n");
|
|
|
905b4d |
+ close(STDOUT_FILENO);
|
|
|
905b4d |
+ talloc_free(main_ctx);
|
|
|
905b4d |
+ return EXIT_SUCCESS;
|
|
|
905b4d |
+fail:
|
|
|
905b4d |
+ DEBUG(SSSDBG_CRIT_FAILURE, "selinux_child failed!\n");
|
|
|
905b4d |
+ close(STDOUT_FILENO);
|
|
|
905b4d |
+ talloc_free(main_ctx);
|
|
|
905b4d |
+ return EXIT_FAILURE;
|
|
|
905b4d |
+}
|
|
|
905b4d |
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
|
|
|
905b4d |
index 5b36780ffcdc6733241cdb942865ecdf38da3bca..d5da64622eebe7f779816c7f2090da5b9a9b13f0 100644
|
|
|
905b4d |
--- a/src/util/util_errors.c
|
|
|
905b4d |
+++ b/src/util/util_errors.c
|
|
|
905b4d |
@@ -62,6 +62,7 @@ struct err_string error_to_str[] = {
|
|
|
905b4d |
{ "Bus method not supported" }, /* ERR_SBUS_NOSUP */
|
|
|
905b4d |
{ "Cannot connect to system bus" }, /* ERR_NO_SYSBUS */
|
|
|
905b4d |
{ "LDAP search returned a referral" }, /* ERR_REFERRAL */
|
|
|
905b4d |
+ { "Error setting SELinux user context" }, /* ERR_SELINUX_CONTEXT */
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
|
|
|
905b4d |
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
|
|
|
905b4d |
index e040ba903b27d06ec75cea31485d2f3111ca5302..2bc576605e613d674d38b54aae1604c0b044635f 100644
|
|
|
905b4d |
--- a/src/util/util_errors.h
|
|
|
905b4d |
+++ b/src/util/util_errors.h
|
|
|
905b4d |
@@ -84,6 +84,7 @@ enum sssd_errors {
|
|
|
905b4d |
ERR_SBUS_NOSUP,
|
|
|
905b4d |
ERR_NO_SYSBUS,
|
|
|
905b4d |
ERR_REFERRAL,
|
|
|
905b4d |
+ ERR_SELINUX_CONTEXT,
|
|
|
905b4d |
ERR_LAST /* ALWAYS LAST */
|
|
|
905b4d |
};
|
|
|
905b4d |
|
|
|
905b4d |
--
|
|
|
905b4d |
1.9.3
|
|
|
905b4d |
|