Blame SOURCES/0033-Issue-5442-Search-results-are-different-between-RHDS.patch

be9751
From 788d7c69a446d1ae324b2c58daaa5d4fd5528748 Mon Sep 17 00:00:00 2001
be9751
From: Mark Reynolds <mreynolds@redhat.com>
be9751
Date: Wed, 20 Jan 2021 16:42:15 -0500
be9751
Subject: [PATCH 1/3] Issue 5442 - Search results are different between RHDS10
be9751
 and RHDS11
be9751
be9751
Bug Description:  In 1.4.x we introduced a change that was overly strict about
be9751
                  how a search on a non-existent subtree returned its error code.
be9751
                  It was changed from returning an error 32 to an error 0 with
be9751
                  zero entries returned.
be9751
be9751
Fix Description:  When finding the entry and processing acl's make sure to
be9751
                  gather the aci's that match the resource even if the resource
be9751
                  does not exist.  This requires some extra checks when processing
be9751
                  the target attribute.
be9751
be9751
relates: https://github.com/389ds/389-ds-base/issues/4542
be9751
be9751
Reviewed by: firstyear, elkris, and tbordaz (Thanks!)
be9751
be9751
Apply Thierry's changes
be9751
be9751
round 2
be9751
be9751
Apply more suggestions from Thierry
be9751
---
be9751
 dirsrvtests/tests/suites/acl/misc_test.py | 108 +++++++-
be9751
 ldap/servers/plugins/acl/acl.c            | 296 ++++++++++------------
be9751
 ldap/servers/slapd/back-ldbm/findentry.c  |   6 +-
be9751
 src/lib389/lib389/_mapped_object.py       |   4 +-
be9751
 4 files changed, 239 insertions(+), 175 deletions(-)
be9751
be9751
diff --git a/dirsrvtests/tests/suites/acl/misc_test.py b/dirsrvtests/tests/suites/acl/misc_test.py
be9751
index 5f0e3eb72..c640e60ad 100644
be9751
--- a/dirsrvtests/tests/suites/acl/misc_test.py
be9751
+++ b/dirsrvtests/tests/suites/acl/misc_test.py
be9751
@@ -12,7 +12,7 @@ import ldap
be9751
 import os
be9751
 import pytest
be9751
 
be9751
-from lib389._constants import DEFAULT_SUFFIX, PW_DM
be9751
+from lib389._constants import DEFAULT_SUFFIX, PW_DM, DN_DM
be9751
 from lib389.idm.user import UserAccount, UserAccounts
be9751
 from lib389._mapped_object import DSLdapObject
be9751
 from lib389.idm.account import Accounts, Anonymous
be9751
@@ -408,14 +408,112 @@ def test_do_bind_as_201_distinct_users(topo, clean, aci_of_user):
be9751
         user = uas.create_test_user(uid=i, gid=i)
be9751
         user.set('userPassword', PW_DM)
be9751
 
be9751
-    for i in range(len(uas.list())):
be9751
-        uas.list()[i].bind(PW_DM)
be9751
+    users = uas.list()
be9751
+    for user in users:
be9751
+        user.bind(PW_DM)
be9751
 
be9751
     ACLPlugin(topo.standalone).replace("nsslapd-aclpb-max-selected-acls", '220')
be9751
     topo.standalone.restart()
be9751
 
