Blame SOURCES/0012-Ticket-49958-extended-search-fail-to-match-entries.patch

fb6657
From 02de69d6987b059459980b50de285c2fd7bb3e2c Mon Sep 17 00:00:00 2001
fb6657
From: Thierry Bordaz <tbordaz@redhat.com>
fb6657
Date: Mon, 24 Sep 2018 14:14:16 +0200
fb6657
Subject: [PATCH] Ticket 49958: extended search fail to match entries
fb6657
fb6657
Bug Description:
fb6657
	During an extended search, a structure is created for each filter component.
fb6657
	The structure contains the keys generated from the assertion and using the given
fb6657
	matching rule indexer.
fb6657
	Later the keys will be compared (with the MR) with keys generated from the
fb6657
	attribute values of the candidate entries.
fb6657
	The bug is that parsing the assertion, instead of removing the heading spaces
fb6657
	the routine clear the assertion that is empty. So the generated keys is NULL.
fb6657
fb6657
Fix Description:
fb6657
	The fix consists to only remove heading spaces
fb6657
fb6657
https://pagure.io/389-ds-base/issue/49958
fb6657
fb6657
Reviewed by: Mark Reynolds
fb6657
fb6657
Platforms tested: F27
fb6657
fb6657
Flag Day: no
fb6657
fb6657
Doc impact: no
fb6657
---
fb6657
 .../tests/suites/filter/filter_test.py        | 203 ++++++++++++++++++
fb6657
 ldap/servers/plugins/collation/orfilter.c     |   4 +-
fb6657
 2 files changed, 204 insertions(+), 3 deletions(-)
fb6657
fb6657
diff --git a/dirsrvtests/tests/suites/filter/filter_test.py b/dirsrvtests/tests/suites/filter/filter_test.py
fb6657
index 280db68a3..61c449989 100644
fb6657
--- a/dirsrvtests/tests/suites/filter/filter_test.py
fb6657
+++ b/dirsrvtests/tests/suites/filter/filter_test.py
fb6657
@@ -83,6 +83,209 @@ def test_filter_search_original_attrs(topology_st):
fb6657
     log.info('test_filter_search_original_attrs: PASSED')
fb6657
 
fb6657
 
