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

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