sssd/0012-SDAP-Add-request-that-iterates-over-all-search-bases.patch
2016-01-19 18:23:34 +01:00

384 lines
13 KiB
Diff

From a9845c875e430e00cfb49a39b09c8595ff8e3416 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 1 Dec 2015 13:08:36 +0100
Subject: [PATCH 12/49] SDAP: Add request that iterates over all search bases
We often need to iterate over many search bases but we always use
mostly copy&paste iterator. This will reduce code duplication and
simplify code flow.
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit d0599eaa9369fd867953e3c58b8d7bb445525ff5)
---
Makefile.am | 2 +
src/providers/ldap/ldap_common.h | 9 +-
src/providers/ldap/sdap.c | 2 +-
src/providers/ldap/sdap_ops.c | 232 +++++++++++++++++++++++++++++++++++++++
src/providers/ldap/sdap_ops.h | 44 ++++++++
src/providers/ldap/sdap_utils.c | 6 +-
6 files changed, 288 insertions(+), 7 deletions(-)
create mode 100644 src/providers/ldap/sdap_ops.c
create mode 100644 src/providers/ldap/sdap_ops.h
diff --git a/Makefile.am b/Makefile.am
index 1937dcbebc4f29c4ffe72eeeb67cdb5344a8e7d1..095b1cfd62f49d266df278e1736d48ed5ef4fa7a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -628,6 +628,7 @@ dist_noinst_HEADERS = \
src/providers/ldap/sdap_users.h \
src/providers/ldap/sdap_dyndns.h \
src/providers/ldap/sdap_async_enum.h \
+ src/providers/ldap/sdap_ops.h \
src/providers/ipa/ipa_common.h \
src/providers/ipa/ipa_config.h \
src/providers/ipa/ipa_access.h \
@@ -2836,6 +2837,7 @@ libsss_ldap_common_la_SOURCES = \
src/providers/ldap/sdap_refresh.c \
src/providers/ldap/sdap_utils.c \
src/providers/ldap/sdap_domain.c \
+ src/providers/ldap/sdap_ops.c \
src/providers/ldap/sdap.c \
src/util/user_info_msg.c \
src/util/sss_ldap.c \
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index ae45fb71b5cf7edab618a829057357bea2d6844b..66434dd0e8bc82649fecd67b1394cb6b102a7d49 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -264,9 +264,12 @@ errno_t list_missing_attrs(TALLOC_CTX *mem_ctx,
bool sdap_is_secure_uri(const char *uri);
-char *sdap_get_id_specific_filter(TALLOC_CTX *mem_ctx,
- const char *base_filter,
- const char *extra_filter);
+char *sdap_combine_filters(TALLOC_CTX *mem_ctx,
+ const char *base_filter,
+ const char *extra_filter);
+
+#define sdap_get_id_specific_filter(mem_ctx, base_filter, extra_filter) \
+ sdap_combine_filters((mem_ctx), (base_filter), (extra_filter))
char *sdap_get_access_filter(TALLOC_CTX *mem_ctx,
const char *base_filter);
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index fcdc4028efe97bba13f265a8cfd7c75fa6b7a07c..f9b9ff7e6913c406547f36d341300b936e121693 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -312,7 +312,7 @@ int sdap_get_map(TALLOC_CTX *memctx,
char *name;
int i, ret;
- map = talloc_array(memctx, struct sdap_attr_map, num_entries);
+ map = talloc_zero_array(memctx, struct sdap_attr_map, num_entries + 1);
if (!map) {
return ENOMEM;
}
diff --git a/src/providers/ldap/sdap_ops.c b/src/providers/ldap/sdap_ops.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2f2c35d0bf49682f522993390cfec2f451bf366
--- /dev/null
+++ b/src/providers/ldap/sdap_ops.c
@@ -0,0 +1,232 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2015 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/>.
+*/
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "util/util.h"
+#include "providers/ldap/sdap.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/ldap_common.h"
+
+struct sdap_search_bases_state {
+ struct tevent_context *ev;
+ struct sdap_options *opts;
+ struct sdap_handle *sh;
+ const char *filter;
+ const char **attrs;
+ struct sdap_attr_map *map;
+ int map_num_attrs;
+ int timeout;
+ bool allow_paging;
+
+ size_t base_iter;
+ struct sdap_search_base *cur_base;
+ struct sdap_search_base **bases;
+
+ size_t reply_count;
+ struct sysdb_attrs **reply;
+};
+
+static errno_t sdap_search_bases_next_base(struct tevent_req *req);
+static void sdap_search_bases_done(struct tevent_req *subreq);
+
+struct tevent_req *sdap_search_bases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map *map,
+ bool allow_paging,
+ int timeout,
+ const char *filter,
+ const char **attrs)
+{
+ struct tevent_req *req;
+ struct sdap_search_bases_state *state;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_search_bases_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (bases == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No search base specified!\n");
+ ret = ERR_INTERNAL;
+ goto immediately;
+ }
+
+ if (map == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No attribute map specified!\n");
+ ret = ERR_INTERNAL;
+ goto immediately;
+ }
+
+ state->ev = ev;
+ state->opts = opts;
+ state->sh = sh;
+ state->bases = bases;
+ state->map = map;
+ state->filter = filter;
+ state->attrs = attrs;
+ state->allow_paging = allow_paging;
+
+ state->timeout = timeout == 0
+ ? dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT)
+ : timeout;
+
+ for (state->map_num_attrs = 0;
+ state->map[state->map_num_attrs].opt_name != NULL;
+ state->map_num_attrs++) {
+ /* no op */;
+ }
+
+ if (state->attrs == NULL) {
+ ret = build_attrs_from_map(state, state->map, state->map_num_attrs,
+ NULL, &state->attrs, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to build attrs from map "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto immediately;
+ }
+ }
+
+ state->base_iter = 0;
+ ret = sdap_search_bases_next_base(req);
+ if (ret == EAGAIN) {
+ /* asynchronous processing */
+ return req;
+ }
+
+immediately:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+
+ return req;
+}
+
+static errno_t sdap_search_bases_next_base(struct tevent_req *req)
+{
+ struct sdap_search_bases_state *state;
+ struct tevent_req *subreq;
+ char *filter;
+
+ state = tevent_req_data(req, struct sdap_search_bases_state);
+ state->cur_base = state->bases[state->base_iter];
+ if (state->cur_base == NULL) {
+ return EOK;
+ }
+
+ /* Combine lookup and search base filters. */
+ filter = sdap_combine_filters(state, state->filter,
+ state->cur_base->filter);
+ if (filter == NULL) {
+ return ENOMEM;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing LDAP lookup with base [%s]\n",
+ state->cur_base->basedn);
+
+ subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
+ state->cur_base->basedn,
+ state->cur_base->scope, filter,
+ state->attrs, state->map,
+ state->map_num_attrs, state->timeout,
+ state->allow_paging);
+ if (subreq == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, sdap_search_bases_done, req);
+
+ state->base_iter++;
+ return EAGAIN;
+}
+
+static void sdap_search_bases_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_search_bases_state *state;
+ struct sysdb_attrs **attrs;
+ size_t count;
+ size_t i;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_search_bases_state);
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Receiving data from base [%s]\n",
+ state->cur_base->basedn);
+
+ ret = sdap_get_generic_recv(subreq, state, &count, &attrs);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Add rules to result. */
+ if (count > 0) {
+ state->reply = talloc_realloc(state, state->reply, struct sysdb_attrs *,
+ state->reply_count + count);
+ if (state->reply == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ state->reply[state->reply_count + i] = talloc_steal(state->reply,
+ attrs[i]);
+ }
+
+ state->reply_count += count;
+ }
+
+ /* Try next search base. */
+ ret = sdap_search_bases_next_base(req);
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ }
+
+ return;
+}
+
+int sdap_search_bases_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *reply_count,
+ struct sysdb_attrs ***reply)
+{
+ struct sdap_search_bases_state *state =
+ tevent_req_data(req, struct sdap_search_bases_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *reply_count = state->reply_count;
+ *reply = talloc_steal(mem_ctx, state->reply);
+
+ return EOK;
+}
diff --git a/src/providers/ldap/sdap_ops.h b/src/providers/ldap/sdap_ops.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc53ff8701c26ca00d5c07b441b170d615bda2ee
--- /dev/null
+++ b/src/providers/ldap/sdap_ops.h
@@ -0,0 +1,44 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2015 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 _SDAP_OPS_H_
+#define _SDAP_OPS_H_
+
+#include <talloc.h>
+#include <tevent.h>
+#include "providers/ldap/ldap_common.h"
+
+struct tevent_req *sdap_search_bases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map *map,
+ bool allow_paging,
+ int timeout,
+ const char *filter,
+ const char **attrs);
+
+int sdap_search_bases_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *reply_count,
+ struct sysdb_attrs ***reply);
+
+#endif /* _SDAP_OPS_H_ */
diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c
index 9da46ea70bf80e7f4d12fdfc7d1c97e99de8d000..7a96f81a1db2644b698e5a5baaed19366a305c6b 100644
--- a/src/providers/ldap/sdap_utils.c
+++ b/src/providers/ldap/sdap_utils.c
@@ -149,9 +149,9 @@ errno_t deref_string_to_val(const char *str, int *val)
return EOK;
}
-char *sdap_get_id_specific_filter(TALLOC_CTX *mem_ctx,
- const char *base_filter,
- const char *extra_filter)
+char *sdap_combine_filters(TALLOC_CTX *mem_ctx,
+ const char *base_filter,
+ const char *extra_filter)
{
char *filter = NULL;
--
2.5.0