summaryrefslogtreecommitdiff
path: root/src/providers/ipa
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-01-18 11:08:06 -0500
committerStephen Gallagher <sgallagh@redhat.com>2012-02-06 08:25:22 -0500
commit71ad247500b417836a1a2edec257a4433a7c415f (patch)
tree55ce381a9f7444b8aaea8d70ed02db2a9477b7e1 /src/providers/ipa
parent8a36504008872f03d1b1ca980adeceba28c331f5 (diff)
downloadsssd-71ad247500b417836a1a2edec257a4433a7c415f.tar.gz
sssd-71ad247500b417836a1a2edec257a4433a7c415f.tar.bz2
sssd-71ad247500b417836a1a2edec257a4433a7c415f.zip
Implemented support for multiple search bases in HBAC rules and services
Diffstat (limited to 'src/providers/ipa')
-rw-r--r--src/providers/ipa/ipa_access.c34
-rw-r--r--src/providers/ipa/ipa_access.h3
-rw-r--r--src/providers/ipa/ipa_common.c25
-rw-r--r--src/providers/ipa/ipa_common.h1
-rw-r--r--src/providers/ipa/ipa_hbac_private.h18
-rw-r--r--src/providers/ipa/ipa_hbac_rules.c157
-rw-r--r--src/providers/ipa/ipa_hbac_rules.h42
-rw-r--r--src/providers/ipa/ipa_hbac_services.c199
-rw-r--r--src/providers/ipa/ipa_init.c1
9 files changed, 364 insertions, 116 deletions
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index 4ee3d82a..7d42e8b4 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -31,30 +31,7 @@
#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)
-{
- char *base;
- int ret;
-
- base = dp_opt_get_string(ipa_options, IPA_HBAC_SEARCH_BASE);
- if (base != NULL) {
- return talloc_strdup(mem_ctx, base);
- }
-
- DEBUG(9, ("ipa_hbac_search_base not available, trying base DN.\n"));
-
- ret = domain_to_basedn(mem_ctx,
- dp_opt_get_string(ipa_options, IPA_KRB5_REALM),
- &base);
- if (ret != EOK) {
- DEBUG(1, ("domain_to_basedn failed.\n"));
- return NULL;
- }
-
- return base;
-}
+#include "providers/ipa/ipa_hbac_rules.h"
static void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status)
{
@@ -119,9 +96,8 @@ void ipa_access_handler(struct be_req *be_req)
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;
- hbac_ctx->hbac_search_base = get_hbac_search_base(hbac_ctx,
- hbac_ctx->ipa_options);
- if (hbac_ctx->hbac_search_base == NULL) {
+ hbac_ctx->search_bases = ipa_access_ctx->hbac_search_bases;
+ if (hbac_ctx->search_bases == NULL) {
DEBUG(1, ("No HBAC search base found.\n"));
goto fail;
}
@@ -334,7 +310,7 @@ static void hbac_get_service_info_step(struct tevent_req *req)
hbac_ctx_sysdb(hbac_ctx),
sdap_id_op_handle(hbac_ctx->sdap_op),
hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
- hbac_ctx->hbac_search_base);
+ hbac_ctx->search_bases);
if (req == NULL) {
DEBUG(1,("Could not get service info\n"));
goto fail;
@@ -399,7 +375,7 @@ static void hbac_get_rule_info_step(struct tevent_req *req)
hbac_ctx_ev(hbac_ctx),
sdap_id_op_handle(hbac_ctx->sdap_op),
hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
- hbac_ctx->hbac_search_base,
+ hbac_ctx->search_bases,
hbac_ctx->ipa_host);
if (req == NULL) {
DEBUG(1, ("Could not get rules\n"));
diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h
index e695acd8..65571013 100644
--- a/src/providers/ipa/ipa_access.h
+++ b/src/providers/ipa/ipa_access.h
@@ -46,6 +46,7 @@ struct ipa_access_ctx {
time_t last_update;
struct sdap_search_base **host_search_bases;
+ struct sdap_search_base **hbac_search_bases;
};
struct hbac_ctx {
@@ -57,7 +58,7 @@ struct hbac_ctx {
struct be_req *be_req;
struct pam_data *pd;
- char *hbac_search_base;
+ struct sdap_search_base **search_bases;
/* Hosts */
size_t host_count;
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 2e6dad8a..9f1178a9 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -572,7 +572,7 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
goto done;
}
- DEBUG(6, ("Option %s set to %s\n",
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Option %s set to %s\n",
ipa_opts->basic[IPA_HOST_SEARCH_BASE].opt_name,
dp_opt_get_string(ipa_opts->basic,
IPA_HOST_SEARCH_BASE)));
@@ -582,6 +582,29 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
&ipa_opts->host_search_bases);
if (ret != EOK) goto done;
+ if (NULL == dp_opt_get_string(ipa_opts->basic,
+ IPA_HBAC_SEARCH_BASE)) {
+ value = talloc_asprintf(tmpctx, "cn=hbac,%s", basedn);
+ if (!value) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = dp_opt_set_string(ipa_opts->basic, IPA_HBAC_SEARCH_BASE, value);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ DEBUG(6, ("Option %s set to %s\n",
+ ipa_opts->basic[IPA_HBAC_SEARCH_BASE].opt_name,
+ dp_opt_get_string(ipa_opts->basic,
+ IPA_HBAC_SEARCH_BASE)));
+ }
+ ret = sdap_parse_search_base(ipa_opts->basic, ipa_opts->basic,
+ IPA_HBAC_SEARCH_BASE,
+ &ipa_opts->hbac_search_bases);
+ if (ret != EOK) goto done;
+
value = dp_opt_get_string(ipa_opts->id->basic, SDAP_DEREF);
if (value != NULL) {
ret = deref_string_to_val(value, &i);
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 9cbd993f..49afe74d 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -98,6 +98,7 @@ struct ipa_options {
struct dp_option *basic;
struct sdap_search_base **host_search_bases;
+ struct sdap_search_base **hbac_search_bases;
struct ipa_service *service;
/* id provider */
diff --git a/src/providers/ipa/ipa_hbac_private.h b/src/providers/ipa/ipa_hbac_private.h
index 6920f9e1..8d735b8b 100644
--- a/src/providers/ipa/ipa_hbac_private.h
+++ b/src/providers/ipa/ipa_hbac_private.h
@@ -144,7 +144,7 @@ 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
ipa_hbac_service_info_recv(struct tevent_req *req,
@@ -166,22 +166,6 @@ get_ipa_servicegroupname(TALLOC_CTX *mem_ctx,
const char *service_dn,
char **servicename);
-/* From ipa_hbac_rules.c */
-struct tevent_req *
-ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
- bool get_deny_rules,
- struct tevent_context *ev,
- struct sdap_handle *sh,
- struct sdap_options *opts,
- const char *search_base,
- struct sysdb_attrs *ipa_host);
-
-errno_t
-ipa_hbac_rule_info_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- size_t *rule_count,
- struct sysdb_attrs ***rules);
-
/* From ipa_hbac_users.c */
errno_t
hbac_user_attrs_to_rule(TALLOC_CTX *mem_ctx,
diff --git a/src/providers/ipa/ipa_hbac_rules.c b/src/providers/ipa/ipa_hbac_rules.c
index 0b567dab..c07cf332 100644
--- a/src/providers/ipa/ipa_hbac_rules.c
+++ b/src/providers/ipa/ipa_hbac_rules.c
@@ -22,15 +22,28 @@
#include "util/util.h"
#include "providers/ipa/ipa_hbac_private.h"
+#include "providers/ipa/ipa_hbac_rules.h"
#include "providers/ldap/sdap_async.h"
struct ipa_hbac_rule_state {
+ struct tevent_context *ev;
+ struct sdap_handle *sh;
struct sdap_options *opts;
+ int search_base_iter;
+ struct sdap_search_base **search_bases;
+
+ const char **attrs;
+ char *rules_filter;
+ char *cur_filter;
+
size_t rule_count;
struct sysdb_attrs **rules;
};
+static errno_t
+ipa_hbac_rule_info_next(struct tevent_req *req,
+ struct ipa_hbac_rule_state *state);
static void
ipa_hbac_rule_info_done(struct tevent_req *subreq);
@@ -40,13 +53,12 @@ ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sdap_handle *sh,
struct sdap_options *opts,
- const char *search_base,
+ struct sdap_search_base **search_bases,
struct sysdb_attrs *ipa_host)
{
errno_t ret;
size_t i;
struct tevent_req *req = NULL;
- struct tevent_req *subreq;
struct ipa_hbac_rule_state *state;
TALLOC_CTX *tmp_ctx;
const char *host_dn;
@@ -54,21 +66,6 @@ ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
char *host_group_clean;
char *rule_filter;
const char **memberof_list;
- const char *rule_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 };
if (ipa_host == NULL) {
DEBUG(1, ("Missing host\n"));
@@ -93,7 +90,31 @@ ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
return NULL;
}
+ state->ev = ev;
+ state->sh = sh;
state->opts = opts;
+ state->search_bases = search_bases;
+ state->search_base_iter = 0;
+ state->attrs = talloc_zero_array(state, const char *, 15);
+ if (state->attrs == NULL) {
+ ret = ENOMEM;
+ goto immediate;
+ }
+ state->attrs[0] = OBJECTCLASS;
+ state->attrs[1] = IPA_CN;
+ state->attrs[2] = IPA_UNIQUE_ID;
+ state->attrs[3] = IPA_ENABLED_FLAG;
+ state->attrs[4] = IPA_ACCESS_RULE_TYPE;
+ state->attrs[5] = IPA_MEMBER_USER;
+ state->attrs[6] = IPA_USER_CATEGORY;
+ state->attrs[7] = IPA_MEMBER_SERVICE;
+ state->attrs[8] = IPA_SERVICE_CATEGORY;
+ state->attrs[9] = IPA_SOURCE_HOST;
+ state->attrs[10] = IPA_SOURCE_HOST_CATEGORY;
+ state->attrs[11] = IPA_EXTERNAL_HOST;
+ state->attrs[12] = IPA_MEMBER_HOST;
+ state->attrs[13] = IPA_HOST_CATEGORY;
+ state->attrs[14] = NULL;
if (get_deny_rules) {
rule_filter = talloc_asprintf(tmp_ctx,
@@ -154,19 +175,16 @@ ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
ret = ENOMEM;
goto immediate;
}
- talloc_steal(state, rule_filter);
+ state->rules_filter = talloc_steal(state, rule_filter);
- subreq = sdap_get_generic_send(state, ev, opts, sh, search_base,
- LDAP_SCOPE_SUB, rule_filter, rule_attrs,
- NULL, 0,
- dp_opt_get_int(state->opts->basic,
- SDAP_ENUM_SEARCH_TIMEOUT));
- if (subreq == NULL) {
- DEBUG(1, ("sdap_get_generic_send failed.\n"));
- ret = ENOMEM;
+ ret = ipa_hbac_rule_info_next(req, state);
+ if (ret == EOK) {
+ ret = EINVAL;
+ }
+
+ if (ret != EAGAIN) {
goto immediate;
}
- tevent_req_set_callback(subreq, ipa_hbac_rule_info_done, req);
talloc_free(tmp_ctx);
return req;
@@ -186,6 +204,45 @@ error:
return NULL;
}
+static errno_t
+ipa_hbac_rule_info_next(struct tevent_req *req,
+ struct ipa_hbac_rule_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->rules_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, ("sdap_get_generic_send failed.\n"));
+ return ENOMEM;
+ }
+ tevent_req_set_callback(subreq, ipa_hbac_rule_info_done, req);
+
+ return EAGAIN;
+}
+
static void
ipa_hbac_rule_info_done(struct tevent_req *subreq)
{
@@ -194,21 +251,59 @@ ipa_hbac_rule_info_done(struct tevent_req *subreq)
tevent_req_callback_data(subreq, struct tevent_req);
struct ipa_hbac_rule_state *state =
tevent_req_data(req, struct ipa_hbac_rule_state);
+ int i;
+ size_t rule_count;
+ size_t total_count;
+ struct sysdb_attrs **rules;
+ struct sysdb_attrs **target;
ret = sdap_get_generic_recv(subreq, state,
- &state->rule_count,
- &state->rules);
+ &rule_count,
+ &rules);
if (ret != EOK) {
DEBUG(3, ("Could not retrieve HBAC rules\n"));
- tevent_req_error(req, ret);
+ goto fail;
+ }
+
+ if (rule_count > 0) {
+ total_count = rule_count + state->rule_count;
+ state->rules = talloc_realloc(state, state->rules,
+ struct sysdb_attrs *,
+ total_count);
+ if (state->rules == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ i = 0;
+ while (state->rule_count < total_count) {
+ target = &state->rules[state->rule_count];
+ *target = talloc_steal(state->rules, rules[i]);
+
+ state->rule_count++;
+ i++;
+ }
+ }
+
+ state->search_base_iter++;
+ ret = ipa_hbac_rule_info_next(req, state);
+ if (ret == EAGAIN) {
return;
- } else if (state->rule_count == 0) {
+ } else if (ret != EOK) {
+ goto fail;
+ } else if (ret == EOK && state->rule_count == 0) {
DEBUG(3, ("No rules apply to this host\n"));
tevent_req_error(req, ENOENT);
return;
}
+ /* We went through all search bases and we have some results */
tevent_req_done(req);
+
+ return;
+
+fail:
+ tevent_req_error(req, ret);
}
errno_t
diff --git a/src/providers/ipa/ipa_hbac_rules.h b/src/providers/ipa/ipa_hbac_rules.h
new file mode 100644
index 00000000..31ff3048
--- /dev/null
+++ b/src/providers/ipa/ipa_hbac_rules.h
@@ -0,0 +1,42 @@
+/*
+ SSSD
+
+ Authors:
+ Jan Zeleny <jzeleny@redhat.com>
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef IPA_HBAC_RULES_H_
+#define IPA_HBAC_RULES_H_
+
+/* From ipa_hbac_rules.c */
+struct tevent_req *
+ipa_hbac_rule_info_send(TALLOC_CTX *mem_ctx,
+ bool get_deny_rules,
+ struct tevent_context *ev,
+ struct sdap_handle *sh,
+ struct sdap_options *opts,
+ struct sdap_search_base **search_bases,
+ struct sysdb_attrs *ipa_host);
+
+errno_t
+ipa_hbac_rule_info_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *rule_count,
+ struct sysdb_attrs ***rules);
+
+#endif /* IPA_HBAC_RULES_H_ */
diff --git a/src/providers/ipa/ipa_hbac_services.c b/src/providers/ipa/ipa_hbac_services.c
index cc4e6dea..3bbdc8ba 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;
}
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 78a102ae..b3544f74 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -375,6 +375,7 @@ int sssm_ipa_access_init(struct be_ctx *bectx,
}
ipa_access_ctx->sdap_ctx = id_ctx->sdap_id_ctx;
ipa_access_ctx->host_search_bases = id_ctx->ipa_options->host_search_bases;
+ ipa_access_ctx->hbac_search_bases = id_ctx->ipa_options->hbac_search_bases;
ret = dp_copy_options(ipa_access_ctx, ipa_options->basic,
IPA_OPTS_BASIC, &ipa_access_ctx->ipa_options);