|
|
dc8c34 |
From 3e7c37a2d605faf7e2f4c5b8ef39309e1b231de1 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
dc8c34 |
Date: Wed, 7 Jan 2015 08:59:06 -0500
|
|
|
dc8c34 |
Subject: [PATCH 291/305] Ticket 47981 - COS cache doesn't properly mark vattr
|
|
|
dc8c34 |
cache as invalid when there are multiple suffixes
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Description: When rebuilding the COS cache, we check each suffix for COS entries.
|
|
|
dc8c34 |
If the last suffix checked does not contain any COS entries, then the
|
|
|
dc8c34 |
virtual attribute cache is incorrectly not invalidated. This allows
|
|
|
dc8c34 |
for already cached entries to hold onto the old COS attributes/values.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Description: Only set the vattr_cacheable flag if a suffix contains COS entries, not
|
|
|
dc8c34 |
if it does not - by default the flag is not set.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47981
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by: nhosoi(Thanks!)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
(cherry picked from commit 42e2df3858a4e14706d57b5c907d1d3768f4d970)
|
|
|
dc8c34 |
(cherry picked from commit c1ba7eb8c41c44bd7689bfc2526a2aa7fff47284)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
dirsrvtests/tickets/ticket47981_test.py | 345 ++++++++++++++++++++++++++++++++
|
|
|
dc8c34 |
ldap/servers/plugins/cos/cos_cache.c | 34 ++--
|
|
|
dc8c34 |
2 files changed, 359 insertions(+), 20 deletions(-)
|
|
|
dc8c34 |
create mode 100644 dirsrvtests/tickets/ticket47981_test.py
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/dirsrvtests/tickets/ticket47981_test.py b/dirsrvtests/tickets/ticket47981_test.py
|
|
|
dc8c34 |
new file mode 100644
|
|
|
dc8c34 |
index 0000000..2a16ce6
|
|
|
dc8c34 |
--- /dev/null
|
|
|
dc8c34 |
+++ b/dirsrvtests/tickets/ticket47981_test.py
|
|
|
dc8c34 |
@@ -0,0 +1,345 @@
|
|
|
dc8c34 |
+import os
|
|
|
dc8c34 |
+import sys
|
|
|
dc8c34 |
+import time
|
|
|
dc8c34 |
+import ldap
|
|
|
dc8c34 |
+import ldap.sasl
|
|
|
dc8c34 |
+import logging
|
|
|
dc8c34 |
+import socket
|
|
|
dc8c34 |
+import pytest
|
|
|
dc8c34 |
+from lib389 import DirSrv, Entry, tools, tasks
|
|
|
dc8c34 |
+from lib389.tools import DirSrvTools
|
|
|
dc8c34 |
+from lib389._constants import *
|
|
|
dc8c34 |
+from lib389.properties import *
|
|
|
dc8c34 |
+from lib389.tasks import *
|
|
|
dc8c34 |
+from constants import *
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+log = logging.getLogger(__name__)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+installation_prefix = None
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+BRANCH = 'ou=people,' + DEFAULT_SUFFIX
|
|
|
dc8c34 |
+USER_DN = 'uid=user1,%s' % (BRANCH)
|
|
|
dc8c34 |
+BRANCH_CONTAINER = 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
|
|
|
dc8c34 |
+BRANCH_COS_DEF = 'cn=nsPwPolicy_CoS,ou=people,dc=example,dc=com'
|
|
|
dc8c34 |
+BRANCH_PWP = 'cn=cn\\3DnsPwPolicyEntry\\2Cou\\3DPeople\\2Cdc\\3Dexample\\2Cdc\\3Dcom,' + \
|
|
|
dc8c34 |
+ 'cn=nsPwPolicyContainer,ou=People,dc=example,dc=com'
|
|
|
dc8c34 |
+BRANCH_COS_TMPL = 'cn=cn\\3DnsPwTemplateEntry\\2Cou\\3DPeople\\2Cdc\\3Dexample\\2Cdc\\3Dcom,' + \
|
|
|
dc8c34 |
+ 'cn=nsPwPolicyContainer,ou=People,dc=example,dc=com'
|
|
|
dc8c34 |
+SECOND_SUFFIX = 'o=netscaperoot'
|
|
|
dc8c34 |
+BE_NAME = 'netscaperoot'
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+class TopologyStandalone(object):
|
|
|
dc8c34 |
+ def __init__(self, standalone):
|
|
|
dc8c34 |
+ standalone.open()
|
|
|
dc8c34 |
+ self.standalone = standalone
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+@pytest.fixture(scope="module")
|
|
|
dc8c34 |
+def topology(request):
|
|
|
dc8c34 |
+ '''
|
|
|
dc8c34 |
+ This fixture is used to standalone topology for the 'module'.
|
|
|
dc8c34 |
+ At the beginning, It may exists a standalone instance.
|
|
|
dc8c34 |
+ It may also exists a backup for the standalone instance.
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ Principle:
|
|
|
dc8c34 |
+ If standalone instance exists:
|
|
|
dc8c34 |
+ restart it
|
|
|
dc8c34 |
+ If backup of standalone exists:
|
|
|
dc8c34 |
+ create/rebind to standalone
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ restore standalone instance from backup
|
|
|
dc8c34 |
+ else:
|
|
|
dc8c34 |
+ Cleanup everything
|
|
|
dc8c34 |
+ remove instance
|
|
|
dc8c34 |
+ remove backup
|
|
|
dc8c34 |
+ Create instance
|
|
|
dc8c34 |
+ Create backup
|
|
|
dc8c34 |
+ '''
|
|
|
dc8c34 |
+ global installation_prefix
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if installation_prefix:
|
|
|
dc8c34 |
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ standalone = DirSrv(verbose=False)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Args for the standalone instance
|
|
|
dc8c34 |
+ args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
dc8c34 |
+ args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
dc8c34 |
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
dc8c34 |
+ args_standalone = args_instance.copy()
|
|
|
dc8c34 |
+ standalone.allocate(args_standalone)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Get the status of the backups
|
|
|
dc8c34 |
+ backup_standalone = standalone.checkBackupFS()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Get the status of the instance and restart it if it exists
|
|
|
dc8c34 |
+ instance_standalone = standalone.exists()
|
|
|
dc8c34 |
+ if instance_standalone:
|
|
|
dc8c34 |
+ # assuming the instance is already stopped, just wait 5 sec max
|
|
|
dc8c34 |
+ standalone.stop(timeout=5)
|
|
|
dc8c34 |
+ standalone.start(timeout=10)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if backup_standalone:
|
|
|
dc8c34 |
+ # The backup exist, assuming it is correct
|
|
|
dc8c34 |
+ # we just re-init the instance with it
|
|
|
dc8c34 |
+ if not instance_standalone:
|
|
|
dc8c34 |
+ standalone.create()
|
|
|
dc8c34 |
+ # Used to retrieve configuration information (dbdir, confdir...)
|
|
|
dc8c34 |
+ standalone.open()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # restore standalone instance from backup
|
|
|
dc8c34 |
+ standalone.stop(timeout=10)
|
|
|
dc8c34 |
+ standalone.restoreFS(backup_standalone)
|
|
|
dc8c34 |
+ standalone.start(timeout=10)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ else:
|
|
|
dc8c34 |
+ # We should be here only in two conditions
|
|
|
dc8c34 |
+ # - This is the first time a test involve standalone instance
|
|
|
dc8c34 |
+ # - Something weird happened (instance/backup destroyed)
|
|
|
dc8c34 |
+ # so we discard everything and recreate all
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Remove the backup. So even if we have a specific backup file
|
|
|
dc8c34 |
+ # (e.g backup_standalone) we clear backup that an instance may have created
|
|
|
dc8c34 |
+ if backup_standalone:
|
|
|
dc8c34 |
+ standalone.clearBackupFS()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Remove the instance
|
|
|
dc8c34 |
+ if instance_standalone:
|
|
|
dc8c34 |
+ standalone.delete()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Create the instance
|
|
|
dc8c34 |
+ standalone.create()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Used to retrieve configuration information (dbdir, confdir...)
|
|
|
dc8c34 |
+ standalone.open()
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Time to create the backups
|
|
|
dc8c34 |
+ standalone.stop(timeout=10)
|
|
|
dc8c34 |
+ standalone.backupfile = standalone.backupFS()
|
|
|
dc8c34 |
+ standalone.start(timeout=10)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # clear the tmp directory
|
|
|
dc8c34 |
+ standalone.clearTmpDir(__file__)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Here we have standalone instance up and running
|
|
|
dc8c34 |
+ # Either coming from a backup recovery
|
|
|
dc8c34 |
+ # or from a fresh (re)init
|
|
|
dc8c34 |
+ # Time to return the topology
|
|
|
dc8c34 |
+ return TopologyStandalone(standalone)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def addSubtreePwPolicy(inst):
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Add subtree policy to the people branch
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.add_s(Entry((BRANCH_CONTAINER, {
|
|
|
dc8c34 |
+ 'objectclass': 'top nsContainer'.split(),
|
|
|
dc8c34 |
+ 'cn': 'nsPwPolicyContainer'
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add subtree container for ou=people: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Add the password policy subentry
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.add_s(Entry((BRANCH_PWP, {
|
|
|
dc8c34 |
+ 'objectclass': 'top ldapsubentry passwordpolicy'.split(),
|
|
|
dc8c34 |
+ 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
|
|
|
dc8c34 |
+ 'passwordMustChange': 'off',
|
|
|
dc8c34 |
+ 'passwordExp': 'off',
|
|
|
dc8c34 |
+ 'passwordHistory': 'off',
|
|
|
dc8c34 |
+ 'passwordMinAge': '0',
|
|
|
dc8c34 |
+ 'passwordChange': 'off',
|
|
|
dc8c34 |
+ 'passwordStorageScheme': 'ssha'
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add passwordpolicy: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Add the COS template
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.add_s(Entry((BRANCH_COS_TMPL, {
|
|
|
dc8c34 |
+ 'objectclass': 'top ldapsubentry costemplate extensibleObject'.split(),
|
|
|
dc8c34 |
+ 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
|
|
|
dc8c34 |
+ 'cosPriority': '1',
|
|
|
dc8c34 |
+ 'cn': 'cn=nsPwTemplateEntry,ou=people,dc=example,dc=com',
|
|
|
dc8c34 |
+ 'pwdpolicysubentry': BRANCH_PWP
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add COS template: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # Add the COS definition
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.add_s(Entry((BRANCH_COS_DEF, {
|
|
|
dc8c34 |
+ 'objectclass': 'top ldapsubentry cosSuperDefinition cosPointerDefinition'.split(),
|
|
|
dc8c34 |
+ 'cn': 'cn=nsPwPolicyEntry,ou=people,dc=example,dc=com',
|
|
|
dc8c34 |
+ 'costemplatedn': BRANCH_COS_TMPL,
|
|
|
dc8c34 |
+ 'cosAttribute': 'pwdpolicysubentry default operational-default'
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add COS def: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ time.sleep(0.5)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def delSubtreePwPolicy(inst):
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.delete_s(BRANCH_COS_DEF)
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to delete COS def: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.delete_s(BRANCH_COS_TMPL)
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to delete COS template: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.delete_s(BRANCH_PWP)
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to delete COS password policy: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ inst.delete_s(BRANCH_CONTAINER)
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to delete COS container: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ time.sleep(0.5)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def test_ticket47981(topology):
|
|
|
dc8c34 |
+ """
|
|
|
dc8c34 |
+ If there are multiple suffixes, and the last suffix checked does not contain any COS entries,
|
|
|
dc8c34 |
+ while other suffixes do, then the vattr cache is not invalidated as it should be. Then any
|
|
|
dc8c34 |
+ cached entries will still contain the old COS attributes/values.
|
|
|
dc8c34 |
+ """
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ log.info('Testing Ticket 47981 - Test that COS def changes are correctly reflected in affected users')
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Create a second backend that does not have any COS entries
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ log.info('Adding second suffix that will not contain any COS entries...\n')
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ topology.standalone.backend.create(SECOND_SUFFIX, {BACKEND_NAME: BE_NAME})
|
|
|
dc8c34 |
+ topology.standalone.mappingtree.create(SECOND_SUFFIX, bename=BE_NAME)
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.add_s(Entry((SECOND_SUFFIX, {
|
|
|
dc8c34 |
+ 'objectclass': 'top organization'.split(),
|
|
|
dc8c34 |
+ 'o': BE_NAME})))
|
|
|
dc8c34 |
+ except ldap.ALREADY_EXISTS:
|
|
|
dc8c34 |
+ pass
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to create suffix entry: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Add People branch, it might already exist
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ log.info('Add our test entries to the default suffix, and proceed with the test...')
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.add_s(Entry((BRANCH, {
|
|
|
dc8c34 |
+ 'objectclass': 'top extensibleObject'.split(),
|
|
|
dc8c34 |
+ 'ou': 'level4'
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.ALREADY_EXISTS:
|
|
|
dc8c34 |
+ pass
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add ou=people: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Add a user to the branch
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.add_s(Entry((USER_DN, {
|
|
|
dc8c34 |
+ 'objectclass': 'top extensibleObject'.split(),
|
|
|
dc8c34 |
+ 'uid': 'user1'
|
|
|
dc8c34 |
+ })))
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to add user1: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Enable password policy and add the subtree policy
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-pwpolicy-local', 'on')])
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.error('Failed to set pwpolicy-local: error ' + e.message['desc'])
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ addSubtreePwPolicy(topology.standalone)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Now check the user has its expected passwordPolicy subentry
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entries = topology.standalone.search_s(USER_DN,
|
|
|
dc8c34 |
+ ldap.SCOPE_BASE,
|
|
|
dc8c34 |
+ '(objectclass=top)',
|
|
|
dc8c34 |
+ ['pwdpolicysubentry', 'dn'])
|
|
|
dc8c34 |
+ if not entries[0].hasAttr('pwdpolicysubentry'):
|
|
|
dc8c34 |
+ log.fatal('User does not have expected pwdpolicysubentry!')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Delete the password policy and make sure it is removed from the same user
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ delSubtreePwPolicy(topology.standalone)
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entries = topology.standalone.search_s(USER_DN, ldap.SCOPE_BASE, '(objectclass=top)', ['pwdpolicysubentry'])
|
|
|
dc8c34 |
+ if entries[0].hasAttr('pwdpolicysubentry'):
|
|
|
dc8c34 |
+ log.fatal('User unexpectedly does have the pwdpolicysubentry!')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ # Add the subtree policvy back and see if the user now has it
|
|
|
dc8c34 |
+ #
|
|
|
dc8c34 |
+ addSubtreePwPolicy(topology.standalone)
|
|
|
dc8c34 |
+ try:
|
|
|
dc8c34 |
+ entries = topology.standalone.search_s(USER_DN, ldap.SCOPE_BASE, '(objectclass=top)', ['pwdpolicysubentry'])
|
|
|
dc8c34 |
+ if not entries[0].hasAttr('pwdpolicysubentry'):
|
|
|
dc8c34 |
+ log.fatal('User does not have expected pwdpolicysubentry!')
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+ except ldap.LDAPError, e:
|
|
|
dc8c34 |
+ log.fatal('Unable to search for entry %s: error %s' % (USER_DN, e.message['desc']))
|
|
|
dc8c34 |
+ assert False
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ # If we got here the test passed
|
|
|
dc8c34 |
+ log.info('Test PASSED')
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def test_ticket47981_final(topology):
|
|
|
dc8c34 |
+ topology.standalone.stop(timeout=10)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+def run_isolated():
|
|
|
dc8c34 |
+ '''
|
|
|
dc8c34 |
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
|
|
|
dc8c34 |
+ To run isolated without py.test, you need to
|
|
|
dc8c34 |
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
|
|
|
dc8c34 |
+ - set the installation prefix
|
|
|
dc8c34 |
+ - run this program
|
|
|
dc8c34 |
+ '''
|
|
|
dc8c34 |
+ global installation_prefix
|
|
|
dc8c34 |
+ installation_prefix = None
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ topo = topology(True)
|
|
|
dc8c34 |
+ test_ticket47981(topo)
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+if __name__ == '__main__':
|
|
|
dc8c34 |
+ run_isolated()
|
|
|
dc8c34 |
\ No newline at end of file
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
|
|
|
dc8c34 |
index 76cc8fd..f41c3de 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/cos/cos_cache.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/cos/cos_cache.c
|
|
|
dc8c34 |
@@ -300,7 +300,7 @@ static int cos_cache_add_tmpl(cosTemplates **pTemplates, cosAttrValue *dn, cosAt
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* cosDefinitions manipulation */
|
|
|
dc8c34 |
static int cos_cache_build_definition_list(cosDefinitions **pDefs, int *vattr_cacheable);
|
|
|
dc8c34 |
-static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs, int *vattr_cacheable);
|
|
|
dc8c34 |
+static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs);
|
|
|
dc8c34 |
static int cos_cache_add_defn(cosDefinitions **pDefs, cosAttrValue **dn, int cosType, cosAttrValue **tree, cosAttrValue **tmpDn, cosAttrValue **spec, cosAttrValue **pAttrs, cosAttrValue **pOverrides, cosAttrValue **pOperational, cosAttrValue **pCosMerge, cosAttrValue **pCosOpDefault);
|
|
|
dc8c34 |
static int cos_cache_entry_is_cos_related( Slapi_Entry *e);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -659,9 +659,9 @@ static int cos_cache_build_definition_list(cosDefinitions **pDefs, int *vattr_ca
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_build_definition_list\n",0,0,0);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- the class of service definitions may be anywhere in the DIT,
|
|
|
dc8c34 |
- so our first task is to find them.
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
+ * The class of service definitions may be anywhere in the DIT,
|
|
|
dc8c34 |
+ * so our first task is to find them.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
attrs[0] = "namingcontexts";
|
|
|
dc8c34 |
attrs[1] = 0;
|
|
|
dc8c34 |
@@ -669,9 +669,9 @@ static int cos_cache_build_definition_list(cosDefinitions **pDefs, int *vattr_ca
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_PLUGIN, "cos: Building class of service cache after status change.\n",0,0,0);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- * XXXrbyrne: this looks really ineficient--should be using
|
|
|
dc8c34 |
+ * XXXrbyrne: this looks really inefficient--should be using
|
|
|
dc8c34 |
* slapi_get_next_suffix(), rather than searching for namingcontexts.
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
pSuffixSearch = slapi_search_internal("",LDAP_SCOPE_BASE,"(objectclass=*)",NULL,attrs,0);
|
|
|
dc8c34 |
if(pSuffixSearch)
|
|
|
dc8c34 |
@@ -711,19 +711,21 @@ static int cos_cache_build_definition_list(cosDefinitions **pDefs, int *vattr_ca
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* here's a suffix, lets search it... */
|
|
|
dc8c34 |
if(suffixVals[valIndex]->bv_val)
|
|
|
dc8c34 |
- if(!cos_cache_add_dn_defs(suffixVals[valIndex]->bv_val ,pDefs, vattr_cacheable))
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ if(!cos_cache_add_dn_defs(suffixVals[valIndex]->bv_val ,pDefs))
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ *vattr_cacheable = -1;
|
|
|
dc8c34 |
cos_def_available = 1;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
valIndex++;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
ber_bvecfree( suffixVals );
|
|
|
dc8c34 |
suffixVals = NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
} while(!slapi_entry_next_attr(pSuffixList[suffixIndex], suffixAttr, &suffixAttr));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
suffixIndex++;
|
|
|
dc8c34 |
@@ -749,7 +751,6 @@ next:
|
|
|
dc8c34 |
slapi_pblock_destroy(pSuffixSearch);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_cache_build_definition_list\n",0,0,0);
|
|
|
dc8c34 |
return ret;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -790,10 +791,6 @@ cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
|
|
|
dc8c34 |
char *norm_dn = NULL;
|
|
|
dc8c34 |
info=(struct dn_defs_info *)callback_data;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- /* assume cacheable */
|
|
|
dc8c34 |
- info->vattr_cacheable = -1;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
cos_cache_add_attrval(&pDn, slapi_entry_get_dn(e));
|
|
|
dc8c34 |
if(slapi_entry_first_attr(e, &dnAttr)) {
|
|
|
dc8c34 |
goto bail;
|
|
|
dc8c34 |
@@ -1119,7 +1116,7 @@ bail:
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#define DN_DEF_FILTER "(&(|(objectclass=cosSuperDefinition)(objectclass=cosDefinition))(objectclass=ldapsubentry))"
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs, int *vattr_cacheable)
|
|
|
dc8c34 |
+static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_PBlock *pDnSearch = 0;
|
|
|
dc8c34 |
struct dn_defs_info info = {NULL, 0, 0};
|
|
|
dc8c34 |
@@ -1127,7 +1124,6 @@ static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs, int *vattr_ca
|
|
|
dc8c34 |
if (pDnSearch) {
|
|
|
dc8c34 |
info.ret=-1; /* assume no good defs */
|
|
|
dc8c34 |
info.pDefs=pDefs;
|
|
|
dc8c34 |
- info.vattr_cacheable = 0; /* assume not cacheable */
|
|
|
dc8c34 |
slapi_search_internal_set_pb(pDnSearch, dn, LDAP_SCOPE_SUBTREE,
|
|
|
dc8c34 |
DN_DEF_FILTER,NULL,0,
|
|
|
dc8c34 |
NULL,NULL,cos_get_plugin_identity(),0);
|
|
|
dc8c34 |
@@ -1139,8 +1135,6 @@ static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs, int *vattr_ca
|
|
|
dc8c34 |
slapi_pblock_destroy (pDnSearch);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- *vattr_cacheable = info.vattr_cacheable;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
return info.ret;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.9.3
|
|
|
dc8c34 |
|