From 11ff8dce300b03ff5c5c005453c0550cd426782a Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Tue, 24 Jan 2012 06:21:59 -0500
Subject: [PATCH 06/13] Added some SELinux-related utility functions

---
 Makefile.am            |    4 +-
 src/util/sss_selinux.c |  187 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/sss_selinux.h |   45 ++++++++++++
 3 files changed, 235 insertions(+), 1 deletions(-)
 create mode 100644 src/util/sss_selinux.c
 create mode 100644 src/util/sss_selinux.h

diff --git a/Makefile.am b/Makefile.am
index eb3c4d897b1c011b4a9382f46a76fdef2c5beee6..acbb73d71728e8c9c612fc0b39f9e5fa625d537b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -303,6 +303,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 \
@@ -405,7 +406,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 0000000000000000000000000000000000000000..bdb117951adc9738d2a2bbf90602ea8db5b65ee3
--- /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 0000000000000000000000000000000000000000..11a5445e65bc1c65c88dec583aa1f0c90b7e6789
--- /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_ */
-- 
1.7.6.4

