|
|
b69e47 |
From 353955ba9b4c487e30315d39d1880b6b784817d2 Mon Sep 17 00:00:00 2001
|
|
|
b69e47 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
b69e47 |
Date: Mon, 27 Mar 2017 10:59:40 -0400
|
|
|
b69e47 |
Subject: [PATCH] Issue 49192 - Deleting suffix can hang server
|
|
|
b69e47 |
|
|
|
b69e47 |
Description: If you attempt to bind as an inactive user the backend rwlock
|
|
|
b69e47 |
is not unlocked. Regression introduced from issue 49051.
|
|
|
b69e47 |
|
|
|
b69e47 |
https://pagure.io/389-ds-base/issue/49192
|
|
|
b69e47 |
|
|
|
b69e47 |
Reviewed by: nhosoi(Thanks!)
|
|
|
b69e47 |
---
|
|
|
b69e47 |
dirsrvtests/tests/tickets/ticket49192_test.py | 177 ++++++++++++++++++++++++++
|
|
|
b69e47 |
ldap/servers/slapd/bind.c | 3 -
|
|
|
b69e47 |
ldap/servers/slapd/pw_verify.c | 8 +-
|
|
|
b69e47 |
3 files changed, 179 insertions(+), 9 deletions(-)
|
|
|
b69e47 |
create mode 100644 dirsrvtests/tests/tickets/ticket49192_test.py
|
|
|
b69e47 |
|
|
|
b69e47 |
diff --git a/dirsrvtests/tests/tickets/ticket49192_test.py b/dirsrvtests/tests/tickets/ticket49192_test.py
|
|
|
b69e47 |
new file mode 100644
|
|
|
b69e47 |
index 0000000..f770ba7
|
|
|
b69e47 |
--- /dev/null
|
|
|
b69e47 |
+++ b/dirsrvtests/tests/tickets/ticket49192_test.py
|
|
|
b69e47 |
@@ -0,0 +1,177 @@
|
|
|
b69e47 |
+import time
|
|
|
b69e47 |
+import ldap
|
|
|
b69e47 |
+import logging
|
|
|
b69e47 |
+import pytest
|
|
|
b69e47 |
+from lib389 import Entry
|
|
|
b69e47 |
+from lib389._constants import *
|
|
|
b69e47 |
+from lib389.properties import *
|
|
|
b69e47 |
+from lib389.tasks import *
|
|
|
b69e47 |
+from lib389.utils import *
|
|
|
b69e47 |
+from lib389.topologies import topology_st as topo
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+DEBUGGING = os.getenv("DEBUGGING", default=False)
|
|
|
b69e47 |
+if DEBUGGING:
|
|
|
b69e47 |
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
b69e47 |
+else:
|
|
|
b69e47 |
+ logging.getLogger(__name__).setLevel(logging.INFO)
|
|
|
b69e47 |
+log = logging.getLogger(__name__)
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+INDEX_DN = 'cn=index,cn=Second_Backend,cn=ldbm database,cn=plugins,cn=config'
|
|
|
b69e47 |
+SUFFIX_DN = 'cn=Second_Backend,cn=ldbm database,cn=plugins,cn=config'
|
|
|
b69e47 |
+MY_SUFFIX = "o=hang.com"
|
|
|
b69e47 |
+USER_DN = 'uid=user,' + MY_SUFFIX
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+def test_ticket49192(topo):
|
|
|
b69e47 |
+ """Trigger deadlock when removing suffix
|
|
|
b69e47 |
+ """
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ # Create a second suffix/backend
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ log.info('Creating second backend...')
|
|
|
b69e47 |
+ topo.standalone.backends.create(None, properties={
|
|
|
b69e47 |
+ BACKEND_NAME: "Second_Backend",
|
|
|
b69e47 |
+ 'suffix': "o=hang.com",
|
|
|
b69e47 |
+ })
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(("o=hang.com", {
|
|
|
b69e47 |
+ 'objectclass': 'top organization'.split(),
|
|
|
b69e47 |
+ 'o': 'hang.com'})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to create 2nd suffix: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ # Add roles
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ log.info('Adding roles...')
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(('cn=nsManagedDisabledRole,' + MY_SUFFIX, {
|
|
|
b69e47 |
+ 'objectclass': ['top', 'LdapSubEntry',
|
|
|
b69e47 |
+ 'nsRoleDefinition',
|
|
|
b69e47 |
+ 'nsSimpleRoleDefinition',
|
|
|
b69e47 |
+ 'nsManagedRoleDefinition'],
|
|
|
b69e47 |
+ 'cn': 'nsManagedDisabledRole'})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add managed role: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(('cn=nsDisabledRole,' + MY_SUFFIX, {
|
|
|
b69e47 |
+ 'objectclass': ['top', 'LdapSubEntry',
|
|
|
b69e47 |
+ 'nsRoleDefinition',
|
|
|
b69e47 |
+ 'nsComplexRoleDefinition',
|
|
|
b69e47 |
+ 'nsNestedRoleDefinition'],
|
|
|
b69e47 |
+ 'cn': 'nsDisabledRole',
|
|
|
b69e47 |
+ 'nsRoledn': 'cn=nsManagedDisabledRole,' + MY_SUFFIX})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add nested role: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(('cn=nsAccountInactivationTmp,' + MY_SUFFIX, {
|
|
|
b69e47 |
+ 'objectclass': ['top', 'nsContainer'],
|
|
|
b69e47 |
+ 'cn': 'nsAccountInactivationTmp'})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add container: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(('cn=\"cn=nsDisabledRole,' + MY_SUFFIX + '\",cn=nsAccountInactivationTmp,' + MY_SUFFIX, {
|
|
|
b69e47 |
+ 'objectclass': ['top', 'extensibleObject', 'costemplate',
|
|
|
b69e47 |
+ 'ldapsubentry'],
|
|
|
b69e47 |
+ 'nsAccountLock': 'true'})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add cos1: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry(('cn=nsAccountInactivation_cos,' + MY_SUFFIX, {
|
|
|
b69e47 |
+ 'objectclass': ['top', 'LdapSubEntry', 'cosSuperDefinition',
|
|
|
b69e47 |
+ 'cosClassicDefinition'],
|
|
|
b69e47 |
+ 'cn': 'nsAccountInactivation_cos',
|
|
|
b69e47 |
+ 'cosTemplateDn': 'cn=nsAccountInactivationTmp,' + MY_SUFFIX,
|
|
|
b69e47 |
+ 'cosSpecifier': 'nsRole',
|
|
|
b69e47 |
+ 'cosAttribute': 'nsAccountLock operational'})))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add cos2 : error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ # Add test entry
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.add_s(Entry((USER_DN, {
|
|
|
b69e47 |
+ 'objectclass': 'top extensibleObject'.split(),
|
|
|
b69e47 |
+ 'uid': 'user',
|
|
|
b69e47 |
+ 'userpassword': 'password',
|
|
|
b69e47 |
+ })))
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to add user: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ # Inactivate the user account
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.modify_s(USER_DN,
|
|
|
b69e47 |
+ [(ldap.MOD_ADD,
|
|
|
b69e47 |
+ 'nsRoleDN',
|
|
|
b69e47 |
+ 'cn=nsManagedDisabledRole,' + MY_SUFFIX)])
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to disable user: error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ time.sleep(1)
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ # Bind as user (should fail)
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.simple_bind_s(USER_DN, 'password')
|
|
|
b69e47 |
+ log.error("Bind incorrectly worked")
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+ except ldap.UNWILLING_TO_PERFORM:
|
|
|
b69e47 |
+ log.info('Got error 53 as expected')
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Bind has unexpected error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ # Bind as root DN
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ topo.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('RootDN Bind has unexpected error ' + e.message['desc'])
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ # Delete suffix
|
|
|
b69e47 |
+ #
|
|
|
b69e47 |
+ log.info('Delete the suffix and children...')
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ index_entries = topo.standalone.search_s(
|
|
|
b69e47 |
+ SUFFIX_DN, ldap.SCOPE_SUBTREE, 'objectclass=top')
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.error('Failed to search: %s - error %s' % (SUFFIX_DN, str(e)))
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ for entry in reversed(index_entries):
|
|
|
b69e47 |
+ try:
|
|
|
b69e47 |
+ log.info("Deleting: " + entry.dn)
|
|
|
b69e47 |
+ if entry.dn != SUFFIX_DN and entry.dn != INDEX_DN:
|
|
|
b69e47 |
+ topo.standalone.search_s(entry.dn,
|
|
|
b69e47 |
+ ldap.SCOPE_ONELEVEL,
|
|
|
b69e47 |
+ 'objectclass=top')
|
|
|
b69e47 |
+ topo.standalone.delete_s(entry.dn)
|
|
|
b69e47 |
+ except ldap.LDAPError as e:
|
|
|
b69e47 |
+ log.fatal('Failed to delete entry: %s - error %s' %
|
|
|
b69e47 |
+ (entry.dn, str(e)))
|
|
|
b69e47 |
+ assert False
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ log.info("Test Passed")
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+if __name__ == '__main__':
|
|
|
b69e47 |
+ # Run isolated
|
|
|
b69e47 |
+ # -s for DEBUG mode
|
|
|
b69e47 |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
b69e47 |
+ pytest.main("-s %s" % CURRENT_FILE)
|
|
|
b69e47 |
+
|
|
|
b69e47 |
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
|
|
|
b69e47 |
index 5c4fada..f83df7d 100644
|
|
|
b69e47 |
--- a/ldap/servers/slapd/bind.c
|
|
|
b69e47 |
+++ b/ldap/servers/slapd/bind.c
|
|
|
b69e47 |
@@ -771,9 +771,6 @@ do_bind( Slapi_PBlock *pb )
|
|
|
b69e47 |
/* need_new_pw failed; need_new_pw already send_ldap_result in it. */
|
|
|
b69e47 |
goto free_and_return;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
- if (be) {
|
|
|
b69e47 |
- slapi_be_Unlock(be);
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
} else { /* anonymous */
|
|
|
b69e47 |
/* set bind creds here so anonymous limits are set */
|
|
|
b69e47 |
bind_credentials_set(pb->pb_conn, authtype, NULL, NULL, NULL, NULL, NULL);
|
|
|
b69e47 |
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
|
|
|
b69e47 |
index a9fd9ec..852b027 100644
|
|
|
b69e47 |
--- a/ldap/servers/slapd/pw_verify.c
|
|
|
b69e47 |
+++ b/ldap/servers/slapd/pw_verify.c
|
|
|
b69e47 |
@@ -50,8 +50,6 @@ pw_verify_root_dn(const char *dn, const Slapi_Value *cred)
|
|
|
b69e47 |
*
|
|
|
b69e47 |
* In the future, this will use the credentials and do mfa.
|
|
|
b69e47 |
*
|
|
|
b69e47 |
- * If you get SLAPI_BIND_SUCCESS or SLAPI_BIND_ANONYMOUS you need to unlock
|
|
|
b69e47 |
- * the backend.
|
|
|
b69e47 |
* All other results, it's already released.
|
|
|
b69e47 |
*/
|
|
|
b69e47 |
int
|
|
|
b69e47 |
@@ -81,10 +79,8 @@ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
|
|
b69e47 |
set_db_default_result_handlers(pb);
|
|
|
b69e47 |
/* now take the dn, and check it */
|
|
|
b69e47 |
rc = (*be->be_bind)(pb);
|
|
|
b69e47 |
- /* now attempt the bind. */
|
|
|
b69e47 |
- if (rc != SLAPI_BIND_SUCCESS && rc != SLAPI_BIND_ANONYMOUS) {
|
|
|
b69e47 |
- slapi_be_Unlock(be);
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
+ slapi_be_Unlock(be);
|
|
|
b69e47 |
+
|
|
|
b69e47 |
return rc;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
--
|
|
|
b69e47 |
2.9.3
|
|
|
b69e47 |
|