|
|
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 |
|