[SSSD] [PATCH] AD enumeration improvements

Jakub Hrozek jhrozek at redhat.com
Tue Sep 17 19:59:21 UTC 2013


On Fri, Sep 13, 2013 at 11:42:58AM +0200, Pavel Březina wrote:
> On 09/04/2013 08:15 AM, Jakub Hrozek wrote:
> >Hi,
> >
> >attached are patches that improve how we enumerate AD domains. The
> >problem is that currently the domain info (subdomain and master domain)
> >is downloaded when a responder queries the DP for domain info. But when
> >enumeration is enabled, the responder might not contact the DP at all as
> >the enumeration task runs on its own. I think the best solution is to
> >extend the enumeration task so that it also downloads the domain data
> >itself.
> >
> >About the implementation, I was considering two options. One is the way
> >I took where the enumeration request is simply extended with downloading
> >master domain data. The other approach I was considering was extending
> >the generic enumeration request with downloading domain data which the
> >generic request would just shortcut. While this might seem like a better
> >approach, it also seemed like a complete overkill..but I'd like to hear
> >other opinons.
> 
> I'm agree with the approach you've chosen.
> 
> >[PATCH 1/3] AD: async request to retrieve master domain info
> >Adds a reusable async request to download the master domain info.
> 
> >+++ b/src/providers/ad/ad_domain_info.c
> >@@ -0,0 +1,350 @@
> >+/*
> >+    SSSD
> >+
> >+    AD Subdomains Module
> 
> AD Master Domain Module?
> 
> >This patch just splits the master domain request from the subdomain
> >request.
> 
> Ack.
> 
> >[PATCH 2/3] LDAP: sdap_id_setup_tasks accepts a custom enum request
> >AD provider will override the default with its own.
> 
> Ack.
> 
> >[PATCH 3/3] AD: Download master domain info when enumerating
> >https://fedorahosted.org/sssd/ticket/2068
> >Adds the master domain download task before the enumeration.
> 
> Ack.

Hi,

thank you for the review. Attached are patches rebased on top of the
current master and with the title of ad_domain_info.c fixed. I chose a
more neutral approach because a subsequent patch will most probably add
another request or extend the current one to download subdomain data and
enable subdomain enumeration.
-------------- next part --------------
>From d8260679de1c83f9439b2f8b130a335ea7620a5d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sat, 17 Aug 2013 01:12:21 +0200
Subject: [PATCH 1/3] AD: async request to retrieve master domain info

Adds a reusable async request to download the master domain info.
---
 Makefile.am                       |   3 +
 src/providers/ad/ad_domain_info.c | 350 ++++++++++++++++++++++++++++++++++++++
 src/providers/ad/ad_domain_info.h |  41 +++++
 src/providers/ad/ad_init.c        |   2 +-
 src/providers/ad/ad_subdomains.c  | 235 +++----------------------
 5 files changed, 417 insertions(+), 214 deletions(-)
 create mode 100644 src/providers/ad/ad_domain_info.c
 create mode 100644 src/providers/ad/ad_domain_info.h

diff --git a/Makefile.am b/Makefile.am
index 5aba760375de59c4203300376e2d6fcd8e90c53f..b2090f78a00e5ef46fdccb811e2dd718a6a844a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1642,6 +1642,7 @@ libsss_ipa_la_SOURCES = \
     src/providers/ad/ad_dyndns.c \
     src/providers/ad/ad_id.c \
     src/providers/ad/ad_srv.c \
+    src/providers/ad/ad_domain_info.c \
     src/util/user_info_msg.c \
     src/util/find_uid.c \
     src/util/sss_ldap.c \
@@ -1695,6 +1696,8 @@ libsss_ad_la_SOURCES = \
     src/providers/ad/ad_srv.c \
     src/providers/ad/ad_subdomains.c \
     src/providers/ad/ad_subdomains.h \
+    src/providers/ad/ad_domain_info.c \
+    src/providers/ad/ad_domain_info.h \
     src/util/find_uid.c \
     src/util/user_info_msg.c \
     src/util/sss_krb5.c \
diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c
new file mode 100644
index 0000000000000000000000000000000000000000..b0c8652c9009d761d8cadd0e8eae187b92ba50ff
--- /dev/null
+++ b/src/providers/ad/ad_domain_info.c
@@ -0,0 +1,350 @@
+/*
+    SSSD
+
+    AD Domain Info Module
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2013 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 <errno.h>
+#include <tevent.h>
+#include <ctype.h>
+#include <ndr.h>
+#include <ndr/ndr_nbt.h>
+
+#include "providers/ldap/sdap.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_idmap.h"
+#include "util/util.h"
+
+#define AD_AT_OBJECT_SID "objectSID"
+#define AD_AT_DNS_DOMAIN "DnsDomain"
+#define AD_AT_NT_VERSION "NtVer"
+#define AD_AT_NETLOGON   "netlogon"
+
+#define MASTER_DOMAIN_SID_FILTER "objectclass=domain"
+
+struct ad_master_domain_state {
+    struct tevent_context *ev;
+    struct sdap_id_conn_ctx *conn;
+    struct sdap_id_op *id_op;
+    struct sdap_id_ctx *id_ctx;
+    struct sdap_options *opts;
+
+    const char *dom_name;
+    int base_iter;
+
+    char *flat;
+    char *sid;
+};
+
+static errno_t ad_master_domain_next(struct tevent_req *req);
+static void ad_master_domain_next_done(struct tevent_req *subreq);
+static void ad_master_domain_netlogon_done(struct tevent_req *req);
+
+struct tevent_req *
+ad_master_domain_send(TALLOC_CTX *mem_ctx,
+                      struct tevent_context *ev,
+                      struct sdap_id_conn_ctx *conn,
+                      struct sdap_id_op *op,
+                      const char *dom_name)
+{
+    errno_t ret;
+    struct tevent_req *req;
+    struct ad_master_domain_state *state;
+
+    req = tevent_req_create(mem_ctx, &state, struct ad_master_domain_state);
+    if (!req) return NULL;
+
+    state->ev = ev;
+    state->id_op = op;
+    state->conn = conn;
+    state->id_ctx = conn->id_ctx;
+    state->opts = conn->id_ctx->opts;
+    state->dom_name = dom_name;
+
+    ret = ad_master_domain_next(req);
+    if (ret != EOK && ret != EAGAIN) {
+        goto immediate;
+    }
+
+    return req;
+
+immediate:
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+    } else {
+        tevent_req_done(req);
+    }
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static errno_t
+ad_master_domain_next(struct tevent_req *req)
+{
+    struct tevent_req *subreq;
+    struct sdap_search_base *base;
+    const char *master_sid_attrs[] = {AD_AT_OBJECT_SID, NULL};
+
+    struct ad_master_domain_state *state =
+        tevent_req_data(req, struct ad_master_domain_state);
+
+    base = state->opts->sdom->search_bases[state->base_iter];
+    if (base == NULL) {
+        return EOK;
+    }
+
+    subreq = sdap_get_generic_send(state, state->ev,
+                                   state->id_ctx->opts,
+                                   sdap_id_op_handle(state->id_op),
+                                   base->basedn, LDAP_SCOPE_BASE,
+                                   MASTER_DOMAIN_SID_FILTER, master_sid_attrs,
+                                   NULL, 0,
+                                   dp_opt_get_int(state->opts->basic,
+                                                  SDAP_SEARCH_TIMEOUT),
+                                   false);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
+        return ENOMEM;
+    }
+    tevent_req_set_callback(subreq, ad_master_domain_next_done, req);
+
+    return EAGAIN;
+}
+
+static void
+ad_master_domain_next_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    size_t reply_count;
+    struct sysdb_attrs **reply = NULL;
+    struct ldb_message_element *el;
+    char *sid_str;
+    enum idmap_error_code err;
+    static const char *attrs[] = {AD_AT_NETLOGON, NULL};
+    char *filter;
+    char *ntver;
+
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_master_domain_state *state =
+        tevent_req_data(req, struct ad_master_domain_state);
+
+    ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
+        goto done;
+    }
+
+    if (reply_count == 0) {
+        state->base_iter++;
+        ret = ad_master_domain_next(req);
+        if (ret == EAGAIN) {
+            /* Async request will get us back here again */
+            return;
+        } else if (ret != EOK) {
+            goto done;
+        }
+
+        /* EOK */
+        tevent_req_done(req);
+        return;
+    } else if (reply_count == 1) {
+        ret = sysdb_attrs_get_el(reply[0], AD_AT_OBJECT_SID, &el);
+        if (ret != EOK || el->num_values != 1) {
+            DEBUG(SSSDBG_OP_FAILURE, ("sdap_attrs_get_el failed.\n"));
+            goto done;
+        }
+
+        err = sss_idmap_bin_sid_to_sid(state->opts->idmap_ctx->map,
+                                       el->values[0].data,
+                                       el->values[0].length,
+                                       &sid_str);
+        if (err != IDMAP_SUCCESS) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Could not convert SID: [%s].\n", idmap_error_string(err)));
+            ret = EFAULT;
+            goto done;
+        }
+
+        state->sid = talloc_steal(state, sid_str);
+    } else {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("More than one result for domain SID found.\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found SID [%s].\n", state->sid));
+
+    ntver = sss_ldap_encode_ndr_uint32(state, NETLOGON_NT_VERSION_5EX |
+                                       NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
+    if (ntver == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sss_ldap_encode_ndr_uint32 failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    filter = talloc_asprintf(state, "(&(%s=%s)(%s=%s))",
+                             AD_AT_DNS_DOMAIN, state->dom_name,
+                             AD_AT_NT_VERSION, ntver);
+    if (filter == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    subreq = sdap_get_generic_send(state, state->ev,
+                                   state->id_ctx->opts,
+                                   sdap_id_op_handle(state->id_op),
+                                   "", LDAP_SCOPE_BASE, filter, attrs, NULL, 0,
+                                   dp_opt_get_int(state->opts->basic,
+                                                  SDAP_SEARCH_TIMEOUT),
+                                   false);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    tevent_req_set_callback(subreq, ad_master_domain_netlogon_done, req);
+    return;
+
+done:
+    tevent_req_error(req, ret);
+}
+
+static void
+ad_master_domain_netlogon_done(struct tevent_req *subreq)
+{
+    int ret;
+    size_t reply_count;
+    struct sysdb_attrs **reply = NULL;
+    struct ldb_message_element *el;
+    DATA_BLOB blob;
+    enum ndr_err_code ndr_err;
+    struct ndr_pull *ndr_pull = NULL;
+    struct netlogon_samlogon_response response;
+
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_master_domain_state *state =
+        tevent_req_data(req, struct ad_master_domain_state);
+
+    ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
+        goto done;
+    }
+
+    if (reply_count == 0) {
+        DEBUG(SSSDBG_TRACE_FUNC, ("No netlogon data available.\n"));
+        ret = ENOENT;
+        goto done;
+    } else if (reply_count > 1) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("More than one netlogon info returned.\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    ret = sysdb_attrs_get_el(reply[0], AD_AT_NETLOGON, &el);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_el() failed\n"));
+        goto done;
+    }
+
+    if (el->num_values == 0) {
+        DEBUG(SSSDBG_OP_FAILURE, ("netlogon has no value\n"));
+        ret = ENOENT;
+        goto done;
+    } else if (el->num_values > 1) {
+        DEBUG(SSSDBG_OP_FAILURE, ("More than one netlogon value?\n"));
+        ret = EIO;
+        goto done;
+    }
+
+    blob.data =  el->values[0].data;
+    blob.length = el->values[0].length;
+
+    ndr_pull = ndr_pull_init_blob(&blob, state);
+    if (ndr_pull == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_init_blob() failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS,
+                                                  &response);
+    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+        DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_netlogon_samlogon_response() "
+                                  "failed [%d]\n", ndr_err));
+        ret = EBADMSG;
+        goto done;
+    }
+
+    if (!(response.ntver & NETLOGON_NT_VERSION_5EX)) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Wrong version returned [%x]\n",
+                                  response.ntver));
+        ret = EBADMSG;
+        goto done;
+    }
+
+    if (response.data.nt5_ex.domain_name != NULL &&
+        *response.data.nt5_ex.domain_name != '\0') {
+        state->flat = talloc_strdup(state, response.data.nt5_ex.domain_name);
+        if (state->flat == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", state->flat));
+    tevent_req_done(req);
+    return;
+
+done:
+    tevent_req_error(req, ret);
+}
+
+errno_t
+ad_master_domain_recv(struct tevent_req *req,
+                      TALLOC_CTX *mem_ctx,
+                      char **_flat,
+                      char **_id)
+{
+    struct ad_master_domain_state *state = tevent_req_data(req,
+                                              struct ad_master_domain_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    if (_flat) {
+        *_flat = talloc_steal(mem_ctx, state->flat);
+    }
+
+    if (_id) {
+        *_id = talloc_steal(mem_ctx, state->sid);
+    }
+
+    return EOK;
+}
diff --git a/src/providers/ad/ad_domain_info.h b/src/providers/ad/ad_domain_info.h
new file mode 100644
index 0000000000000000000000000000000000000000..d21706396034509a498391e666e03a8e2eda8e08
--- /dev/null
+++ b/src/providers/ad/ad_domain_info.h
@@ -0,0 +1,41 @@
+/*
+    SSSD
+
+    AD Master Domain Module
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2013 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 _AD_MASTER_DOMAIN_H_
+#define _AD_MASTER_DOMAIN_H_
+
+struct tevent_req *
+ad_master_domain_send(TALLOC_CTX *mem_ctx,
+                      struct tevent_context *ev,
+                      struct sdap_id_conn_ctx *conn,
+                      struct sdap_id_op *op,
+                      const char *dom_name);
+
+errno_t
+ad_master_domain_recv(struct tevent_req *req,
+                      TALLOC_CTX *mem_ctx,
+                      char **_flat,
+                      char **_id);
+
+#endif /* _AD_MASTER_DOMAIN_H_ */
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index f181afe6e37ace4cd0d7fba83923129b3161aad3..992881951edc215c9ad6b94efcab905abb3812f5 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -40,6 +40,7 @@
 #include "providers/ad/ad_srv.h"
 #include "providers/dp_dyndns.h"
 #include "providers/ad/ad_subdomains.h"
+#include "providers/ad/ad_domain_info.h"
 
 struct ad_options *ad_options = NULL;
 
@@ -214,7 +215,6 @@ sssm_ad_id_init(struct be_ctx *bectx,
                           &ad_ctx->sdap_id_ctx->opts->idmap_ctx);
     if (ret != EOK) goto done;
 
-
     ret = setup_tls_config(ad_ctx->sdap_id_ctx->opts->basic);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 876850888a8d58d7cb967bf39ecbcae1bf2d5f0c..f15a013803f34ee36ac5ac70162f23525ab4be36 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -24,6 +24,7 @@
 
 #include "providers/ldap/sdap_async.h"
 #include "providers/ad/ad_subdomains.h"
+#include "providers/ad/ad_domain_info.h"
 #include "util/util_sss_idmap.h"
 #include <ctype.h>
 #include <ndr.h>
@@ -264,9 +265,7 @@ done:
 }
 
 static void ad_subdomains_get_conn_done(struct tevent_req *req);
-static errno_t ad_subdomains_get_master_sid(struct ad_subdomains_req_ctx *ctx);
-static void ad_subdomains_get_master_sid_done(struct tevent_req *req);
-static void ad_subdomains_get_netlogon_done(struct tevent_req *req);
+static void ad_subdomains_master_dom_done(struct tevent_req *req);
 static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx);
 
 static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
