Blame SOURCES/0050-Ticket-49278-GetEffectiveRights-gives-false-negative.patch

058656
From 6e00c3bac13811bc6d94b810b17a59f9428c29f6 Mon Sep 17 00:00:00 2001
058656
From: Ludwig Krispenz <lkrispen@redhat.com>
058656
Date: Thu, 11 Jan 2018 15:17:56 +0100
058656
Subject: [PATCH]    Ticket 49278 - GetEffectiveRights gives false-negative
058656
058656
    Bug: If geteffective rights was issued for an non existing entry the
058656
         mechanism to genrate a template entry no longer worked and no results were
058656
         returned.
058656
    Fix: Improve the handling in itreating the result set, so that template entries (if
058656
         requested) are genereated and are not applied to existing entries.
058656
         Also some code cleanup in iterate()
058656
    Reviewed by: Thierry, thanks
058656
---
058656
 ldap/servers/slapd/opshared.c | 239 ++++++++++++++++++++----------------------
058656
 1 file changed, 114 insertions(+), 125 deletions(-)
058656
058656
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
058656
index 24157120e..46dcf6fba 100644
058656
--- a/ldap/servers/slapd/opshared.c
058656
+++ b/ldap/servers/slapd/opshared.c
058656
@@ -33,6 +33,7 @@ static char *pwpolicy_lock_attrs_all[] = {"passwordRetryCount",
058656
 static void compute_limits(Slapi_PBlock *pb);
058656
 static int send_results_ext(Slapi_PBlock *pb, int send_result, int *nentries, int pagesize, unsigned int *pr_stat);
058656
 static int process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result);
058656
+static void send_entry(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Operation *operation, char **attrs, int attrsonly, int *pnentries);
058656
 
058656
 int
058656
 op_shared_is_allowed_attr(const char *attr_name, int replicated_op)
058656
@@ -1040,6 +1041,31 @@ process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result)
058656
 
058656
     return 0;
058656
 }
058656
+static void
058656
+send_entry(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Operation *operation, char **attrs, int attrsonly, int *pnentries)
058656
+{
058656
+                /*
058656
+             * It's a regular entry, or it's a referral and
058656
+             * managedsait control is on.  In either case, send
058656
+             * the entry.
058656
+             */
058656
+                switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
058656
+                case 0: /* entry sent ok */
058656
+                    (*pnentries)++;
058656
+                    slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
058656
+                    break;
058656
+                case 1: /* entry not sent */
058656
+                    break;
058656
+                case -1: /* connection closed */
058656
+                    /*
058656
+                     * mark the operation as abandoned so the backend
058656
+                     * next entry function gets called again and has
058656
+                     * a chance to clean things up.
058656
+                     */
058656
+                    operation->o_status = SLAPI_OP_STATUS_ABANDONED;
058656
+                    break;
058656
+                }
058656
+}
058656
 
058656
 #if 0
058656
 /* Loops through search entries and sends them to the client.
058656
@@ -1214,7 +1240,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
058656
     *pnentries = 0;
058656
 
058656
     while (!done) {
058656
-        Slapi_Entry *gerentry = NULL;
058656
+        Slapi_Entry *ger_template_entry = NULL;
058656
         Slapi_Operation *operation;
058656
 
058656
         slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
058656
@@ -1236,57 +1262,57 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
058656
         slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
058656
 
058656
         /* Check for possible get_effective_rights control */
058656
-        if (e) {
058656
-            if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
058656
-                char *errbuf = NULL;
058656
+        if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
058656
+            char *errbuf = NULL;
058656
+
058656
+            if (PAGEDRESULTS_PAGE_END == pr_stat) {
058656
+                /*
058656
+                 * read ahead -- there is at least more entry.
058656
+                 * undo it and return the PAGE_END
058656
+                 */
058656
+                be->be_prev_search_results(pb);
058656
+                done = 1;
058656
+                continue;
058656
+            }
058656
+            if ( e == NULL ) {
058656
                 char **gerattrs = NULL;
058656
                 char **gerattrsdup = NULL;
058656
                 char **gap = NULL;
058656
                 char *gapnext = NULL;
058656
-
058656
-                if (PAGEDRESULTS_PAGE_END == pr_stat) {
058656
-                    /*
058656
-                 * read ahead -- there is at least more entry.
058656
-                 * undo it and return the PAGE_END
058656
+                /* we have no more entries
058656
+                 * but we might create a template entry for GER
058656
+                 * so we need to continue, but make sure to stop
058656
+                 * after handling the template entry.
058656
+                 * the template entry is a temporary entry returned by the acl
058656
+                 * plugin in the pblock and will be freed
058656
                  */
058656
-                    be->be_prev_search_results(pb);
058656
-                    done = 1;
058656
-                    continue;
058656
-                }
058656
+                done = 1;
058656
+                pr_stat = PAGEDRESULTS_SEARCH_END;
058656
 
058656
                 slapi_pblock_get(pb, SLAPI_SEARCH_GERATTRS, &gerattrs);
058656
                 gerattrsdup = cool_charray_dup(gerattrs);
058656
                 gap = gerattrsdup;
058656
-                do {
058656
+                while (gap && *gap) {
058656
                     gapnext = NULL;
058656
-                    if (gap) {
058656
-                        if (*gap && *(gap + 1)) {
058656
-                            gapnext = *(gap + 1);
058656
-                            *(gap + 1) = NULL;
058656
-                        }
058656
-                        slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gap);
058656
-                        rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
058656
-                                                    SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
058656
-                                                    &errbuf);
058656
-                        if (NULL != gapnext) {
058656
-                            *(gap + 1) = gapnext;
058656
-                        }
058656
-                    } else if (NULL != e) {
058656
-                        rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
058656
-                                                    SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
058656
-                                                    &errbuf);
058656
+                    if (*(gap + 1)) {
058656
+                        gapnext = *(gap + 1);
058656
+                        *(gap + 1) = NULL;
058656
+                    }
058656
+                    slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gap);
058656
+                    rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
058656
+                                                SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
058656
+                                                &errbuf);
058656
+                    if (NULL != gapnext) {
058656
+                        *(gap + 1) = gapnext;
058656
                     }
