andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame 0271-Ticket-47900-Server-fails-to-start-if-password-admin.patch

dc8c34
From cd4d6a649e69e61ba8ffe778b23214130be87b99 Mon Sep 17 00:00:00 2001
dc8c34
From: Mark Reynolds <mreynolds@redhat.com>
dc8c34
Date: Thu, 2 Oct 2014 10:17:13 -0400
dc8c34
Subject: [PATCH 271/305] Ticket 47900 - Server fails to start if password
dc8c34
 admin is set
dc8c34
dc8c34
Bug Description:  The server will crash at startup if the password admin is set.
dc8c34
dc8c34
Fix Description:  When creating a password policy for the pblock, which we do
dc8c34
                  for add and modifiy operations, make sure the server is fully
dc8c34
                  up and running before searching backends for password admins.
dc8c34
dc8c34
                  Also, allow passwordAdminDN to be deleted from the cn=config.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/47900
dc8c34
dc8c34
Reviewed by: nhosoi(Thanks!)
dc8c34
dc8c34
(cherry picked from commit 4711de687174d6e5dd7b2c04782b62dc1cb90a6e)
dc8c34
(cherry picked from commit ed6f09b278431967f9e8f1ca0ccb7484dc07f189)
dc8c34
---
dc8c34
 dirsrvtests/tickets/ticket47900_test.py | 398 ++++++++++++++++++++++++++++++++
dc8c34
 ldap/servers/slapd/libglobs.c           |   2 +-
dc8c34
 ldap/servers/slapd/pw.c                 |  18 +-
dc8c34
 3 files changed, 415 insertions(+), 3 deletions(-)
dc8c34
 create mode 100644 dirsrvtests/tickets/ticket47900_test.py
