diff options
author | Sumit Bose <sbose@redhat.com> | 2010-05-19 15:23:34 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-06-02 11:11:51 -0400 |
commit | c5b4479301dbf1ac9dd82b6b41e436ec28d08c82 (patch) | |
tree | 1bc77372e3575d2a1074b6ce36ed3cebc4c462a7 /src/providers | |
parent | 1f77bdebb06d9d1e2d3ca5479904afa292f09658 (diff) | |
download | sssd-c5b4479301dbf1ac9dd82b6b41e436ec28d08c82.tar.gz sssd-c5b4479301dbf1ac9dd82b6b41e436ec28d08c82.tar.bz2 sssd-c5b4479301dbf1ac9dd82b6b41e436ec28d08c82.zip |
Use new schema for HBAC service checks
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/ipa/ipa_access.c | 658 | ||||
-rw-r--r-- | src/providers/ipa/ipa_access.h | 4 |
2 files changed, 641 insertions, 21 deletions
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index 56bb269d..bd324518 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -31,7 +31,8 @@ #include "providers/ipa/ipa_access.h" #include "providers/ipa/ipa_timerules.h" -#define IPA_HOST_MEMBEROF "memberOf" +#define OBJECTCLASS "objectclass" +#define IPA_MEMBEROF "memberOf" #define IPA_HOST_SERVERHOSTNAME "serverHostName" #define IPA_HOST_FQDN "fqdn" #define IPA_ACCESS_RULE_TYPE "accessRuleType" @@ -47,14 +48,21 @@ #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_SERVICEGROUP_MEMBER "member" #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 IPA_SERVICEGROUPS_BASE_TMPL "cn=hbacservicegroups,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" +#define HBAC_SERVICEGROUPS_SUBDIR "hbac_servicegroups" static errno_t msgs2attrs_array(TALLOC_CTX *mem_ctx, size_t count, struct ldb_message **msgs, @@ -98,6 +106,490 @@ static void ipa_access_reply(struct be_req *be_req, int pam_status) } } +struct hbac_get_service_data_state { + struct tevent_context *ev; + struct sdap_id_ctx *sdap_ctx; + struct sysdb_ctx *sysdb; + struct sysdb_handle *handle; + const char *basedn; + bool offline; + + char *services_filter; + char *services_search_base; + const char **services_attrs; + struct sysdb_attrs **services_reply_list; + size_t services_reply_count; + + char *servicegroups_filter; + char *servicegroups_search_base; + const char **servicegroups_attrs; + struct sysdb_attrs **servicegroups_reply_list; + size_t servicegroups_reply_count; + + size_t current_item; +}; + +static void hbac_get_services_connect_done(struct tevent_req *subreq); +static void hbac_services_get_done(struct tevent_req *subreq); +static void hbac_get_servicegroups(struct tevent_req *req); +static void hbac_servicegroups_get_done(struct tevent_req *subreq); + +struct tevent_req *hbac_get_service_data_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + bool offline, + struct sdap_id_ctx *sdap_ctx, + struct sysdb_ctx *sysdb, + const char *basedn) +{ + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct hbac_get_service_data_state *state; + int ret; + struct ldb_message **msgs; + + 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->ev = ev; + state->offline = offline; + state->sdap_ctx = sdap_ctx; + state->sysdb = sysdb; + state->handle = NULL; + state->basedn = basedn; + + state->services_reply_list = NULL; + state->services_reply_count = 0; + + state->servicegroups_filter = NULL; + state->servicegroups_search_base = NULL; + state->servicegroups_attrs = NULL; + state->servicegroups_reply_list = NULL; + state->servicegroups_reply_count = 0; + + state->current_item = 0; + + state->services_search_base = talloc_asprintf(state, IPA_SERVICES_BASE_TMPL, + basedn); + if (state->services_search_base == NULL) { + DEBUG(1, ("Failed to create service search base.\n")); + ret = ENOMEM; + goto fail; + } + + 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 (offline) { + ret = sysdb_search_custom(state, state->sysdb, + state->sdap_ctx->be->domain, + state->services_filter, HBAC_SERVICES_SUBDIR, + state->services_attrs, + &state->services_reply_count, &msgs); + if (ret) { + DEBUG(1, ("sysdb_search_custom failed.\n")); + goto fail; + } + + ret = msgs2attrs_array(state, state->services_reply_count, msgs, + &state->services_reply_list); + talloc_zfree(msgs); + if (ret != EOK) { + DEBUG(1, ("msgs2attrs_array failed.\n")); + goto fail; + } + hbac_get_servicegroups(req); + tevent_req_post(req, ev); + return req; + } + + if (sdap_ctx->gsh == NULL || ! sdap_ctx->gsh->connected) { + subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts, + sdap_ctx->be, sdap_ctx->service, NULL); + if (!subreq) { + DEBUG(1, ("sdap_cli_connect_send failed.\n")); + ret = ENOMEM; + goto fail; + } + + tevent_req_set_callback(subreq, hbac_get_services_connect_done, req); + + return req; + } + + subreq = sdap_get_generic_send(state, state->ev, + state->sdap_ctx->opts, + state->sdap_ctx->gsh, + state->services_search_base, + LDAP_SCOPE_SUB, + state->services_filter, + state->services_attrs, + NULL, 0); + + 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, ev); + return req; +} + +static void hbac_get_services_connect_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 = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh, + NULL); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + subreq = sdap_get_generic_send(state, state->ev, + state->sdap_ctx->opts, + state->sdap_ctx->gsh, + state->services_search_base, + LDAP_SCOPE_SUB, + state->services_filter, + state->services_attrs, + NULL, 0); + + 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; + +fail: + tevent_req_error(req, ret); + return; +} + +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 = sdap_get_generic_recv(subreq, state, &state->services_reply_count, + &state->services_reply_list); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + hbac_get_servicegroups(req); + return; +} + +static void hbac_get_servicegroups(struct tevent_req *req) +{ + struct hbac_get_service_data_state *state = tevent_req_data(req, + struct hbac_get_service_data_state); + int ret; + struct ldb_message **msgs; + struct tevent_req *subreq; + + state->servicegroups_search_base = talloc_asprintf(state, + IPA_SERVICEGROUPS_BASE_TMPL, + state->basedn); + if (state->servicegroups_search_base == NULL) { + DEBUG(1, ("Failed to create service groups search base.\n")); + ret = ENOMEM; + goto fail; + } + + state->servicegroups_attrs = talloc_array(state, const char *, 8); + if (state->servicegroups_attrs == NULL) { + DEBUG(1, ("Failed to allocate servicegroup attribute list.\n")); + ret = ENOMEM; + goto fail; + } + state->servicegroups_attrs[0] = IPA_CN; + state->servicegroups_attrs[1] = IPA_SERVICEGROUP_MEMBER; + state->servicegroups_attrs[2] = SYSDB_ORIG_DN; + state->servicegroups_attrs[3] = IPA_UNIQUE_ID; + state->servicegroups_attrs[4] = IPA_MEMBEROF; + state->servicegroups_attrs[5] = SYSDB_ORIG_MEMBEROF; + state->servicegroups_attrs[6] = OBJECTCLASS; + state->servicegroups_attrs[7] = NULL; + + state->servicegroups_filter = talloc_asprintf(state, + "(objectclass=ipaHBACServiceGroup)"); + if (state->servicegroups_filter == NULL) { + ret = ENOMEM; + goto fail; + } + + DEBUG(9, ("Services filter: [%s].\n", state->servicegroups_filter)); + + if (state->offline) { + ret = sysdb_search_custom(state, state->sysdb, + state->sdap_ctx->be->domain, + state->servicegroups_filter, + HBAC_SERVICEGROUPS_SUBDIR, + state->servicegroups_attrs, + &state->servicegroups_reply_count, &msgs); + if (ret) { + DEBUG(1, ("sysdb_search_custom failed.\n")); + goto fail; + } + + ret = msgs2attrs_array(state, state->servicegroups_reply_count, msgs, + &state->servicegroups_reply_list); + talloc_zfree(msgs); + if (ret != EOK) { + DEBUG(1, ("msgs2attrs_array failed.\n")); + goto fail; + } + tevent_req_done(req); + return; + } + + subreq = sdap_get_generic_send(state, state->ev, + state->sdap_ctx->opts, + state->sdap_ctx->gsh, + state->servicegroups_search_base, + LDAP_SCOPE_SUB, + state->servicegroups_filter, + state->servicegroups_attrs, + NULL, 0); + + if (subreq == NULL) { + DEBUG(1, ("sdap_get_generic_send failed.\n")); + ret = ENOMEM; + goto fail; + } + + tevent_req_set_callback(subreq, hbac_servicegroups_get_done, req); + return; + +fail: + tevent_req_error(req, ret); + return; +} + +static void hbac_servicegroups_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; + bool in_transaction = false; + struct ldb_dn *base_dn; + int i; + struct ldb_message_element *el; + char *object_name; + + ret = sdap_get_generic_recv(subreq, state, + &state->servicegroups_reply_count, + &state->servicegroups_reply_list); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + if ((state->services_reply_count == 0 && + state->servicegroups_reply_count == 0)|| state->offline) { + tevent_req_done(req); + return; + } + + ret = sysdb_transaction_start(state->sysdb); + if (ret != EOK) { + DEBUG(1, ("sysdb_transaction_start failed.\n")); + tevent_req_error(req, ret); + return; + } + in_transaction = true; + + base_dn = sysdb_custom_subtree_dn(state->sysdb, state, + state->sdap_ctx->be->domain->name, + HBAC_SERVICES_SUBDIR); + if (base_dn == NULL) { + ret = ENOMEM; + goto fail; + } + + ret = sysdb_delete_recursive(state, state->sysdb, base_dn, true); + if (ret) { + DEBUG(1, ("sysdb_delete_recursive failed.\n")); + goto fail; + } + + base_dn = sysdb_custom_subtree_dn(state->sysdb, state, + state->sdap_ctx->be->domain->name, + HBAC_SERVICEGROUPS_SUBDIR); + if (base_dn == NULL) { + ret = ENOMEM; + goto fail; + } + + ret = sysdb_delete_recursive(state, state->sysdb, base_dn, true); + if (ret) { + DEBUG(1, ("sysdb_delete_recursive failed.\n")); + goto fail; + } + + for (i = 0; i < state->services_reply_count; i++) { + ret = sysdb_attrs_get_el(state->services_reply_list[i], IPA_UNIQUE_ID, + &el); + if (ret != EOK) { + DEBUG(1, ("sysdb_attrs_get_el failed.\n")); + goto fail; + } + if (el->num_values == 0) { + ret = EINVAL; + goto fail; + } + object_name = talloc_strndup(state, (const char *)el->values[0].data, + el->values[0].length); + if (object_name == NULL) { + ret = ENOMEM; + goto fail; + } + DEBUG(9, ("Object name: [%s].\n", object_name)); + + ret = sysdb_attrs_replace_name(state->services_reply_list[i], + IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF); + if (ret != EOK) { + DEBUG(1, ("sysdb_attrs_replace_name failed.\n")); + goto fail; + } + + ret = sysdb_store_custom(state, state->sysdb, + state->sdap_ctx->be->domain, object_name, + HBAC_SERVICES_SUBDIR, + state->services_reply_list[i]); + if (ret) { + DEBUG(1, ("sysdb_store_custom failed.\n")); + goto fail; + } + } + for (i = 0; i < state->servicegroups_reply_count; i++) { + ret = sysdb_attrs_get_el(state->servicegroups_reply_list[i], + IPA_UNIQUE_ID, &el); + if (ret != EOK) { + DEBUG(1, ("sysdb_attrs_get_el failed.\n")); + goto fail; + } + if (el->num_values == 0) { + ret = EINVAL; + goto fail; + } + object_name = talloc_strndup(state, (const char *)el->values[0].data, + el->values[0].length); + if (object_name == NULL) { + ret = ENOMEM; + goto fail; + } + DEBUG(9, ("Object name: [%s].\n", object_name)); + + ret = sysdb_attrs_replace_name(state->servicegroups_reply_list[i], + IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF); + if (ret != EOK) { + DEBUG(1, ("sysdb_attrs_replace_name failed.\n")); + goto fail; + } + + ret = sysdb_store_custom(state, state->sysdb, + state->sdap_ctx->be->domain, object_name, + HBAC_SERVICEGROUPS_SUBDIR, + state->servicegroups_reply_list[i]); + if (ret) { + DEBUG(1, ("sysdb_store_custom failed.\n")); + goto fail; + } + } + + ret = sysdb_transaction_commit(state->sysdb); + if (ret) { + DEBUG(1, ("sysdb_transaction_commit failed.\n")); + goto fail; + } + in_transaction = false; + + tevent_req_done(req); + return; + +fail: + if (in_transaction) { + sysdb_transaction_cancel(state->sysdb); + } + tevent_req_error(req, ret); + 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, + size_t *hbac_servicegroups_count, + struct sysdb_attrs ***hbac_servicegroups_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]); + } + + *hbac_servicegroups_count = state->servicegroups_reply_count; + *hbac_servicegroups_list = talloc_steal(memctx, + state->servicegroups_reply_list); + for (i = 0; i < state->servicegroups_reply_count; i++) { + talloc_steal(memctx, state->servicegroups_reply_list[i]); + } + return EOK; +} static int hbac_get_user_info(TALLOC_CTX *memctx, struct be_ctx *be_ctx, @@ -299,7 +791,7 @@ static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, ret = ENOMEM; goto fail; } - state->host_attrs[0] = IPA_HOST_MEMBEROF; + 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"; @@ -579,7 +1071,7 @@ static void hbac_get_host_memberof(struct tevent_req *req, ret = sysdb_attrs_replace_name(state->host_reply_list[i], - IPA_HOST_MEMBEROF, SYSDB_ORIG_MEMBEROF); + IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF); if (ret != EOK) { DEBUG(1, ("sysdb_attrs_replace_name failed.\n")); goto fail; @@ -697,7 +1189,7 @@ static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx, goto fail; } - state->hbac_attrs = talloc_array(state, const char *, 16); + state->hbac_attrs = talloc_array(state, const char *, 18); if (state->hbac_attrs == NULL) { DEBUG(1, ("Failed to allocate HBAC attribute list.\n")); ret = ENOMEM; @@ -714,11 +1206,13 @@ static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx, state->hbac_attrs[8] = IPA_UNIQUE_ID; state->hbac_attrs[9] = IPA_ENABLED_FLAG; state->hbac_attrs[10] = IPA_CN; - state->hbac_attrs[11] = "objectclass"; + state->hbac_attrs[11] = OBJECTCLASS; state->hbac_attrs[12] = IPA_MEMBER_HOST; state->hbac_attrs[13] = IPA_HOST_CATEGORY; - state->hbac_attrs[14] = SYSDB_ORIG_DN; - state->hbac_attrs[15] = NULL; + state->hbac_attrs[14] = IPA_MEMBER_SERVICE; + state->hbac_attrs[15] = IPA_SERVICE_CATEGORY; + state->hbac_attrs[16] = SYSDB_ORIG_DN; + state->hbac_attrs[17] = NULL; state->hbac_filter = talloc_asprintf(state, "(&(objectclass=ipaHBACRule)" @@ -1004,41 +1498,129 @@ enum check_result { RULE_ERROR }; -enum check_result check_service(struct pam_data *pd, +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 (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 (pd->service == NULL) { + 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_NAME, &el); + 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, ("No services in rule specified, assuming rule applies.\n")); - return RULE_APPLICABLE; + DEBUG(9, ("Service category is not set.\n")); } else { for (i = 0; i < el->num_values; i++) { - if (strlen(pd->service) == el->values[i].length && - strncasecmp(pd->service, (const char *) el->values[i].data, + if (strncasecmp("all", (const char *) el->values[i].data, el->values[i].length) == 0) { - DEBUG(9, ("Service [%s] found, rule applies.\n", - pd->service)); + 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)); } - DEBUG(9, ("No matching service found, rule does not apply.\n")); + } + + 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; } - return RULE_ERROR; + 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_access_time(struct time_rules_ctx *tr_ctx, @@ -1325,7 +1907,7 @@ static errno_t check_if_rule_applies(struct hbac_ctx *hbac_ctx, return EINVAL; } - ret = check_service(pd, rule_attrs); + ret = check_service(hbac_ctx, rule_attrs); if (ret != RULE_APPLICABLE) { goto not_applicable; } @@ -1399,6 +1981,7 @@ static int evaluate_ipa_hbac_rules(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); void ipa_access_handler(struct be_req *be_req) { @@ -1533,11 +2116,9 @@ fail: static void hbac_get_rules_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; struct be_req *be_req = hbac_ctx->be_req; int ret; int pam_status = PAM_SYSTEM_ERR; - bool access_allowed = false; ret = hbac_get_rules_recv(req, hbac_ctx, &hbac_ctx->hbac_rule_count, &hbac_ctx->hbac_rule_list); @@ -1546,6 +2127,41 @@ static void hbac_get_rules_done(struct tevent_req *req) goto failed; } + req = hbac_get_service_data_send(hbac_ctx, be_req->be_ctx->ev, + hbac_ctx->offline, hbac_ctx->sdap_ctx, + be_req->be_ctx->sysdb, + hbac_ctx->ldap_basedn); + if (req == NULL) { + DEBUG(1, ("hbac_get_service_data_send failed.\n")); + goto failed; + } + + tevent_req_set_callback(req, hbac_get_service_data_done, hbac_ctx); + return; + +failed: + ipa_access_reply(be_req, pam_status); +} + +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; + struct be_req *be_req = hbac_ctx->be_req; + int ret; + int pam_status = PAM_SYSTEM_ERR; + bool access_allowed = false; + + ret = hbac_get_service_data_recv(req, hbac_ctx, + &hbac_ctx->hbac_services_count, + &hbac_ctx->hbac_services_list, + &hbac_ctx->hbac_servicegroups_count, + &hbac_ctx->hbac_servicegroups_list); + talloc_zfree(req); + if (ret != EOK) { + goto failed; + } + ret = hbac_get_user_info(hbac_ctx, be_req->be_ctx, pd->user, &hbac_ctx->user_dn, &hbac_ctx->groups_count, &hbac_ctx->groups); diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h index e3ba5c30..e3e0c4ff 100644 --- a/src/providers/ipa/ipa_access.h +++ b/src/providers/ipa/ipa_access.h @@ -60,6 +60,10 @@ struct hbac_ctx { const char **groups; bool offline; char *ldap_basedn; + struct sysdb_attrs **hbac_services_list; + size_t hbac_services_count; + struct sysdb_attrs **hbac_servicegroups_list; + size_t hbac_servicegroups_count; }; void ipa_access_handler(struct be_req *be_req); |