@@ -341,236 +340,46 @@ static void ad_subdomains_get_conn_done(struct tevent_req *req)
         goto fail;
     }
 
-    ret = ad_subdomains_get_master_sid(ctx);
-    if (ret == EAGAIN) {
-        return;
-    } else if (ret != EOK) {
+    req = ad_master_domain_send(ctx, ctx->sd_ctx->be_ctx->ev,
+                                ctx->sd_ctx->ldap_ctx,
+                                ctx->sdap_op,
+                                ctx->sd_ctx->domain_name);
+    if (req == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("ad_master_domain_send failed.\n"));
+        ret = ENOMEM;
         goto fail;
     }
-
-    DEBUG(SSSDBG_OP_FAILURE, ("No search base available.\n"));
-    ret = EINVAL;
+    tevent_req_set_callback(req, ad_subdomains_master_dom_done, ctx);
+    return;
 
 fail:
     be_req_terminate(ctx->be_req, dp_error, ret, NULL);
 }
 
-static errno_t ad_subdomains_get_master_sid(struct ad_subdomains_req_ctx *ctx)
+static void ad_subdomains_master_dom_done(struct tevent_req *req)
 {
-    struct tevent_req *req;
-    struct sdap_search_base *base;
-    const char *master_sid_attrs[] = {AD_AT_OBJECT_SID, NULL};
-
-
-    base = ctx->sd_ctx->sdom->search_bases[ctx->base_iter];
-    if (base == NULL) {
-        return EOK;
-    }
-
-    req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
-                           ctx->sd_ctx->sdap_id_ctx->opts,
-                           sdap_id_op_handle(ctx->sdap_op),
-                           base->basedn, LDAP_SCOPE_BASE,
-                           MASTER_DOMAIN_SID_FILTER, master_sid_attrs,
-                           NULL, 0,
-                           dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
-                                          SDAP_SEARCH_TIMEOUT),
-                           false);
-
-    if (req == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
-        return ENOMEM;
-    }
-
-    tevent_req_set_callback(req, ad_subdomains_get_master_sid_done, ctx);
-
-    return EAGAIN;
-}
-
-static void ad_subdomains_get_master_sid_done(struct tevent_req *req)
-{
-    int ret;
-    size_t reply_count;
-    struct sysdb_attrs **reply = NULL;
     struct ad_subdomains_req_ctx *ctx;
-    struct ldb_message_element *el;
-    char *sid_str;
-    enum idmap_error_code err;
-    static const char *attrs[] = {AD_AT_NETLOGON, NULL};
-    char *filter;
-    char *ntver;
+    errno_t ret;
 
     ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
 
-    ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
+    ret = ad_master_domain_recv(req, ctx,
+                                &ctx->flat_name, &ctx->master_sid);
     talloc_zfree(req);
     if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
-        goto done;
-    }
-
-    if (reply_count == 0) {
-        ctx->base_iter++;
-        ret = ad_subdomains_get_master_sid(ctx);
-        if (ret == EAGAIN) {
-            return;
-        } else if (ret != EOK) {
-            goto done;
-        }
-    } else if (reply_count == 1) {
-        ret = sysdb_attrs_get_el(reply[0], AD_AT_OBJECT_SID, &el);
-        if (ret != EOK || el->num_values != 1) {
-            DEBUG(SSSDBG_OP_FAILURE, ("sdap_attrs_get_el failed.\n"));
-            goto done;
-        }
-
-        err = sss_idmap_bin_sid_to_sid(ctx->sd_ctx->idmap_ctx,
-                                       el->values[0].data,
-                                       el->values[0].length,
-                                       &sid_str);
-        if (err != IDMAP_SUCCESS) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  ("Could not convert SID: [%s].\n", idmap_error_string(err)));
-            ret = EFAULT;
-            goto done;
-        }
-
-        ctx->master_sid = talloc_steal(ctx, sid_str);
-    } else {
-        DEBUG(SSSDBG_OP_FAILURE,
-              ("More than one result for domain SID found.\n"));
-        ret = EINVAL;
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n"));
         goto done;
     }
 