dc8c34
dc8c34
diff --git a/dirsrvtests/tickets/ticket47900_test.py b/dirsrvtests/tickets/ticket47900_test.py
dc8c34
new file mode 100644
dc8c34
index 0000000..4e6f5d7
dc8c34
--- /dev/null
dc8c34
+++ b/dirsrvtests/tickets/ticket47900_test.py
dc8c34
@@ -0,0 +1,398 @@
dc8c34
+import os
dc8c34
+import sys
dc8c34
+import time
dc8c34
+import ldap
dc8c34
+import logging
dc8c34
+import socket
dc8c34
+import pytest
dc8c34
+from lib389 import DirSrv, Entry, tools
dc8c34
+from lib389.tools import DirSrvTools
dc8c34
+from lib389._constants import *
dc8c34
+from lib389.properties import *
dc8c34
+from constants import *
dc8c34
+
dc8c34
+log = logging.getLogger(__name__)
dc8c34
+
dc8c34
+installation_prefix = None
dc8c34
+
dc8c34
+CONFIG_DN  = 'cn=config'
dc8c34
+ADMIN_NAME = 'passwd_admin'
dc8c34
+ADMIN_DN   = 'cn=%s,%s' % (ADMIN_NAME, SUFFIX)
dc8c34
+ADMIN_PWD  = 'adminPassword_1'
dc8c34
+ENTRY_NAME = 'Joe Schmo'
dc8c34
+ENTRY_DN   = 'cn=%s,%s' % (ENTRY_NAME, SUFFIX)
dc8c34
+INVALID_PWDS = ('2_Short', 'No_Number', 'N0Special', '{SSHA}bBy8UdtPZwu8uZna9QOYG3Pr41RpIRVDl8wddw==')
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 test_ticket47900(topology):
dc8c34
+    """
dc8c34
+        Test that password administrators/root DN can
dc8c34
+        bypass password syntax/policy.
dc8c34
+
dc8c34
+        We need to test how passwords are modified in
dc8c34
+        existing entries, and when adding new entries.
dc8c34
+        
dc8c34
+        Create the Password Admin entry, but do not set
dc8c34
+        it as an admin yet.  Use the entry to verify invalid
dc8c34
+        passwords are caught.  Then activate the password 
dc8c34
+        admin and make sure it can bypass password policy.
dc8c34
+    """
dc8c34
+
dc8c34
+    # Prepare the Password Administator
dc8c34
+    entry = Entry(ADMIN_DN)
dc8c34
+    entry.setValues('objectclass', 'top', 'person')
dc8c34
+    entry.setValues('sn', ADMIN_NAME)
dc8c34
+    entry.setValues('cn', ADMIN_NAME)
dc8c34
+    entry.setValues('userpassword', ADMIN_PWD)
dc8c34
+
dc8c34
+    topology.standalone.log.info("Creating Password Administator entry %s..." % ADMIN_DN)
dc8c34
+    try:
dc8c34
+        topology.standalone.add_s(entry)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Unexpected result ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+        topology.standalone.log.error("Failed to add Password Administator %s, error: %s "
dc8c34
+                % (ADMIN_DN, e.message['desc']))
dc8c34
+        assert False
dc8c34
+
dc8c34
+    topology.standalone.log.info("Configuring password policy...")
dc8c34
+    try:
dc8c34
+        topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-pwpolicy-local' , 'on'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordCheckSyntax', 'on'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordMinCategories' , '1'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordMinTokenLength' , '1'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordExp' , 'on'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordMinDigits' , '1'),
dc8c34
+                                                 (ldap.MOD_REPLACE, 'passwordMinSpecials' , '1')])
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed configure password policy: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Add an aci to allow everyone all access (just makes things easier)
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Add aci to allow password admin to add/update entries...")
dc8c34
+
dc8c34
+    ACI_TARGET       = "(target = \"ldap:///%s\")" % SUFFIX
dc8c34
+    ACI_TARGETATTR   = "(targetattr = *)"
dc8c34
+    ACI_ALLOW        = "(version 3.0; acl \"Password Admin Access\"; allow (all) "
dc8c34
+    ACI_SUBJECT      = "(userdn = \"ldap:///anyone\");)"
dc8c34
+    ACI_BODY         = ACI_TARGET + ACI_TARGETATTR + ACI_ALLOW + ACI_SUBJECT
dc8c34
+    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
dc8c34
+    try:
dc8c34
+        topology.standalone.modify_s(SUFFIX, mod)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to add aci for password admin: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Bind as the Password Admin
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Bind as the Password Administator (before activating)...")
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(ADMIN_DN, ADMIN_PWD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to bind as the Password Admin: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Setup our test entry, and test password policy is working
dc8c34
+    #
dc8c34
+    entry = Entry(ENTRY_DN)
dc8c34
+    entry.setValues('objectclass', 'top', 'person')
dc8c34
+    entry.setValues('sn', ENTRY_NAME)
dc8c34
+    entry.setValues('cn', ENTRY_NAME)
dc8c34
+
dc8c34
+    #
dc8c34
+    # Start by attempting to add an entry with an invalid password
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Attempt to add entries with invalid passwords, these adds should fail...")
dc8c34
+    for passwd in INVALID_PWDS:
dc8c34
+        failed_as_expected = False
dc8c34
+        entry.setValues('userpassword', passwd)
dc8c34
+        topology.standalone.log.info("Create a regular user entry %s with password (%s)..." % (ENTRY_DN, passwd))
dc8c34
+        try:
dc8c34
+            topology.standalone.add_s(entry)
dc8c34
+        except ldap.LDAPError, e:
dc8c34
+            # We failed as expected
dc8c34
+            failed_as_expected = True
dc8c34
+            topology.standalone.log.info('Add failed as expected: password (%s) result (%s)'
dc8c34
+                    % (passwd, e.message['desc']))
dc8c34
+
dc8c34
+        if not failed_as_expected:
dc8c34
+            topology.standalone.log.error("We were incorrectly able to add an entry " +
dc8c34
+                    "with an invalid password (%s)" % (passwd))
dc8c34
+            assert False
dc8c34
+
dc8c34
+
dc8c34
+    #
dc8c34
+    # Now activate a password administator, bind as root dn to do the config
dc8c34
+    # update, then rebind as the password admin
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Activate the Password Administator...")
dc8c34
+    
dc8c34
+    # Bind as Root DN
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(DN_DM, PASSWORD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Root DN failed to authenticate: ' + e.message['desc'])
dc8c34
+        assert False 
dc8c34
+        
dc8c34
+    # Update config
dc8c34
+    try:
dc8c34
+        topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'passwordAdminDN', ADMIN_DN)])
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to add password admin to config: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+    
dc8c34
+    # Bind as Password Admin
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(ADMIN_DN, ADMIN_PWD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to bind as the Password Admin: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Start adding entries with invalid passwords, delete the entry after each pass.
dc8c34
+    #
dc8c34
+    for passwd in INVALID_PWDS:
dc8c34
+        entry.setValues('userpassword', passwd)
dc8c34
+        topology.standalone.log.info("Create a regular user entry %s with password (%s)..." % (ENTRY_DN, passwd))
dc8c34
+        try:
dc8c34
+            topology.standalone.add_s(entry)
dc8c34
+        except ldap.LDAPError, e:
dc8c34
+            topology.standalone.log.error('Failed to add entry with password (%s) result (%s)'
dc8c34
+                    % (passwd, e.message['desc']))
dc8c34
+            assert False
dc8c34
+
dc8c34
+        topology.standalone.log.info('Succesfully added entry (%s)' % ENTRY_DN)
dc8c34
+
dc8c34
+        # Delete entry for the next pass
dc8c34
+        try:
dc8c34
+            topology.standalone.delete_s(ENTRY_DN)
dc8c34
+        except ldap.LDAPError, e:
dc8c34
+            topology.standalone.log.error('Failed to delete entry: %s' % (e.message['desc']))
dc8c34
+            assert False
dc8c34
+
dc8c34
+
dc8c34
+    #
dc8c34
+    # Add the entry for the next round of testing (modify password)
dc8c34
+    #
dc8c34
+    entry.setValues('userpassword', ADMIN_PWD)
dc8c34
+    try:
dc8c34
+        topology.standalone.add_s(entry)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to add entry with valid password (%s) result (%s)'
dc8c34
+                % (passwd, e.message['desc']))
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Deactivate the password admin and make sure invalid password updates fail
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Deactivate Password Administator and try invalid password updates...")
dc8c34
+    
dc8c34
+    # Bind as root DN
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(DN_DM, PASSWORD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Root DN failed to authenticate: ' + e.message['desc'])
dc8c34
+        assert False 
dc8c34
+
dc8c34
+    # Update config
dc8c34
+    try:
dc8c34
+        topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_DELETE, 'passwordAdminDN', None)])
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to remove password admin from config: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    # Bind as Password Admin
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(ADMIN_DN, ADMIN_PWD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to bind as the Password Admin: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+        
dc8c34
+    #
dc8c34
+    # Make invalid password updates that should fail
dc8c34
+    #
dc8c34
+    for passwd in INVALID_PWDS:
dc8c34
+        failed_as_expected = False
dc8c34
+        entry.setValues('userpassword', passwd)
dc8c34
+        try:
dc8c34
+            topology.standalone.modify_s(ENTRY_DN, [(ldap.MOD_REPLACE, 'userpassword', passwd)])
dc8c34
+        except ldap.LDAPError, e:
dc8c34
+            # We failed as expected
dc8c34
+            failed_as_expected = True
dc8c34
+            topology.standalone.log.info('Password update failed as expected: password (%s) result (%s)'
dc8c34
+                    % (passwd, e.message['desc']))
dc8c34
+
dc8c34
+        if not failed_as_expected:
dc8c34
+            topology.standalone.log.error("We were incorrectly able to add an invalid password (%s)"
dc8c34
+                    % (passwd))
dc8c34
+            assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Now activate a password administator
dc8c34
+    #
dc8c34
+    topology.standalone.log.info("Activate Password Administator and try updates again...")
dc8c34
+    
dc8c34
+    # Bind as root DN
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(DN_DM, PASSWORD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Root DN failed to authenticate: ' + e.message['desc'])
dc8c34
+        assert False 
dc8c34
+
dc8c34
+    # Update config
dc8c34
+    try:
dc8c34
+        topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'passwordAdminDN', ADMIN_DN)])
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to add password admin to config: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+        
dc8c34
+    # Bind as Password Admin
dc8c34
+    try:
dc8c34
+        topology.standalone.simple_bind_s(ADMIN_DN, ADMIN_PWD)
dc8c34
+    except ldap.LDAPError, e:
dc8c34
+        topology.standalone.log.error('Failed to bind as the Password Admin: ' + e.message['desc'])
dc8c34
+        assert False
dc8c34
+
dc8c34
+    #
dc8c34
+    # Make the same password updates, but this time they should succeed
dc8c34
+    #
dc8c34
+    for passwd in INVALID_PWDS:
dc8c34
+        entry.setValues('userpassword', passwd)
dc8c34
+        try:
dc8c34
+            topology.standalone.modify_s(ENTRY_DN, [(ldap.MOD_REPLACE, 'userpassword', passwd)])
dc8c34
+        except ldap.LDAPError, e:
dc8c34
+            topology.standalone.log.error('Password update failed unexpectedly: password (%s) result (%s)'
dc8c34
+                    % (passwd, e.message['desc']))
dc8c34
+            assert False
dc8c34
+        topology.standalone.log.info('Password update succeeded (%s)' % passwd) 
dc8c34
+    #
dc8c34
+    # Test passed
dc8c34
+    #
dc8c34
+    topology.standalone.log.info('Test 47900 Passed.')
dc8c34
+
dc8c34
+
dc8c34
+def test_ticket47900_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_ticket47900(topo)
dc8c34
+
dc8c34
+if __name__ == '__main__':
dc8c34
+    run_isolated()
dc8c34
+
dc8c34
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
dc8c34
index b2cb8e2..63093e1 100644
dc8c34
--- a/ldap/servers/slapd/libglobs.c
dc8c34
+++ b/ldap/servers/slapd/libglobs.c
dc8c34
@@ -1446,7 +1446,7 @@ FrontendConfig_init () {
dc8c34
 
dc8c34
   init_entryusn_global = cfg->entryusn_global = LDAP_OFF; 
dc8c34
   cfg->entryusn_import_init = slapi_ch_strdup(ENTRYUSN_IMPORT_INIT); 
dc8c34
-  cfg->allowed_to_delete_attrs = slapi_ch_strdup("nsslapd-listenhost nsslapd-securelistenhost nsslapd-defaultnamingcontext");
dc8c34
+  cfg->allowed_to_delete_attrs = slapi_ch_strdup("passwordadmindn nsslapd-listenhost nsslapd-securelistenhost nsslapd-defaultnamingcontext");
dc8c34
   cfg->default_naming_context = NULL; /* store normalized dn */
dc8c34
 
dc8c34
   init_disk_monitoring = cfg->disk_monitoring = LDAP_OFF;
dc8c34
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
dc8c34
index cf400a1..eb9eacb 100644
dc8c34
--- a/ldap/servers/slapd/pw.c
dc8c34
+++ b/ldap/servers/slapd/pw.c
dc8c34
@@ -1643,13 +1643,27 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
dc8c34
 	slapdFrontendConfig_t *slapdFrontendConfig;
dc8c34
 	int optype = -1;
dc8c34
 
dc8c34
-	slapdFrontendConfig = getFrontendConfig();
dc8c34
-	pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy));
dc8c34
+	/* If we already allocated a pw policy, return it */
dc8c34
+	if(pb && pb->pwdpolicy){
dc8c34
+		return pb->pwdpolicy;
dc8c34
+	}
dc8c34
+
dc8c34
+	if (g_get_active_threadcnt() == 0){
dc8c34
+		/*
dc8c34
+		 * If the server is starting up the thread count will be zero, so
dc8c34
+		 * we should not proceed, because not all the backends have been
dc8c34
+		 * initialized yet.
dc8c34
+		 */
dc8c34
+		return NULL;
dc8c34
+	}
dc8c34
 
dc8c34
 	if (pb) {
dc8c34
 		slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype );
dc8c34
 	}
dc8c34
 
dc8c34
+	slapdFrontendConfig = getFrontendConfig();
dc8c34
+	pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy));
dc8c34
+
dc8c34
 	if (dn && (slapdFrontendConfig->pwpolicy_local == 1)) {
dc8c34
 		/*  If we're doing an add, COS does not apply yet so we check
dc8c34
 			parents for the pwdpolicysubentry.  We look only for virtual
dc8c34
-- 
dc8c34
1.9.3
dc8c34