From 6a57a4384f03adbc642e0d1e6fc91d43aa102a3b Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Mon, 3 Oct 2011 11:28:35 -0400
Subject: [PATCH 13/14] LDAP: Add support for multiple search bases for user
 enumeration

---
 src/providers/ldap/ldap_id.c          |    3 +-
 src/providers/ldap/ldap_id_enum.c     |    3 +-
 src/providers/ldap/sdap_async.h       |    3 +-
 src/providers/ldap/sdap_async_users.c |   49 +++++++++++++++++++++++++++++----
 4 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 3e93bb8525bf1c9a9bbb51a348941c09d8c0c3da..c381c19b1bf56f6a66bde46ba15d655f1995abac 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -172,7 +172,8 @@ static void users_get_connect_done(struct tevent_req *subreq)
                                  sdap_id_op_handle(state->op),
                                  state->attrs, state->filter,
                                  dp_opt_get_int(state->ctx->opts->basic,
-                                                SDAP_SEARCH_TIMEOUT));
+                                                SDAP_SEARCH_TIMEOUT),
+                                 false);
     if (!subreq) {
         tevent_req_error(req, ENOMEM);
         return;
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 45f4ef78a9caa38e4f4d77b23b4e55e65f3f559d..9923379db94b7cb46daa5da8795d5c08c4d96695 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -482,7 +482,8 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
                                  sdap_id_op_handle(state->op),
                                  state->attrs, state->filter,
                                  dp_opt_get_int(state->ctx->opts->basic,
-                                                SDAP_ENUM_SEARCH_TIMEOUT));
+                                                SDAP_ENUM_SEARCH_TIMEOUT),
+                                 true);
     if (!subreq) {
         ret = ENOMEM;
         goto fail;
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index ef18c775a35a4ff6b25ee0bd4e5432815700a088..262c04a0d5096bb57b95ba0b15c60feed267e359 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -49,7 +49,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
                                        struct sdap_handle *sh,
                                        const char **attrs,
                                        const char *filter,
-                                       int timeout);
+                                       int timeout,
+                                       bool enumeration);
 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 e43477f2a888f75fb0ab3ae213caa15a97a1988d..36ca6ac54e45fd957b624ea2d854b28af5e26a64 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -430,6 +430,7 @@ struct sdap_get_users_state {
     const char *base_filter;
     char *filter;
     int timeout;
+    bool enumeration;
 
     char *higher_usn;
     struct sysdb_attrs **users;
@@ -451,7 +452,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
                                        struct sdap_handle *sh,
                                        const char **attrs,
                                        const char *filter,
-                                       int timeout)
+                                       int timeout,
+                                       bool enumeration)
 {
     errno_t ret;
     struct tevent_req *req;
@@ -473,6 +475,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
     state->base_filter = filter;
     state->base_iter = 0;
     state->search_bases = search_bases;
+    state->enumeration = enumeration;
 
     ret = sdap_get_users_next_base(req);
     if (ret != EOK) {
@@ -524,20 +527,49 @@ static void sdap_get_users_process(struct tevent_req *subreq)
     struct sdap_get_users_state *state = tevent_req_data(req,
                                             struct sdap_get_users_state);
     int ret;
+    size_t count, i;
+    struct sysdb_attrs **users;
+    bool next_base = false;
 
     ret = sdap_get_generic_recv(subreq, state,
-                                &state->count, &state->users);
+                                &count, &users);
     talloc_zfree(subreq);
     if (ret) {
         tevent_req_error(req, ret);
         return;
     }
 
-    DEBUG(6, ("Search for users, returned %d results.\n", state->count));
+    DEBUG(6, ("Search for users, returned %d results.\n", count));
 
-    if (state->count == 0) {
-        /* No users found in this search */
-        talloc_zfree(state->users);
+    if (state->enumeration || count == 0) {
+        /* No users found in this search or enumerating */
+        next_base = true;
+    }
+
+    /* Add this batch of users to the list */
+    if (count > 0) {
+        state->users =
+                talloc_realloc(state,
+                               state->users,
+                               struct sysdb_attrs *,
+                               state->count + count + 1);
+        if (!state->users) {
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+
+        /* Copy the new users into the list
+         * They're already allocated on 'state'
+         */
+        for (i = 0; i < count; i++) {
+            state->users[state->count + i] = users[i];
+        }
+
+        state->count += count;
+        state->users[state->count] = NULL;
+    }
+
+    if (next_base) {
         talloc_zfree(state->filter);
 
         state->base_iter++;
@@ -549,7 +581,12 @@ static void sdap_get_users_process(struct tevent_req *subreq)
             }
             return;
         }
+    }
 
+    /* No more search bases
+     * Return ENOENT if no users were found
+     */
+    if (state->count == 0) {
         tevent_req_error(req, ENOENT);
         return;
     }
-- 
1.7.6.2

