Blob Blame Raw
From 94702aa0f07dcea5b7ebe7886b2fdc9ab0092cf4 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 21 Feb 2019 16:54:52 +0100
Subject: [PATCH] Ticket 50234 - one level search returns not matching entry

Bug: if in a onelevel search the IDList for the parentid is smaller than the filter
	threshold and smaller than the list generated by the search filter
	then the intersection is aborted and all children are returned.

Fix: In the above case we need to set the flag that the filter evaluation
	cannot be bypassed

Reviewed by: William, Thierry. Thanks
---
 dirsrvtests/tests/tickets/ticket50234_test.py | 70 +++++++++++++++++++
 ldap/servers/slapd/back-ldbm/idl_set.c        |  1 +
 2 files changed, 71 insertions(+)
 create mode 100644 dirsrvtests/tests/tickets/ticket50234_test.py

diff --git a/dirsrvtests/tests/tickets/ticket50234_test.py b/dirsrvtests/tests/tickets/ticket50234_test.py
new file mode 100644
index 000000000..c605c4531
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket50234_test.py
@@ -0,0 +1,70 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2019 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import logging
+import time
+import ldap
+import pytest
+
+from lib389.topologies import topology_st
+
+from lib389._constants import DEFAULT_SUFFIX
+
+from lib389.idm.user import UserAccount, UserAccounts
+from lib389.idm.organizationalunit import OrganizationalUnit
+
+log = logging.getLogger(__name__)
+
+def test_ticket50234(topology_st):
+    """
+    The fix for ticket 50234
+
+
+    The test sequence is:
+    - create more than 10 entries with objectclass organizational units ou=org{}
+    - add an Account in one of them, eg below ou=org5
+    - do searches with search base ou=org5 and search filter "objectclass=organizationalunit"
+    - a subtree search should return 1 entry, the base entry
+    - a onelevel search should return no entry
+    """
+
+    log.info('Testing Ticket 50234 - onelvel search returns not matching entry')
+
+    for i in range(1,15):
+        ou = OrganizationalUnit(topology_st.standalone, "ou=Org{},{}".format(i, DEFAULT_SUFFIX))
+        ou.create(properties={'ou': 'Org'.format(i)})
+
+    properties = {
+            'uid': 'Jeff Vedder',
+            'cn': 'Jeff Vedder',
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + 'JeffVedder',
+            'userPassword': 'password'
+        }
+    user = UserAccount(topology_st.standalone, "cn=Jeff Vedder,ou=org5,{}".format(DEFAULT_SUFFIX))
+    user.create(properties=properties)
+
+    # in a subtree search the entry used as search base matches the filter and shoul be returned
+    ent = topology_st.standalone.getEntry("ou=org5,{}".format(DEFAULT_SUFFIX), ldap.SCOPE_SUBTREE, "(objectclass=organizationalunit)")
+
+    # in a onelevel search the only child is an useraccount which does not match the filter
+    # no entry should be returned, which would cause getEntry to raise an exception we need to handle
+    found = 1
+    try:
+        ent = topology_st.standalone.getEntry("ou=org5,{}".format(DEFAULT_SUFFIX), ldap.SCOPE_ONELEVEL, "(objectclass=organizationalunit)")
+    except ldap.NO_SUCH_OBJECT:
+        found = 0
+    assert (found == 0)
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/ldap/servers/slapd/back-ldbm/idl_set.c b/ldap/servers/slapd/back-ldbm/idl_set.c
index f9a900f1f..6b6586799 100644
--- a/ldap/servers/slapd/back-ldbm/idl_set.c
+++ b/ldap/servers/slapd/back-ldbm/idl_set.c
@@ -371,6 +371,7 @@ idl_set_intersect(IDListSet *idl_set, backend *be)
         result_list = idl_set->head;
     } else if (idl_set->minimum->b_nids <= FILTER_TEST_THRESHOLD) {
         result_list = idl_set->minimum;
+        slapi_be_set_flag(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST);
 
         /* Free the other IDLs which are not the minimum. */
         IDList *next = NULL;
-- 
2.17.2