From 71ad247500b417836a1a2edec257a4433a7c415f Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Wed, 18 Jan 2012 11:08:06 -0500 Subject: Implemented support for multiple search bases in HBAC rules and services --- src/providers/ipa/ipa_hbac_services.c | 199 +++++++++++++++++++++++++++------- 1 file changed, 162 insertions(+), 37 deletions(-) (limited to 'src/providers/ipa/ipa_hbac_services.c') diff --git a/src/providers/ipa/ipa_hbac_services.c b/src/providers/ipa/ipa_hbac_services.c index cc4e6dea5..3bbdc8ba1 100644 --- a/src/providers/ipa/ipa_hbac_services.c +++ b/src/providers/ipa/ipa_hbac_services.c @@ -29,9 +29,14 @@ struct ipa_hbac_service_state { struct sysdb_ctx *sysdb; struct sdap_handle *sh; struct sdap_options *opts; - const char *search_base; const char **attrs; + char *service_filter; + char *cur_filter; + + struct sdap_search_base **search_bases; + int search_base_iter; + /* Return values */ size_t service_count; struct sysdb_attrs **services; @@ -40,8 +45,14 @@ struct ipa_hbac_service_state { struct sysdb_attrs **servicegroups; }; +static errno_t +ipa_hbac_service_info_next(struct tevent_req *req, + struct ipa_hbac_service_state *state); static void ipa_hbac_service_info_done(struct tevent_req *subreq); +static errno_t +ipa_hbac_servicegroup_info_next(struct tevent_req *req, + struct ipa_hbac_service_state *state); static void ipa_hbac_servicegroup_info_done(struct tevent_req *subreq); @@ -51,12 +62,11 @@ ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct sdap_handle *sh, struct sdap_options *opts, - const char *search_base) + struct sdap_search_base **search_bases) { errno_t ret; struct ipa_hbac_service_state *state; struct tevent_req *req; - struct tevent_req *subreq; char *service_filter; req = tevent_req_create(mem_ctx, &state, struct ipa_hbac_service_state); @@ -69,7 +79,9 @@ ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx, state->sysdb = sysdb; state->sh = sh; state->opts = opts; - state->search_base = search_base; + + state->search_bases = search_bases; + state->search_base_iter = 0; service_filter = talloc_asprintf(state, "(objectClass=%s)", IPA_HBAC_SERVICE); @@ -78,6 +90,9 @@ ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx, goto immediate; } + state->service_filter = service_filter; + state->cur_filter = NULL; + state->attrs = talloc_array(state, const char *, 6); if (state->attrs == NULL) { DEBUG(1, ("Failed to allocate service attribute list.\n")); @@ -91,17 +106,14 @@ ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx, state->attrs[4] = IPA_MEMBEROF; state->attrs[5] = NULL; - subreq = sdap_get_generic_send(state, ev, opts, sh, search_base, - LDAP_SCOPE_SUB, service_filter, - state->attrs, NULL, 0, - dp_opt_get_int(opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT)); - if (subreq == NULL) { - DEBUG(1, ("Error requesting service info\n")); - ret = EIO; + ret = ipa_hbac_service_info_next(req, state); + if (ret == EOK) { + ret = EINVAL; + } + + if (ret != EAGAIN) { goto immediate; } - tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req); return req; @@ -115,6 +127,43 @@ immediate: return req; } +static errno_t ipa_hbac_service_info_next(struct tevent_req *req, + struct ipa_hbac_service_state *state) +{ + struct tevent_req *subreq; + struct sdap_search_base *base; + + base = state->search_bases[state->search_base_iter]; + if (base == NULL) { + return EOK; + } + + talloc_zfree(state->cur_filter); + state->cur_filter = sdap_get_id_specific_filter(state, + state->service_filter, + base->filter); + if (state->cur_filter == NULL) { + return ENOMEM; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Sending request for next search base: " + "[%s][%d][%s]\n", base->basedn, base->scope, + base->filter)); + subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, + base->basedn, base->scope, + state->cur_filter, + state->attrs, NULL, 0, + dp_opt_get_int(state->opts->basic, + SDAP_ENUM_SEARCH_TIMEOUT)); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Error requesting service info\n")); + return EIO; + } + tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req); + + return EAGAIN; +} + static void ipa_hbac_service_info_done(struct tevent_req *subreq) { @@ -141,9 +190,14 @@ ipa_hbac_service_info_done(struct tevent_req *subreq) * There's no reason to try to process groups */ + state->search_base_iter++; + ret = ipa_hbac_service_info_next(req, state); + if (ret == EAGAIN) { + return; + } + state->service_count = 0; state->services = NULL; - ret = EOK; goto done; } @@ -162,18 +216,18 @@ ipa_hbac_service_info_done(struct tevent_req *subreq) goto done; } - /* Look up service groups */ - subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, - state->search_base, LDAP_SCOPE_SUB, - servicegroup_filter, state->attrs, NULL, 0, - dp_opt_get_int(state->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT)); - if (subreq == NULL) { - DEBUG(1, ("Error requesting host info\n")); - ret = EIO; + talloc_zfree(state->service_filter); + state->service_filter = servicegroup_filter; + + state->search_base_iter = 0; + ret = ipa_hbac_servicegroup_info_next(req, state); + if (ret == EOK) { + ret = EINVAL; + } + + if (ret != EAGAIN) { goto done; } - tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req); return; @@ -185,6 +239,44 @@ done: } } +static errno_t +ipa_hbac_servicegroup_info_next(struct tevent_req *req, + struct ipa_hbac_service_state *state) +{ + struct tevent_req *subreq; + struct sdap_search_base *base; + + base = state->search_bases[state->search_base_iter]; + if (base == NULL) { + return EOK; + } + + talloc_zfree(state->cur_filter); + state->cur_filter = sdap_get_id_specific_filter(state, + state->service_filter, + base->filter); + if (state->cur_filter == NULL) { + return ENOMEM; + } + + /* Look up service groups */ + DEBUG(SSSDBG_TRACE_FUNC, ("Sending request for next search base: " + "[%s][%d][%s]\n", base->basedn, base->scope, + base->filter)); + subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, + base->basedn, base->scope, + state->cur_filter, state->attrs, NULL, 0, + dp_opt_get_int(state->opts->basic, + SDAP_ENUM_SEARCH_TIMEOUT)); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Error requesting servicegroup info\n")); + return EIO; + } + tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req); + + return EAGAIN; +} + static void ipa_hbac_servicegroup_info_done(struct tevent_req *subreq) { @@ -193,28 +285,61 @@ ipa_hbac_servicegroup_info_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct tevent_req); struct ipa_hbac_service_state *state = tevent_req_data(req, struct ipa_hbac_service_state); + size_t total_count; + size_t group_count; + struct sysdb_attrs **groups; + struct sysdb_attrs **target; + int i; ret = sdap_get_generic_recv(subreq, state, - &state->servicegroup_count, - &state->servicegroups); + &group_count, + &groups); talloc_zfree(subreq); if (ret != EOK) { goto done; } - ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER, - state->servicegroup_count, - state->servicegroups); - if (ret != EOK) { - DEBUG(1, ("Could not replace attribute names\n")); - goto done; + if (group_count > 0) { + ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER, + group_count, + groups); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not replace attribute names\n")); + goto done; + } + + ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF, + state->servicegroup_count, + state->servicegroups); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not replace attribute names\n")); + goto done; + } + + total_count = state->servicegroup_count + group_count; + state->servicegroups = talloc_realloc(state, state->servicegroups, + struct sysdb_attrs *, + total_count); + if (state->servicegroups == NULL) { + ret = ENOMEM; + goto done; + } + + i = 0; + while (state->servicegroup_count < total_count) { + target = &state->servicegroups[state->servicegroup_count]; + *target = talloc_steal(state->servicegroups, groups[i]); + + state->servicegroup_count++; + i++; + } } - ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF, - state->servicegroup_count, - state->servicegroups); - if (ret != EOK) { - DEBUG(1, ("Could not replace attribute names\n")); + state->search_base_iter++; + ret = ipa_hbac_servicegroup_info_next(req, state); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { goto done; } -- cgit