tldap search paged

swen swen at
Wed Apr 8 17:07:57 UTC 2020

On Wed, 2020-04-08 at 09:07 -0700, Jeremy Allison wrote:
> On Wed, Apr 08, 2020 at 08:32:50AM +0200, swen via samba-technical
> wrote:
> > Hi Uri, Jeremy, Ralph, Volker, Metze and others
> > 
> > I know you all have received enough emails about this subject
> > already,
> > but I'd like to ask you one more time to revisit merge request 1258
> > 
> >
> > 
> > I'm not sure if you all got informed about the comments / updates
> > since
> > our last conversation round, therefore, I'm sending out this
> > friendly
> > reminder :-)
> > 
> > As stated in the MR, I have updated the code according to your
> > comments
> > and suggestions, including an abort mechanism for the async-
> > callback
> > variant. 
> > ...and yes, for now, I threw out the _all-variant.
> > 
> > In order to re-start my work on winbindd_ldap, which is the "real"
> > project I'm working on, I need to have a stable foundation in the
> > tldap-area.
> > 
> > So please, if your time permits, have another look at the MR.
> You haven't explained *why* you need this code.
Hmm sorry, I thought I did say that I'm in the process of creating a
winbindd_ldap which is supposed to replace winbindd_ads.
> I see tldap changes, and a test which is great.
> I don't see any *users* of this code.
> Adding utility code without any use requirements
> is a receipe for bad API's and design.
The API is there already and wasn't created or changed by me.
In fact, the utility code exists since 2009.

The things I did include:
1. Extend the torture test to actually execute a real world scenario
   ...pretty much what I will do in winbindd_ldap's enum_dom_groups()
2. Externalizing tldap_context's last_msg, which was asked for by Metze
   and adding a torture test for it.
3. Introducing #2 to the existing search_paged function
4. Creating the possibility to abort the async-callback for 
search_paged which was asked for by Uri
   ...and creating a test for it.

> Please show the need for this code before
> we go any further spending valuable review
> time on it.
I was trying to split the review process and my coding efforts
into smaller chunks which should help everyboy to consume and digest
the changes better.
If I only present the end-version, then it could get ugly to change
major parts of it.
Therefore, It thought the early presentation and inclusion of self-
contained code parts would be the smarter way.

Anyhow, here is a code snippet of what is currently part of my new
winbindd_ldap.c which shows how the proposed code changes are used.

static void enum_dom_groups_cb(struct tevent_req *req)
        struct dom_groups_res *res =
                tevent_req_callback_data(req, struct dom_groups_res);
        struct wb_acct_info *tmp;
        struct tldap_message *msg;
        size_t array_size;
        char *name = NULL;
        char *gecos = NULL;
        struct dom_sid sid = {0};
        uint32_t rid;
        TLDAPRC rc;

        if (!tevent_req_is_in_progress(req)) {

        rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
        if (!TLDAP_RC_IS_SUCCESS(rc)) {
                DBG_ERR("SSS in callback-2 rc=%d\n", rc.rc);
                tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);

        switch (tldap_msg_type(msg)) {
                if (res->num_info >= talloc_array_length(res->info)) {
                        array_size = res->num_info + res->page_size;
                        if (array_size < res->page_size) {
                                tevent_req_ldap_error(req, TLDAP_PARAM_ERROR);

                        tmp = talloc_realloc(req,
                                             struct wb_acct_info,

                        if (tmp == NULL) {
                                tevent_req_ldap_error(req, TLDAP_NO_MEMORY);

                        res->info = tmp;

                name = tldap_talloc_single_attribute(msg,
                if (name == NULL) {
                        DBG_INFO("Object lacks sAMAccountName attribute\n");
                        goto out;

                gecos = tldap_talloc_single_attribute(msg, "name", req);
                if (gecos == NULL) {
                        DBG_INFO("Object lacks name attribute\n");
                        goto out;

                if (!tldap_pull_binsid(msg, "objectSid", &sid)) {
                        DBG_INFO("No SID found\n");
                        goto out;

                if (!sid_peek_check_rid(res->dom_sid, &sid, &rid)) {
                        DBG_INFO("No rid for %s !?\n", name);
                        goto out;

                res->info[res->num_info].acct_name = name;
                res->info[res->num_info].acct_desc = gecos;
                res->info[res->num_info].rid = rid;



static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
                                uint32_t *num_entries,
                                struct wb_acct_info **info)
        const char *attrs[] = {"sAMAccountName", "objectSid", "name",
                               "userPrincipalName", NULL};
        struct tevent_context *ev;
        struct dom_groups_res *res;
        struct wb_ldap_context *ctx = NULL;
        const size_t page_size = 1000;
        struct tevent_req *req;
        const char *filter;
        TLDAPRC ret;

        if (domain == NULL || !winbindd_can_contact_domain(domain)) {
                DBG_ERR("No incoming trust for domain %s\n",
                          domain ? domain->name : "NULL");

                /* Tell the cache manager not to remember this one */

        ret = wb_ldap_connection(domain);
        if (!TLDAP_RC_IS_SUCCESS(ret)) {
                goto out;

        filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group))");

        ctx = talloc_get_type_abort(domain->private_data,
                                    struct wb_ldap_context);

        if (filter == NULL) {
                status = NT_STATUS_NO_MEMORY;
                goto out;
        ev = samba_tevent_context_init(mem_ctx);
        if (ev == NULL) {
                DBG_ERR("Failed to create event context\n");
                goto out;

        req = tldap_search_paged_send(mem_ctx, ev, ctx->ld, ctx->naming_ctx,
                                      TLDAP_SCOPE_SUB, filter,
                                      attrs, 4, 0,
                                      NULL, 0, NULL, 0, 0, 0, 0, page_size);

        if (req == NULL) {
                DBG_ERR("Search paged failed.\n");
                goto out;

        res = talloc_zero(req, struct dom_groups_res);
        res->page_size = page_size;
        res->dom_sid = &domain->sid;
        tevent_req_set_callback(req, enum_dom_groups_cb, res);

        tevent_req_poll(req, ev);

        *info = res->info;
        *num_entries = res->num_info;
        return status;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <>

More information about the samba-technical mailing list