ipa_hbac_common.c revision 95f5e7963a36b7b68859ce91ae4b232088bbaa09
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/*
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi SSSD
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi Authors:
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi Stephen Gallagher <sgallagh@redhat.com>
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi Copyright (C) 2011 Red Hat
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi This program is free software; you can redistribute it and/or modify
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi it under the terms of the GNU General Public License as published by
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi the Free Software Foundation; either version 3 of the License, or
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi (at your option) any later version.
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi This program is distributed in the hope that it will be useful,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi but WITHOUT ANY WARRANTY; without even the implied warranty of
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi GNU General Public License for more details.
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi You should have received a copy of the GNU General Public License
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi along with this program. If not, see <http://www.gnu.org/licenses/>.
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi*/
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "providers/ipa/ipa_hbac_private.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "providers/ipa/ipa_hbac.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "providers/ipa/ipa_common.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomierrno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomiipa_hbac_save_list(struct sysdb_ctx *sysdb, bool delete_subdir,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *subdir, struct sss_domain_info *domain,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *naming_attribute, size_t count,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct sysdb_attrs **list)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi int ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t c;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct ldb_dn *base_dn;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *object_name;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct ldb_message_element *el;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi TALLOC_CTX *tmp_ctx;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi tmp_ctx = talloc_new(NULL);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (tmp_ctx == NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("talloc_new failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (delete_subdir) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi base_dn = sysdb_custom_subtree_dn(sysdb, tmp_ctx, subdir);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (base_dn == NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_delete_recursive(sysdb, base_dn, true);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("sysdb_delete_recursive failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi for (c = 0; c < count; c++) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_attrs_get_el(list[c], naming_attribute, &el);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (el->num_values == 0) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("[%s] not found.\n", naming_attribute));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = EINVAL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi object_name = talloc_strndup(tmp_ctx, (const char *)el->values[0].data,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi el->values[0].length);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (object_name == NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("talloc_strndup failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(9, ("Object name: [%s].\n", object_name));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_store_custom(sysdb, object_name, subdir, list[c]);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("sysdb_store_custom failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = EOK;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomidone:
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi talloc_free(tmp_ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomierrno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomiipa_hbac_sysdb_save(struct sysdb_ctx *sysdb, struct sss_domain_info *domain,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *primary_subdir, const char *attr_name,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t primary_count, struct sysdb_attrs **primary,
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek const char *group_subdir, const char *groupattr_name,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t group_count, struct sysdb_attrs **groups)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi errno_t ret, sret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi bool in_transaction = false;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if ((primary_count == 0 || primary == NULL)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi || (group_count > 0 && groups == NULL)) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* There always has to be at least one
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi * primary entry.
84b746f56209d4a85af73cd26850e75f519ae0b0Timo Sirainen */
84b746f56209d4a85af73cd26850e75f519ae0b0Timo Sirainen return EINVAL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* Save the entries and groups to the cache */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_transaction_start(sysdb);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi };
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi in_transaction = true;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* First, save the specific entries */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = ipa_hbac_save_list(sysdb, true,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi primary_subdir,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi domain,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi attr_name,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi primary_count,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi primary);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("Could not save %s. [%d][%s]\n",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi primary_subdir, ret, strerror(ret)));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* Second, save the groups */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (group_count > 0) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = ipa_hbac_save_list(sysdb, true,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi group_subdir,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi domain,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi groupattr_name,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi group_count,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi groups);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("Could not save %s. [%d][%s]\n",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi group_subdir, ret, strerror(ret)));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_transaction_commit(sysdb);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi in_transaction = false;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomidone:
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (in_transaction) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi sret = sysdb_transaction_cancel(sysdb);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (sret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(0, ("Could not cancel sysdb transaction\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(3, ("Error [%d][%s]\n", ret, strerror(ret)));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomierrno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomireplace_attribute_name(const char *old_name,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *new_name, const size_t count,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct sysdb_attrs **list)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi int ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi int i;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi for (i = 0; i < count; i++) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_attrs_replace_name(list[i], old_name, new_name);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("sysdb_attrs_replace_name failed.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return EOK;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic errno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomicreate_empty_grouplist(struct hbac_request_element *el)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi el->groups = talloc_array(el, const char *, 1);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!el->groups) return ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi el->groups[0] = NULL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return EOK;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi/********************************************
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi * Functions for handling conversion to the *
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi * HBAC evaluator format *
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ********************************************/
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic errno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomihbac_attrs_to_rule(TALLOC_CTX *mem_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_ctx *hbac_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t index,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_rule **rule);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic errno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomihbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_ctx *hbac_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_eval_req **request);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomierrno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomihbac_ctx_to_rules(TALLOC_CTX *mem_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_ctx *hbac_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_rule ***rules,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_eval_req **request)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi errno_t ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_rule **new_rules;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_eval_req *new_request;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t i;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi TALLOC_CTX *tmp_ctx = NULL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!rules || !request) return EINVAL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi tmp_ctx = talloc_new(mem_ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (tmp_ctx == NULL) return ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* First create an array of rules */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi new_rules = talloc_array(tmp_ctx, struct hbac_rule *,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi hbac_ctx->rule_count + 1);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (new_rules == NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* Create each rule one at a time */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi for (i = 0; i < hbac_ctx->rule_count ; i++) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = hbac_attrs_to_rule(new_rules, hbac_ctx, i, &(new_rules[i]));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret == EPERM) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi } else if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("Could not construct rules\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi new_rules[i] = NULL;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* Create the eval request */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = hbac_ctx_to_eval_request(tmp_ctx, hbac_ctx, &new_request);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(1, ("Could not construct eval request\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi goto done;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi *rules = talloc_steal(mem_ctx, new_rules);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi *request = talloc_steal(mem_ctx, new_request);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = EOK;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomidone:
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi talloc_free(tmp_ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic errno_t
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomihbac_attrs_to_rule(TALLOC_CTX *mem_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_ctx *hbac_ctx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi size_t idx,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_rule **rule)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi errno_t ret;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct hbac_rule *new_rule;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi struct ldb_message_element *el;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *rule_type;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi new_rule = talloc_zero(mem_ctx, struct hbac_rule);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (new_rule == NULL) return ENOMEM;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ret = sysdb_attrs_get_el(hbac_ctx->rules[idx],
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IPA_CN, &el);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ret != EOK || el->num_values == 0) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi DEBUG(4, ("rule has no name, assuming '(none)'.\n"));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi new_rule->name = talloc_strdup(new_rule, "(none)");
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi } else {
new_rule->name = talloc_strndup(new_rule,
(const char*) el->values[0].data,
el->values[0].length);
}
DEBUG(7, ("Processing rule [%s]\n", new_rule->name));
ret = sysdb_attrs_get_bool(hbac_ctx->rules[idx], IPA_ENABLED_FLAG,
&new_rule->enabled);
if (ret != EOK) goto done;
if (!new_rule->enabled) {
ret = EOK;
goto done;
}
ret = sysdb_attrs_get_string(hbac_ctx->rules[idx],
IPA_ACCESS_RULE_TYPE,
&rule_type);
if (ret != EOK) goto done;
if (strcasecmp(rule_type, IPA_HBAC_ALLOW) != 0) {
DEBUG(7, ("Rule [%s] is not an ALLOW rule\n", new_rule->name));
ret = EPERM;
goto done;
}
/* Get the users */
ret = hbac_user_attrs_to_rule(new_rule,
hbac_ctx_sysdb(hbac_ctx),
new_rule->name,
hbac_ctx->rules[idx],
&new_rule->users);
if (ret != EOK) {
DEBUG(1, ("Could not parse users for rule [%s]\n",
new_rule->name));
goto done;
}
/* Get the services */
ret = hbac_service_attrs_to_rule(new_rule,
hbac_ctx_sysdb(hbac_ctx),
new_rule->name,
hbac_ctx->rules[idx],
&new_rule->services);
if (ret != EOK) {
DEBUG(1, ("Could not parse services for rule [%s]\n",
new_rule->name));
goto done;
}
/* Get the target hosts */
ret = hbac_thost_attrs_to_rule(new_rule,
hbac_ctx_sysdb(hbac_ctx),
new_rule->name,
hbac_ctx->rules[idx],
&new_rule->targethosts);
if (ret != EOK) {
DEBUG(1, ("Could not parse target hosts for rule [%s]\n",
new_rule->name));
goto done;
}
/* Get the source hosts */
ret = hbac_shost_attrs_to_rule(new_rule,
hbac_ctx_sysdb(hbac_ctx),
new_rule->name,
hbac_ctx->rules[idx],
dp_opt_get_bool(hbac_ctx->ipa_options,
IPA_HBAC_SUPPORT_SRCHOST),
&new_rule->srchosts);
if (ret != EOK) {
DEBUG(1, ("Could not parse source hosts for rule [%s]\n",
new_rule->name));
goto done;
}
*rule = new_rule;
ret = EOK;
done:
if (ret != EOK) talloc_free(new_rule);
return ret;
}
errno_t
hbac_get_category(struct sysdb_attrs *attrs,
const char *category_attr,
uint32_t *_categories)
{
errno_t ret;
size_t i;
uint32_t cats = HBAC_CATEGORY_NULL;
const char **categories;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) return ENOMEM;
ret = sysdb_attrs_get_string_array(attrs, category_attr,
tmp_ctx, &categories);
if (ret != EOK && ret != ENOENT) goto done;
if (ret != ENOENT) {
for (i = 0; categories[i]; i++) {
if (strcasecmp("all", categories[i]) == 0) {
DEBUG(5, ("Category is set to 'all'.\n"));
cats |= HBAC_CATEGORY_ALL;
continue;
}
DEBUG(9, ("Unsupported user category [%s].\n",
categories[i]));
}
}
*_categories = cats;
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
static errno_t
hbac_eval_user_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
const char *username,
struct hbac_request_element **user_element);
static errno_t
hbac_eval_service_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char *servicename,
struct hbac_request_element **svc_element);
static errno_t
hbac_eval_host_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char *hostname,
struct hbac_request_element **host_element);
static errno_t
hbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
struct hbac_ctx *hbac_ctx,
struct hbac_eval_req **request)
{
errno_t ret;
struct pam_data *pd = hbac_ctx->pd;
TALLOC_CTX *tmp_ctx;
struct hbac_eval_req *eval_req;
struct sysdb_ctx *sysdb = hbac_ctx_sysdb(hbac_ctx);
struct sss_domain_info *domain = hbac_ctx_be(hbac_ctx)->domain;
const char *rhost;
const char *thost;
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) return ENOMEM;
eval_req = talloc_zero(tmp_ctx, struct hbac_eval_req);
if (eval_req == NULL) {
ret = ENOMEM;
goto done;
}
eval_req->request_time = time(NULL);
/* Get user the user name and groups */
ret = hbac_eval_user_element(eval_req, sysdb,
pd->user, &eval_req->user);
if (ret != EOK) goto done;
/* Get the PAM service and service groups */
ret = hbac_eval_service_element(eval_req, sysdb, domain,
pd->service, &eval_req->service);
if (ret != EOK) goto done;
/* Get the source host */
if (pd->rhost == NULL || pd->rhost[0] == '\0') {
/* If we haven't been passed an rhost,
* the rhost is unknown. This will fail
* to match any rule requiring the
* source host.
*/
rhost = NULL;
} else {
rhost = pd->rhost;
}
ret = hbac_eval_host_element(eval_req, sysdb, domain,
rhost, &eval_req->srchost);
if (ret != EOK) goto done;
/* The target host is always the current machine */
thost = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
if (thost == NULL) {
DEBUG(1, ("Missing ipa_hostname, this should never happen.\n"));
ret = EINVAL;
goto done;
}
ret = hbac_eval_host_element(eval_req, sysdb, domain,
thost, &eval_req->targethost);
if (ret != EOK) goto done;
*request = talloc_steal(mem_ctx, eval_req);
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
static errno_t
hbac_eval_user_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
const char *username,
struct hbac_request_element **user_element)
{
errno_t ret;
unsigned int i;
unsigned int num_groups = 0;
TALLOC_CTX *tmp_ctx;
const char *member_dn;
struct hbac_request_element *users;
struct ldb_message *msg;
struct ldb_message_element *el;
const char *attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) return ENOMEM;
users = talloc_zero(tmp_ctx, struct hbac_request_element);
if (users == NULL) {
ret = ENOMEM;
goto done;
}
users->name = username;
/* Read the originalMemberOf attribute
* This will give us the list of both POSIX and
* non-POSIX groups that this user belongs to.
*/
ret = sysdb_search_user_by_name(tmp_ctx, sysdb, users->name, attrs, &msg);
if (ret != EOK) {
DEBUG(1, ("Could not determine user memberships for [%s]\n",
users->name));
goto done;
}
el = ldb_msg_find_element(msg, SYSDB_ORIG_MEMBEROF);
if (el == NULL || el->num_values == 0) {
DEBUG(7, ("No groups for [%s]\n", users->name));
ret = create_empty_grouplist(users);
goto done;
}
DEBUG(7, ("[%d] groups for [%s]\n", el->num_values, users->name));
users->groups = talloc_array(users, const char *, el->num_values + 1);
if (users->groups == NULL) {
ret = ENOMEM;
goto done;
}
for (i = 0; i < el->num_values; i++) {
member_dn = (const char *)el->values[i].data;
ret = get_ipa_groupname(users->groups, sysdb, member_dn,
&users->groups[num_groups]);
if (ret != EOK && ret != ENOENT) {
DEBUG(3, ("Parse error on [%s]\n", member_dn));
goto done;
} else if (ret == EOK) {
DEBUG(7, ("Added group [%s] for user [%s]\n",
users->groups[num_groups], users->name));
num_groups++;
continue;
}
/* Skip entries that are not groups */
DEBUG(8, ("Skipping non-group memberOf [%s]\n", member_dn));
}
users->groups[num_groups] = NULL;
if (num_groups < el->num_values) {
/* Shrink the array memory */
users->groups = talloc_realloc(users, users->groups, const char *,
num_groups+1);
if (users->groups == NULL) {
ret = ENOMEM;
goto done;
}
}
ret = EOK;
done:
if (ret == EOK) {
*user_element = talloc_steal(mem_ctx, users);
}
talloc_free(tmp_ctx);
return ret;
}
static errno_t
hbac_eval_service_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char *servicename,
struct hbac_request_element **svc_element)
{
errno_t ret;
size_t i, j, count;
TALLOC_CTX *tmp_ctx;
struct hbac_request_element *svc;
struct ldb_message **msgs;
struct ldb_message_element *el;
struct ldb_dn *svc_dn;
const char *memberof_attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
char *name;
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) return ENOMEM;
svc = talloc_zero(tmp_ctx, struct hbac_request_element);
if (svc == NULL) {
ret = ENOMEM;
goto done;
}
svc->name = servicename;
svc_dn = sysdb_custom_dn(sysdb, tmp_ctx, svc->name, HBAC_SERVICES_SUBDIR);
if (svc_dn == NULL) {
ret = ENOMEM;
goto done;
}
/* Look up the service to get its originalMemberOf entries */
ret = sysdb_search_entry(tmp_ctx, sysdb, svc_dn,
LDB_SCOPE_BASE, NULL,
memberof_attrs,
&count, &msgs);
if (ret == ENOENT || count == 0) {
/* We won't be able to identify any groups
* This rule will only match the name or
* a service category of ALL
*/
ret = create_empty_grouplist(svc);
goto done;
} else if (ret != EOK) {
goto done;
} else if (count > 1) {
DEBUG(1, ("More than one result for a BASE search!\n"));
ret = EIO;
goto done;
}
el = ldb_msg_find_element(msgs[0], SYSDB_ORIG_MEMBEROF);
if (!el) {
/* Service is not a member of any groups
* This rule will only match the name or
* a service category of ALL
*/
ret = create_empty_grouplist(svc);
goto done;
}
svc->groups = talloc_array(svc, const char *, el->num_values + 1);
if (svc->groups == NULL) {
ret = ENOMEM;
goto done;
}
for (i = j = 0; i < el->num_values; i++) {
ret = get_ipa_servicegroupname(tmp_ctx, sysdb,
(const char *)el->values[i].data,
&name);
if (ret != EOK && ret != ENOENT) goto done;
/* ENOENT means we had a memberOf entry that wasn't a
* service group. We'll just ignore those (could be
* HBAC rules)
*/
if (ret == EOK) {
svc->groups[j] = talloc_steal(svc->groups, name);
j++;
}
}
svc->groups[j] = NULL;
ret = EOK;
done:
if (ret == EOK) {
*svc_element = talloc_steal(mem_ctx, svc);
}
talloc_free(tmp_ctx);
return ret;
}
static errno_t
hbac_eval_host_element(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char *hostname,
struct hbac_request_element **host_element)
{
errno_t ret;
size_t i, j, count;
TALLOC_CTX *tmp_ctx;
struct hbac_request_element *host;
struct ldb_message **msgs;
struct ldb_message_element *el;
struct ldb_dn *host_dn;
const char *memberof_attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
char *name;
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) return ENOMEM;
host = talloc_zero(tmp_ctx, struct hbac_request_element);
if (host == NULL) {
ret = ENOMEM;
goto done;
}
host->name = hostname;
if (host->name == NULL) {
/* We don't know the host (probably an rhost)
* So we can't determine it's groups either.
*/
ret = create_empty_grouplist(host);
goto done;
}
host_dn = sysdb_custom_dn(sysdb, tmp_ctx, host->name, HBAC_HOSTS_SUBDIR);
if (host_dn == NULL) {
ret = ENOMEM;
goto done;
}
/* Look up the host to get its originalMemberOf entries */
ret = sysdb_search_entry(tmp_ctx, sysdb, host_dn,
LDB_SCOPE_BASE, NULL,
memberof_attrs,
&count, &msgs);
if (ret == ENOENT || count == 0) {
/* We won't be able to identify any groups
* This rule will only match the name or
* a host category of ALL
*/
ret = create_empty_grouplist(host);
goto done;
} else if (ret != EOK) {
goto done;
} else if (count > 1) {
DEBUG(1, ("More than one result for a BASE search!\n"));
ret = EIO;
goto done;
}
el = ldb_msg_find_element(msgs[0], SYSDB_ORIG_MEMBEROF);
if (!el) {
/* Host is not a member of any groups
* This rule will only match the name or
* a host category of ALL
*/
ret = create_empty_grouplist(host);
goto done;
}
host->groups = talloc_array(host, const char *, el->num_values + 1);
if (host->groups == NULL) {
ret = ENOMEM;
goto done;
}
for (i = j = 0; i < el->num_values; i++) {
ret = get_ipa_hostgroupname(tmp_ctx, sysdb,
(const char *)el->values[i].data,
&name);
if (ret != EOK && ret != ENOENT) goto done;
/* ENOENT means we had a memberOf entry that wasn't a
* host group. We'll just ignore those (could be
* HBAC rules)
*/
if (ret == EOK) {
host->groups[j] = talloc_steal(host->groups, name);
j++;
}
}
host->groups[j] = NULL;
ret = EOK;
done:
if (ret == EOK) {
*host_element = talloc_steal(mem_ctx, host);
}
talloc_free(tmp_ctx);
return ret;
}