058656
+                    gap++;
058656
+                    /* get the template entry, if any */
058656
+                    slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
058656
                     if (NULL == e) {
058656
-                        /* get the template entry, if any */
058656
-                        slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
058656
-                        if (NULL == e) {
058656
-                            /* everything is ok - don't send the result */
058656
-                            pr_stat = PAGEDRESULTS_SEARCH_END;
058656
-                            done = 1;
058656
-                            continue;
058656
-                        }
058656
-                        gerentry = e;
058656
+                        /* everything is ok - don't send the result */
058656
+                        continue;
058656
                     }
058656
+                    ger_template_entry = e;
058656
                     if (rc != LDAP_SUCCESS) {
058656
                         /* Send error result and
058656
                        abort op if the control is critical */
058656
@@ -1294,65 +1320,53 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
058656
                                       "Failed to get effective rights for entry (%s), rc=%d\n",
058656
                                       slapi_entry_get_dn_const(e), rc);
058656
                         send_ldap_result(pb, rc, NULL, errbuf, 0, NULL);
058656
-                        slapi_ch_free((void **)&errbuf);
058656
-                        if (gerentry) {
058656
-                            slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
058656
-                            slapi_entry_free(gerentry);
058656
-                            gerentry = e = NULL;
058656
-                        }
058656
-                        pr_stat = PAGEDRESULTS_SEARCH_END;
058656
                         rval = -1;
058656
-                        done = 1;
058656
-                        continue;
058656
-                    }
058656
-                    slapi_ch_free((void **)&errbuf);
058656
-                    if (process_entry(pb, e, send_result)) {
058656
-                        /* shouldn't send this entry */
058656
-                        if (gerentry) {
058656
-                            slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
058656
-                            slapi_entry_free(gerentry);
058656
-                            gerentry = e = NULL;
058656
+                    } else {
058656
+                        if (!process_entry(pb, e, send_result)) {
058656
+                            /* should send this entry now*/
058656
+                            send_entry(pb, e, operation, attrs, attrsonly, pnentries);
058656
                         }
058656
-                        continue;
058656
                     }
058656
 
058656
-                    /*
058656
-                 * It's a regular entry, or it's a referral and
058656
-                 * managedsait control is on.  In either case, send
058656
-                 * the entry.
058656
-                 */
058656
-                    switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
058656
-                    case 0: /* entry sent ok */
058656
-                        (*pnentries)++;
058656
-                        slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
058656
-                        break;
058656
-                    case 1: /* entry not sent */
058656
-                        break;
058656
-                    case -1: /* connection closed */
058656
-                        /*
058656
-                         * mark the operation as abandoned so the backend
058656
-                         * next entry function gets called again and has
058656
-                         * a chance to clean things up.
058656
-                         */
058656
-                        operation->o_status = SLAPI_OP_STATUS_ABANDONED;
058656
-                        break;
058656
-                    }
058656
-                    if (gerentry) {
058656
+                    slapi_ch_free((void **)&errbuf);
058656
+                    if (ger_template_entry) {
058656
                         slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
058656
-                        slapi_entry_free(gerentry);
058656
-                        gerentry = e = NULL;
058656
+                        slapi_entry_free(ger_template_entry);
058656
+                        ger_template_entry = e = NULL;
058656
                     }
058656
-                } while (gap && ++gap && *gap);
058656
+                } /* while ger template */
058656
                 slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gerattrs);
