Blob Blame History Raw
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