fb6657
+@pytest.mark.bz1511462
fb6657
+def test_filter_scope_one(topology_st):
fb6657
+    """Test ldapsearch with scope one gives only single entry
fb6657
+
fb6657
+    :id: cf5a6078-bbe6-4d43-ac71-553c45923f91
fb6657
+    :setup: Standalone instance
fb6657
+    :steps:
fb6657
+         1. Search cn=Directory Administrators,dc=example,dc=com using ldapsearch with
fb6657
+            scope one using base as dc=example,dc=com
fb6657
+         2. Check that search should return only one entry
fb6657
+    :expectedresults:
fb6657
+         1. This should pass
fb6657
+         2. This should pass
fb6657
+    """
fb6657
+
fb6657
+    parent_dn="dn: dc=example,dc=com"
fb6657
+    child_dn="dn: cn=Directory Administrators,dc=example,dc=com"
fb6657
+
fb6657
+    log.info('Search user using ldapsearch with scope one')
fb6657
+    results = topology_st.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_ONELEVEL,'cn=Directory Administrators',['cn'] )
fb6657
+    log.info(results)
fb6657
+
fb6657
+    log.info('Search should only have one entry')
fb6657
+    assert len(results) == 1
fb6657
+
fb6657
+@pytest.mark.ds47313
fb6657
+def test_filter_with_attribute_subtype(topology_st):
fb6657
+    """Adds 2 test entries and Search with
fb6657
+    filters including subtype and !
fb6657
+
fb6657
+    :id: 0e69f5f2-6a0a-480e-8282-fbcc50231908
fb6657
+    :setup: Standalone instance
fb6657
+    :steps:
fb6657
+        1. Add 2 entries and create 3 filters
fb6657
+        2. Search for entry with filter: (&(cn=test_entry en only)(!(cn=test_entry fr)))
fb6657
+        3. Search for entry with filter: (&(cn=test_entry en only)(!(cn;fr=test_entry fr)))
fb6657
+        4. Search for entry with filter: (&(cn=test_entry en only)(!(cn;en=test_entry en)))
fb6657
+        5. Delete the added entries
fb6657
+    :expectedresults:
fb6657
+        1. Operation should be successful
fb6657
+        2. Search should be successful
fb6657
+        3. Search should be successful
fb6657
+        4. Search should not be successful
fb6657
+        5. Delete the added entries
fb6657
+    """
fb6657
+
fb6657
+    # bind as directory manager
fb6657
+    topology_st.standalone.log.info("Bind as %s" % DN_DM)
fb6657
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
fb6657
+
fb6657
+    # enable filter error logging
fb6657
+    # mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '32')]
fb6657
+    # topology_st.standalone.modify_s(DN_CONFIG, mod)
fb6657
+
fb6657
+    topology_st.standalone.log.info("\n\n######################### ADD ######################\n")
fb6657
+
fb6657
+    # Prepare the entry with cn;fr & cn;en
fb6657
+    entry_name_fr = '%s fr' % (ENTRY_NAME)
fb6657
+    entry_name_en = '%s en' % (ENTRY_NAME)
fb6657
+    entry_name_both = '%s both' % (ENTRY_NAME)
fb6657
+    entry_dn_both = 'cn=%s, %s' % (entry_name_both, SUFFIX)
fb6657
+    entry_both = Entry(entry_dn_both)
fb6657
+    entry_both.setValues('objectclass', 'top', 'person')
fb6657
+    entry_both.setValues('sn', entry_name_both)
fb6657
+    entry_both.setValues('cn', entry_name_both)
fb6657
+    entry_both.setValues('cn;fr', entry_name_fr)
fb6657
+    entry_both.setValues('cn;en', entry_name_en)
fb6657
+
fb6657
+    # Prepare the entry with one member
fb6657
+    entry_name_en_only = '%s en only' % (ENTRY_NAME)
fb6657
+    entry_dn_en_only = 'cn=%s, %s' % (entry_name_en_only, SUFFIX)
fb6657
+    entry_en_only = Entry(entry_dn_en_only)
fb6657
+    entry_en_only.setValues('objectclass', 'top', 'person')
fb6657
+    entry_en_only.setValues('sn', entry_name_en_only)
fb6657
+    entry_en_only.setValues('cn', entry_name_en_only)
fb6657
+    entry_en_only.setValues('cn;en', entry_name_en)
fb6657
+
fb6657
+    topology_st.standalone.log.info("Try to add Add %s: %r" % (entry_dn_both, entry_both))
fb6657
+    topology_st.standalone.add_s(entry_both)
fb6657
+
fb6657
+    topology_st.standalone.log.info("Try to add Add %s: %r" % (entry_dn_en_only, entry_en_only))
fb6657
+    topology_st.standalone.add_s(entry_en_only)
fb6657
+
fb6657
+    topology_st.standalone.log.info("\n\n######################### SEARCH ######################\n")
fb6657
+
fb6657
+    # filter: (&(cn=test_entry en only)(!(cn=test_entry fr)))
fb6657
+    myfilter = '(&(sn=%s)(!(cn=%s)))' % (entry_name_en_only, entry_name_fr)
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+    assert ensure_str(ents[0].sn) == entry_name_en_only
fb6657
+    topology_st.standalone.log.info("Found %s" % ents[0].dn)
fb6657
+
fb6657
+    # filter: (&(cn=test_entry en only)(!(cn;fr=test_entry fr)))
fb6657
+    myfilter = '(&(sn=%s)(!(cn;fr=%s)))' % (entry_name_en_only, entry_name_fr)
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+    assert ensure_str(ents[0].sn) == entry_name_en_only
fb6657
+    topology_st.standalone.log.info("Found %s" % ents[0].dn)
fb6657
+
fb6657
+    # filter: (&(cn=test_entry en only)(!(cn;en=test_entry en)))
fb6657
+    myfilter = '(&(sn=%s)(!(cn;en=%s)))' % (entry_name_en_only, entry_name_en)
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 0
fb6657
+    topology_st.standalone.log.info("Found none")
fb6657
+
fb6657
+    topology_st.standalone.log.info("\n\n######################### DELETE ######################\n")
fb6657
+
fb6657
+    topology_st.standalone.log.info("Try to delete  %s " % entry_dn_both)
fb6657
+    topology_st.standalone.delete_s(entry_dn_both)
fb6657
+
fb6657
+    topology_st.standalone.log.info("Try to delete  %s " % entry_dn_en_only)
fb6657
+    topology_st.standalone.delete_s(entry_dn_en_only)
fb6657
+
fb6657
+    log.info('Testcase PASSED')
fb6657
+
fb6657
+
fb6657
+@pytest.mark.bz1615155
fb6657
+def test_extended_search(topology_st):
fb6657
+    """Test we can search with equality extended matching rule
fb6657
+
fb6657
+    :id: 
fb6657
+    :setup: Standalone instance
fb6657
+    :steps:
fb6657
+         1. Add a test user with 'sn: ext-test-entry'
fb6657
+         2. Search '(cn:de:=ext-test-entry)'
fb6657
+         3. Search '(sn:caseIgnoreIA5Match:=EXT-TEST-ENTRY)'
fb6657
+         4. Search '(sn:caseIgnoreMatch:=EXT-TEST-ENTRY)'
fb6657
+         5. Search '(sn:caseExactMatch:=EXT-TEST-ENTRY)'
fb6657
+         6. Search '(sn:caseExactMatch:=ext-test-entry)'
fb6657
+         7. Search '(sn:caseExactIA5Match:=EXT-TEST-ENTRY)'
fb6657
+         8. Search '(sn:caseExactIA5Match:=ext-test-entry)'
fb6657
+    :expectedresults:
fb6657
+         1. This should pass
fb6657
+         2. This should return one entry
fb6657
+         3. This should return one entry
fb6657
+         4. This should return one entry
fb6657
+         5. This should return NO entry
fb6657
+         6. This should return one entry
fb6657
+         7. This should return NO entry
fb6657
+         8. This should return one entry
fb6657
+         3. return one entry
fb6657
+    """
fb6657
+    log.info('Running test_filter_escaped...')
fb6657
+    
fb6657
+    ATTR_VAL = 'ext-test-entry'
fb6657
+    USER1_DN = "uid=%s,%s" % (ATTR_VAL, DEFAULT_SUFFIX)
fb6657
+
fb6657
+    try:
fb6657
+        topology_st.standalone.add_s(Entry((USER1_DN, {'objectclass': "top extensibleObject".split(),
fb6657
+                                                       'sn': ATTR_VAL.encode(),
fb6657
+                                                       'cn': ATTR_VAL.encode(),
fb6657
+                                                       'uid': ATTR_VAL.encode()})))
fb6657
+    except ldap.LDAPError as e:
fb6657
+        log.fatal('test_extended_search: Failed to add test user ' + USER1_DN + ': error ' +
fb6657
+                  e.message['desc'])
fb6657
+        assert False
fb6657
+
fb6657
+    # filter: '(cn:de:=ext-test-entry)'
fb6657
+    myfilter = '(cn:de:=%s)' % ATTR_VAL
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+
fb6657
+    # filter: '(sn:caseIgnoreIA5Match:=EXT-TEST-ENTRY)'
fb6657
+    myfilter = '(cn:caseIgnoreIA5Match:=%s)' % ATTR_VAL.upper()
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+
fb6657
+    # filter: '(sn:caseIgnoreMatch:=EXT-TEST-ENTRY)'
fb6657
+    myfilter = '(cn:caseIgnoreMatch:=%s)' % ATTR_VAL.upper()
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+
fb6657
+    # filter: '(sn:caseExactMatch:=EXT-TEST-ENTRY)'
fb6657
+    myfilter = '(cn:caseExactMatch:=%s)' % ATTR_VAL.upper()
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 0
fb6657
+
fb6657
+    # filter: '(sn:caseExactMatch:=ext-test-entry)'
fb6657
+    myfilter = '(cn:caseExactMatch:=%s)' % ATTR_VAL
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+
fb6657
+    # filter: '(sn:caseExactIA5Match:=EXT-TEST-ENTRY)'
fb6657
+    myfilter = '(cn:caseExactIA5Match:=%s)' % ATTR_VAL.upper()
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 0
fb6657
+
fb6657
+    # filter: '(sn:caseExactIA5Match:=ext-test-entry)'
fb6657
+    myfilter = '(cn:caseExactIA5Match:=%s)' % ATTR_VAL
fb6657
+    topology_st.standalone.log.info("Try to search with filter %s" % myfilter)
fb6657
+    ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
fb6657
+    assert len(ents) == 1
fb6657
+
fb6657
+
fb6657
 if __name__ == '__main__':
fb6657
     # Run isolated
fb6657
     # -s for DEBUG mode
fb6657
diff --git a/ldap/servers/plugins/collation/orfilter.c b/ldap/servers/plugins/collation/orfilter.c
fb6657
index 7705de9d6..c092d77ca 100644
fb6657
--- a/ldap/servers/plugins/collation/orfilter.c
fb6657
+++ b/ldap/servers/plugins/collation/orfilter.c
fb6657
@@ -531,10 +531,8 @@ or_filter_create(Slapi_PBlock *pb)
fb6657
             default:
fb6657
                 break;
fb6657
             }
fb6657
-            for (; len > 0 && *val != ' '; ++val, --len)
fb6657
+            for (; len > 0 && *val == ' '; ++val, --len)
fb6657
                 ;
fb6657
-            if (len > 0)
fb6657
-                ++val, --len; /* skip the space */
fb6657
             bv.bv_len = len;
fb6657
             bv.bv_val = (len > 0) ? val : NULL;
fb6657
         } else { /* mrOID does not identify an ordering rule. */
fb6657
-- 
fb6657
2.17.2
fb6657