From 2c2f87a02180a1587465663a23cc1cd417ba9a7a 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/14] 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 |   75 +++++++++++++++++++++++++++------
 4 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 46f68897627448ba3c67d656ad0046bd2714486e..f3a2a1b3a561bb5fdb2014ad3a0ae0771fed8aaa 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 8714e2bad7589b93c21530644c64d66aea84ffea..c1637be5ed206828c53761272a2f6a8d8d51d3ec 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 949cc026813c91a036ac797b7f4d374c404833c4..b2623a3fd281c3072d413f79d296a1297167c426 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -430,13 +430,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,
@@ -444,12 +450,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);
@@ -460,26 +468,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)
@@ -501,6 +539,17 @@ 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 */
+        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.7

