diff options
author | Jan Zeleny <jzeleny@redhat.com> | 2012-01-24 06:21:59 -0500 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-02-06 08:25:22 -0500 |
commit | 823a5b3f4375f12b6edae4dd5169ee01771baebe (patch) | |
tree | 4c7e3a7f852ca88ad179169e2599fc0cfd026c4e /src/util | |
parent | 9674f0f018c65a9af6b18dd0a4e515f726803d27 (diff) | |
download | sssd-823a5b3f4375f12b6edae4dd5169ee01771baebe.tar.gz sssd-823a5b3f4375f12b6edae4dd5169ee01771baebe.tar.bz2 sssd-823a5b3f4375f12b6edae4dd5169ee01771baebe.zip |
Added some SELinux-related utility functions
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/sss_selinux.c | 187 | ||||
-rw-r--r-- | src/util/sss_selinux.h | 45 |
2 files changed, 232 insertions, 0 deletions
diff --git a/src/util/sss_selinux.c b/src/util/sss_selinux.c new file mode 100644 index 00000000..bdb11795 --- /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 00000000..11a5445e --- /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_ */ |