-    DEBUG(SSSDBG_TRACE_FUNC, ("Found SID [%s].\n", ctx->master_sid));
-
-    ntver = sss_ldap_encode_ndr_uint32(ctx, NETLOGON_NT_VERSION_5EX |
-                                       NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
-    if (ntver == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sss_ldap_encode_ndr_uint32 failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-
-    filter = talloc_asprintf(ctx, "(&(%s=%s)(%s=%s))",
-                             AD_AT_DNS_DOMAIN, ctx->sd_ctx->domain_name,
-                             AD_AT_NT_VERSION, ntver);
-    if (filter == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-
-    req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
-                           ctx->sd_ctx->sdap_id_ctx->opts,
-                           sdap_id_op_handle(ctx->sdap_op),
-                           "", LDAP_SCOPE_BASE, filter, attrs, NULL, 0,
-                           dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
-                                          SDAP_SEARCH_TIMEOUT),
-                           false);
-    if (req == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-
-    tevent_req_set_callback(req, ad_subdomains_get_netlogon_done, ctx);
-    return;
-
-done:
-    be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
-}
-
-static void ad_subdomains_get_netlogon_done(struct tevent_req *req)
-{
-    int ret;
-    size_t reply_count;
-    struct sysdb_attrs **reply = NULL;
-    struct ad_subdomains_req_ctx *ctx;
-    struct ldb_message_element *el;
-    DATA_BLOB blob;
-    enum ndr_err_code ndr_err;
-    struct ndr_pull *ndr_pull = NULL;
-    struct netlogon_samlogon_response response;
-    int dp_error = DP_ERR_FATAL;
-
-    ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
-
-    ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
-    talloc_zfree(req);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
-        goto done;
-    }
-
-    if (reply_count == 0) {
-        DEBUG(SSSDBG_TRACE_FUNC, ("No netlogon data available.\n"));
-        ret = ENOENT;
-        goto done;
-    } else if (reply_count > 1) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              ("More than one netlogon info returned.\n"));
-        ret = EINVAL;
-        goto done;
-    }
-
-    ret = sysdb_attrs_get_el(reply[0], AD_AT_NETLOGON, &el);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_el() failed\n"));
-        goto done;
-    }
-
-    if (el->num_values == 0) {
-        DEBUG(SSSDBG_OP_FAILURE, ("netlogon has no value\n"));
-        ret = ENOENT;
-        goto done;
-    } else if (el->num_values > 1) {
-        DEBUG(SSSDBG_OP_FAILURE, ("More than one netlogon value?\n"));
-        ret = EIO;
-        goto done;
-    }
-
-    blob.data =  el->values[0].data;
-    blob.length = el->values[0].length;
-
-    ndr_pull = ndr_pull_init_blob(&blob, ctx);
-    if (ndr_pull == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_init_blob() failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-
-    ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS,
-                                                  &response);
-    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-        DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_netlogon_samlogon_response() "
-                                  "failed [%d]\n", ndr_err));
-        ret = EBADMSG;
-        goto done;
-    }
-
-    if (!(response.ntver & NETLOGON_NT_VERSION_5EX)) {
-        DEBUG(SSSDBG_OP_FAILURE, ("Wrong version returned [%x]\n",
-                                  response.ntver));
-        ret = EBADMSG;
-        goto done;
-    }
-
-    if (response.data.nt5_ex.domain_name != NULL &&
-        *response.data.nt5_ex.domain_name != '\0') {
-        ctx->flat_name = talloc_strdup(ctx, response.data.nt5_ex.domain_name);
-        if (ctx->flat_name == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
-            ret = ENOMEM;
-            goto done;
-        }
-    }
-
     DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", ctx->flat_name));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found master SID [%s].\n", ctx->master_sid));
 
     ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
                                        ctx->flat_name, ctx->master_sid);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n"));
