summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--src/util/sss_selinux.c187
-rw-r--r--src/util/sss_selinux.h45
3 files changed, 235 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index b3d8e90b9..2ac3b1c39 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -308,6 +308,7 @@ dist_noinst_HEADERS = \
src/util/sss_ldap.h \
src/util/sss_python.h \
src/util/sss_krb5.h \
+ src/util/sss_selinux.h \
src/util/sss_utf8.h \
src/util/refcount.h \
src/util/find_uid.h \
@@ -414,7 +415,8 @@ libsss_util_la_SOURCES = \
src/util/refcount.c \
src/util/sss_utf8.c \
src/util/sss_tc_utf8.c \
- src/util/murmurhash3.c
+ src/util/murmurhash3.c \
+ src/util/sss_selinux.c
libsss_util_la_LIBADD = \
$(SSSD_LIBS) \
$(UNICODE_LIBS) \
diff --git a/src/util/sss_selinux.c b/src/util/sss_selinux.c
new file mode 100644
index 000000000..bdb117951
--- /dev/null
+++ b/src/util/sss_selinux.c
@@ -0,0 +1,187 @@
+/*
+ SSSD
+
+ SELinux-related utility functions
+
+ Authors:
+ Jan Zeleny <jzeleny@redhat.com>
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/sss_selinux.h"
+#include "util/sss_utf8.h"
+#include "db/sysdb_selinux.h"
+
+static bool match_entity(struct ldb_message_element *values,
+ struct ldb_message_element *sought_values)
+{
+ int i, j;
+
+ for (i = 0; i < values->num_values; i++) {
+ for (j = 0; j < sought_values->num_values; j++) {
+ if (values->values[i].length != sought_values->values[j].length) {
+ continue;
+ }
+
+ if (strncasecmp((char *)values->values[i].data,
+ (char *)sought_values->values[j].data,
+ values->values[i].length) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool sss_selinux_match(struct sysdb_attrs *usermap,
+ struct sysdb_attrs *user,
+ struct sysdb_attrs *host)
+{
+ struct ldb_message_element *users_el = NULL;
+ struct ldb_message_element *usercat = NULL;
+ struct ldb_message_element *hosts_el = NULL;
+ struct ldb_message_element *hostcat = NULL;
+ struct ldb_message_element *dn;
+ struct ldb_message_element *memberof;
+ int i;
+ errno_t ret;
+
+ if (usermap == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("NULL given as usermap! Skipping ...\n"));
+ return false;
+ }
+
+ /* Search for user and host related elements */
+ for (i = 0; i < usermap->num; i++) {
+ if (!strcasecmp(usermap->a[i].name, SYSDB_ORIG_MEMBER_USER)) {
+ users_el = &usermap->a[i];
+ } else if (!strcasecmp(usermap->a[i].name, SYSDB_ORIG_MEMBER_HOST)) {
+ hosts_el = &usermap->a[i];
+ } else if (!strcasecmp(usermap->a[i].name, SYSDB_USER_CATEGORY)) {
+ usercat = &usermap->a[i];
+ } else if (!strcasecmp(usermap->a[i].name, SYSDB_HOST_CATEGORY)) {
+ hostcat = &usermap->a[i];
+ }
+ }
+
+ if (user) {
+ ret = sysdb_attrs_get_el(user, SYSDB_ORIG_DN, &dn);
+ if (ret != EOK) return false;
+ ret = sysdb_attrs_get_el(user, SYSDB_ORIG_MEMBEROF, &memberof);
+ if (ret != EOK) return false;
+
+ /**
+ * The rule won't match if user category != "all" and user map doesn't
+ * contain neither user nor any of his groups in memberUser attribute
+ */
+ if (usercat == NULL || usercat->num_values == 0 ||
+ strcasecmp((char *)usercat->values[0].data, "all") != 0) {
+ if (users_el == NULL || (!match_entity(users_el, dn) &&
+ !match_entity(users_el, memberof))) {
+ return false;
+ }
+ }
+ }
+
+ if (host) {
+ ret = sysdb_attrs_get_el(host, SYSDB_ORIG_DN, &dn);
+ if (ret != EOK) return false;
+ ret = sysdb_attrs_get_el(host, SYSDB_ORIG_MEMBEROF, &memberof);
+ if (ret != EOK) return false;
+
+ /**
+ * The rule won't match if host category != "all" and user map doesn't
+ * contain neither host nor any of its groups in memberHost attribute
+ */
+ if (hostcat == NULL || hostcat->num_values == 0 ||
+ strcasecmp((char *)hostcat->values[0].data, "all") != 0) {
+ if (hosts_el == NULL || (!match_entity(hosts_el, dn) &&
+ !match_entity(hosts_el, memberof))) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+errno_t sss_selinux_extract_user(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *username,
+ struct sysdb_attrs **_user_attrs)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char **attrs;
+ struct sysdb_attrs *user_attrs;
+ struct ldb_message *user_msg;
+
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ attrs = talloc_array(tmp_ctx, const char *, 3);
+ if (attrs == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_array failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ attrs[0] = SYSDB_ORIG_DN;
+ attrs[1] = SYSDB_ORIG_MEMBEROF;
+ attrs[2] = NULL;
+
+ ret = sysdb_search_user_by_name(tmp_ctx, sysdb, username,
+ attrs, &user_msg);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_search_user_by_name failed.\n"));
+ goto done;
+ }
+
+ user_attrs = talloc_zero(tmp_ctx, struct sysdb_attrs);
+ if (user_attrs == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ user_attrs->a = talloc_steal(user_attrs, user_msg->elements);
+ user_attrs->num = user_msg->num_elements;
+
+ *_user_attrs = talloc_steal(mem_ctx, user_attrs);
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+const char *sss_selinux_map_get_seuser(struct ldb_message *usermap)
+{
+ int i;
+ const uint8_t *name;
+ const uint8_t *template = (const uint8_t *)SYSDB_SELINUX_USER;
+
+ for (i = 0; i < usermap->num_elements; i++) {
+ name = (const uint8_t *)usermap->elements[i].name;
+ if (sss_utf8_case_eq(name, template) == 0) {
+ return (const char *)usermap->elements[i].values[0].data;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/util/sss_selinux.h b/src/util/sss_selinux.h
new file mode 100644
index 000000000..11a5445e6
--- /dev/null
+++ b/src/util/sss_selinux.h
@@ -0,0 +1,45 @@
+/*
+ SSSD
+
+ SELinux-related utility functions
+
+ Authors:
+ Jan Zeleny <jzeleny@redhat.com>
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SSS_SELINUX_H_
+#define SSS_SELINUX_H_
+
+#include <talloc.h>
+#include <errno.h>
+
+#include <db/sysdb.h>
+
+errno_t
+sss_selinux_extract_user(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *username,
+ struct sysdb_attrs **_user_attrs);
+
+bool sss_selinux_match(struct sysdb_attrs *usermap,
+ struct sysdb_attrs *user,
+ struct sysdb_attrs *host);
+
+const char *sss_selinux_map_get_seuser(struct ldb_message *usermap);
+
+#endif /* SSS_SELINUX_H_ */