be9751
-    for i in range(len(uas.list())):
be9751
-        uas.list()[i].bind(PW_DM)
be9751
+    users = uas.list()
be9751
+    for user in users:
be9751
+        user.bind(PW_DM)
be9751
+
be9751
+
be9751
+def test_info_disclosure(request, topo):
be9751
+    """Test that a search returns 32 when base entry does not exist
be9751
+
be9751
+    :id: f6dec4c2-65a3-41e4-a4c0-146196863333
be9751
+    :setup: Standalone Instance
be9751
+    :steps:
be9751
+        1. Add aci
be9751
+        2. Add test user
be9751
+        3. Bind as user and search for non-existent entry
be9751
+    :expectedresults:
be9751
+        1. Success
be9751
+        2. Success
be9751
+        3. Error 32 is returned
be9751
+    """
be9751
+
be9751
+    ACI_TARGET = "(targetattr = \"*\")(target = \"ldap:///%s\")" % (DEFAULT_SUFFIX)
be9751
+    ACI_ALLOW = "(version 3.0; acl \"Read/Search permission for all users\"; allow (read,search)"
be9751
+    ACI_SUBJECT = "(userdn=\"ldap:///all\");)"
be9751
+    ACI = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
be9751
+
be9751
+    # Get current ACi's so we can restore them when we are done
be9751
+    suffix = Domain(topo.standalone, DEFAULT_SUFFIX)
be9751
+    preserved_acis = suffix.get_attr_vals_utf8('aci')
be9751
+
be9751
+    def finofaci():
be9751
+        domain = Domain(topo.standalone, DEFAULT_SUFFIX)
be9751
+        try:
be9751
+            domain.remove_all('aci')
be9751
+            domain.replace_values('aci', preserved_acis)
be9751
+        except:
be9751
+            pass
be9751
+    request.addfinalizer(finofaci)
be9751
+
be9751
+    # Remove aci's
be9751
+    suffix.remove_all('aci')
be9751
+
be9751
+    # Add test user
be9751
+    USER_DN = "uid=test,ou=people," + DEFAULT_SUFFIX
be9751
+    users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
be9751
+    users.create(properties={
be9751
+        'uid': 'test',
be9751
+        'cn': 'test',
be9751
+        'sn': 'test',
be9751
+        'uidNumber': '1000',
be9751
+        'gidNumber': '2000',
be9751
+        'homeDirectory': '/home/test',
be9751
+        'userPassword': PW_DM
be9751
+    })
be9751
+
be9751
+    # bind as user
be9751
+    conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
be9751
+
be9751
+    # Search fo existing base DN
be9751
+    test = Domain(conn, DEFAULT_SUFFIX)
be9751
+    try:
be9751
+        test.get_attr_vals_utf8_l('dc')
be9751
+        assert False
be9751
+    except IndexError:
be9751
+        pass
be9751
+
be9751
+    # Search for a non existent bases
be9751
+    subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
be9751
+    try:
be9751
+        subtree.get_attr_vals_utf8_l('objectclass')
be9751
+    except IndexError:
be9751
+        pass
be9751
+    subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
be9751
+    try:
be9751
+        subtree.get_attr_vals_utf8_l('objectclass')
be9751
+    except IndexError:
be9751
+        pass
be9751
+    # Try ONE level search instead of BASE
be9751
+    try:
be9751
+        Accounts(conn, "ou=does_not_exist," + DEFAULT_SUFFIX).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL)
be9751
+    except IndexError:
be9751
+        pass
be9751
+
be9751
+    # add aci
be9751
+    suffix.add('aci', ACI)
be9751
+
be9751
+    # Search for a non existent entry which should raise an exception
be9751
+    with pytest.raises(ldap.NO_SUCH_OBJECT):
be9751
+        conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
be9751
+        subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
be9751
+        subtree.get_attr_vals_utf8_l('objectclass')
be9751
+    with pytest.raises(ldap.NO_SUCH_OBJECT):
be9751
+        conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
be9751
+        subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
be9751
+        subtree.get_attr_vals_utf8_l('objectclass')
be9751
+    with pytest.raises(ldap.NO_SUCH_OBJECT):
be9751
+        conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
be9751
+        DN = "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX
be9751
+        Accounts(conn, DN).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL, strict=True)
be9751
+
be9751
 
be9751
 if __name__ == "__main__":
be9751
     CURRENT_FILE = os.path.realpath(__file__)
be9751
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
be9751
index 41a909a18..4e811f73a 100644
be9751
--- a/ldap/servers/plugins/acl/acl.c
be9751
+++ b/ldap/servers/plugins/acl/acl.c
be9751
@@ -2111,10 +2111,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
     aci_right = aci->aci_access;
be9751
     res_right = aclpb->aclpb_access;
be9751
     if (!(aci_right & res_right)) {
be9751
-        /* If we are looking for read/search and the acl has read/search
be9751
-        ** then go further because if targets match we may keep that
be9751
-        ** acl in  the entry cache list.
be9751
-        */
be9751
+        /*
be9751
+         * If we are looking for read/search and the acl has read/search
be9751
+         * then go further because if targets match we may keep that
be9751
+         * acl in the entry cache list.
be9751
+         */
be9751
         if (!((res_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) &&
be9751
               (aci_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)))) {
be9751
             matches = ACL_FALSE;
be9751
@@ -2122,30 +2123,29 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
         }
be9751
     }
be9751
 