+        goto done;
+    }
 
     ret = ad_subdomains_get_slave(ctx);
     if (ret == EAGAIN) {
@@ -580,7 +389,7 @@ static void ad_subdomains_get_netlogon_done(struct tevent_req *req)
     }
 
 done:
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
 }
 
 static void ad_subdomains_get_slave_domain_done(struct tevent_req *req);
-- 
1.8.3.1

-------------- next part --------------
>From 3e6766bcb1de201a6eff4cf8e4d21e92e61f5d72 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sat, 24 Aug 2013 14:43:57 +0200
Subject: [PATCH 2/3] LDAP: sdap_id_setup_tasks accepts a custom enum request

AD provider will override the default with its own.
---
 src/providers/ipa/ipa_subdomains.c |  4 +++-
 src/providers/ldap/ldap_common.c   | 10 +++++++---
 src/providers/ldap/ldap_common.h   | 16 ++++++++++++++--
 src/providers/ldap/ldap_id_enum.c  | 17 +++++------------
 4 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index c28af0e76a41352b80ab816076de156607243c1d..496af42b7c134bec8b106b3302cfb09a2a7fbc53 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -186,7 +186,9 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
     }
 
     ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx,
-                              ad_id_ctx->ldap_ctx, sdom);
+                              ad_id_ctx->ldap_ctx, sdom,
+                              ldap_enumeration_send,
+                              ldap_enumeration_recv);
     if (ret != EOK) {
         talloc_free(ad_options);
         return ret;
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 0df5afe8eab3f68f56dd47b1c01f2692b612c160..b668a48e33ab9791be73d4788e28b27d5822255b 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -938,12 +938,16 @@ void sdap_mark_offline(struct sdap_id_ctx *ctx)
 
 int ldap_id_setup_tasks(struct sdap_id_ctx *ctx)
 {
-    return sdap_id_setup_tasks(ctx, ctx->conn, ctx->opts->sdom);
+    return sdap_id_setup_tasks(ctx, ctx->conn, ctx->opts->sdom,
+                               ldap_enumeration_send,
+                               ldap_enumeration_recv);
 }
 
 int sdap_id_setup_tasks(struct sdap_id_ctx *ctx,
                         struct sdap_id_conn_ctx *conn,
-                        struct sdap_domain *sdom)
+                        struct sdap_domain *sdom,
+                        be_ptask_send_t send_fn,
+                        be_ptask_recv_t recv_fn)
 {
     struct timeval tv;
     int ret = EOK;
@@ -952,7 +956,7 @@ int sdap_id_setup_tasks(struct sdap_id_ctx *ctx,
     /* set up enumeration task */
     if (sdom->dom->enumerate) {
         DEBUG(SSSDBG_TRACE_FUNC, ("Setting up enumeration for %s\n", sdom->dom->name));
-        ret = ldap_setup_enumeration(ctx, conn, sdom);
+        ret = ldap_setup_enumeration(ctx, conn, sdom, send_fn, recv_fn);
     } else {
         /* the enumeration task, runs the cleanup process by itself,
          * but if enumeration is not running we need to schedule it */
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index a5f3dee94c14eb2fb5f72eb9768d24b7a20ccce9..b21de0024c90ae7a62e5461091e0eeaad1526601 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -95,7 +95,9 @@ void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx,
 int ldap_id_setup_tasks(struct sdap_id_ctx *ctx);
 int sdap_id_setup_tasks(struct sdap_id_ctx *ctx,
                         struct sdap_id_conn_ctx *conn,
-                        struct sdap_domain *sdom);
+                        struct sdap_domain *sdom,
+                        be_ptask_send_t send_fn,
+                        be_ptask_recv_t recv_fn);
 
 struct tevent_req *
 sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
@@ -169,7 +171,17 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx,
 
 errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
                                struct sdap_id_conn_ctx *conn,
-                               struct sdap_domain *sdom);
+                               struct sdap_domain *sdom,
+                               be_ptask_send_t send_fn,
+                               be_ptask_recv_t recv_fn);
+struct tevent_req *
+ldap_enumeration_send(TALLOC_CTX *mem_ctx,
+                      struct tevent_context *ev,
+                      struct be_ctx *be_ctx,
+                      struct be_ptask *be_ptask,
+                      void *pvt);
+errno_t ldap_enumeration_recv(struct tevent_req *req);
+
 errno_t ldap_id_cleanup(struct sdap_options *opts,
                         struct sdap_domain *sdom);
 int ldap_id_cleanup_create_timer(struct sdap_id_ctx *ctx,
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 961c72f3d888fa92d1002ca483776319d007b679..2a42fdafb66eff9640b30c1f21b8c6470f5abc4f 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -27,14 +27,6 @@
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async_enum.h"
 
-static struct tevent_req *
-ldap_enumeration_send(TALLOC_CTX *mem_ctx,
-                      struct tevent_context *ev,
-                      struct be_ctx *be_ctx,
-                      struct be_ptask *be_ptask,
-                      void *pvt);
-errno_t ldap_enumeration_recv(struct tevent_req *req);
-
 struct ldap_enum_ctx {
     struct sdap_id_ctx *ctx;
     struct sdap_domain *sdom;
@@ -43,7 +35,9 @@ struct ldap_enum_ctx {
 
 errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
                                struct sdap_id_conn_ctx *conn,
-                               struct sdap_domain *sdom)
+                               struct sdap_domain *sdom,
+                               be_ptask_send_t send_fn,
+                               be_ptask_recv_t recv_fn)
 {
     errno_t ret;
     time_t first_delay;
@@ -88,7 +82,7 @@ errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
                           5,                        /* enabled delay */
                           period,                   /* timeout */
                           BE_PTASK_OFFLINE_SKIP,
-                          ldap_enumeration_send, ldap_enumeration_recv,
+                          send_fn, recv_fn,
                           ectx, "enumeration", &sdom->enum_task);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
@@ -101,7 +95,6 @@ errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
     return EOK;
 }
 
