summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2015-04-09 22:18:35 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-04-14 19:58:30 +0200
commit1e0fa55fb377db788e065de917ba8e149eb56161 (patch)
tree23135820ad4753a5588655d37d1a0fefbc3e6066
parent748b38a7991d78cbf4726f2a14ace5e926629a54 (diff)
downloadsssd-1e0fa55fb377db788e065de917ba8e149eb56161.tar.gz
sssd-1e0fa55fb377db788e065de917ba8e149eb56161.tar.xz
sssd-1e0fa55fb377db788e065de917ba8e149eb56161.zip
selinux: Only call semanage if the context actually changes
https://fedorahosted.org/sssd/ticket/2624 Add a function to query the libsemanage database for a user context and only update the database if the context differes from the one set on the server. Adds talloc dependency to libsss_semanage. Reviewed-by: Michal Židek <mzidek@redhat.com>
-rw-r--r--Makefile.am5
-rw-r--r--src/providers/ipa/selinux_child.c35
-rw-r--r--src/util/sss_semanage.c71
-rw-r--r--src/util/util.h2
4 files changed, 109 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index d9724093d..52fbd510d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -789,10 +789,15 @@ endif
libsss_util_la_LDFLAGS = -avoid-version
pkglib_LTLIBRARIES += libsss_semanage.la
+libsss_semanage_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(TALLOC_CFLAGS) \
+ $(NULL)
libsss_semanage_la_SOURCES = \
src/util/sss_semanage.c \
$(NULL)
libsss_semanage_la_LIBADD = \
+ $(TALLOC_LIBS) \
libsss_debug.la \
$(NULL)
if BUILD_SEMANAGE
diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
index 81c1de877..7c5731d66 100644
--- a/src/providers/ipa/selinux_child.c
+++ b/src/providers/ipa/selinux_child.c
@@ -165,6 +165,29 @@ static int sc_set_seuser(const char *login_name, const char *seuser_name,
return ret;
}
+static bool seuser_needs_update(struct input_buffer *ibuf)
+{
+ bool needs_update = true;
+ char *db_seuser = NULL;
+ char *db_mls_range = NULL;
+ errno_t ret;
+
+ ret = get_seuser(ibuf, ibuf->username, &db_seuser, &db_mls_range);
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "get_seuser: ret: %d seuser: %s mls: %s\n",
+ ret, db_seuser ? db_seuser : "unknown",
+ db_mls_range ? db_mls_range : "unknown");
+ if (ret == EOK && db_seuser && db_mls_range &&
+ strcmp(db_seuser, ibuf->seuser) == 0 &&
+ strcmp(db_mls_range, ibuf->mls_range) == 0) {
+ needs_update = false;
+ }
+
+ talloc_free(db_seuser);
+ talloc_free(db_mls_range);
+ return needs_update;
+}
+
int main(int argc, const char *argv[])
{
int opt;
@@ -177,6 +200,7 @@ int main(int argc, const char *argv[])
struct input_buffer *ibuf = NULL;
struct response *resp = NULL;
ssize_t written;
+ bool needs_update;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -296,10 +320,13 @@ int main(int argc, const char *argv[])
DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
- ret = sc_set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
- goto fail;
+ needs_update = seuser_needs_update(ibuf);
+ if (needs_update == true) {
+ ret = sc_set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
+ goto fail;
+ }
}
ret = prepare_response(main_ctx, ret, &resp);
diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
index c0342498c..01a2f41d8 100644
--- a/src/util/sss_semanage.c
+++ b/src/util/sss_semanage.c
@@ -369,6 +369,71 @@ done:
return ret;
}
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range)
+{
+ errno_t ret;
+ const char *seuser;
+ const char *mls_range;
+ semanage_handle_t *sm_handle = NULL;
+ semanage_seuser_t *sm_user = NULL;
+ semanage_seuser_key_t *sm_key = NULL;
+
+ sm_handle = sss_semanage_init();
+ if (sm_handle == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux handle\n");
+ ret = EIO;
+ goto done;
+ }
+
+ ret = semanage_seuser_key_create(sm_handle, login_name, &sm_key);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create key for %s\n", login_name);
+ ret = EIO;
+ goto done;
+ }
+
+ ret = semanage_seuser_query(sm_handle, sm_key, &sm_user);
+ if (ret < 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot query for %s\n", login_name);
+ ret = EIO;
+ goto done;
+ }
+
+ seuser = semanage_seuser_get_sename(sm_user);
+ if (seuser != NULL) {
+ *_seuser = talloc_strdup(mem_ctx, seuser);
+ if (*_seuser == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_OP_FAILURE,
+ "SELinux user for %s: %s\n", login_name, *_seuser);
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get sename for %s\n", login_name);
+ }
+
+ mls_range = semanage_seuser_get_mlsrange(sm_user);
+ if (mls_range != NULL) {
+ *_mls_range = talloc_strdup(mem_ctx, mls_range);
+ if (*_mls_range == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_OP_FAILURE,
+ "SELinux range for %s: %s\n", login_name, *_mls_range);
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get mlsrange for %s\n", login_name);
+ }
+
+ ret = EOK;
+done:
+ semanage_seuser_key_free(sm_key);
+ semanage_seuser_free(sm_user);
+ sss_semanage_close(sm_handle);
+ return ret;
+}
+
#else /* HAVE_SEMANAGE */
int set_seuser(const char *login_name, const char *seuser_name,
const char *mls)
@@ -380,4 +445,10 @@ int del_seuser(const char *login_name)
{
return EOK;
}
+
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range)
+{
+ return EOK;
+}
#endif /* HAVE_SEMANAGE */
diff --git a/src/util/util.h b/src/util/util.h
index d831d533f..c86bcea5b 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -655,6 +655,8 @@ errno_t restore_creds(struct sss_creds *saved_creds);
int set_seuser(const char *login_name, const char *seuser_name,
const char *mlsrange);
int del_seuser(const char *login_name);
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range);
/* convert time from generalized form to unix time */
errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *unix_time);