Blame SOURCES/0044-Ticket-49246-ns-slapd-crashes-in-role-cache-creation.patch

6f51e1
From 18491418e661b5dc1b9ca4c6bb4adb85bfb0bf0d Mon Sep 17 00:00:00 2001
6f51e1
From: Mark Reynolds <mreynolds@redhat.com>
6f51e1
Date: Tue, 9 May 2017 16:31:52 -0400
6f51e1
Subject: [PATCH] Ticket 49246 - ns-slapd crashes in role cache creation
6f51e1
6f51e1
Bug Description:  Using a nested filter for a filtered role can
6f51e1
                  cause a crash.  This was due to the way the filter
6f51e1
                  was being checked by the roles plugin.
6f51e1
6f51e1
Fix Description:  Properly resurse over a filter.
6f51e1
6f51e1
https://pagure.io/389-ds-base/issue/49246
6f51e1
6f51e1
Reviewed by: firstyear & tbordaz(Thanks!!)
6f51e1
6f51e1
(cherry picked from commit 54e4fca35899550e0c25b25e7f7c756302d258ce)
6f51e1
---
6f51e1
 dirsrvtests/tests/tickets/ticket49122_test.py | 61 ++++++++++++++++++---------
6f51e1
 ldap/servers/plugins/roles/roles_cache.c      | 34 +++++++++++----
6f51e1
 2 files changed, 66 insertions(+), 29 deletions(-)
6f51e1
6f51e1
diff --git a/dirsrvtests/tests/tickets/ticket49122_test.py b/dirsrvtests/tests/tickets/ticket49122_test.py
6f51e1
index ff1e8d1..0945122 100644
6f51e1
--- a/dirsrvtests/tests/tickets/ticket49122_test.py
6f51e1
+++ b/dirsrvtests/tests/tickets/ticket49122_test.py
6f51e1
@@ -2,8 +2,7 @@ import time
6f51e1
 import ldap
6f51e1
 import logging
6f51e1
 import pytest
6f51e1
-from lib389 import DirSrv, Entry, tools, tasks
6f51e1
-from lib389.tools import DirSrvTools
6f51e1
+from lib389 import Entry
6f51e1
 from lib389._constants import *
6f51e1
 from lib389.properties import *
6f51e1
 from lib389.tasks import *
6f51e1
@@ -19,6 +18,15 @@ log = logging.getLogger(__name__)
6f51e1
 
6f51e1
 USER_DN = 'uid=user,' + DEFAULT_SUFFIX
6f51e1
 ROLE_DN = 'cn=Filtered_Role_That_Includes_Empty_Role,' + DEFAULT_SUFFIX
6f51e1
+filters = ['nsrole=cn=empty,dc=example,dc=com',
6f51e1
+           '(nsrole=cn=empty,dc=example,dc=com)',
6f51e1
+           '(&(nsrole=cn=empty,dc=example,dc=com))',
6f51e1
+           '(!(nsrole=cn=empty,dc=example,dc=com))',
6f51e1
+           '(&(|(objectclass=person)(sn=app*))(userpassword=*))',
6f51e1
+           '(&(|(objectclass=person)(nsrole=cn=empty,dc=example,dc=com))(userpassword=*))',
6f51e1
+           '(&(|(nsrole=cn=empty,dc=example,dc=com)(sn=app*))(userpassword=*))',
6f51e1
+           '(&(|(objectclass=person)(sn=app*))(nsrole=cn=empty,dc=example,dc=com))',
6f51e1
+           '(&(|(&(cn=*)(objectclass=person)(nsrole=cn=empty,dc=example,dc=com)))(uid=*))']
6f51e1
 
6f51e1
 
6f51e1
 def test_ticket49122(topo):
6f51e1
@@ -29,18 +37,6 @@ def test_ticket49122(topo):
6f51e1
     topo.standalone.plugins.enable(name=PLUGIN_ROLES)
6f51e1
     topo.standalone.restart()
6f51e1
 
6f51e1
-    # Add invalid role
6f51e1
-    try:
6f51e1
-        topo.standalone.add_s(Entry((
6f51e1
-            ROLE_DN, {'objectclass': ['top', 'ldapsubentry', 'nsroledefinition',
6f51e1
-                                      'nscomplexroledefinition', 'nsfilteredroledefinition'],
6f51e1
-                      'cn': 'Filtered_Role_That_Includes_Empty_Role',
6f51e1
-                      'nsRoleFilter': '(!(nsrole=cn=This_Is_An_Empty_Managed_NsRoleDefinition,dc=example,dc=com))',
6f51e1
-                      'description': 'A filtered role with filter that will crash the server'})))
6f51e1
-    except ldap.LDAPError as e:
6f51e1
-        topo.standalone.log.fatal('Failed to add filtered role: error ' + e.message['desc'])
6f51e1
-        assert False
6f51e1
-
6f51e1
     # Add test user
6f51e1
     try:
