summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--src/db/sysdb.h9
-rw-r--r--src/db/sysdb_selinux.c471
-rw-r--r--src/db/sysdb_selinux.h66
4 files changed, 547 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 2ac3b1c39..90b6d8139 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -333,6 +333,7 @@ dist_noinst_HEADERS = \
src/db/sysdb.h \
src/db/sysdb_sudo.h \
src/db/sysdb_autofs.h \
+ src/db/sysdb_selinux.h \
src/db/sysdb_private.h \
src/db/sysdb_services.h \
src/confdb/confdb.h \
@@ -393,6 +394,7 @@ libsss_util_la_SOURCES = \
src/db/sysdb.c \
src/db/sysdb_ops.c \
src/db/sysdb_search.c \
+ src/db/sysdb_selinux.c \
src/db/sysdb_upgrade.c \
src/db/sysdb_services.c \
src/db/sysdb_autofs.c \
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 698dc46d3..a74c9d431 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -45,6 +45,8 @@
#define SYSDB_GROUP_CLASS "group"
#define SYSDB_NETGROUP_CLASS "netgroup"
#define SYSDB_HOST_CLASS "host"
+#define SYSDB_SELINUX_USERMAP_CLASS "selinuxusermap"
+#define SYSDB_SELINUX_CLASS "selinux"
#define SYSDB_NAME "name"
#define SYSDB_NAME_ALIAS "nameAlias"
@@ -65,6 +67,8 @@
#define SYSDB_MEMBER "member"
#define SYSDB_MEMBERUID "memberUid"
#define SYSDB_POSIX "isPosix"
+#define SYSDB_USER_CATEGORY "userCategory"
+#define SYSDB_HOST_CATEGORY "hostCategory"
#define SYSDB_DEFAULTGROUP "defaultGroup"
#define SYSDB_GECOS "gecos"
@@ -91,6 +95,10 @@
#define SYSDB_NETGROUP_MEMBER "memberNisNetgroup"
#define SYSDB_DESCRIPTION "description"
+#define SYSDB_SELINUX_SEEALSO "seeAlso"
+#define SYSDB_SELINUX_USER "selinuxUser"
+#define SYSDB_SELINUX_ENABLED "enabled"
+
#define SYSDB_CACHEDPWD "cachedPassword"
#define SYSDB_UUID "uniqueID"
@@ -100,7 +108,6 @@
#define SYSDB_ORIG_DN "originalDN"
#define SYSDB_ORIG_MODSTAMP "originalModifyTimestamp"
#define SYSDB_ORIG_MEMBEROF "originalMemberOf"
-
#define SYSDB_ORIG_MEMBER_USER "originalMemberUser"
#define SYSDB_ORIG_MEMBER_HOST "originalMemberHost"
diff --git a/src/db/sysdb_selinux.c b/src/db/sysdb_selinux.c
new file mode 100644
index 000000000..5df5fe0e3
--- /dev/null
+++ b/src/db/sysdb_selinux.c
@@ -0,0 +1,471 @@
+/*
+ SSSD
+
+ System Database - SELinux support
+
+ Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2012
+
+ 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 "db/sysdb_selinux.h"
+#include "db/sysdb_private.h"
+
+/* Some generic routines */
+static errno_t get_rm_msg(TALLOC_CTX *mem_ctx,
+ struct ldb_message *old_msg,
+ struct sysdb_attrs *new_attrs,
+ struct ldb_message **_msg)
+{
+ struct ldb_message *rm_msg;
+ const char *tmp_str;
+ errno_t ret;
+ int i;
+
+ rm_msg = ldb_msg_new(mem_ctx);
+ if (rm_msg == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ rm_msg->dn = old_msg->dn;
+ rm_msg->elements = talloc_zero_array(rm_msg, struct ldb_message_element,
+ old_msg->num_elements);
+ rm_msg->num_elements = 0;
+
+ for (i = 0; i < old_msg->num_elements; i++) {
+ ret = sysdb_attrs_get_string(new_attrs, old_msg->elements[i].name, &tmp_str);
+ if (ret != ENOENT) {
+ continue;
+ }
+
+ rm_msg->elements[rm_msg->num_elements] = old_msg->elements[i];
+ rm_msg->elements[rm_msg->num_elements].flags = LDB_FLAG_MOD_DELETE;
+ rm_msg->num_elements++;
+ }
+
+done:
+ if (ret != EOK) {
+ talloc_free(rm_msg);
+ } else {
+ *_msg = rm_msg;
+ }
+
+ return ret;
+}
+
+static errno_t
+sysdb_add_selinux_entity(struct sysdb_ctx *sysdb,
+ struct ldb_dn *dn,
+ const char *objectclass,
+ struct sysdb_attrs *attrs,
+ time_t now)
+{
+ struct ldb_message *msg;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, objectclass);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not set map object class [%d]: %s\n",
+ ret, strerror(ret)));
+ return ret;
+ }
+
+ if (!now) {
+ now = time(NULL);
+ }
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_CREATE_TIME, now);
+ if (ret) goto done;
+
+ msg->dn = dn;
+ msg->elements = attrs->a;
+ msg->num_elements = attrs->num;
+
+ ret = ldb_add(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(ret);
+
+done:
+ if (ret) {
+ DEBUG(SSSDBG_TRACE_LIBS, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+static errno_t sysdb_store_selinux_entity(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs,
+ enum selinux_entity_type type)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message *msg;
+ struct ldb_message *rm_msg;
+ bool in_transaction = false;
+ const char *objectclass;
+ const char *name;
+ char *clean_name;
+ struct ldb_dn *dn;
+ errno_t sret = EOK;
+ errno_t ret;
+ time_t now;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ switch (type) {
+ case SELINUX_USER_MAP:
+ objectclass = SYSDB_SELINUX_USERMAP_CLASS;
+ ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_dn_sanitize(tmp_ctx, name, &clean_name);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SEUSERMAP,
+ clean_name, sysdb->domain->name);
+ break;
+ case SELINUX_CONFIG:
+ objectclass = SYSDB_SELINUX_CLASS;
+ dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SELINUX_BASE,
+ sysdb->domain->name);
+ break;
+ }
+
+ if (type != SELINUX_CONFIG && type != SELINUX_USER_MAP) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Bad SELinux entity type: [%d]\n", type));
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (!dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_transaction_start(sysdb);
+ if (ret != EOK) goto done;
+
+ in_transaction = true;
+
+ now = time(NULL);
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
+ if (ret) goto done;
+
+ if (type == SELINUX_CONFIG) {
+ ret = sysdb_search_selinux_config(tmp_ctx, sysdb, NULL, &msg);
+ } else if (type == SELINUX_USER_MAP) {
+ ret = sysdb_search_selinux_usermap_by_mapname(tmp_ctx, sysdb, name,
+ NULL, &msg);
+ }
+
+ if (ret && ret != ENOENT) {
+ goto done;
+ }
+ if (ret == ENOENT) {
+ ret = sysdb_add_selinux_entity(sysdb, dn, objectclass, attrs, now);
+ goto done;
+ }
+
+ ret = sysdb_set_entry_attr(sysdb, dn, attrs, SYSDB_MOD_REP);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Now delete attributes which are no longer present */
+ ret = get_rm_msg(tmp_ctx, msg, attrs, &rm_msg);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (rm_msg->num_elements > 0) {
+ ret = ldb_modify(sysdb->ldb, rm_msg);
+ }
+
+done:
+ if (in_transaction) {
+ if (ret == EOK) {
+ sret = sysdb_transaction_commit(sysdb);
+ if (sret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not commit transaction\n"));
+ }
+ }
+
+ if (ret != EOK || sret != EOK){
+ sret = sysdb_transaction_cancel(sysdb);
+ if (sret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not cancel transaction\n"));
+ }
+ }
+ }
+ if (ret) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_store_selinux_usermap(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs)
+{
+ return sysdb_store_selinux_entity(sysdb, attrs, SELINUX_USER_MAP);
+}
+
+errno_t sysdb_store_selinux_config(struct sysdb_ctx *sysdb,
+ const char *default_user,
+ const char *order)
+{
+ errno_t ret;
+ struct sysdb_attrs *attrs;
+
+ attrs = talloc_zero(NULL, struct sysdb_attrs);
+ if (attrs == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_USER,
+ default_user);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_ORDER,
+ order);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_store_selinux_entity(sysdb, attrs, SELINUX_CONFIG);
+done:
+ talloc_free(attrs);
+ return ret;
+}
+
+
+
+/* --- SYSDB SELinux search routines --- */
+errno_t sysdb_search_selinux_usermap_by_mapname(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ const char **attrs,
+ struct ldb_message **_usermap)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *def_attrs[] = { SYSDB_NAME,
+ SYSDB_USER_CATEGORY,
+ SYSDB_HOST_CATEGORY,
+ SYSDB_ORIG_MEMBER_USER,
+ SYSDB_ORIG_MEMBER_HOST,
+ SYSDB_SELINUX_USER,
+ NULL };
+ struct ldb_message **msgs = NULL;
+ struct ldb_dn *basedn;
+ size_t msgs_count = 0;
+ char *clean_name;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_dn_sanitize(tmp_ctx, name, &clean_name);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SEUSERMAP,
+ clean_name, sysdb->domain->name);
+ if (!basedn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
+ attrs?attrs:def_attrs, &msgs_count, &msgs);
+ if (ret) {
+ goto done;
+ }
+
+ *_usermap = talloc_steal(mem_ctx, msgs[0]);
+
+done:
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
+ }
+ else if (ret) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_search_selinux_usermap_by_username(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *username,
+ struct ldb_message ***_usermaps)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = { SYSDB_NAME,
+ SYSDB_USER_CATEGORY,
+ SYSDB_HOST_CATEGORY,
+ SYSDB_ORIG_MEMBER_USER,
+ SYSDB_ORIG_MEMBER_HOST,
+ SYSDB_SELINUX_USER,
+ NULL };
+ struct ldb_message **msgs = NULL;
+ struct sysdb_attrs *user;
+ struct sysdb_attrs *tmp_attrs;
+ struct ldb_message **usermaps;
+ struct sss_domain_info *domain;
+ struct ldb_dn *basedn;
+ size_t msgs_count = 0;
+ size_t usermaps_cnt;
+ char *filter;
+ errno_t ret;
+ int i;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ /* Now extract user attributes */
+ ret = sss_selinux_extract_user(tmp_ctx, sysdb, username, &user);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Now extract all SELinux user maps */
+ domain = sysdb_ctx_get_domain(sysdb);
+ basedn = ldb_dn_new_fmt(tmp_ctx, sysdb_ctx_get_ldb(sysdb),
+ SYSDB_TMPL_SELINUX_BASE, domain->name);
+ if (!basedn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ filter = talloc_asprintf(tmp_ctx, "(objectclass=%s)", SYSDB_SELINUX_USERMAP_CLASS);
+ if (filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
+ attrs, &msgs_count, &msgs);
+ if (ret) {
+ goto done;
+ }
+
+ /* Now filter those that match */
+ tmp_attrs = talloc_zero(tmp_ctx, struct sysdb_attrs);
+ if (tmp_attrs == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ usermaps = talloc_zero_array(tmp_ctx, struct ldb_message *, msgs_count + 1);
+ if (usermaps == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ usermaps_cnt = 0;
+ for (i = 0; i < msgs_count; i++) {
+ tmp_attrs->a = msgs[i]->elements;
+ tmp_attrs->num = msgs[i]->num_elements;
+
+ if (sss_selinux_match(tmp_attrs, user, NULL)) {
+ usermaps[usermaps_cnt] = talloc_steal(usermaps, msgs[i]);
+ usermaps_cnt++;
+ } else {
+ talloc_zfree(msgs[i]);
+ }
+ }
+
+ if (usermaps[0] == NULL) {
+ ret = ENOENT;
+ goto done;
+ }
+
+ *_usermaps = talloc_steal(mem_ctx, usermaps);
+
+done:
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_search_selinux_config(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char **attrs,
+ struct ldb_message **_config)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *def_attrs[] = { SYSDB_SELINUX_DEFAULT_USER,
+ SYSDB_SELINUX_DEFAULT_ORDER,
+ NULL };
+ struct ldb_message **msgs;
+ size_t msgs_count;
+ struct ldb_dn *basedn;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SELINUX_BASE,
+ sysdb->domain->name);
+ if (!basedn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
+ attrs?attrs:def_attrs, &msgs_count, &msgs);
+ if (ret) {
+ goto done;
+ }
+
+ *_config = talloc_steal(mem_ctx, msgs[0]);
+
+done:
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No SELinux root entry found\n"));
+ } else if (ret) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
diff --git a/src/db/sysdb_selinux.h b/src/db/sysdb_selinux.h
new file mode 100644
index 000000000..7a0229236
--- /dev/null
+++ b/src/db/sysdb_selinux.h
@@ -0,0 +1,66 @@
+/*
+ SSSD
+
+ System Database Header - SELinux support
+
+ Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2012
+
+ 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 __SYS_DB_SELINUX_H__
+#define __SYS_DB_SELINUX_H__
+
+#include "db/sysdb.h"
+
+#define SYSDB_SELINUX_CONTAINER "cn=selinux"
+#define SYSDB_TMPL_SELINUX_BASE SYSDB_SELINUX_CONTAINER",cn=%s,"SYSDB_BASE
+#define SYSDB_TMPL_SEUSERMAP SYSDB_NAME"=%s,"SYSDB_TMPL_SELINUX_BASE
+
+#define SYSDB_SELINUX_NAME "config"
+#define SYSDB_SELINUX_SEEALSO "seeAlso"
+#define SYSDB_SELINUX_USER "selinuxUser"
+#define SYSDB_SELINUX_ENABLED "enabled"
+#define SYSDB_SELINUX_DEFAULT_USER "user"
+#define SYSDB_SELINUX_DEFAULT_ORDER "order"
+
+enum selinux_entity_type {
+ SELINUX_CONFIG,
+ SELINUX_USER_MAP
+};
+
+errno_t sysdb_store_selinux_usermap(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs);
+
+errno_t sysdb_store_selinux_config(struct sysdb_ctx *sysdb,
+ const char *default_map,
+ const char *order);
+
+errno_t sysdb_search_selinux_usermap_by_mapname(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *name,
+ const char **attrs,
+ struct ldb_message **_usermap);
+
+errno_t sysdb_search_selinux_usermap_by_username(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *username,
+ struct ldb_message ***_usermaps);
+
+errno_t sysdb_search_selinux_config(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char **attrs,
+ struct ldb_message **_config);
+
+#endif