-
 struct ldap_enumeration_state {
     struct ldap_enum_ctx *ectx;
     struct sss_domain_info *dom;
@@ -109,7 +102,7 @@ struct ldap_enumeration_state {
 
 static void ldap_enumeration_done(struct tevent_req *subreq);
 
-static struct tevent_req *
+struct tevent_req *
 ldap_enumeration_send(TALLOC_CTX *mem_ctx,
                       struct tevent_context *ev,
                       struct be_ctx *be_ctx,
-- 
1.8.3.1

-------------- next part --------------
>From 354d31598d63409dad59f789db38f0c48bb46117 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Sat, 24 Aug 2013 15:45:57 +0200
Subject: [PATCH 3/3] AD: Download master domain info when enumerating

https://fedorahosted.org/sssd/ticket/2068

With the current design, downloading master domain data was tied to
subdomains refresh, triggered by responders. But because enumeration is
a background task that can't be triggered on its own, we can't rely on
responders to download the master domain data and we need to check the
master domain on each enumeration request.
---
 src/providers/ad/ad_id.c          | 185 ++++++++++++++++++++++++++++++++++++++
 src/providers/ad/ad_id.h          |  10 +++
 src/providers/ad/ad_init.c        |   6 +-
 src/providers/ldap/ldap_common.h  |  11 +++
 src/providers/ldap/ldap_id_enum.c |   6 --
 5 files changed, 211 insertions(+), 7 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 48ad842590d0a8904744cd5518ac511205416f28..1d45440e197e79a60dbc038d2b0c0c8ffe823642 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -22,6 +22,8 @@
 #include "util/util.h"
 #include "providers/ad/ad_common.h"
 #include "providers/ad/ad_id.h"
+#include "providers/ad/ad_domain_info.h"
+#include "providers/ldap/sdap_async_enum.h"
 
 struct ad_handle_acct_info_state {
     struct be_req *breq;
@@ -309,3 +311,186 @@ ad_check_online(struct be_req *be_req)
 
     return sdap_do_online_check(be_req, ad_ctx->sdap_id_ctx);
 }
+
+struct ad_enumeration_state {
+    struct ldap_enum_ctx *ectx;
+    struct sdap_id_op *sdap_op;
+    struct tevent_context *ev;
+
+    struct sdap_domain *sdom;
+};
+
+static void ad_enumeration_conn_done(struct tevent_req *subreq);
+static void ad_enumeration_master_done(struct tevent_req *subreq);
+static void ad_enumeration_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ad_enumeration_send(TALLOC_CTX *mem_ctx,
+                    struct tevent_context *ev,
+                    struct be_ctx *be_ctx,
+                    struct be_ptask *be_ptask,
+                    void *pvt)
+{
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct ad_enumeration_state *state;
+    struct ldap_enum_ctx *ectx;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state, struct ad_enumeration_state);
+    if (req == NULL) return NULL;
+
+    ectx = talloc_get_type(pvt, struct ldap_enum_ctx);
+    if (ectx == NULL) {
+        ret = EFAULT;
+        goto fail;
+    }
+
+    state->ectx = ectx;
+    state->ev = ev;
+    state->sdom = ectx->sdom;
+
+    state->sdap_op = sdap_id_op_create(state, ectx->conn->conn_cache);
+    if (state->sdap_op == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: %d(%s).\n",
+                                  ret, strerror(ret)));
+        goto fail;
+    }
+    tevent_req_set_callback(subreq, ad_enumeration_conn_done, req);
+
+    return req;
+
+fail:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static void
+ad_enumeration_conn_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_enumeration_state *state = tevent_req_data(req,
+                                                 struct ad_enumeration_state);
+    int ret, dp_error;
+
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        if (dp_error == DP_ERR_OFFLINE) {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  ("Backend is marked offline, retry later!\n"));
+            tevent_req_done(req);
+        } else {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Domain enumeration failed to connect to " \
+                   "LDAP server: (%d)[%s]\n", ret, strerror(ret)));
+            tevent_req_error(req, ret);
+        }
+        return;
+    }
+
+    subreq = ad_master_domain_send(state, state->ev,
+                                   state->ectx->conn,
+                                   state->sdap_op,
+                                   state->sdom->dom->name);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("ad_master_domain_send failed.\n"));
+        tevent_req_error(req, ret);
+        return;
+    }
+    tevent_req_set_callback(subreq, ad_enumeration_master_done, req);
+}
+
+static void
+ad_enumeration_master_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_enumeration_state *state = tevent_req_data(req,
+                                                struct ad_enumeration_state);
+    char *flat_name;
+    char *master_sid;
+
+    ret = ad_master_domain_recv(subreq, state,
+                                &flat_name, &master_sid);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n"));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", flat_name));
+    DEBUG(SSSDBG_TRACE_FUNC, ("Found master SID [%s].\n", master_sid));
+
+    ret = sysdb_master_domain_add_info(state->sdom->dom,
+                                       flat_name, master_sid);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n"));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    subreq = sdap_dom_enum_send(state, state->ev, state->ectx->ctx,
+                                state->sdom, state->ectx->conn);
+    if (subreq == NULL) {
+        /* The ptask API will reschedule the enumeration on its own on
+         * failure */
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Failed to schedule enumeration, retrying later!\n"));
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+    tevent_req_set_callback(subreq, ad_enumeration_done, req);
+}
+
+static void
+ad_enumeration_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_enumeration_state *state = tevent_req_data(req,
+                                                struct ad_enumeration_state);
+
+    ret = sdap_dom_enum_recv(subreq);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Could not enumerate domain %s\n", state->sdom->dom->name));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    /* Ok, we've completed an enumeration. Save this to the
+     * sysdb so we can postpone starting up the enumeration
+     * process on the next SSSD service restart (to avoid
+     * slowing down system boot-up
+     */
+    ret = sysdb_set_enumerated(state->sdom->dom->sysdb,
+                               state->sdom->dom, true);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              ("Could not mark domain as having enumerated.\n"));
+        /* This error is non-fatal, so continue */
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t
+ad_enumeration_recv(struct tevent_req *req)
+{
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+    return EOK;
+}
diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h
index 1fd6b599a8c42ccf9b68cec6b450a01c5ad80796..74b85645c2d6458617a4064fe3fb3f99696c3741 100644
--- a/src/providers/ad/ad_id.h
+++ b/src/providers/ad/ad_id.h
@@ -37,6 +37,16 @@ errno_t
 ad_handle_acct_info_recv(struct tevent_req *req,
                          int *_dp_error, const char **_err);
 
