From 823a5b3f4375f12b6edae4dd5169ee01771baebe Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Tue, 24 Jan 2012 06:21:59 -0500 Subject: 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 deletion(-) 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 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 + + 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 . +*/ + +#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 + + 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 . +*/ + +#ifndef SSS_SELINUX_H_ +#define SSS_SELINUX_H_ + +#include +#include + +#include + +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_ */ -- cgit