be9751
-
be9751
-    /* first Let's see if the entry is under the subtree where the
be9751
-    ** ACL resides. We can't let somebody affect a target beyond the
be9751
-    ** scope of where the ACL resides
be9751
-    ** Example: ACL is located in "ou=engineering, o=ace industry, c=us
be9751
-    ** but if the target is "o=ace industry, c=us", then we are in trouble.
be9751
-    **
be9751
-    ** If the aci is in the rootdse and the entry is not, then we do not
be9751
-    ** match--ie. acis in the rootdse do NOT apply below...for the moment.
be9751
-    **
be9751
-    */
be9751
+    /*
be9751
+     * First Let's see if the entry is under the subtree where the
be9751
+     * ACL resides. We can't let somebody affect a target beyond the
be9751
+     * scope of where the ACL resides
be9751
+     * Example: ACL is located in "ou=engineering, o=ace industry, c=us
be9751
+     * but if the target is "o=ace industry, c=us", then we are in trouble.
be9751
+     *
be9751
+     * If the aci is in the rootdse and the entry is not, then we do not
be9751
+     * match--ie. acis in the rootdse do NOT apply below...for the moment.
be9751
+     */
be9751
     res_ndn = slapi_sdn_get_ndn(aclpb->aclpb_curr_entry_sdn);
be9751
     aci_ndn = slapi_sdn_get_ndn(aci->aci_sdn);
be9751
-    if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) || (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn))) {
be9751
-
be9751
-        /* cant' poke around */
be9751
+    if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) ||
be9751
+        (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn)))
be9751
+    {
be9751
+        /* can't poke around */
be9751
         matches = ACL_FALSE;
be9751
         goto acl__resource_match_aci_EXIT;
be9751
     }
be9751
 
be9751
     /*
be9751
-    ** We have a single ACI which we need to find if it applies to
be9751
-    ** the resource or not.
be9751
-    */
be9751
+     * We have a single ACI which we need to find if it applies to the resource or not.
be9751
+     */
be9751
     if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) {
be9751
         char *avaType;
be9751
         struct berval *avaValue;
be9751
@@ -2173,25 +2173,23 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
         char *avaType;
be9751
         struct berval *avaValue;
be9751
         char logbuf[1024];
be9751
-
be9751
-        /* We are evaluating the moddn permission.
be9751
-                 * The aci contains target_to and target_from
be9751
-                 *
be9751
-                 * target_to filter must be checked against the resource ndn that was stored in
be9751
-                 * aclpb->aclpb_curr_entry_sdn
be9751
-                 *
be9751
-                 * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
be9751
-                 * (sdn was stored in the pblock)
be9751
-                 */
be9751
+        /*
be9751
+         * We are evaluating the moddn permission.
be9751
+         * The aci contains target_to and target_from
be9751
+         *
be9751
+         * target_to filter must be checked against the resource ndn that was stored in
be9751
+         * aclpb->aclpb_curr_entry_sdn
be9751
+         *
be9751
+         * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
be9751
+         * (sdn was stored in the pblock)
be9751
+         */
be9751
         if (aci->target_to) {
be9751
             f = aci->target_to;
be9751
             dn_matched = ACL_TRUE;
be9751
 
be9751
             /* Now check if the filter is a simple or substring filter */
be9751
             if (aci->aci_type & ACI_TARGET_MODDN_TO_PATTERN) {
be9751
-                /* This is a filter with substring
be9751
-                     * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
be9751
-                     */
be9751
+                /* This is a filter with substring e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com */
be9751
                 slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to substring: %s\n",
be9751
                               slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
be9751
                 if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffix */)) != ACL_TRUE) {
be9751
@@ -2204,9 +2202,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                     }
be9751
                 }
be9751
             } else {
be9751
-                /* This is a filter without substring
be9751
-                     * e.g. ldap:///cn=accounts,dc=example,dc=com
be9751
-                     */
be9751
+                /* This is a filter without substring  e.g. ldap:///cn=accounts,dc=example,dc=com */
be9751
                 slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to: %s\n",
be9751
                               slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
be9751
                 slapi_filter_get_ava(f, &avaType, &avaValue);
be9751
@@ -2230,8 +2226,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
             /* Now check if the filter is a simple or substring filter */
be9751
             if (aci->aci_type & ACI_TARGET_MODDN_FROM_PATTERN) {
be9751
                 /* This is a filter with substring
be9751
-                         * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
be9751
-                         */
be9751
+                 * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
be9751
+                 */
be9751
                 slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from substring: %s\n",
be9751
                               slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
be9751
                 if ((rv = acl_match_substring(f, (char *)slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), 0 /* match suffix */)) != ACL_TRUE) {
be9751
@@ -2243,11 +2239,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                         goto acl__resource_match_aci_EXIT;
be9751
                     }
be9751
                 }