+struct tevent_req *
+ad_enumeration_send(TALLOC_CTX *mem_ctx,
+                    struct tevent_context *ev,
+                    struct be_ctx *be_ctx,
+                    struct be_ptask *be_ptask,
+                    void *pvt);
+
+errno_t
+ad_enumeration_recv(struct tevent_req *req);
+
 void
 ad_check_online(struct be_req *be_req);
 #endif /* AD_ID_H_ */
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 992881951edc215c9ad6b94efcab905abb3812f5..c829cc861a421db35b1e5f7a91941e20a3684ee6 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -205,7 +205,11 @@ sssm_ad_id_init(struct be_ctx *bectx,
         goto done;
     }
 
-    ret = ldap_id_setup_tasks(ad_ctx->sdap_id_ctx);
+    ret = sdap_id_setup_tasks(ad_ctx->sdap_id_ctx,
+                              ad_ctx->sdap_id_ctx->conn,
+                              ad_ctx->sdap_id_ctx->opts->sdom,
+                              ad_enumeration_send,
+                              ad_enumeration_recv);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index b21de0024c90ae7a62e5461091e0eeaad1526601..0d565fc63b7e949e628ae5cf079e54c134464e77 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -169,6 +169,17 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx,
                             const char *conf_path,
                             struct sdap_options *opts);
 
+/* Calling ldap_setup_enumeration will set up a periodic task
+ * that would periodically call send_fn/recv_fn request. The
+ * send_fn's pvt parameter will be a pointer to ldap_enum_ctx
+ * structure that contains the request data
+ */
+struct ldap_enum_ctx {
+    struct sdap_id_ctx *ctx;
+    struct sdap_domain *sdom;
+    struct sdap_id_conn_ctx *conn;
+};
+
 errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
                                struct sdap_id_conn_ctx *conn,
                                struct sdap_domain *sdom,
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 2a42fdafb66eff9640b30c1f21b8c6470f5abc4f..8cccaa916a24beb10fe692d9a0e09f5f47ceb6f7 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -27,12 +27,6 @@
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async_enum.h"
 
-struct ldap_enum_ctx {
-    struct sdap_id_ctx *ctx;
-    struct sdap_domain *sdom;
-    struct sdap_id_conn_ctx *conn;
-};
-
 errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx,
                                struct sdap_id_conn_ctx *conn,
                                struct sdap_domain *sdom,
-- 
1.8.3.1



More information about the sssd-devel mailing list