summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2011-06-06 22:38:15 -0400
committerStephen Gallagher <sgallagh@redhat.com>2011-07-08 15:12:24 -0400
commit32a5516cc2822cf6ad9950278e3c9701a9389bb4 (patch)
treeb5fc71c09371ff0c7a6f498c9c3bb2a9cf375839
parent90890b6f4ee75194db0e6dc9c99a8d21f34dd8be (diff)
downloadsssd-32a5516cc2822cf6ad9950278e3c9701a9389bb4.tar.gz
sssd-32a5516cc2822cf6ad9950278e3c9701a9389bb4.tar.bz2
sssd-32a5516cc2822cf6ad9950278e3c9701a9389bb4.zip
Add new HBAC lookup and evaluation routines
-rw-r--r--Makefile.am3
-rw-r--r--src/providers/ipa/ipa_access.c504
-rw-r--r--src/providers/ipa/ipa_access.h18
3 files changed, 400 insertions, 125 deletions
diff --git a/Makefile.am b/Makefile.am
index 8ffa650a..8eaa7e03 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -926,7 +926,8 @@ libsss_ipa_la_LIBADD = \
$(DHASH_LIBS) \
$(KEYUTILS_LIBS) \
$(KRB5_LIBS) \
- libsss_util.la
+ libsss_util.la \
+ libipa_hbac.la
libsss_ipa_la_LDFLAGS = \
-avoid-version \
-module
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index 51392bb4..18cf3104 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -29,6 +29,8 @@
#include "providers/ldap/sdap_async.h"
#include "providers/ipa/ipa_common.h"
#include "providers/ipa/ipa_access.h"
+#include "providers/ipa/ipa_hbac.h"
+#include "providers/ipa/ipa_hbac_private.h"
static char *get_hbac_search_base(TALLOC_CTX *mem_ctx,
struct dp_option *ipa_options)
@@ -56,21 +58,32 @@ static char *get_hbac_search_base(TALLOC_CTX *mem_ctx,
static void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status)
{
+ struct be_req *be_req = hbac_ctx->be_req;
+ struct pam_data *pd;
+ pd = talloc_get_type(be_req->req_data, struct pam_data);
+ pd->pam_status = pam_status;
- return EOK;
+ /* destroy HBAC context now to release all used resources and LDAP connection */
+ talloc_zfree(hbac_ctx);
-not_applicable:
- if (ret == RULE_NOT_APPLICABLE) {
- *result = HBAC_NOT_APPLICABLE;
+ if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED) {
+ be_req->fn(be_req, DP_ERR_OK, pam_status, NULL);
} else {
- *result = HBAC_DENY;
+ be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
}
- return EOK;
}
+enum hbac_result {
+ HBAC_ALLOW = 1,
+ HBAC_DENY,
+ HBAC_NOT_APPLICABLE
+};
- return EOK;
-}
+enum check_result {
+ RULE_APPLICABLE = 0,
+ RULE_NOT_APPLICABLE,
+ RULE_ERROR
+};
static int hbac_retry(struct hbac_ctx *hbac_ctx);
static void hbac_connect_done(struct tevent_req *subreq);
@@ -78,6 +91,8 @@ static bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret);
static int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx);
+static void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx);
+
void ipa_access_handler(struct be_req *be_req)
{
struct pam_data *pd;
@@ -93,6 +108,7 @@ void ipa_access_handler(struct be_req *be_req)
DEBUG(1, ("talloc failed.\n"));
goto fail;
}
+ hbac_ctx->get_deny_rules = true; /* make this a config option */
hbac_ctx->be_req = be_req;
hbac_ctx->pd = pd;
ipa_access_ctx = talloc_get_type(
@@ -128,18 +144,36 @@ static int hbac_retry(struct hbac_ctx *hbac_ctx)
{
struct tevent_req *subreq;
int ret;
+ bool offline;
+
+ offline = be_is_offline(hbac_ctx->be_req->be_ctx);
+ DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online"));
+
+ if (!offline) {
+ if (hbac_ctx->sdap_op == NULL) {
+ hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx,
+ hbac_ctx_sdap_id_ctx(hbac_ctx)->conn_cache);
+ if (hbac_ctx->sdap_op == NULL) {
+ DEBUG(1, ("sdap_id_op_create failed.\n"));
+ return EIO;
+ }
+ }
- if (hbac_ctx_is_offline(hbac_ctx)) {
- return hbac_get_host_info_step(hbac_ctx);
- }
+ subreq = sdap_id_op_connect_send(hbac_ctx_sdap_id_op(hbac_ctx), hbac_ctx, &ret);
+ if (!subreq) {
+ DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret)));
+ talloc_zfree(hbac_ctx->sdap_op);
+ return ret;
+ }
- subreq = sdap_id_op_connect_send(hbac_ctx_sdap_id_op(hbac_ctx), hbac_ctx, &ret);
- if (!subreq) {
- DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret)));
- return ret;
+ tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx);
+ } else {
+ /* Evaluate the rules based on what we have in the
+ * sysdb
+ */
+ ipa_hbac_evaluate_rules(hbac_ctx);
+ return EOK;
}
-
- tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx);
return EOK;
}
@@ -154,6 +188,9 @@ static void hbac_connect_done(struct tevent_req *subreq)
if (dp_error == DP_ERR_OFFLINE) {
/* switching to offline mode */
talloc_zfree(hbac_ctx->sdap_op);
+
+ ipa_hbac_evaluate_rules(hbac_ctx);
+ return;
} else if (ret != EOK) {
goto fail;
}
@@ -169,6 +206,24 @@ fail:
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
+static void hbac_clear_rule_data(struct hbac_ctx *hbac_ctx)
+{
+ hbac_ctx->host_count = 0;
+ talloc_zfree(hbac_ctx->hosts);
+
+ hbac_ctx->hostgroup_count = 0;
+ talloc_zfree(hbac_ctx->hostgroups);
+
+ hbac_ctx->service_count = 0;
+ talloc_zfree(hbac_ctx->services);
+
+ hbac_ctx->servicegroup_count = 0;
+ talloc_zfree(hbac_ctx->servicegroups);
+
+ hbac_ctx->rule_count = 0;
+ talloc_zfree(hbac_ctx->rules);
+}
+
/* Check the step result code and continue, retry, get offline result or abort accordingly */
static bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret)
{
@@ -189,6 +244,10 @@ static bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret)
if (dp_error == DP_ERR_OFFLINE) {
/* switching to offline mode */
talloc_zfree(hbac_ctx->sdap_op);
+
+ /* Free any of the results we've gotten */
+ hbac_clear_rule_data(hbac_ctx);
+
dp_error = DP_ERR_OK;
}
@@ -205,173 +264,370 @@ static bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret)
return false;
}
+static void hbac_get_service_info_step(struct tevent_req *req);
+static void hbac_get_rule_info_step(struct tevent_req *req);
+static void hbac_sysdb_save (struct tevent_req *req);
+
static int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx)
{
- struct pam_data *pd = hbac_ctx->pd;
- const char *hostlist[3];
- struct tevent_req *subreq;
-
- hostlist[0] = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
- if (hostlist[0] == NULL) {
- DEBUG(1, ("ipa_hostname not available.\n"));
- return EINVAL;
+ struct tevent_req *req =
+ ipa_hbac_host_info_send(hbac_ctx,
+ hbac_ctx_ev(hbac_ctx),
+ hbac_ctx_sysdb(hbac_ctx),
+ hbac_ctx_be(hbac_ctx)->domain,
+ sdap_id_op_handle(hbac_ctx->sdap_op),
+ hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
+ hbac_ctx->hbac_search_base);
+ if (req == NULL) {
+ DEBUG(1, ("Could not get host info\n"));
+ return ENOMEM;
}
- if (pd->rhost != NULL && *pd->rhost != '\0') {
- hostlist[1] = pd->rhost;
- hostlist[2] = NULL;
- } else {
- hostlist[1] = NULL;
- pd->rhost = discard_const_p(char, hostlist[0]);
+ tevent_req_set_callback(req, hbac_get_service_info_step, hbac_ctx);
+
+ return EOK;
+}
+
+static void hbac_get_service_info_step(struct tevent_req *req)
+{
+ errno_t ret;
+ struct hbac_ctx *hbac_ctx =
+ tevent_req_callback_data(req, struct hbac_ctx);
+
+ ret = ipa_hbac_host_info_recv(req, hbac_ctx,
+ &hbac_ctx->host_count,
+ &hbac_ctx->hosts,
+ &hbac_ctx->hostgroup_count,
+ &hbac_ctx->hostgroups);
+ talloc_zfree(req);
+ if (!hbac_check_step_result(hbac_ctx, ret)) {
+ return;
}
- subreq = hbac_get_host_info_send(hbac_ctx, hbac_ctx, hostlist);
- if (!subreq) {
- DEBUG(1, ("hbac_get_host_info_send failed.\n"));
- return ENOMEM;
+ /* Get services and service groups */
+ req = ipa_hbac_service_info_send(hbac_ctx,
+ hbac_ctx_ev(hbac_ctx),
+ hbac_ctx_sysdb(hbac_ctx),
+ hbac_ctx_be(hbac_ctx)->domain,
+ sdap_id_op_handle(hbac_ctx->sdap_op),
+ hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
+ hbac_ctx->hbac_search_base);
+ if (req == NULL) {
+ DEBUG(1,("Could not get service info\n"));
+ goto fail;
}
+ tevent_req_set_callback(req, hbac_get_rule_info_step, hbac_ctx);
+ return;
- tevent_req_set_callback(subreq, hbac_get_host_info_done, hbac_ctx);
- return EOK;
+fail:
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
-static void hbac_get_host_info_done(struct tevent_req *req)
+static void hbac_get_rule_info_step(struct tevent_req *req)
{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
+ errno_t ret;
+ size_t i;
const char *ipa_hostname;
- struct hbac_host_info *local_hhi = NULL;
-
- ret = hbac_get_host_info_recv(req, hbac_ctx, &hbac_ctx->hbac_hosts_count,
- &hbac_ctx->hbac_hosts_list);
+ const char *hostname;
+ struct hbac_ctx *hbac_ctx =
+ tevent_req_callback_data(req, struct hbac_ctx);
+
+ ret = ipa_hbac_service_info_recv(req, hbac_ctx,
+ &hbac_ctx->service_count,
+ &hbac_ctx->services,
+ &hbac_ctx->servicegroup_count,
+ &hbac_ctx->servicegroups);
talloc_zfree(req);
-
if (!hbac_check_step_result(hbac_ctx, ret)) {
return;
}
+ /* Get the ipa_host attrs */
+ hbac_ctx->ipa_host = NULL;
ipa_hostname = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
if (ipa_hostname == NULL) {
DEBUG(1, ("Missing ipa_hostname, this should never happen.\n"));
goto fail;
}
- ret = set_local_and_remote_host_info(hbac_ctx, hbac_ctx->hbac_hosts_count,
- hbac_ctx->hbac_hosts_list, ipa_hostname,
- hbac_ctx->pd->rhost, &local_hhi,
- &hbac_ctx->remote_hhi);
- if (ret != EOK) {
- DEBUG(1, ("set_local_and_remote_host_info failed.\n"));
- goto fail;
- }
+ for (i = 0; i < hbac_ctx->host_count; i++) {
+ ret = sysdb_attrs_get_string(hbac_ctx->hosts[i],
+ IPA_HOST_FQDN,
+ &hostname);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not locate IPA host\n"));
+ goto fail;
+ }
- if (local_hhi == NULL) {
- DEBUG(1, ("Missing host info for [%s].\n", ipa_hostname));
- pam_status = PAM_PERM_DENIED;
+ if (strcmp(hostname, ipa_hostname) == 0) {
+ hbac_ctx->ipa_host = hbac_ctx->hosts[i];
+ break;
+ }
+ }
+ if (hbac_ctx->ipa_host == NULL) {
+ DEBUG(1, ("Could not locate IPA host\n"));
goto fail;
}
- req = hbac_get_rules_send(hbac_ctx, hbac_ctx, local_hhi->dn,
- local_hhi->memberof);
+
+
+ /* Get the list of applicable rules */
+ req = ipa_hbac_rule_info_send(hbac_ctx,
+ hbac_ctx->get_deny_rules,
+ hbac_ctx_ev(hbac_ctx),
+ hbac_ctx_sysdb(hbac_ctx),
+ hbac_ctx_be(hbac_ctx)->domain,
+ sdap_id_op_handle(hbac_ctx->sdap_op),
+ hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
+ hbac_ctx->hbac_search_base,
+ hbac_ctx->ipa_host);
if (req == NULL) {
- DEBUG(1, ("hbac_get_rules_send failed.\n"));
+ DEBUG(1, ("Could not get rules\n"));
goto fail;
}
- tevent_req_set_callback(req, hbac_get_rules_done, hbac_ctx);
+ tevent_req_set_callback(req, hbac_sysdb_save, hbac_ctx);
return;
fail:
- ipa_access_reply(hbac_ctx, pam_status);
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
-static void hbac_get_rules_done(struct tevent_req *req)
+static void hbac_sysdb_save(struct tevent_req *req)
{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
+ errno_t ret;
+ bool in_transaction = false;
+ struct hbac_ctx *hbac_ctx =
+ tevent_req_callback_data(req, struct hbac_ctx);
+ struct sss_domain_info *domain = hbac_ctx_be(hbac_ctx)->domain;
+ struct sysdb_ctx *sysdb = hbac_ctx_sysdb(hbac_ctx);
+ struct ldb_dn *base_dn;
+ struct be_ctx *be_ctx = hbac_ctx_be(hbac_ctx);
+ struct ipa_access_ctx *access_ctx =
+ talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
+ struct ipa_access_ctx);
+ TALLOC_CTX *tmp_ctx;
+
+ ret = ipa_hbac_rule_info_recv(req, hbac_ctx,
+ &hbac_ctx->rule_count,
+ &hbac_ctx->rules);
+ talloc_zfree(req);
+ if (ret == ENOENT) {
+ /* No rules were found that apply to this
+ * host.
+ */
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
+ }
+ /* Delete any rules in the sysdb so offline logins
+ * are also denied.
+ */
+ base_dn = sysdb_custom_subtree_dn(sysdb, tmp_ctx,
+ domain->name,
+ HBAC_RULES_SUBDIR);
+ if (base_dn == NULL) {
+ talloc_free(tmp_ctx);
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
+ }
- hbac_ctx->hbac_rule_count = 0;
- talloc_zfree(hbac_ctx->hbac_rule_list);
+ ret = sysdb_delete_recursive(tmp_ctx, sysdb, base_dn, true);
+ talloc_free(tmp_ctx);
+ if (ret != EOK) {
+ DEBUG(1, ("sysdb_delete_recursive failed.\n"));
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
+ }
- ret = hbac_get_rules_recv(req, hbac_ctx, &hbac_ctx->hbac_rule_count,
- &hbac_ctx->hbac_rule_list);
- talloc_zfree(req);
+ /* If no rules are found, we default to DENY */
+ ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
+ return;
+ }
if (!hbac_check_step_result(hbac_ctx, ret)) {
return;
}
- req = hbac_get_service_data_send(hbac_ctx, hbac_ctx);
- if (req == NULL) {
- DEBUG(1, ("hbac_get_service_data_send failed.\n"));
- goto failed;
+ ret = sysdb_transaction_start(sysdb);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not start transaction\n"));
+ goto fail;
+ }
+ in_transaction = true;
+
+ /* Save the hosts */
+ ret = ipa_hbac_sysdb_save(sysdb, domain,
+ HBAC_HOSTS_SUBDIR, IPA_HOST_FQDN,
+ hbac_ctx->host_count, hbac_ctx->hosts,
+ HBAC_HOSTGROUPS_SUBDIR, IPA_CN,
+ hbac_ctx->hostgroup_count,
+ hbac_ctx->hostgroups);
+ if (ret != EOK) {
+ DEBUG(1, ("Error saving hosts: [%d][%s]\n",
+ ret, strerror(ret)));
+ goto fail;
}
- tevent_req_set_callback(req, hbac_get_service_data_done, hbac_ctx);
- return;
+ /* Save the services */
+ ret = ipa_hbac_sysdb_save(sysdb, domain,
+ HBAC_SERVICES_SUBDIR, IPA_CN,
+ hbac_ctx->service_count, hbac_ctx->services,
+ HBAC_SERVICEGROUPS_SUBDIR, IPA_CN,
+ hbac_ctx->servicegroup_count,
+ hbac_ctx->servicegroups);
+ if (ret != EOK) {
+ DEBUG(1, ("Error saving services: [%d][%s]\n",
+ ret, strerror(ret)));
+ goto fail;
+ }
+ /* Save the rules */
+ ret = ipa_hbac_sysdb_save(sysdb, domain,
+ HBAC_RULES_SUBDIR, IPA_UNIQUE_ID,
+ hbac_ctx->rule_count,
+ hbac_ctx->rules,
+ NULL, NULL, 0, NULL);
+ if (ret != EOK) {
+ DEBUG(1, ("Error saving rules: [%d][%s]\n",
+ ret, strerror(ret)));
+ goto fail;
+ }
-failed:
- ipa_access_reply(hbac_ctx, pam_status);
-}
+ ret = sysdb_transaction_commit(sysdb);
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to commit transaction\n"));
+ goto fail;
+ }
-static void hbac_get_service_data_done(struct tevent_req *req)
-{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- struct pam_data *pd = hbac_ctx->pd;
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
- bool access_allowed = false;
+ /* We don't need the rule data any longer,
+ * the rest of the processing relies on
+ * sysdb lookups.
+ */
+ hbac_clear_rule_data(hbac_ctx);
- hbac_ctx->hbac_services_count = 0;
- talloc_zfree(hbac_ctx->hbac_services_list);
+ /* Now evaluate the request against the rules */
+ ipa_hbac_evaluate_rules(hbac_ctx);
- ret = hbac_get_service_data_recv(req, hbac_ctx,
- &hbac_ctx->hbac_services_count,
- &hbac_ctx->hbac_services_list);
- talloc_zfree(req);
+ return;
- if (!hbac_check_step_result(hbac_ctx, ret)) {
- return;
+fail:
+ if (in_transaction) {
+ ret = sysdb_transaction_cancel(sysdb);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not cancel transaction\n"));
+ }
}
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+}
+
+static errno_t hbac_get_cached_rules(TALLOC_CTX *mem_ctx,
+ struct hbac_ctx *hbac_ctx);
- if (hbac_ctx->user_dn) {
- talloc_free(discard_const_p(TALLOC_CTX, hbac_ctx->user_dn));
- hbac_ctx->user_dn = 0;
+void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx)
+{
+ errno_t ret;
+ struct hbac_rule **hbac_rules;
+ struct hbac_eval_req *eval_req;
+ enum hbac_eval_result result;
+ struct hbac_info *info;
+
+ /* Get HBAC rules from the sysdb */
+ ret = hbac_get_cached_rules(hbac_ctx, hbac_ctx);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not retrieve rules from the cache\n"));
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
- if (!hbac_ctx_is_offline(hbac_ctx)) {
- ret = hbac_save_data_to_sysdb(hbac_ctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to save data, "
- "offline authentication might not work.\n"));
- /* This is not a fatal error. */
- }
+ ret = hbac_ctx_to_rules(hbac_ctx, hbac_ctx,
+ &hbac_rules, &eval_req);
+ if (ret == EPERM) {
+ DEBUG(1, ("DENY rules detected. Denying access to all users\n"));
+ ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
+ return;
+ } else if (ret != EOK) {
+ DEBUG(1, ("Could not construct HBAC rules\n"));
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
}
- hbac_ctx->groups_count = 0;
- talloc_zfree(hbac_ctx->groups);
+ result = hbac_evaluate(hbac_rules, eval_req, &info);
+ if (result == HBAC_EVAL_ALLOW) {
+ DEBUG(3, ("Access granted by HBAC rule [%s]\n",
+ info->rule_name));
+ hbac_free_info(info);
+ ipa_access_reply(hbac_ctx, PAM_SUCCESS);
+ return;
+ } else if (result == HBAC_EVAL_ERROR) {
+ DEBUG(1, ("Error [%s] occurred in rule [%s]\n",
+ hbac_error_string(info->code),
+ info->rule_name));
+ hbac_free_info(info);
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
+ } else if (result == HBAC_EVAL_OOM) {
+ DEBUG(1, ("Insufficient memory\n"));
+ ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
+ return;
+ }
- ret = hbac_get_user_info(hbac_ctx, hbac_ctx_be(hbac_ctx),
- pd->user, &hbac_ctx->user_dn,
- &hbac_ctx->groups_count, &hbac_ctx->groups);
- if (ret != EOK) {
- goto failed;
+ DEBUG(3, ("Access denied by HBAC rules\n"));
+ ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
+}
+
+static errno_t hbac_get_cached_rules(TALLOC_CTX *mem_ctx,
+ struct hbac_ctx *hbac_ctx)
+{
+ errno_t ret;
+ struct sysdb_ctx *sysdb = hbac_ctx_sysdb(hbac_ctx);
+ struct sss_domain_info *domain = hbac_ctx_be(hbac_ctx)->domain;
+ size_t count;
+ struct ldb_message **msgs;
+ TALLOC_CTX *tmp_ctx;
+ char *filter;
+ const char *attrs[] = { OBJECTCLASS,
+ IPA_CN,
+ IPA_UNIQUE_ID,
+ IPA_ENABLED_FLAG,
+ IPA_ACCESS_RULE_TYPE,
+ IPA_MEMBER_USER,
+ IPA_USER_CATEGORY,
+ IPA_MEMBER_SERVICE,
+ IPA_SERVICE_CATEGORY,
+ IPA_SOURCE_HOST,
+ IPA_SOURCE_HOST_CATEGORY,
+ IPA_EXTERNAL_HOST,
+ IPA_MEMBER_HOST,
+ IPA_HOST_CATEGORY,
+ NULL };
+
+ tmp_ctx = talloc_new(hbac_ctx);
+ if (tmp_ctx == NULL) return ENOMEM;
+
+ filter = talloc_asprintf(tmp_ctx, "(objectClass=%s)", IPA_HBAC_RULE);
+ if (filter == NULL) {
+ ret = ENOMEM;
+ goto done;
}
- ret = evaluate_ipa_hbac_rules(hbac_ctx, &access_allowed);
- if (ret != EOK) {
- DEBUG(1, ("evaluate_ipa_hbac_rules failed.\n"));
- goto failed;
+ ret = sysdb_search_custom(mem_ctx, sysdb, domain, filter,
+ HBAC_RULES_SUBDIR, attrs,
+ &count, &msgs);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(1, ("Error looking up HBAC rules"));
+ goto done;
+ } if (ret == ENOENT) {
+ count = 0;
}
- if (access_allowed) {
- pam_status = PAM_SUCCESS;
- DEBUG(5, ("Access allowed.\n"));
- } else {
- pam_status = PAM_PERM_DENIED;
- DEBUG(3, ("Access denied.\n"));
+ ret = msgs2attrs_array(mem_ctx, count, msgs, &hbac_ctx->rules);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not convert ldb message to sysdb_attrs\n"));
+ goto done;
}
+ hbac_ctx->rule_count = count;
-failed:
- ipa_access_reply(hbac_ctx, pam_status);
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
}
diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h
index d24056a8..da43fea2 100644
--- a/src/providers/ipa/ipa_access.h
+++ b/src/providers/ipa/ipa_access.h
@@ -54,6 +54,24 @@ struct hbac_ctx {
struct pam_data *pd;
char *hbac_search_base;
+
+ /* Hosts */
+ size_t host_count;
+ struct sysdb_attrs **hosts;
+ size_t hostgroup_count;
+ struct sysdb_attrs **hostgroups;
+ struct sysdb_attrs *ipa_host;
+
+ /* Rules */
+ bool get_deny_rules;
+ size_t rule_count;
+ struct sysdb_attrs **rules;
+
+ /* Services */
+ size_t service_count;
+ struct sysdb_attrs **services;
+ size_t servicegroup_count;
+ struct sysdb_attrs **servicegroups;
};
/* Get BE context associated with HBAC context */