6f51e1
         topo.standalone.add_s(Entry((
6f51e1
@@ -51,16 +47,39 @@ def test_ticket49122(topo):
6f51e1
         assert False
6f51e1
 
6f51e1
     if DEBUGGING:
6f51e1
-        # Add debugging steps(if any)...
6f51e1
         print("Attach gdb")
6f51e1
         time.sleep(20)
6f51e1
 
6f51e1
-    # Search for the role
6f51e1
-    try:
6f51e1
-        topo.standalone.search_s(USER_DN, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nsrole'])
6f51e1
-    except ldap.LDAPError as e:
6f51e1
-        topo.standalone.log.fatal('Search failed: error ' + str(e))
6f51e1
-        assert False
6f51e1
+    # Loop over filters
6f51e1
+    for role_filter in filters:
6f51e1
+        log.info('Testing filter: ' + role_filter)
6f51e1
+
6f51e1
+        # Add invalid role
6f51e1
+        try:
6f51e1
+            topo.standalone.add_s(Entry((
6f51e1
+                ROLE_DN, {'objectclass': ['top', 'ldapsubentry', 'nsroledefinition',
6f51e1
+                                          'nscomplexroledefinition', 'nsfilteredroledefinition'],
6f51e1
+                          'cn': 'Filtered_Role_That_Includes_Empty_Role',
6f51e1
+                          'nsRoleFilter': role_filter,
6f51e1
+                          'description': 'A filtered role with filter that will crash the server'})))
6f51e1
+        except ldap.LDAPError as e:
6f51e1
+            topo.standalone.log.fatal('Failed to add filtered role: error ' + e.message['desc'])
6f51e1
+            assert False
6f51e1
+
6f51e1
+        # Search for the role
6f51e1
+        try:
6f51e1
+            topo.standalone.search_s(USER_DN, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nsrole'])
6f51e1
+        except ldap.LDAPError as e:
6f51e1
+            topo.standalone.log.fatal('Search failed: error ' + str(e))
6f51e1
+            assert False
6f51e1
+
6f51e1
+        # Cleanup
6f51e1
+        try:
6f51e1
+            topo.standalone.delete_s(ROLE_DN)
6f51e1
+        except ldap.LDAPError as e:
6f51e1
+            topo.standalone.log.fatal('delete failed: error ' + str(e))
6f51e1
+            assert False
6f51e1
+        time.sleep(1)
6f51e1
 
6f51e1
     topo.standalone.log.info('Test Passed')
6f51e1
 
6f51e1
diff --git a/ldap/servers/plugins/roles/roles_cache.c b/ldap/servers/plugins/roles/roles_cache.c
6f51e1
index 4f27c4c..3697eaa 100644
6f51e1
--- a/ldap/servers/plugins/roles/roles_cache.c
6f51e1
+++ b/ldap/servers/plugins/roles/roles_cache.c
6f51e1
@@ -1073,20 +1073,38 @@ static int roles_cache_create_role_under(roles_cache_def** roles_cache_suffix, S
6f51e1
 }
6f51e1
 
6f51e1
 /*
6f51e1
- * Check that we are not using nsrole in the filter
6f51e1
+ * Check that we are not using nsrole in the filter, recurse over all the
6f51e1
+ * nested filters.
6f51e1
  */
6f51e1
 static int roles_check_filter(Slapi_Filter *filter_list)
6f51e1
 {
6f51e1
 	Slapi_Filter  *f;
6f51e1
 	char *type = NULL;
6f51e1
 
6f51e1
-	for ( f = slapi_filter_list_first( filter_list );
6f51e1
-	          f != NULL;
6f51e1
-	          f = slapi_filter_list_next( filter_list, f ) )
6f51e1
-	{
6f51e1
-		slapi_filter_get_attribute_type(f, &type);
6f51e1
-		if (strcasecmp(type, NSROLEATTR) == 0){
6f51e1
-			return -1;
6f51e1
+	f = slapi_filter_list_first( filter_list );
6f51e1
+	if (f == NULL){
6f51e1
+		/* Single filter */
6f51e1
+		if (slapi_filter_get_attribute_type(filter_list, &type) == 0){
6f51e1
+			if (strcasecmp(type, NSROLEATTR) == 0){
6f51e1
+				return -1;
6f51e1
+			}
6f51e1
+		}
6f51e1
+	}
6f51e1
+	for ( ; f != NULL; f = slapi_filter_list_next(filter_list, f) ){
6f51e1
+		/* Complex filter */
6f51e1
+		if (slapi_filter_list_first(f)) {
6f51e1
+			/* Another filter list - recurse */
6f51e1
+			if (roles_check_filter(f) == -1){
6f51e1
+				/* Done, break out */
6f51e1
+				return -1;
6f51e1
+			}
6f51e1
+		} else {
6f51e1
+			/* Not a filter list, so check the type */
6f51e1
+			if (slapi_filter_get_attribute_type(f, &type) == 0){
6f51e1
+				if (strcasecmp(type, NSROLEATTR) == 0){
6f51e1
+					return -1;
6f51e1
+				}
6f51e1
+			}
6f51e1
 		}
6f51e1
 	}
6f51e1
 
6f51e1
-- 
6f51e1
2.9.4
6f51e1