be9751
-
be9751
             } else {
be9751
-                /* This is a filter without substring
be9751
-                         * e.g. ldap:///cn=accounts,dc=example,dc=com
be9751
-                         */
be9751
+                /* This is a filter without substring  e.g. ldap:///cn=accounts,dc=example,dc=com */
be9751
                 slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from: %s\n",
be9751
                               slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
be9751
                 if (!slapi_dn_issuffix(slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), avaValue->bv_val)) {
be9751
@@ -2269,10 +2262,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
     }
be9751
 
be9751
     if (aci->aci_type & ACI_TARGET_PATTERN) {
be9751
-
be9751
         f = aci->target;
be9751
         dn_matched = ACL_TRUE;
be9751
-
be9751
         if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffux */)) != ACL_TRUE) {
be9751
             dn_matched = ACL_FALSE;
be9751
             if (rv == ACL_ERR) {
be9751
@@ -2296,7 +2287,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
 
be9751
     /*
be9751
      * Is it a (target="ldap://cn=*,($dn),o=sun.com") kind of thing.
be9751
-    */
be9751
+     */
be9751
     if (aci->aci_type & ACI_TARGET_MACRO_DN) {
be9751
         /*
be9751
          * See if the ($dn) component matches the string and
be9751
@@ -2306,8 +2297,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
          * entry is the same one don't recalculate it--
be9751
          * this flag only works for search right now, could
be9751
          * also optimise for mods by making it work for mods.
be9751
-        */
be9751
-
be9751
+         */
be9751
         if ((aclpb->aclpb_res_type & ACLPB_NEW_ENTRY) == 0) {
be9751
             /*
be9751
              * Here same entry so just look up the matched value,
be9751
@@ -2356,8 +2346,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                  * If there is already an entry for this aci in this
be9751
                  * aclpb then remove it--it's an old value for a
be9751
                  * different entry.
be9751
-                */
be9751
-
be9751
+                 */
be9751
                 acl_ht_add_and_freeOld(aclpb->aclpb_macro_ht,
be9751
                                        (PLHashNumber)aci->aci_index,
be9751
                                        matched_val);
be9751
@@ -2381,30 +2370,27 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
     }
be9751
 
be9751
     /*
be9751
-    ** Here, if there's a targetfilter field, see if it matches.
be9751
-    **
be9751
-    ** The commented out code below was an erroneous attempt to skip
be9751
-    ** this test.  It is wrong because: 1. you need to store
be9751
-    ** whether the last test matched or not (you cannot just assume it did)
be9751
-    ** and 2. It may not be the same aci, so the previous matched
be9751
-    ** value is a function of the aci.
be9751
-    ** May be interesting to build such a cache...but no evidence for
be9751
-    ** for that right now. See Bug 383424.
be9751
-    **
be9751
-    **
be9751
-    **   && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
be9751
-    **    (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
be9751
-    */
be9751
+     * Here, if there's a targetfilter field, see if it matches.
be9751
+     *
be9751
+     * The commented out code below was an erroneous attempt to skip
be9751
+     * this test.  It is wrong because: 1. you need to store
be9751
+     * whether the last test matched or not (you cannot just assume it did)
be9751
+     * and 2. It may not be the same aci, so the previous matched
be9751
+     * value is a function of the aci.
be9751
+     * May be interesting to build such a cache...but no evidence for
be9751
+     * for that right now. See Bug 383424.
be9751
+     *
be9751
+     *
be9751
+     *   && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
be9751
+     *    (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
be9751
+     */
be9751
     if (aci->aci_type & ACI_TARGET_FILTER) {
be9751
         int filter_matched = ACL_TRUE;
be9751
-
be9751
         /*
be9751
          * Check for macros.
be9751
          * For targetfilter we need to fake the lasinfo structure--it's
be9751
          * created "naturally" for subjects but not targets.
be9751
-        */
be9751
-
be9751
-
be9751
+         */
be9751
         if (aci->aci_type & ACI_TARGET_FILTER_MACRO_DN) {
be9751
 
be9751
             lasInfo *lasinfo = NULL;
be9751
@@ -2419,11 +2405,9 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                                                     ACL_EVAL_TARGET_FILTER);
be9751
             slapi_ch_free((void **)&lasinfo);
be9751
         } else {
be9751
-
be9751
-
be9751
             if (slapi_vattr_filter_test(NULL, aclpb->aclpb_curr_entry,
be9751
                                         aci->targetFilter,
be9751
-                                        0 /*don't do acess chk*/) != 0) {
be9751
+                                        0 /*don't do access check*/) != 0) {
be9751
                 filter_matched = ACL_FALSE;
be9751
             }
be9751
         }
be9751
@@ -2450,7 +2434,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
      * Check to see if we need to evaluate any targetattrfilters.
be9751
      * They look as follows:
be9751
      * (targetattrfilters="add=sn:(sn=rob) && gn:(gn!=byrne),
be9751
-     *                       del=sn:(sn=rob) && gn:(gn=byrne)")
be9751
+     *                     del=sn:(sn=rob) && gn:(gn=byrne)")
be9751
      *
be9751
      * For ADD/DELETE:
be9751
      * If theres's a targetattrfilter then each add/del filter
be9751
@@ -2458,29 +2442,25 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
      * by each value of the attribute in the entry.
be9751
      *
be9751
      * For MODIFY:
be9751
-     *    If there's a targetattrfilter then the add/del filter
be9751
+     * If there's a targetattrfilter then the add/del filter
be9751
      * must be satisfied by the attribute to be added/deleted.
be9751
      * (MODIFY acl is evaluated one value at a time).
be9751
      *
be9751
      *
be9751
-    */
be9751
-
be9751
+     */
be9751
     if (((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
be9751
          (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
be9751
         ((aclpb->aclpb_access & SLAPI_ACL_DELETE) &&
be9751
-         (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
be9751
-
be9751
+         (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
be9751
+    {
be9751
         Targetattrfilter **attrFilterArray = NULL;
be9751
-
be9751
         Targetattrfilter *attrFilter = NULL;
be9751
-
be9751
         Slapi_Attr *attr_ptr = NULL;
be9751
         Slapi_Value *sval;
be9751
         const struct berval *attrVal;
be9751
         int k;
be9751
         int done;
be9751
 
be9751
-
be9751
         if ((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
be9751
             (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) {
be9751
 
be9751
@@ -2497,28 +2477,20 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
 
be9751
         while (attrFilterArray && attrFilterArray[num_attrs] && attr_matched) {
be9751
             attrFilter = attrFilterArray[num_attrs];
be9751
-
be9751
             /*
be9751
-                 * If this filter applies to an attribute in the entry,
be9751
-                 * apply it to the entry.
be9751
-                 * Otherwise just ignore it.
be9751
-                 *
be9751
-                */
be9751
-
be9751
-            if (slapi_entry_attr_find(aclpb->aclpb_curr_entry,
be9751
-                                      attrFilter->attr_str,
be9751
-                                      &attr_ptr) == 0) {
be9751
-
be9751
+             * If this filter applies to an attribute in the entry,
be9751
+             * apply it to the entry.
be9751
+             * Otherwise just ignore it.
be9751
+             *
be9751
+             */
be9751
+            if (slapi_entry_attr_find(aclpb->aclpb_curr_entry, attrFilter->attr_str, &attr_ptr) == 0) {
be9751
                 /*
be9751
-                     * This is an applicable filter.
be9751
-                     *  The filter is to be appplied to the entry being added
be9751
-                     * or deleted.
be9751
-                     * The filter needs to be satisfied by _each_ occurence
be9751
-                     * of the attribute in the entry--otherwise you
be9751
-                     * could satisfy the filter and then put loads of other
be9751
-                     * values in on the back of it.
be9751
-                     */
be9751
-
be9751
+                 * This is an applicable filter.
be9751
+                 * The filter is to be applied to the entry being added or deleted.
be9751
+                 * The filter needs to be satisfied by _each_ occurrence of the
be9751
+                 * attribute in the entry--otherwise you could satisfy the filter
be9751
+                 * and then put loads of other values in on the back of it.
be9751
+                 */
be9751
                 sval = NULL;
be9751
                 attrVal = NULL;
be9751
                 k = slapi_attr_first_value(attr_ptr, &sval);
be9751
@@ -2528,12 +2500,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
 
be9751
                     if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
be9751
                                                     attrFilter->attr_str,
be9751
-                                                    (struct berval *)attrVal) == LDAP_SUCCESS) {
be9751
-
be9751
+                                                    (struct berval *)attrVal) == LDAP_SUCCESS)
be9751
+                    {
be9751
                         attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
be9751
                                                         attrFilter->filter,
be9751
-                                                        1 /* Do filter sense evaluation below */
be9751
-                                                        );
be9751
+                                                        1 /* Do filter sense evaluation below */);
be9751
                         done = !attr_matched;
be9751
                         slapi_entry_free(aclpb->aclpb_filter_test_entry);
be9751
                     }
be9751
@@ -2542,19 +2513,19 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                 } /* while */
be9751
 
be9751
                 /*
be9751
-                     * Here, we applied an applicable filter to the entry.
be9751
-                     * So if attr_matched is ACL_TRUE then every value
be9751
-                     * of the attribute in the entry satisfied the filter.
be9751
-                     * Otherwise, attr_matched is ACL_FALSE and not every
be9751
-                     * value satisfied the filter, so we will teminate the
be9751
-                     * scan of the filter list.
be9751
-                     */
be9751
+                 * Here, we applied an applicable filter to the entry.
be9751
+                 * So if attr_matched is ACL_TRUE then every value
be9751
+                 * of the attribute in the entry satisfied the filter.
be9751
+                 * Otherwise, attr_matched is ACL_FALSE and not every
be9751
+                 * value satisfied the filter, so we will terminate the
be9751
+                 * scan of the filter list.
be9751
+                 */
be9751
             }
be9751
 
be9751
             num_attrs++;
be9751
         } /* while */
be9751
 
be9751
-/*
be9751
+        /*
be9751
          * Here, we've applied all the applicable filters to the entry.
be9751
          * Each one must have been satisfied by all the values of the attribute.
be9751
          * The result of this is stored in attr_matched.
be9751
@@ -2585,7 +2556,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
     } else if (((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
be9751
                 (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
be9751
                ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) &&
be9751
-                (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
be9751
+                (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
be9751
+    {
be9751
         /*
be9751
          * Here, it's a modify add/del and we have attr filters.
be9751
          * So, we need to scan the add/del filter list to find the filter
be9751
@@ -2629,11 +2601,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
          * Otherwise, ignore the targetattrfilters.
be9751
          */
be9751
         if (found) {
be9751
-
be9751
             if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
be9751
                                             aclpb->aclpb_curr_attrEval->attrEval_name,
be9751
-                                            aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS) {
be9751
-
be9751
+                                            aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS)
be9751
+            {
be9751
                 attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
be9751
                                                 attrFilter->filter,
be9751
                                                 1 /* Do filter sense evaluation below */
be9751
@@ -2651,20 +2622,21 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
              * Here this attribute appeared and was matched in a
be9751
              * targetattrfilters list, so record this fact so we do
be9751
              * not have to scan the targetattr list for the attribute.
be9751
-            */
be9751
+             */
be9751
 
be9751
             attr_matched_in_targetattrfilters = 1;
be9751
         }
be9751
     } /* targetvaluefilters */
be9751
 
be9751
 
be9751
-    /* There are 3 cases  by which acis are selected.
be9751
-    ** 1) By scanning the whole list and picking based on the resource.
be9751
-    ** 2) By picking a subset of the list which will be used for the whole
be9751
-    **    acl evaluation.
be9751
-    ** 3) A finer granularity, i.e, a selected list of acls which will be
be9751
-    ** used for only that entry's evaluation.
be9751
-    */
be9751
+    /*
be9751
+     * There are 3 cases  by which acis are selected.
be9751
+     * 1) By scanning the whole list and picking based on the resource.
be9751
+     * 2) By picking a subset of the list which will be used for the whole
be9751
+     *    acl evaluation.
be9751
+     * 3) A finer granularity, i.e, a selected list of acls which will be
be9751
+     * used for only that entry's evaluation.
be9751
+     */
be9751
     if (!(skip_attrEval) && (aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_ENTRY_LIST) &&
be9751
         (res_right & SLAPI_ACL_SEARCH) &&
be9751
         ((aci->aci_access & SLAPI_ACL_READ) || (aci->aci_access & SLAPI_ACL_SEARCH))) {
be9751
@@ -2680,7 +2652,6 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
         }
be9751
     }
be9751
 
be9751
-
be9751
     /* If we are suppose to skip attr eval, then let's skip it */
be9751
     if ((aclpb->aclpb_access & SLAPI_ACL_SEARCH) && (!skip_attrEval) &&
be9751
         (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY)) {
be9751
@@ -2697,9 +2668,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
         goto acl__resource_match_aci_EXIT;
be9751
     }
be9751
 
be9751
-    /* We need to check again because we don't want to select this handle
be9751
-    ** if the right doesn't match for now.
be9751
-    */
be9751
+    /*
be9751
+     * We need to check again because we don't want to select this handle
be9751
+     * if the right doesn't match for now.
be9751
+     */
be9751
     if (!(aci_right & res_right)) {
be9751
         matches = ACL_FALSE;
be9751
         goto acl__resource_match_aci_EXIT;
be9751
@@ -2718,20 +2690,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
      * rbyrneXXX if we had a proper permission for modrdn eg SLAPI_ACL_MODRDN
be9751
      * then we would not need this crappy way of telling it was a MODRDN
be9751
      * request ie. SLAPI_ACL_WRITE && !(c_attrEval).
be9751
-    */
be9751
-
be9751
+     */
be9751
     c_attrEval = aclpb->aclpb_curr_attrEval;
be9751
 
be9751
     /*
be9751
      * If we've already matched on targattrfilter then do not
be9751
      * bother to look at the attrlist.
be9751
-    */
be9751
-
be9751
+     */
be9751
     if (!attr_matched_in_targetattrfilters) {
be9751
-
be9751
         /* match target attr */
be9751
-        if ((c_attrEval) &&
be9751
-            (aci->aci_type & ACI_TARGET_ATTR)) {
be9751
+        if ((c_attrEval) && (aci->aci_type & ACI_TARGET_ATTR)) {
be9751
             /* there is a target ATTR */
be9751
             Targetattr **attrArray = aci->targetAttr;
be9751
             Targetattr *attr = NULL;
be9751
@@ -2773,46 +2741,43 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
                 matches = (attr_matched ? ACL_TRUE : ACL_FALSE);
be9751
             }
be9751
 
be9751
-
be9751
             aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
be9751
             /* figure out how it matched, i.e star matched */
be9751
-            if (matches && star_matched && num_attrs == 1 &&
be9751
-                !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE))
be9751
+            if (matches && star_matched && num_attrs == 1 && !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE)) {
be9751
                 aclpb->aclpb_state |= ACLPB_ATTR_STAR_MATCHED;
be9751
-            else {
be9751
+            } else {
be9751
                 /* we are here means that there is a specific
be9751
-                ** attr in the rule for this resource.
be9751
-                ** We need to avoid this case
be9751
-                ** Rule 1: (targetattr = "uid")
be9751
-                ** Rule 2: (targetattr = "*")
be9751
-                ** we cannot use STAR optimization
be9751
-                */
be9751
+                 * attr in the rule for this resource.
be9751
+                 * We need to avoid this case
be9751
+                 * Rule 1: (targetattr = "uid")
be9751
+                 * Rule 2: (targetattr = "*")
be9751
+                 * we cannot use STAR optimization
be9751
+                 */
be9751
                 aclpb->aclpb_state |= ACLPB_FOUND_ATTR_RULE;
be9751
                 aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
be9751
             }
be9751
-        } else if ((c_attrEval) ||
be9751
-                   (aci->aci_type & ACI_TARGET_ATTR)) {
be9751
+        } else if ((c_attrEval) || (aci->aci_type & ACI_TARGET_ATTR)) {
be9751
             if ((aci_right & ACL_RIGHTS_TARGETATTR_NOT_NEEDED) &&
be9751
                 (aclpb->aclpb_access & ACL_RIGHTS_TARGETATTR_NOT_NEEDED)) {
be9751
                 /*
be9751
-            ** Targetattr rule doesn't  make any sense
be9751
-            ** in this case. So select this rule
be9751
-            ** default: matches = ACL_TRUE;
be9751
-            */
be9751
+                 * Targetattr rule doesn't make any sense
be9751
+                 * in this case. So select this rule
be9751
+                 * default: matches = ACL_TRUE;
be9751
+                 */
be9751
                 ;
be9751
-            } else if (aci_right & SLAPI_ACL_WRITE &&
be9751
+            } else if ((aci_right & SLAPI_ACL_WRITE) &&
be9751
                        (aci->aci_type & ACI_TARGET_ATTR) &&
be9751
                        !(c_attrEval) &&
be9751
                        (aci->aci_type & ACI_HAS_ALLOW_RULE)) {
be9751
                 /* We need to handle modrdn operation.  Modrdn doesn't
be9751
-            ** change any attrs but changes the RDN and so (attr=NULL).
be9751
-            ** Here we found an acl which has a targetattr but
be9751
-            ** the resource doesn't need one. In that case, we should
be9751
-            ** consider this acl.
be9751
-            ** the opposite is true if it is a deny rule, only a deny without
be9751
-            ** any targetattr should deny modrdn
be9751
-            ** default: matches = ACL_TRUE;
be9751
-            */
be9751
+                 * change any attrs but changes the RDN and so (attr=NULL).
be9751
+                 * Here we found an acl which has a targetattr but
be9751
+                 * the resource doesn't need one. In that case, we should
be9751
+                 * consider this acl.
be9751
+                 * the opposite is true if it is a deny rule, only a deny without
be9751
+                 * any targetattr should deny modrdn
be9751
+                 * default: matches = ACL_TRUE;
be9751
+                 */
be9751
                 ;
be9751
             } else {
be9751
                 matches = ACL_FALSE;
be9751
@@ -2821,16 +2786,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
be9751
     } /* !attr_matched_in_targetattrfilters */
be9751
 
be9751
     /*
be9751
-    ** Here we are testing if we find a entry test rule (which should
be9751
-    ** be rare). In that case, just remember it. An entry test rule
be9751
-    ** doesn't have "(targetattr)".
be9751
-    */
be9751
+     * Here we are testing if we find a entry test rule (which should
be9751
+     * be rare). In that case, just remember it. An entry test rule
be9751
+     * doesn't have "(targetattr)".
be9751
+     */
be9751
     if ((aclpb->aclpb_state & ACLPB_EVALUATING_FIRST_ATTR) &&
be9751
         (!(aci->aci_type & ACI_TARGET_ATTR))) {
be9751
         aclpb->aclpb_state |= ACLPB_FOUND_A_ENTRY_TEST_RULE;
be9751
     }
be9751
 
be9751
-/*
be9751
+    /*
be9751
      * Generic exit point for this routine:
be9751
      * matches is ACL_TRUE if the aci matches the target of the resource,
be9751
      * ACL_FALSE othrewise.
be9751
@@ -2853,6 +2818,7 @@ acl__resource_match_aci_EXIT:
be9751
 
be9751
     return (matches);
be9751
 }
be9751
+
be9751
 /* Macro to determine if the cached result is valid or not. */
be9751
 #define ACL_CACHED_RESULT_VALID(result)          \
be9751
     (((result & ACLPB_CACHE_READ_RES_ALLOW) &&   \
be9751
diff --git a/ldap/servers/slapd/back-ldbm/findentry.c b/ldap/servers/slapd/back-ldbm/findentry.c
be9751
index 6e53a0aea..bff751c88 100644
be9751
--- a/ldap/servers/slapd/back-ldbm/findentry.c
be9751
+++ b/ldap/servers/slapd/back-ldbm/findentry.c
be9751
@@ -93,7 +93,6 @@ find_entry_internal_dn(
be9751
     size_t tries = 0;
be9751
     int isroot = 0;
be9751
     int op_type;
be9751
-    char *errbuf = NULL;
be9751
 
be9751
     /* get the managedsait ldap message control */
be9751
     slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
be9751
@@ -207,8 +206,8 @@ find_entry_internal_dn(
be9751
                     break;
be9751
                 }
be9751
                 if (acl_type > 0) {
be9751
-                    err = plugin_call_acl_plugin(pb, me->ep_entry, NULL, NULL, acl_type,
be9751
-                                                 ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
be9751
+                    char *dummy_attr = "1.1";
be9751
+                    err = slapi_access_allowed(pb, me->ep_entry, dummy_attr, NULL, acl_type);
be9751
                 }
be9751
                 if (((acl_type > 0) && err) || (op_type == SLAPI_OPERATION_BIND)) {
be9751
                     /*
be9751
@@ -237,7 +236,6 @@ find_entry_internal_dn(
be9751
         CACHE_RETURN(&inst->inst_cache, &me);
be9751
     }
be9751
 
be9751
-    slapi_ch_free_string(&errbuf);
be9751
     slapi_log_err(SLAPI_LOG_TRACE, "find_entry_internal_dn", "<= Not found (%s)\n",
be9751
                   slapi_sdn_get_dn(sdn));
be9751
     return (NULL);
be9751
diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py
be9751
index c60837601..ca6ea6ef8 100644
be9751
--- a/src/lib389/lib389/_mapped_object.py
be9751
+++ b/src/lib389/lib389/_mapped_object.py
be9751
@@ -1190,7 +1190,7 @@ class DSLdapObjects(DSLogging, DSLints):
be9751
         # Now actually commit the creation req
be9751
         return co.ensure_state(rdn, properties, self._basedn)
be9751
 
be9751
-    def filter(self, search, scope=None):
be9751
+    def filter(self, search, scope=None, strict=False):
be9751
         # This will yield and & filter for objectClass with as many terms as needed.
be9751
         if search:
be9751
             search_filter = _gen_and([self._get_objectclass_filter(), search])
be9751
@@ -1211,5 +1211,7 @@ class DSLdapObjects(DSLogging, DSLints):
be9751
             insts = [self._entry_to_instance(dn=r.dn, entry=r) for r in results]
be9751
         except ldap.NO_SUCH_OBJECT:
be9751
             # There are no objects to select from, se we return an empty array
be9751
+            if strict:
be9751
+                raise ldap.NO_SUCH_OBJECT
be9751
             insts = []
be9751
         return insts
be9751
-- 
be9751
2.26.2
be9751