dirsrvtests/tests/tickets/ticket48844_test.py | 175 ++++++++++++++++++++++++++
ldap/servers/slapd/plugin_mr.c | 67 +++++----
2 files changed, 215 insertions(+), 27 deletions(-)
New commits:
commit 7ebc1707275bfd6dbf1e04585d9152ae6a031649
Author: Thierry Bordaz <tbordaz(a)redhat.com>
Date: Thu May 19 15:45:26 2016 +0200
Ticket 48844 Regression introduced in matching rules by DS 48746
Bug Description:
Old style MR plugin (like bitwise, collation) register their own indexer
function.
new style MR plugin just use the default_mr_indexer_create.
When looking for a MR plugin that can handle a given OID we must look to old style
and
new style MR plugin.
In the fix
https://fedorahosted.org/389/ticket/48746, the code looking up into old
style
MR plugin has been erronously removed.
Fix Description:
Make sure that plugin_mr_filter_create looks up in old and new style MR
https://fedorahosted.org/389/ticket/48745
Reviewed by: William Brown (thanks William!)
Platforms tested: F23
Flag Day: no
Doc impact: no
diff --git a/dirsrvtests/tests/tickets/ticket48844_test.py
b/dirsrvtests/tests/tickets/ticket48844_test.py
new file mode 100644
index 0000000..5b720e3
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket48844_test.py
@@ -0,0 +1,175 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+PLUGIN_BITWISE = 'Bitwise Plugin'
+TESTBASEDN="dc=bitwise,dc=com"
+TESTBACKEND_NAME="TestBitw"
+
+F1 = 'objectclass=testperson'
+BITWISE_F2 = '(&(%s)(testUserAccountControl:1.2.840.113556.1.4.803:=514))' %
F1
+BITWISE_F3 = '(&(%s)(testUserAccountControl:1.2.840.113556.1.4.803:=513))' %
F1
+BITWISE_F6 =
'(&(%s)(testUserAccountControl:1.2.840.113556.1.4.803:=16777216))' % F1
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ global installation1_prefix
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Delete each instance in the end
+ def fin():
+ standalone.delete()
+ #request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+def _addBitwiseEntries(topology):
+
+ users = [
+ ('testuser2', '65536' ,'PasswordNeverExpired' ),
+ ('testuser3', '8388608' ,'PasswordExpired'),
+ ('testuser4', '256' ,'TempDuplicateAccount'),
+ ('testuser5', '16777216' ,'TrustedAuthDelegation'),
+ ('testuser6', '528' ,'AccountLocked'),
+ ('testuser7', '513' ,'AccountActive'),
+ ('testuser8', '98536 99512 99528'.split() ,'AccountActive
PasswordExxpired AccountLocked'.split()),
+ ('testuser9', '87536 912'.split() ,'AccountActive
PasswordNeverExpired'.split()),
+ ('testuser10', '89536 97546 96579'.split() ,'TestVerify1
TestVerify2 TestVerify3'.split() ),
+ ('testuser11', '655236' ,'TestStatus1'),
+ ('testuser12', '665522' ,'TestStatus2'),
+ ('testuser13', '266552' ,'TestStatus3')]
+ try:
+ topology.standalone.add_s(Entry((TESTBASEDN,
+ {'objectclass': "top
dcobject".split(),
+ 'dc': 'bitwise',
+ 'aci': '(target
=\"ldap:///dc=bitwise,dc=com\")' +\
+ '(targetattr !=
\"userPassword\")' +\
+ '(version 3.0;acl \"Anonymous
read-search access\";' +\
+ 'allow (read, search, compare)(userdn
= \"ldap:///anyone\");)'})))
+
+ topology.standalone.add_s(Entry(('uid=btestuser1,%s' % TESTBASEDN,
+ {'objectclass': 'top testperson
organizationalPerson inetorgperson'.split(),
+ 'mail':
'btestuser1(a)redhat.com',
+ 'uid': 'btestuser1',
+ 'givenName': 'bit',
+ 'sn': 'testuser1',
+ 'userPassword': 'testuser1',
+ 'testUserAccountControl':
'514',
+ 'testUserStatus': 'Disabled',
+ 'cn': 'bit tetsuser1'})))
+ for (userid, accCtl,accStatus) in users:
+ topology.standalone.add_s(Entry(('uid=b%s,%s' % (userid,
TESTBASEDN),
+ {'objectclass': 'top testperson
organizationalPerson inetorgperson'.split(),
+ 'mail': '%s(a)redhat.com' %
userid,
+ 'uid': 'b%s' % userid,
+ 'givenName': 'bit',
+ 'sn': userid,
+ 'userPassword': userid,
+ 'testUserAccountControl': accCtl,
+ 'testUserStatus': accStatus,
+ 'cn': 'bit %s' % userid})))
+ except ValueError:
+ topology.standalone.log.fatal("add_s failed: %s", ValueError)
+
+def test_ticket48844_init(topology):
+ # create a suffix where test entries will be stored
+ BITW_SCHEMA_AT_1 = '( NAME \'testUserAccountControl\' DESC
\'Attribute Bitwise filteri-Multi-Valued\' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
)'
+ BITW_SCHEMA_AT_2 = '( NAME \'testUserStatus\' DESC \'State of User
account active/disabled\' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )'
+ BITW_SCHEMA_OC_1 = '( NAME \'testperson\' SUP top STRUCTURAL MUST ( sn $
cn $ testUserAccountControl $ testUserStatus )' +\
+ ' MAY ( userPassword $ telephoneNumber $ seeAlso $ description )
X-ORIGIN \'BitWise\' )'
+ topology.standalone.schema.add_schema('attributetypes', [BITW_SCHEMA_AT_1,
BITW_SCHEMA_AT_2])
+ topology.standalone.schema.add_schema('objectClasses', BITW_SCHEMA_OC_1)
+
+ topology.standalone.backend.create(TESTBASEDN, {BACKEND_NAME: TESTBACKEND_NAME})
+ topology.standalone.mappingtree.create(TESTBASEDN, bename=TESTBACKEND_NAME,
parent=None)
+ _addBitwiseEntries(topology)
+
+
+def test_ticket48844_bitwise_on(topology):
+ """
+ Check that bitwise plugin (old style MR plugin) that defines
+ Its own indexer create function, is selected to evaluate the filter
+ """
+
+ topology.standalone.plugins.enable(name=PLUGIN_BITWISE)
+ topology.standalone.restart(timeout=10)
+ ents = topology.standalone.search_s('cn=%s,cn=plugins,cn=config' %
PLUGIN_BITWISE, ldap.SCOPE_BASE, 'objectclass=*')
+ assert(ents[0].hasValue('nsslapd-pluginEnabled', 'on'))
+
+ expect = 2
+ ents = topology.standalone.search_s(TESTBASEDN, ldap.SCOPE_SUBTREE, BITWISE_F2)
+ assert (len(ents) == expect)
+
+ expect=1
+ ents = topology.standalone.search_s(TESTBASEDN, ldap.SCOPE_SUBTREE, BITWISE_F3)
+ assert (len(ents) == expect)
+ assert (ents[0].hasAttr('testUserAccountControl'))
+
+ expect=1
+ ents = topology.standalone.search_s(TESTBASEDN, ldap.SCOPE_SUBTREE, BITWISE_F6)
+ assert (len(ents) == expect)
+ assert (ents[0].hasAttr('testUserAccountControl'))
+
+def test_ticket48844_bitwise_off(topology):
+ """
+ Check that when bitwise plugin is not enabled, no plugin
+ is identified to evaluate the filter -> ldap.UNAVAILABLE_CRITICAL_EXTENSION:
+ """
+ topology.standalone.plugins.disable(name=PLUGIN_BITWISE)
+ topology.standalone.restart(timeout=10)
+ ents = topology.standalone.search_s('cn=%s,cn=plugins,cn=config' %
PLUGIN_BITWISE, ldap.SCOPE_BASE, 'objectclass=*')
+ assert(ents[0].hasValue('nsslapd-pluginEnabled', 'off'))
+
+ res = 0
+ try:
+ ents = topology.standalone.search_s(TESTBASEDN, ldap.SCOPE_SUBTREE, BITWISE_F2)
+ except ldap.UNAVAILABLE_CRITICAL_EXTENSION:
+ res = 12
+ assert (res == 12)
+
+
+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/plugin_mr.c b/ldap/servers/slapd/plugin_mr.c
index 0ff4b78..e0c1a14 100644
--- a/ldap/servers/slapd/plugin_mr.c
+++ b/ldap/servers/slapd/plugin_mr.c
@@ -165,43 +165,44 @@ slapi_mr_indexer_create (Slapi_PBlock* opb)
}
else
{
- /* look for a new syntax-style mr plugin */
- struct slapdplugin* pi = plugin_mr_find(oid);
- rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
-
- /* register that plugin at the condition it has a createFn/index/indexSvFn */
- if (pi) {
+ /* call each plugin, until one is able to handle this request. */
+ rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp =
mrp->plg_next)
+ {
IFP indexFn = NULL;
IFP indexSvFn = NULL;
Slapi_PBlock pb;
- memcpy(&pb, opb, sizeof (Slapi_PBlock));
- slapi_pblock_set(&pb, SLAPI_PLUGIN, pi);
- slapi_pblock_get(&pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn);
+ memcpy (&pb, opb, sizeof(Slapi_PBlock));
+ slapi_pblock_set(&pb, SLAPI_PLUGIN, mrp);
+ if (slapi_pblock_get(&pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn)) {
+ /* plugin not a matchingrule type */
+ continue;
+ }
if (createFn && !createFn(&pb)) {
- /* we need to call the createFn before testing the indexFn/indexSvFn
- * because it sets the index callbacks
- */
slapi_pblock_get(&pb, SLAPI_PLUGIN_MR_INDEX_FN, &indexFn);
slapi_pblock_get(&pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &indexSvFn);
if (indexFn || indexSvFn) {
- /* Use the defined indexer_create function if it exists */
+ /* Success: this plugin can handle it. */
memcpy(opb, &pb, sizeof (Slapi_PBlock));
- plugin_mr_bind(oid, pi); /* for future reference */
+ plugin_mr_bind(oid, mrp); /* for future reference */
rc = 0; /* success */
+ break;
}
+
}
- }
- if (pi && (rc != 0)) {
- /* No defined indexer_create or it fails
- * Let's use the default one
- */
- Slapi_PBlock pb;
- memcpy(&pb, opb, sizeof (Slapi_PBlock));
- slapi_pblock_set(&pb, SLAPI_PLUGIN, pi);
- rc = default_mr_indexer_create(&pb);
- if (!rc) {
- memcpy(opb, &pb, sizeof (Slapi_PBlock));
- plugin_mr_bind(oid, pi); /* for future reference */
+ }
+ if (rc != 0) {
+ /* look for a new syntax-style mr plugin */
+ struct slapdplugin *pi = plugin_mr_find(oid);
+ if (pi) {
+ Slapi_PBlock pb;
+ memcpy (&pb, opb, sizeof(Slapi_PBlock));
+ slapi_pblock_set(&pb, SLAPI_PLUGIN, pi);
+ rc = default_mr_indexer_create(&pb);
+ if (!rc) {
+ memcpy (opb, &pb, sizeof(Slapi_PBlock));
+ plugin_mr_bind (oid, pi); /* for future reference */
+ }
}
}
}
@@ -579,7 +580,19 @@ plugin_mr_filter_create (mr_filter_t* f)
{
rc = attempt_mr_filter_create (f, mrp, &pb);
}
- if (!mrp || rc)
+ else
+ {
+ /* call each plugin, until one is able to handle this request. */
+ for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp =
mrp->plg_next)
+ {
+ if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
+ {
+ plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
+ break;
+ }
+ }
+ }
+ if (rc)
{
/* look for a new syntax-style mr plugin */
mrp = plugin_mr_find(f->mrf_oid);