From 3bcc7dd1a61a27a8af06618dea4620a40a1a3989 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 16 Sep 2011 14:54:29 -0400
Subject: [PATCH 05/11] LDAP: Support multiple user search bases
 (non-enumeration)

---
 src/providers/ldap/ldap_id.c          |    1 +
 src/providers/ldap/ldap_id_enum.c     |    5 ++
 src/providers/ldap/sdap_async.h       |    3 +-
 src/providers/ldap/sdap_async_users.c |   78 +++++++++++++++++++++++++++-----
 4 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 2d8aefff818bc93e1d28a2d9c2a4416e4157cf19..1beb00e61fada4444701236d0656075db6383cff 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -178,6 +178,7 @@ static void users_get_connect_done(struct tevent_req *subreq)
     subreq = sdap_get_users_send(state, state->ev,
                                  state->domain, state->sysdb,
                                  state->ctx->opts,
+                                 state->ctx->opts->user_search_bases,
                                  sdap_id_op_handle(state->op),
                                  state->attrs, state->filter,
                                  dp_opt_get_int(state->ctx->opts->basic,
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index eced42a88944024f0d09c2d92401725ce40728b7..d85c52203d611ba516174f3d2fe0700fdd401bfa 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -480,10 +480,15 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
                                SDAP_OPTS_USER, &state->attrs);
     if (ret != EOK) goto fail;
 
+    /* TODO: restrict the enumerations to using a single
+     * search base at a time.
+     */
+
     subreq = sdap_get_users_send(state, state->ev,
                                  state->ctx->be->domain,
                                  state->ctx->be->sysdb,
                                  state->ctx->opts,
+                                 state->ctx->opts->user_search_bases,
                                  sdap_id_op_handle(state->op),
                                  state->attrs, state->filter,
                                  dp_opt_get_int(state->ctx->opts->basic,
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 9b5a3079786ff82dae566b16e2a34f2372b04237..0ffaa017635fe45bb613f9cddba8c9f94d25879b 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -45,9 +45,10 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
                                        struct sss_domain_info *dom,
                                        struct sysdb_ctx *sysdb,
                                        struct sdap_options *opts,
+                                       struct sdap_search_base **search_bases,
                                        struct sdap_handle *sh,
                                        const char **attrs,
-                                       const char *wildcard,
+                                       const char *filter,
                                        int timeout);
 int sdap_get_users_recv(struct tevent_req *req,
                         TALLOC_CTX *mem_ctx, char **timestamp);
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
index 82338dc1775393bd2e22752178dedc5dc19a542a..266b1f0acff415178c398110d78ae67a3737cadd 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -406,13 +406,19 @@ struct sdap_get_users_state {
     struct sss_domain_info *dom;
     struct sysdb_ctx *sysdb;
     const char **attrs;
-    const char *filter;
+    const char *base_filter;
+    char *filter;
+    int timeout;
 
     char *higher_usn;
     struct sysdb_attrs **users;
     size_t count;
+
+    size_t base_iter;
+    struct sdap_search_base **search_bases;
 };
 
+static errno_t sdap_get_users_next_base(struct tevent_req *req);
 static void sdap_get_users_process(struct tevent_req *subreq);
 
 struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
@@ -420,12 +426,14 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
                                        struct sss_domain_info *dom,
                                        struct sysdb_ctx *sysdb,
                                        struct sdap_options *opts,
+                                       struct sdap_search_base **search_bases,
                                        struct sdap_handle *sh,
                                        const char **attrs,
                                        const char *filter,
                                        int timeout)
 {
-    struct tevent_req *req, *subreq;
+    errno_t ret;
+    struct tevent_req *req;
     struct sdap_get_users_state *state;
 
     req = tevent_req_create(memctx, &state, struct sdap_get_users_state);
@@ -436,26 +444,56 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
     state->dom = dom;
     state->sh = sh;
     state->sysdb = sysdb;
-    state->filter = filter;
     state->attrs = attrs;
     state->higher_usn = NULL;
     state->users =  NULL;
     state->count = 0;
+    state->timeout = timeout;
+    state->base_filter = filter;
+    state->base_iter = 0;
+    state->search_bases = search_bases;
 
-    subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
-                                   dp_opt_get_string(state->opts->basic,
-                                                     SDAP_USER_SEARCH_BASE),
-                                   LDAP_SCOPE_SUBTREE,
-                                   state->filter, state->attrs,
-                                   state->opts->user_map, SDAP_OPTS_USER,
-                                   timeout);
+    ret = sdap_get_users_next_base(req);
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        tevent_req_post(req, state->ev);
+    }
+
+    return req;
+}
+
+static errno_t sdap_get_users_next_base(struct tevent_req *req)
+{
+    struct tevent_req *subreq;
+    struct sdap_get_users_state *state;
+
+    state = tevent_req_data(req, struct sdap_get_users_state);
+
+    talloc_zfree(state->filter);
+    state->filter = sdap_get_id_specific_filter(state,
+                        state->base_filter,
+                        state->search_bases[state->base_iter]->filter);
+    if (!state->filter) {
+        return ENOMEM;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC,
+          ("Searching for users with base [%s]\n",
+           state->search_bases[state->base_iter]->basedn));
+
+    subreq = sdap_get_generic_send(
+            state, state->ev, state->opts, state->sh,
+            state->search_bases[state->base_iter]->basedn,
+            state->search_bases[state->base_iter]->scope,
+            state->filter, state->attrs,
+            state->opts->user_map, SDAP_OPTS_USER,
+            state->timeout);
     if (!subreq) {
-        talloc_zfree(req);
-        return NULL;
+        return ENOMEM;
     }
     tevent_req_set_callback(subreq, sdap_get_users_process, req);
 
-    return req;
+    return EOK;
 }
 
 static void sdap_get_users_process(struct tevent_req *subreq)
@@ -477,6 +515,20 @@ static void sdap_get_users_process(struct tevent_req *subreq)
     DEBUG(6, ("Search for users, returned %d results.\n", state->count));
 
     if (state->count == 0) {
+        /* No users found in this search */
+        talloc_zfree(state->users);
+        talloc_zfree(state->filter);
+
+        state->base_iter++;
+        if (state->search_bases[state->base_iter]) {
+            /* There are more search bases to try */
+            ret = sdap_get_users_next_base(req);
+            if (ret != EOK) {
+                tevent_req_error(req, ret);
+            }
+            return;
+        }
+
         tevent_req_error(req, ENOENT);
         return;
     }
-- 
1.7.6.2

