diff options
Diffstat (limited to 'src/providers/ipa/ipa_access.c')
-rw-r--r-- | src/providers/ipa/ipa_access.c | 2069 |
1 files changed, 383 insertions, 1686 deletions
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index f07eb7b5b..3bd377320 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -29,36 +29,8 @@ #include "providers/ldap/sdap_async.h" #include "providers/ipa/ipa_common.h" #include "providers/ipa/ipa_access.h" - -#define OBJECTCLASS "objectclass" -#define IPA_MEMBEROF "memberOf" -#define IPA_HOST_SERVERHOSTNAME "serverHostName" -#define IPA_HOST_FQDN "fqdn" -#define IPA_ACCESS_RULE_TYPE "accessRuleType" -#define IPA_MEMBER_USER "memberUser" -#define IPA_USER_CATEGORY "userCategory" -#define IPA_SERVICE_NAME "serviceName" -#define IPA_SOURCE_HOST "sourceHost" -#define IPA_SOURCE_HOST_CATEGORY "sourceHostCategory" -#define IPA_EXTERNAL_HOST "externalHost" -#define IPA_UNIQUE_ID "ipauniqueid" -#define IPA_ENABLED_FLAG "ipaenabledflag" -#define IPA_MEMBER_HOST "memberHost" -#define IPA_HOST_CATEGORY "hostCategory" -#define IPA_CN "cn" -#define IPA_MEMBER_SERVICE "memberService" -#define IPA_SERVICE_CATEGORY "serviceCategory" -#define IPA_TRUE_VALUE "TRUE" - -#define IPA_HOST_BASE_TMPL "cn=computers,cn=accounts,%s" -#define IPA_HBAC_BASE_TMPL "cn=hbac,%s" -#define IPA_SERVICES_BASE_TMPL "cn=hbacservices,cn=accounts,%s" - -#define SYSDB_HBAC_BASE_TMPL "cn=hbac,"SYSDB_TMPL_CUSTOM_BASE - -#define HBAC_RULES_SUBDIR "hbac_rules" -#define HBAC_HOSTS_SUBDIR "hbac_hosts" -#define HBAC_SERVICES_SUBDIR "hbac_services" +#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) @@ -84,247 +56,6 @@ static char *get_hbac_search_base(TALLOC_CTX *mem_ctx, return base; } -static errno_t msgs2attrs_array(TALLOC_CTX *mem_ctx, size_t count, - struct ldb_message **msgs, - struct sysdb_attrs ***attrs) -{ - int i; - struct sysdb_attrs **a; - - a = talloc_array(mem_ctx, struct sysdb_attrs *, count); - if (a == NULL) { - DEBUG(1, ("talloc_array failed.\n")); - return ENOMEM; - } - - for (i = 0; i < count; i++) { - a[i] = talloc(a, struct sysdb_attrs); - if (a[i] == NULL) { - DEBUG(1, ("talloc_array failed.\n")); - talloc_free(a); - return ENOMEM; - } - a[i]->num = msgs[i]->num_elements; - a[i]->a = talloc_steal(a[i], msgs[i]->elements); - } - - *attrs = a; - - return EOK; -} - -static errno_t replace_attribute_name(const char *old_name, - const char *new_name, const size_t count, - struct sysdb_attrs **list) -{ - int ret; - int i; - - for (i = 0; i < count; i++) { - ret = sysdb_attrs_replace_name(list[i], old_name, new_name); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_replace_name failed.\n")); - return ret; - } - } - - return EOK; -} - -static errno_t hbac_sdap_data_recv(struct tevent_req *subreq, - TALLOC_CTX *mem_ctx, size_t *count, - struct sysdb_attrs ***attrs) -{ - int ret; - - ret = sdap_get_generic_recv(subreq, mem_ctx, count, attrs); - if (ret != EOK) { - DEBUG(1, ("sdap_get_generic_recv failed.\n")); - return ret; - } - - ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF, - *count, *attrs); - if (ret != EOK) { - DEBUG(1, ("replace_attribute_name failed.\n")); - return ret; - } - - return EOK; -} - -static errno_t hbac_sysdb_data_recv(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *filter, - const char *subtree_name, - const char **search_attrs, - size_t *count, - struct sysdb_attrs ***reply_attrs) -{ - int ret; - struct ldb_message **msgs; - - ret = sysdb_search_custom(mem_ctx, sysdb, domain, filter, subtree_name, - search_attrs, count, &msgs); - if (ret != EOK) { - if (ret == ENOENT) { - *count = 0; - *reply_attrs = NULL; - return EOK; - } - DEBUG(1, ("sysdb_search_custom failed.\n")); - return ret; - } - - ret = msgs2attrs_array(mem_ctx, *count, msgs, reply_attrs); - talloc_zfree(msgs); - if (ret != EOK) { - DEBUG(1, ("msgs2attrs_array failed.\n")); - return ret; - } - - return EOK; -} - -static errno_t set_local_and_remote_host_info(TALLOC_CTX *mem_ctx, - size_t host_count, - struct sysdb_attrs **host_list, - const char *local_hostname, - const char *remote_hostname, - struct hbac_host_info **local_hhi, - struct hbac_host_info **remote_hhi) - -{ - size_t c; - int ret; - struct hbac_host_info *hhi; - struct ldb_message_element *el; - TALLOC_CTX *tmp_ctx = NULL; - - if (local_hostname == NULL || *local_hostname == '\0') { - DEBUG(1, ("Missing local hostname.\n")); - ret = EINVAL; - goto done; - } - - if (host_count == 0) { - DEBUG(1, ("No host data available.\n")); - ret = EINVAL; - goto done; - } - - tmp_ctx = talloc_new(mem_ctx); - if (tmp_ctx == NULL) { - ret = ENOMEM; - goto done; - } - - for (c = 0; c < host_count; c++) { - hhi = talloc_zero(tmp_ctx, struct hbac_host_info); - if (hhi == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto done; - } - - ret = sysdb_attrs_get_el(host_list[c], SYSDB_ORIG_DN, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - goto done; - } - if (el->num_values == 0) { - DEBUG(1, ("Missing OriginalDN.\n")); - ret = EINVAL; - goto done; - } - DEBUG(9, ("OriginalDN: [%.*s].\n", el->values[0].length, - (char *)el->values[0].data)); - hhi->dn = talloc_strndup(hhi, (char *)el->values[0].data, - el->values[0].length); - if (hhi->dn == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto done; - } - - ret = sysdb_attrs_get_el(host_list[c], IPA_HOST_SERVERHOSTNAME, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - goto done; - } - if (el->num_values == 0) { - DEBUG(1, ("Missing ServerHostName.\n")); - ret = EINVAL; - goto done; - } - DEBUG(9, ("ServerHostName: [%.*s].\n", el->values[0].length, - (char *)el->values[0].data)); - hhi->serverhostname = talloc_strndup(hhi, (char *)el->values[0].data, - el->values[0].length); - if (hhi->serverhostname == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto done; - } - - ret = sysdb_attrs_get_el(host_list[c], IPA_HOST_FQDN, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - goto done; - } - if (el->num_values == 0) { - DEBUG(1, ("Missing FQDN.\n")); - ret = EINVAL; - goto done; - } - DEBUG(9, ("FQDN: [%.*s].\n", el->values[0].length, - (char *)el->values[0].data)); - hhi->fqdn = talloc_strndup(hhi, (char *)el->values[0].data, - el->values[0].length); - if (hhi->fqdn == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto done; - } - - ret = sysdb_attrs_get_string_array(host_list[c], SYSDB_ORIG_MEMBEROF, - hhi, &hhi->memberof); - if (ret != EOK) { - if (ret != ENOENT) { - DEBUG(1, ("sysdb_attrs_get_string_array failed.\n")); - goto done; - } - - hhi->memberof = talloc_array(hhi, const char *, 1); - if (hhi->memberof == NULL) { - DEBUG(1, ("talloc_array failed.\n")); - ret = ENOMEM; - goto done; - } - hhi->memberof[0] = NULL; - } - - if (strcmp(hhi->fqdn, local_hostname) == 0 || - strcmp(hhi->serverhostname, local_hostname) == 0) { - *local_hhi = talloc_steal(mem_ctx, hhi); - } - - if (remote_hostname != NULL && *remote_hostname != '\0') { - if (strcmp(hhi->fqdn, remote_hostname) == 0 || - strcmp(hhi->serverhostname, remote_hostname) == 0) { - *remote_hhi = talloc_steal(mem_ctx, hhi); - } - } - } - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - static void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status) { struct be_req *be_req = hbac_ctx->be_req; @@ -342,873 +73,6 @@ static void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status) } } -static errno_t hbac_save_list(struct sysdb_ctx *sysdb, bool delete_subdir, - const char *subdir, struct sss_domain_info *domain, - const char *naming_attribute, size_t count, - struct sysdb_attrs **list) -{ - int ret; - size_t c; - struct ldb_dn *base_dn; - const char *object_name; - struct ldb_message_element *el; - TALLOC_CTX *tmp_ctx; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(1, ("talloc_new failed.\n")); - return ENOMEM; - } - - if (delete_subdir) { - base_dn = sysdb_custom_subtree_dn(sysdb, tmp_ctx, domain->name, subdir); - if (base_dn == NULL) { - ret = ENOMEM; - goto done; - } - - ret = sysdb_delete_recursive(tmp_ctx, sysdb, base_dn, true); - if (ret != EOK) { - DEBUG(1, ("sysdb_delete_recursive failed.\n")); - goto done; - } - } - - for (c = 0; c < count; c++) { - ret = sysdb_attrs_get_el(list[c], naming_attribute, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - goto done; - } - if (el->num_values == 0) { - DEBUG(1, ("IPA_UNIQUE_ID not found.\n")); - ret = EINVAL; - goto done; - } - object_name = talloc_strndup(tmp_ctx, (const char *)el->values[0].data, - el->values[0].length); - if (object_name == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto done; - } - DEBUG(9, ("Object name: [%s].\n", object_name)); - - ret = sysdb_store_custom(tmp_ctx, sysdb, domain, object_name, subdir, - list[c]); - if (ret != EOK) { - DEBUG(1, ("sysdb_store_custom failed.\n")); - goto done; - } - } - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - -static errno_t hbac_save_data_to_sysdb(struct hbac_ctx *hbac_ctx) -{ - int ret; - bool in_transaction = false; - struct sysdb_ctx *sysdb = hbac_ctx_sysdb(hbac_ctx); - struct sss_domain_info *domain = hbac_ctx_be(hbac_ctx)->domain; - - ret = sysdb_transaction_start(sysdb); - if (ret != EOK) { - DEBUG(1, ("sysdb_transaction_start failed.\n")); - return ret; - } - in_transaction = true; - - ret = hbac_save_list(sysdb, true, HBAC_SERVICES_SUBDIR, domain, - IPA_UNIQUE_ID, hbac_ctx->hbac_services_count, - hbac_ctx->hbac_services_list); - if (ret != EOK) { - DEBUG(1, ("hbac_save_list failed.\n")); - goto done; - } - - ret = hbac_save_list(sysdb, true, HBAC_RULES_SUBDIR, domain, - IPA_UNIQUE_ID, hbac_ctx->hbac_rule_count, - hbac_ctx->hbac_rule_list); - if (ret != EOK) { - DEBUG(1, ("hbac_save_list failed.\n")); - goto done; - } - - ret = hbac_save_list(sysdb, false, HBAC_HOSTS_SUBDIR, domain, - IPA_HOST_FQDN, hbac_ctx->hbac_hosts_count, - hbac_ctx->hbac_hosts_list); - if (ret != EOK) { - DEBUG(1, ("hbac_save_list failed.\n")); - goto done; - } - - ret = sysdb_transaction_commit(sysdb); - if (ret != EOK) { - DEBUG(1, ("sysdb_transaction_commit failed.\n")); - goto done; - } - in_transaction = false; - - ret = EOK; - -done: - if (in_transaction) { - sysdb_transaction_cancel(sysdb); - } - return ret; -} - -struct hbac_get_service_data_state { - struct hbac_ctx *hbac_ctx; - bool offline; - - char *services_filter; - const char **services_attrs; - struct sysdb_attrs **services_reply_list; - size_t services_reply_count; - - size_t current_item; -}; - -static void hbac_services_get_done(struct tevent_req *subreq); - -struct tevent_req *hbac_get_service_data_send(TALLOC_CTX *memctx, - struct hbac_ctx *hbac_ctx) -{ - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct hbac_get_service_data_state *state; - struct sdap_handle *sdap_handle; - int ret; - - req = tevent_req_create(memctx, &state, struct hbac_get_service_data_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->hbac_ctx = hbac_ctx; - - state->services_reply_list = NULL; - state->services_reply_count = 0; - - state->current_item = 0; - - state->services_attrs = talloc_array(state, const char *, 7); - if (state->services_attrs == NULL) { - DEBUG(1, ("Failed to allocate service attribute list.\n")); - ret = ENOMEM; - goto fail; - } - state->services_attrs[0] = IPA_CN; - state->services_attrs[1] = SYSDB_ORIG_DN; - state->services_attrs[2] = IPA_UNIQUE_ID; - state->services_attrs[3] = IPA_MEMBEROF; - state->services_attrs[4] = SYSDB_ORIG_MEMBEROF; - state->services_attrs[5] = OBJECTCLASS; - state->services_attrs[6] = NULL; - - state->services_filter = talloc_asprintf(state, - "(objectclass=ipaHBACService)"); - if (state->services_filter == NULL) { - ret = ENOMEM; - goto fail; - } - - DEBUG(9, ("Services filter: [%s].\n", state->services_filter)); - - if (hbac_ctx_is_offline(state->hbac_ctx)) { - ret = hbac_sysdb_data_recv(state, - hbac_ctx_sysdb(state->hbac_ctx), - hbac_ctx_be(state->hbac_ctx)->domain, - state->services_filter, HBAC_SERVICES_SUBDIR, - state->services_attrs, - &state->services_reply_count, - &state->services_reply_list); - if (ret) { - DEBUG(1, ("hbac_sysdb_data_recv failed.\n")); - goto fail; - } - - tevent_req_done(req); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; - } - - sdap_handle = sdap_id_op_handle(hbac_ctx_sdap_id_op(state->hbac_ctx)); - if (sdap_handle == NULL) { - DEBUG(1, ("Bug: sdap_id_op is disconnected.\n")); - ret = EIO; - goto fail; - } - subreq = sdap_get_generic_send(state, - hbac_ctx_ev(state->hbac_ctx), - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts, - sdap_handle, - state->hbac_ctx->hbac_search_base, - LDAP_SCOPE_SUB, - state->services_filter, - state->services_attrs, - NULL, 0, - dp_opt_get_int( - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT)); - - if (subreq == NULL) { - DEBUG(1, ("sdap_get_generic_send failed.\n")); - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, hbac_services_get_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; -} - -static void hbac_services_get_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct hbac_get_service_data_state *state = tevent_req_data(req, - struct hbac_get_service_data_state); - int ret; - - ret = hbac_sdap_data_recv(subreq, state, &state->services_reply_count, - &state->services_reply_list); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int hbac_get_service_data_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - size_t *hbac_services_count, - struct sysdb_attrs ***hbac_services_list) -{ - struct hbac_get_service_data_state *state = tevent_req_data(req, - struct hbac_get_service_data_state); - int i; - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *hbac_services_count = state->services_reply_count; - *hbac_services_list = talloc_steal(memctx, state->services_reply_list); - for (i = 0; i < state->services_reply_count; i++) { - talloc_steal(memctx, state->services_reply_list[i]); - } - - return EOK; -} - -static int hbac_get_user_info(TALLOC_CTX *memctx, - struct be_ctx *be_ctx, - const char *user, - const char **user_dn, - size_t *groups_count, - const char ***_groups) -{ - TALLOC_CTX *tmpctx; - const char *attrs[] = { SYSDB_ORIG_DN, NULL }; - struct ldb_message *user_msg; - const char *user_orig_dn; - struct ldb_message **msgs; - size_t count; - const char **groups; - int ret; - int i; - - tmpctx = talloc_new(memctx); - if (!tmpctx) { - return ENOMEM; - } - - ret = sysdb_search_user_by_name(tmpctx, be_ctx->sysdb, - be_ctx->domain, user, attrs, &user_msg); - if (ret != EOK) { - goto fail; - } - - DEBUG(9, ("Found user info for user [%s].\n", user)); - user_orig_dn = ldb_msg_find_attr_as_string(user_msg, SYSDB_ORIG_DN, NULL); - if (user_orig_dn == NULL) { - DEBUG(1, ("Original DN of user [%s] not available.\n", user)); - ret = EINVAL; - goto fail; - } - DEBUG(9, ("Found original DN [%s] for user [%s].\n", - user_orig_dn, user)); - - ret = sysdb_asq_search(tmpctx, be_ctx->sysdb, be_ctx->domain, - user_msg->dn, NULL, SYSDB_MEMBEROF, attrs, - &count, &msgs); - if (ret != EOK) { - DEBUG(1, ("sysdb_asq_search on user %s failed.\n", user)); - goto fail; - } - - if (count == 0) { - *user_dn = talloc_strdup(memctx, user_orig_dn); - if (*user_dn == NULL) { - ret = ENOMEM; - goto fail; - } - *groups_count = 0; - *_groups = NULL; - talloc_zfree(tmpctx); - return EOK; - } - - groups = talloc_array(tmpctx, const char *, count); - if (groups == NULL) { - DEBUG(1, ("talloc_groups failed.\n")); - ret = ENOMEM; - goto fail; - } - - for(i = 0; i < count; i++) { - if (msgs[i]->num_elements != 1) { - DEBUG(1, ("Unexpected number of elements.\n")); - ret = EINVAL; - goto fail; - } - - if (msgs[i]->elements[0].num_values != 1) { - DEBUG(1, ("Unexpected number of values.\n")); - ret = EINVAL; - goto fail; - } - - groups[i] = talloc_strndup(groups, - (const char *)msgs[i]->elements[0].values[0].data, - msgs[i]->elements[0].values[0].length); - if (groups[i] == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto fail; - } - - DEBUG(9, ("Found group [%s].\n", groups[i])); - } - - *user_dn = talloc_strdup(memctx, user_orig_dn); - if (*user_dn == NULL) { - ret = ENOMEM; - goto fail; - } - *groups_count = count; - *_groups = talloc_steal(memctx, groups); - - talloc_zfree(tmpctx); - return EOK; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - talloc_zfree(tmpctx); - return ret; -} - - -struct hbac_get_host_info_state { - struct hbac_ctx *hbac_ctx; - - char *host_filter; - const char **host_attrs; - - struct sysdb_attrs **host_reply_list; - size_t host_reply_count; - size_t current_item; - struct hbac_host_info **hbac_host_info; -}; - -static void hbac_get_host_memberof(struct tevent_req *req, bool offline); -static void hbac_get_host_memberof_done(struct tevent_req *subreq); - -static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, - struct hbac_ctx *hbac_ctx, - const char **hostnames) -{ - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct hbac_get_host_info_state *state; - struct sdap_handle *sdap_handle; - char *host; - int ret; - int i; - - if (hostnames == NULL) { - DEBUG(1, ("Missing hostnames.\n")); - return NULL; - } - - req = tevent_req_create(memctx, &state, struct hbac_get_host_info_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->hbac_ctx = hbac_ctx; - - state->host_reply_list = NULL; - state->host_reply_count = 0; - state->current_item = 0; - state->hbac_host_info = NULL; - - state->host_filter = talloc_asprintf(state, "(&(objectclass=ipaHost)(|"); - if (state->host_filter == NULL) { - DEBUG(1, ("Failed to create filter.\n")); - ret = ENOMEM; - goto fail; - } - for (i = 0; hostnames[i] != NULL; i++) { - ret = sss_filter_sanitize(state->host_filter, hostnames[i], &host); - if (ret != EOK) { - goto fail; - } - - state->host_filter = talloc_asprintf_append(state->host_filter, - "(%s=%s)(%s=%s)", - IPA_HOST_FQDN, host, - IPA_HOST_SERVERHOSTNAME, host); - - if (state->host_filter == NULL) { - ret = ENOMEM; - goto fail; - } - talloc_zfree(host); - } - state->host_filter = talloc_asprintf_append(state->host_filter, "))"); - if (state->host_filter == NULL) { - ret = ENOMEM; - goto fail; - } - - state->host_attrs = talloc_array(state, const char *, 8); - if (state->host_attrs == NULL) { - DEBUG(1, ("Failed to allocate host attribute list.\n")); - ret = ENOMEM; - goto fail; - } - state->host_attrs[0] = IPA_MEMBEROF; - state->host_attrs[1] = IPA_HOST_SERVERHOSTNAME; - state->host_attrs[2] = IPA_HOST_FQDN; - state->host_attrs[3] = "objectClass"; - state->host_attrs[4] = SYSDB_ORIG_DN; - state->host_attrs[5] = SYSDB_ORIG_MEMBEROF; - state->host_attrs[6] = IPA_UNIQUE_ID; - state->host_attrs[7] = NULL; - - if (hbac_ctx_is_offline(state->hbac_ctx)) { - ret = hbac_sysdb_data_recv(state, hbac_ctx_sysdb(state->hbac_ctx), - hbac_ctx_be(state->hbac_ctx)->domain, - state->host_filter, HBAC_HOSTS_SUBDIR, - state->host_attrs, - &state->host_reply_count, - &state->host_reply_list); - if (ret != EOK) { - DEBUG(1, ("hbac_sysdb_data_recv failed.\n")); - goto fail; - } - hbac_get_host_memberof(req, true); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; - } - - sdap_handle = sdap_id_op_handle(hbac_ctx_sdap_id_op(state->hbac_ctx)); - if (sdap_handle == NULL) { - DEBUG(1, ("Bug: sdap_id_op is disconnected.\n")); - ret = EIO; - goto fail; - } - subreq = sdap_get_generic_send(state, hbac_ctx_ev(state->hbac_ctx), - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts, - sdap_handle, - state->hbac_ctx->hbac_search_base, - LDAP_SCOPE_SUB, - state->host_filter, - state->host_attrs, - NULL, 0, - dp_opt_get_int( - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT)); - - if (subreq == NULL) { - DEBUG(1, ("sdap_get_generic_send failed.\n")); - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, hbac_get_host_memberof_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; -} - -static void hbac_get_host_memberof_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct hbac_get_host_info_state *state = tevent_req_data(req, - struct hbac_get_host_info_state); - int ret; - - ret = hbac_sdap_data_recv(subreq, state, &state->host_reply_count, - &state->host_reply_list); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - hbac_get_host_memberof(req, false); -} - -static bool hbac_is_known_host(size_t host_reply_count, - struct sysdb_attrs **host_reply_list, - const char *fqdn) -{ - int i; - const char *new_fqdn; - int ret; - - if (!host_reply_list || !fqdn) { - return false; - } - - for (i = 0; i < host_reply_count; i++) { - ret = sysdb_attrs_get_string(host_reply_list[i], IPA_HOST_FQDN, - &new_fqdn); - if (ret != 0) { - DEBUG(1, ("missing FQDN in new HBAC host record\n")); - continue; - } - - if(strcmp(new_fqdn, fqdn) == 0) { - return true; - } - } - - return false; -} - -static void hbac_get_host_memberof(struct tevent_req *req, bool offline) -{ - struct hbac_get_host_info_state *state = - tevent_req_data(req, struct hbac_get_host_info_state); - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - bool in_transaction = false; - int ret; - int i; - const char *fqdn_attrs[] = { IPA_HOST_FQDN, NULL }; - const char *fqdn; - - size_t cached_count; - struct ldb_message **cached_entries = 0; - - if (offline) { - tevent_req_done(req); - return; - } - - sysdb = hbac_ctx_sysdb(state->hbac_ctx); - domain = hbac_ctx_be(state->hbac_ctx)->domain; - - ret = sysdb_transaction_start(sysdb); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - in_transaction = true; - - ret = sysdb_search_custom(state, sysdb, domain, - state->host_filter, HBAC_HOSTS_SUBDIR, - fqdn_attrs, - &cached_count, - &cached_entries); - - if (ret == ENOENT) { - cached_count = 0; - ret = EOK; - } - - if (ret) { - DEBUG(1, ("sysdb_search_custom failed: [%d](%s)\n", ret, strerror(ret))); - goto fail; - } - - for (i = 0; i < cached_count; i++) { - fqdn = ldb_msg_find_attr_as_string(cached_entries[i], IPA_HOST_FQDN, NULL); - if (!fqdn) { - DEBUG(1, ("missing FQDN in cached HBAC host record\n")); - } else if (hbac_is_known_host(state->host_reply_count, - state->host_reply_list, fqdn)) { - continue; - } else { - DEBUG(9, ("deleting obsolete HBAC host record for %s\n", fqdn)); - } - - ret = sysdb_delete_entry(sysdb, cached_entries[i]->dn, true); - if (ret) { - DEBUG(1, ("sysdb_delete_entry failed: [%d](%s)\n", ret, strerror(ret))); - goto fail; - } - } - - talloc_zfree(cached_entries); - - ret = sysdb_transaction_commit(sysdb); - if (ret) { - DEBUG(1, ("sysdb_transaction_commit failed.\n")); - goto fail; - } - in_transaction = false; - - tevent_req_done(req); - return; - -fail: - talloc_zfree(cached_entries); - - if (in_transaction) { - sysdb_transaction_cancel(sysdb); - } - tevent_req_error(req, ret); - return; -} - -static int hbac_get_host_info_recv(struct tevent_req *req, TALLOC_CTX *memctx, - size_t *hbac_hosts_count, - struct sysdb_attrs ***hbac_hosts_list) -{ - size_t c; - struct hbac_get_host_info_state *state = tevent_req_data(req, - struct hbac_get_host_info_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *hbac_hosts_count = state->host_reply_count; - *hbac_hosts_list = talloc_steal(memctx, state->host_reply_list); - for (c = 0; c < state->host_reply_count; c++) { - talloc_steal(memctx, state->host_reply_list[c]); - } - - return EOK; -} - - -struct hbac_get_rules_state { - struct hbac_ctx *hbac_ctx; - - const char *host_dn; - const char **memberof; - char *hbac_filter; - const char **hbac_attrs; - - struct ldb_message *old_rules; - struct sysdb_attrs **hbac_reply_list; - size_t hbac_reply_count; - int current_item; -}; - -static void hbac_rule_get_done(struct tevent_req *subreq); - -static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx, - struct hbac_ctx *hbac_ctx, - const char *host_dn, - const char **memberof) -{ - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct hbac_get_rules_state *state; - struct sdap_handle *sdap_handle; - char *host_dn_clean; - int ret; - int i; - - if (host_dn == NULL) { - DEBUG(1, ("Missing host_dn.\n")); - return NULL; - } - - req = tevent_req_create(memctx, &state, struct hbac_get_rules_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->hbac_ctx = hbac_ctx; - state->host_dn = host_dn; - state->memberof = memberof; - - state->old_rules = NULL; - state->hbac_reply_list = NULL; - state->hbac_reply_count = 0; - state->current_item = 0; - - state->hbac_attrs = talloc_array(state, const char *, 17); - if (state->hbac_attrs == NULL) { - DEBUG(1, ("Failed to allocate HBAC attribute list.\n")); - ret = ENOMEM; - goto fail; - } - state->hbac_attrs[0] = IPA_ACCESS_RULE_TYPE; - state->hbac_attrs[1] = IPA_MEMBER_USER; - state->hbac_attrs[2] = IPA_USER_CATEGORY; - state->hbac_attrs[3] = IPA_SERVICE_NAME; - state->hbac_attrs[4] = IPA_SOURCE_HOST; - state->hbac_attrs[5] = IPA_SOURCE_HOST_CATEGORY; - state->hbac_attrs[6] = IPA_EXTERNAL_HOST; - state->hbac_attrs[7] = IPA_UNIQUE_ID; - state->hbac_attrs[8] = IPA_ENABLED_FLAG; - state->hbac_attrs[9] = IPA_CN; - state->hbac_attrs[10] = OBJECTCLASS; - state->hbac_attrs[11] = IPA_MEMBER_HOST; - state->hbac_attrs[12] = IPA_HOST_CATEGORY; - state->hbac_attrs[13] = IPA_MEMBER_SERVICE; - state->hbac_attrs[14] = IPA_SERVICE_CATEGORY; - state->hbac_attrs[15] = SYSDB_ORIG_DN; - state->hbac_attrs[16] = NULL; - - ret = sss_filter_sanitize(state, host_dn, &host_dn_clean); - if (ret != EOK) { - goto fail; - } - - state->hbac_filter = talloc_asprintf(state, - "(&(objectclass=ipaHBACRule)" - "(%s=%s)(|(%s=%s)(%s=%s)", - IPA_ENABLED_FLAG, IPA_TRUE_VALUE, - IPA_HOST_CATEGORY, "all", - IPA_MEMBER_HOST, host_dn_clean); - if (state->hbac_filter == NULL) { - ret = ENOMEM; - goto fail; - } - talloc_zfree(host_dn_clean); - - for (i = 0; memberof[i] != NULL; i++) { - state->hbac_filter = talloc_asprintf_append(state->hbac_filter, - "(%s=%s)", - IPA_MEMBER_HOST, - memberof[i]); - if (state->hbac_filter == NULL) { - ret = ENOMEM; - goto fail; - } - } - state->hbac_filter = talloc_asprintf_append(state->hbac_filter, "))"); - if (state->hbac_filter == NULL) { - ret = ENOMEM; - goto fail; - } - - DEBUG(9, ("HBAC rule filter: [%s].\n", state->hbac_filter)); - - if (hbac_ctx_is_offline(state->hbac_ctx)) { - ret = hbac_sysdb_data_recv(state, hbac_ctx_sysdb(state->hbac_ctx), - hbac_ctx_be(state->hbac_ctx)->domain, - state->hbac_filter, HBAC_RULES_SUBDIR, - state->hbac_attrs, - &state->hbac_reply_count, - &state->hbac_reply_list); - if (ret) { - DEBUG(1, ("hbac_sysdb_data_recv failed.\n")); - goto fail; - } - tevent_req_done(req); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; - } - - sdap_handle = sdap_id_op_handle(hbac_ctx_sdap_id_op(state->hbac_ctx)); - if (sdap_handle == NULL) { - DEBUG(1, ("Bug: sdap_id_op is disconnected.\n")); - ret = EIO; - goto fail; - } - subreq = sdap_get_generic_send(state, hbac_ctx_ev(state->hbac_ctx), - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts, - sdap_handle, - state->hbac_ctx->hbac_search_base, - LDAP_SCOPE_SUB, - state->hbac_filter, - state->hbac_attrs, - NULL, 0, - dp_opt_get_int( - hbac_ctx_sdap_id_ctx(state->hbac_ctx)->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT)); - - if (subreq == NULL) { - DEBUG(1, ("sdap_get_generic_send failed.\n")); - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, hbac_rule_get_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, hbac_ctx_ev(state->hbac_ctx)); - return req; -} - -static void hbac_rule_get_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct hbac_get_rules_state *state = tevent_req_data(req, - struct hbac_get_rules_state); - int ret; - - ret = hbac_sdap_data_recv(subreq, state, &state->hbac_reply_count, - &state->hbac_reply_list); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int hbac_get_rules_recv(struct tevent_req *req, TALLOC_CTX *memctx, - size_t *hbac_rule_count, - struct sysdb_attrs ***hbac_rule_list) -{ - struct hbac_get_rules_state *state = tevent_req_data(req, - struct hbac_get_rules_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *hbac_rule_count = state->hbac_reply_count; - *hbac_rule_list = talloc_steal(memctx, state->hbac_reply_list); - /* we do not need to steal each hbac_reply_list[i] - * as it belongs to hbac_reply_list memory block */ - return EOK; -} - enum hbac_result { HBAC_ALLOW = 1, HBAC_DENY, @@ -1221,442 +85,21 @@ enum check_result { RULE_ERROR }; -static errno_t get_service_data(const char *cn, size_t count, - struct sysdb_attrs **list, const char **dn, - struct ldb_message_element **mof) -{ - int ret; - int i; - int j; - struct ldb_message_element *el; - - for (i = 0; i < count; i++) { - ret = sysdb_attrs_get_el(list[i], IPA_CN, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return ENOENT; - } - if (el->num_values == 0) { - DEBUG(9, ("No cn found.\n")); - return ENOENT; - } else { - for (j = 0; j < el->num_values; j++) { - if (strlen(cn) == el->values[j].length && - strncmp(cn, (const char *) el->values[j].data, - el->values[j].length) == 0) { - - ret = sysdb_attrs_get_string(list[i], SYSDB_ORIG_DN, dn); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_string failed.\n")); - return ret; - } - - ret = sysdb_attrs_get_el(list[i], SYSDB_ORIG_MEMBEROF, mof); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return ret; - } - - return EOK; - } - } - } - } - - return ENOENT; -} - -enum check_result check_service(struct hbac_ctx *hbac_ctx, - struct sysdb_attrs *rule_attrs) -{ - int ret; - int i; - int g; - struct ldb_message_element *el; - const char *service_dn; - struct ldb_message_element *service_memberof; - - if (hbac_ctx->pd->service == NULL) { - DEBUG(1, ("No service in pam data, assuming error.\n")); - return RULE_ERROR; - } - - ret = sysdb_attrs_get_el(rule_attrs, IPA_SERVICE_CATEGORY, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - if (el->num_values == 0) { - DEBUG(9, ("Service category is not set.\n")); - } else { - for (i = 0; i < el->num_values; i++) { - if (strncasecmp("all", (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("Service category is set to 'all', rule applies.\n")); - return RULE_APPLICABLE; - } - DEBUG(9, ("Unsupported service category [%.*s].\n", - el->values[i].length, - (char *) el->values[i].data)); - } - } - - ret = get_service_data(hbac_ctx->pd->service, hbac_ctx->hbac_services_count, - hbac_ctx->hbac_services_list, &service_dn, - &service_memberof); - if (ret != EOK) { - DEBUG(1, ("Cannot find original DN for service [%s].\n", - hbac_ctx->pd->service)); - return RULE_ERROR; - } - DEBUG(9, ("OriginalDN for service [%s]: [%s].\n", hbac_ctx->pd->service, - service_dn)); - - ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_SERVICE, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - if (el->num_values == 0) { - DEBUG(9, ("No service or service group specified, rule does not apply.\n")); - return RULE_NOT_APPLICABLE; - } - - for (i = 0; i < el->num_values; i++) { - if (strncmp(service_dn, (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("Service [%s] found in the list of allowed " - "services.\n", hbac_ctx->pd->service)); - return RULE_APPLICABLE; - } - - for (g = 0; g < service_memberof->num_values; g++) { - if (service_memberof->values[g].length == el->values[i].length && - strncmp((const char *) service_memberof->values[g].data, - (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("Service [%s] is a member of a group in the list of " - "allowed service groups.\n", hbac_ctx->pd->service)); - return RULE_APPLICABLE; - } - } - } - - DEBUG(9, ("Service [%s] was not found in the list of allowed services and " - "service groups.\n", hbac_ctx->pd->service)); - return RULE_NOT_APPLICABLE; -} - -enum check_result check_user(struct hbac_ctx *hbac_ctx, - struct sysdb_attrs *rule_attrs) -{ - int ret; - int i; - int g; - struct ldb_message_element *el; - - if (hbac_ctx->user_dn == NULL) { - DEBUG(1, ("No user DN available, this should never happen.\n")); - return RULE_ERROR; - } - - ret = sysdb_attrs_get_el(rule_attrs, IPA_USER_CATEGORY, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - if (el->num_values == 0) { - DEBUG(9, ("User category is not set.\n")); - } else { - for (i = 0; i < el->num_values; i++) { - if (strncasecmp("all", (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("User category is set to 'all', rule applies.\n")); - return RULE_APPLICABLE; - } - DEBUG(9, ("Unsupported user category [%.*s].\n", - el->values[i].length, - (char *) el->values[i].data)); - } - } - - ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_USER, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - if (el->num_values == 0) { - DEBUG(9, ("No user specified, rule does not apply.\n")); - return RULE_NOT_APPLICABLE; - } else { - for (i = 0; i < el->num_values; i++) { - DEBUG(9, ("Searching matches for [%.*s].\n", el->values[i].length, - (const char *) el->values[i].data)); - DEBUG(9, ("Checking user [%s].\n", hbac_ctx->user_dn)); - if (strncmp(hbac_ctx->user_dn, (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("User [%s] found, rule applies.\n", - hbac_ctx->user_dn)); - return RULE_APPLICABLE; - } - - for (g = 0; g < hbac_ctx->groups_count; g++) { - DEBUG(9, ("Checking group [%s].\n", hbac_ctx->groups[g])); - if (strncmp(hbac_ctx->groups[g], - (const char *) el->values[i].data, - el->values[i].length) == 0) { - DEBUG(9, ("Group [%s] found, rule applies.\n", - hbac_ctx->groups[g])); - return RULE_APPLICABLE; - } - } - } - DEBUG(9, ("No matching user found, rule does not apply.\n")); - return RULE_NOT_APPLICABLE; - } - - return RULE_ERROR; -} - -enum check_result check_remote_hosts(const char *rhost, - struct hbac_host_info *hhi, - struct sysdb_attrs *rule_attrs) -{ - int ret; - int i; - int m; - struct ldb_message_element *cat_el; - struct ldb_message_element *src_el; - struct ldb_message_element *ext_el; - - if (hhi == NULL && (rhost == NULL || *rhost == '\0')) { - DEBUG(1, ("No remote host information specified, assuming error.\n")); - return RULE_ERROR; - } - - ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST_CATEGORY, &cat_el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - if (cat_el->num_values == 0) { - DEBUG(9, ("Source host category not set.\n")); - } else { - for(i = 0; i < cat_el->num_values; i++) { - if (strncasecmp("all", (const char *) cat_el->values[i].data, - cat_el->values[i].length) == 0) { - DEBUG(9, ("Source host category is set to 'all', " - "rule applies.\n")); - return RULE_APPLICABLE; - } - DEBUG(9, ("Unsupported source hosts category [%.*s].\n", - cat_el->values[i].length, - (char *) cat_el->values[i].data)); - } - } - - ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST, &src_el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - ret = sysdb_attrs_get_el(rule_attrs, IPA_EXTERNAL_HOST, &ext_el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return RULE_ERROR; - } - - if (src_el->num_values == 0 && ext_el->num_values == 0) { - DEBUG(9, ("No remote host specified in rule, rule does not apply.\n")); - return RULE_NOT_APPLICABLE; - } else { - if (hhi != NULL) { - for (i = 0; i < src_el->num_values; i++) { - if (strncasecmp(hhi->dn, (const char *) src_el->values[i].data, - src_el->values[i].length) == 0) { - DEBUG(9, ("Source host [%s] found, rule applies.\n", - hhi->dn)); - return RULE_APPLICABLE; - } - for (m = 0; hhi->memberof[m] != NULL; m++) { - if (strncasecmp(hhi->memberof[m], - (const char *) src_el->values[i].data, - src_el->values[i].length) == 0) { - DEBUG(9, ("Source host group [%s] found, rule applies.\n", - hhi->memberof[m])); - return RULE_APPLICABLE; - } - } - } - } - - if (rhost != NULL && *rhost != '\0') { - for (i = 0; i < ext_el->num_values; i++) { - if (strncasecmp(rhost, (const char *) ext_el->values[i].data, - ext_el->values[i].length) == 0) { - DEBUG(9, ("External host [%s] found, rule applies.\n", - rhost)); - return RULE_APPLICABLE; - } - } - } - DEBUG(9, ("No matching remote host found.\n")); - return RULE_NOT_APPLICABLE; - } - - return RULE_ERROR; -} - -static errno_t check_if_rule_applies(struct hbac_ctx *hbac_ctx, - struct sysdb_attrs *rule_attrs, - enum hbac_result *result) { - int ret; - struct ldb_message_element *el; - enum hbac_result rule_type; - char *rule_name; - struct pam_data *pd = hbac_ctx->pd; - - ret = sysdb_attrs_get_el(rule_attrs, IPA_CN, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return ret; - } - if (el->num_values == 0) { - DEBUG(4, ("rule has no name, assuming '(none)'.\n")); - rule_name = talloc_strdup(rule_attrs, "(none)"); - } else { - rule_name = talloc_strndup(rule_attrs, (const char*) el->values[0].data, - el->values[0].length); - } - if (rule_name == NULL) { - DEBUG(1, ("talloc_strdup failed.\n")); - return ENOMEM; - } - DEBUG(9, ("Processsing rule [%s].\n", rule_name)); - - ret = sysdb_attrs_get_el(rule_attrs, IPA_ENABLED_FLAG, &el); - if (ret != EOK) { - DEBUG(1, ("Failed to find out if rule is enabled or not, " - "assuming it is enabled.\n")); - } else { - if (el->num_values == 0) { - DEBUG(1, ("Failed to find out if rule is enabled or not, " - "assuming it is enabled.\n")); - } else { - if (strncasecmp("false", (const char*) el->values[0].data, - el->values[0].length) == 0) { - DEBUG(7, ("Rule is disabled.\n")); - *result = HBAC_NOT_APPLICABLE; - return EOK; - } - } - } - - /* rule type */ - ret = sysdb_attrs_get_el(rule_attrs, IPA_ACCESS_RULE_TYPE, &el); - if (ret != EOK) { - DEBUG(1, ("sysdb_attrs_get_el failed.\n")); - return ret; - } - if (el->num_values == 0) { - DEBUG(4, ("rule has no type, assuming 'deny'.\n")); - rule_type = HBAC_DENY; - } else if (el->num_values == 1) { - if (strncasecmp((const char *) el->values[0].data, "allow", - el->values[0].length) == 0) { - rule_type = HBAC_ALLOW; - } else { - rule_type = HBAC_DENY; - } - } else { - DEBUG(1, ("rule has an unsupported number of values [%d].\n", - el->num_values)); - return EINVAL; - } - - ret = check_service(hbac_ctx, rule_attrs); - if (ret != RULE_APPLICABLE) { - goto not_applicable; - } - - ret = check_user(hbac_ctx, rule_attrs); - if (ret != RULE_APPLICABLE) { - goto not_applicable; - } - - ret = check_remote_hosts(pd->rhost, hbac_ctx->remote_hhi, rule_attrs); - if (ret != RULE_APPLICABLE) { - goto not_applicable; - } - - *result = rule_type; - - return EOK; - -not_applicable: - if (ret == RULE_NOT_APPLICABLE) { - *result = HBAC_NOT_APPLICABLE; - } else { - *result = HBAC_DENY; - } - return EOK; -} - -static int evaluate_ipa_hbac_rules(struct hbac_ctx *hbac_ctx, - bool *access_allowed) -{ - bool allow_matched = false; - enum hbac_result result; - int ret; - int i; - - *access_allowed = false; - - for (i = 0; i < hbac_ctx->hbac_rule_count ; i++) { - - ret = check_if_rule_applies(hbac_ctx, hbac_ctx->hbac_rule_list[i], - &result); - if (ret != EOK) { - DEBUG(1, ("check_if_rule_applies failed.\n")); - return ret; - } - - switch (result) { - case HBAC_DENY: - DEBUG(3, ("Access denied by single rule.\n")); - return EOK; - break; - case HBAC_ALLOW: - allow_matched = true; - DEBUG(9, ("Current rule allows access.\n")); - break; - default: - DEBUG(9, ("Current rule does not apply.\n")); - } - - } - - *access_allowed = allow_matched; - - return EOK; -} - static int hbac_retry(struct hbac_ctx *hbac_ctx); static void hbac_connect_done(struct tevent_req *subreq); 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 hbac_get_host_info_done(struct tevent_req *req); -static void hbac_get_rules_done(struct tevent_req *req); -static void hbac_get_service_data_done(struct tevent_req *req); + +static void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx); void ipa_access_handler(struct be_req *be_req) { struct pam_data *pd; struct hbac_ctx *hbac_ctx; + const char *deny_method; int pam_status = PAM_SYSTEM_ERR; struct ipa_access_ctx *ipa_access_ctx; - bool offline; int ret; pd = talloc_get_type(be_req->req_data, struct pam_data); @@ -1666,11 +109,13 @@ void ipa_access_handler(struct be_req *be_req) DEBUG(1, ("talloc failed.\n")); goto fail; } + hbac_ctx->be_req = be_req; hbac_ctx->pd = pd; ipa_access_ctx = talloc_get_type( be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, struct ipa_access_ctx); + hbac_ctx->access_ctx = ipa_access_ctx; hbac_ctx->sdap_ctx = ipa_access_ctx->sdap_ctx; hbac_ctx->ipa_options = ipa_access_ctx->ipa_options; hbac_ctx->tr_ctx = ipa_access_ctx->tr_ctx; @@ -1681,16 +126,12 @@ void ipa_access_handler(struct be_req *be_req) goto fail; } - offline = be_is_offline(be_req->be_ctx); - DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online")); - - if (!offline) { - hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx, - hbac_ctx_sdap_id_ctx(hbac_ctx)->conn_cache); - if (!hbac_ctx->sdap_op) { - DEBUG(1, ("sdap_id_op_create failed.\n")); - goto fail; - } + deny_method = dp_opt_get_string(hbac_ctx->ipa_options, + IPA_HBAC_DENY_METHOD); + if (strcasecmp(deny_method, "IGNORE") == 0) { + hbac_ctx->get_deny_rules = false; + } else { + hbac_ctx->get_deny_rules = true; } ret = hbac_retry(hbac_ctx); @@ -1713,18 +154,48 @@ static int hbac_retry(struct hbac_ctx *hbac_ctx) { struct tevent_req *subreq; int ret; + bool offline; + time_t now, refresh_interval; + struct ipa_access_ctx *access_ctx = hbac_ctx->access_ctx; - if (hbac_ctx_is_offline(hbac_ctx)) { - return hbac_get_host_info_step(hbac_ctx); - } + offline = be_is_offline(hbac_ctx->be_req->be_ctx); + DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online")); + + refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options, + IPA_HBAC_REFRESH); - 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; + now = time(NULL); + if (now < access_ctx->last_update + refresh_interval) { + /* Simulate offline mode and just go to the cache */ + DEBUG(6, ("Performing cached HBAC evaluation\n")); + offline = true; } - tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx); + 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; + } + } + + 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; + } + + 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; + } return EOK; } @@ -1739,6 +210,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; } @@ -1754,6 +228,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) { @@ -1774,6 +266,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; } @@ -1790,173 +286,374 @@ 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; - } - 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]); - } - - subreq = hbac_get_host_info_send(hbac_ctx, hbac_ctx, hostlist); - if (!subreq) { - DEBUG(1, ("hbac_get_host_info_send failed.\n")); + 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; } + tevent_req_set_callback(req, hbac_get_service_info_step, hbac_ctx); - tevent_req_set_callback(subreq, hbac_get_host_info_done, hbac_ctx); return EOK; } -static void hbac_get_host_info_done(struct tevent_req *req) +static void hbac_get_service_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; - const char *ipa_hostname; - struct hbac_host_info *local_hhi = NULL; + errno_t ret; + struct hbac_ctx *hbac_ctx = + tevent_req_callback_data(req, struct hbac_ctx); - ret = hbac_get_host_info_recv(req, hbac_ctx, &hbac_ctx->hbac_hosts_count, - &hbac_ctx->hbac_hosts_list); + 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; + } + + /* 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; + +fail: + ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR); +} +static void hbac_get_rule_info_step(struct tevent_req *req) +{ + errno_t ret; + size_t i; + const char *ipa_hostname; + 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; - - hbac_ctx->hbac_rule_count = 0; - talloc_zfree(hbac_ctx->hbac_rule_list); + 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 = hbac_get_rules_recv(req, hbac_ctx, &hbac_ctx->hbac_rule_count, - &hbac_ctx->hbac_rule_list); + 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; + } + + 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; + } + + /* 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; - tevent_req_set_callback(req, hbac_get_service_data_done, hbac_ctx); - return; + /* 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; + } -failed: - ipa_access_reply(hbac_ctx, pam_status); -} + /* 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; + } -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; + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(0, ("Failed to commit transaction\n")); + goto fail; + } - hbac_ctx->hbac_services_count = 0; - talloc_zfree(hbac_ctx->hbac_services_list); + /* We don't need the rule data any longer, + * the rest of the processing relies on + * sysdb lookups. + */ + hbac_clear_rule_data(hbac_ctx); - ret = hbac_get_service_data_recv(req, hbac_ctx, - &hbac_ctx->hbac_services_count, - &hbac_ctx->hbac_services_list); - talloc_zfree(req); - if (!hbac_check_step_result(hbac_ctx, ret)) { - return; - } + access_ctx->last_update = time(NULL); - if (hbac_ctx->user_dn) { - talloc_free(discard_const_p(TALLOC_CTX, hbac_ctx->user_dn)); - hbac_ctx->user_dn = 0; - } + /* Now evaluate the request against the rules */ + ipa_hbac_evaluate_rules(hbac_ctx); + + return; - if (!hbac_ctx_is_offline(hbac_ctx)) { - ret = hbac_save_data_to_sysdb(hbac_ctx); +fail: + if (in_transaction) { + ret = sysdb_transaction_cancel(sysdb); if (ret != EOK) { - DEBUG(1, ("Failed to save data, " - "offline authentication might not work.\n")); - /* This is not a fatal error. */ + 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); - hbac_ctx->groups_count = 0; - talloc_zfree(hbac_ctx->groups); +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; - 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); + /* Get HBAC rules from the sysdb */ + ret = hbac_get_cached_rules(hbac_ctx, hbac_ctx); if (ret != EOK) { - goto failed; + DEBUG(1, ("Could not retrieve rules from the cache\n")); + ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR); } - ret = evaluate_ipa_hbac_rules(hbac_ctx, &access_allowed); - if (ret != EOK) { - DEBUG(1, ("evaluate_ipa_hbac_rules failed.\n")); - goto failed; + 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; } - if (access_allowed) { - pam_status = PAM_SUCCESS; - DEBUG(5, ("Access allowed.\n")); - } else { - pam_status = PAM_PERM_DENIED; - DEBUG(3, ("Access denied.\n")); + 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; + } + + DEBUG(3, ("Access denied by HBAC rules\n")); + hbac_free_info(info); + 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 = 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; + } + + 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; } |