058656
                 cool_charray_free(gerattrsdup);
058656
-                if (pagesize == *pnentries) {
058656
-                    /* PAGED RESULTS: reached the pagesize */
058656
-                    /* We don't set "done = 1" here.
058656
-                 * We read ahead next entry to check whether there is
058656
-                 * more entries to return or not. */
058656
-                    pr_stat = PAGEDRESULTS_PAGE_END;
058656
+            } else {
058656
+                /* we are processing geteffective rights for an existing entry */
058656
+                rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
058656
+                                            SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
058656
+                                             &errbuf);
058656
+                if (rc != LDAP_SUCCESS) {
058656
+                    /* Send error result and
058656
+                       abort op if the control is critical */
058656
+                    slapi_log_err(SLAPI_LOG_ERR, "iterate",
058656
+                                  "Failed to get effective rights for entry (%s), rc=%d\n",
058656
+                                  slapi_entry_get_dn_const(e), rc);
058656
+                    send_ldap_result(pb, rc, NULL, errbuf, 0, NULL);
058656
+                    rval = -1;
058656
+                } else {
058656
+                    if (!process_entry(pb, e, send_result)) {
058656
+                        /* should send this entry now*/
058656
+                        send_entry(pb, e, operation, attrs, attrsonly, pnentries);
058656
+                        if (pagesize == *pnentries) {
058656
+                            /* PAGED RESULTS: reached the pagesize */
058656
+                            /* We don't set "done = 1" here.
058656
+                             * We read ahead next entry to check whether there is
058656
+                             * more entries to return or not. */
058656
+                            pr_stat = PAGEDRESULTS_PAGE_END;
058656
+                        }
058656
+                    }
058656
                 }
058656
-            } else { /* not GET_EFFECTIVE_RIGHTS */
058656
+                slapi_ch_free((void **)&errbuf);
058656
+            }
058656
+        /* not GET_EFFECTIVE_RIGHTS */
058656
+        } else if (e) {
058656
                 if (PAGEDRESULTS_PAGE_END == pr_stat) {
058656
                     /*
058656
                  * read ahead -- there is at least more entry.
058656
@@ -1364,46 +1378,21 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
058656
                 }
058656
                 /* Adding shadow password attrs. */
058656
                 add_shadow_ext_password_attrs(pb, &e);
058656
-                if (process_entry(pb, e, send_result)) {
058656
-                    /* shouldn't  send this entry */
058656
-                    struct slapi_entry *pb_pw_entry = slapi_pblock_get_pw_entry(pb);
058656
-                    slapi_entry_free(pb_pw_entry);
058656
-                    slapi_pblock_set_pw_entry(pb, NULL);
058656
-                    continue;
058656
-                }
058656
-
058656
-                /*
058656
-             * It's a regular entry, or it's a referral and
058656
-             * managedsait control is on.  In either case, send
058656
-             * the entry.
058656
-             */
058656
-                switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
058656
-                case 0: /* entry sent ok */
058656
-                    (*pnentries)++;
058656
-                    slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
058656
-                    break;
058656
-                case 1: /* entry not sent */
058656
-                    break;
058656
-                case -1: /* connection closed */
058656
-                    /*
058656
-                     * mark the operation as abandoned so the backend
058656
-                     * next entry function gets called again and has
058656
-                     * a chance to clean things up.
058656
-                     */
058656
-                    operation->o_status = SLAPI_OP_STATUS_ABANDONED;
058656
-                    break;
058656
+                if (!process_entry(pb, e, send_result)) {
058656
+                    /*this entry was not sent, do it now*/
058656
+                    send_entry(pb, e, operation, attrs, attrsonly, pnentries);
058656
+                    if (pagesize == *pnentries) {
058656
+                        /* PAGED RESULTS: reached the pagesize */
058656
+                        /* We don't set "done = 1" here.
058656
+                         * We read ahead next entry to check whether there is
058656
+                         * more entries to return or not. */
058656
+                        pr_stat = PAGEDRESULTS_PAGE_END;
058656
+                    }
058656
                 }
058656
+                /* cleanup pw entry . sent or not */
058656
                 struct slapi_entry *pb_pw_entry = slapi_pblock_get_pw_entry(pb);
058656
                 slapi_entry_free(pb_pw_entry);
058656
                 slapi_pblock_set_pw_entry(pb, NULL);
058656
-                if (pagesize == *pnentries) {
058656
-                    /* PAGED RESULTS: reached the pagesize */
058656
-                    /* We don't set "done = 1" here.
058656
-                 * We read ahead next entry to check whether there is
058656
-                 * more entries to return or not. */
058656
-                    pr_stat = PAGEDRESULTS_PAGE_END;
058656
-                }
058656
-            }
058656
         } else {
058656
             /* no more entries */
058656
             done = 1;
058656
-- 
058656
2.13.6
058656