andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
6405db
From 2741a6db134ad40662cfa0233c4542d2d4148997 Mon Sep 17 00:00:00 2001
6405db
From: Mark Reynolds <mreynolds@redhat.com>
6405db
Date: Tue, 3 Oct 2017 17:22:37 -0400
6405db
Subject: [PATCH] Ticket 49389 - unable to retrieve specific cosAttribute when
6405db
 subtree                password policy is configured
6405db
6405db
Bug Description:   If indirect cos is being used and a subtree password
6405db
                   policy is added, th orignal COS attributes aren't always
6405db
                   returned.  The issue is that when the subtree password
6405db
                   policy attribute was encountered during the virtual
6405db
                   attribute processing it set a flag that said the attribute
6405db
                   was operational (which is correct for the password policy
6405db
                   attr: pwdpolicysubentry).
6405db
6405db
                   However, this flag was accidentally carried over to the
6405db
                   following virtual attributes that were being processed.
6405db
                   Which caused those attributes to be seen as operational
6405db
                   which is why it was no longer being returned to the client.
6405db
6405db
Fix Description:   Reset the prop flags before processing the next COS attribute
6405db
6405db
https://pagure.io/389-ds-base/issue/49389
6405db
6405db
Reviewed by: firstyear(Thanks!)
6405db
6405db
(cherry picked from commit 0953e6011368bc29300990e9493ac13e5aba9586)
6405db
---
6405db
 dirsrvtests/tests/suites/cos/__init__.py          |   0
6405db
 dirsrvtests/tests/suites/cos/indirect_cos_test.py | 191 ++++++++++++++++++++++
6405db
 ldap/servers/plugins/cos/cos_cache.c              |  68 ++++----
6405db
 3 files changed, 223 insertions(+), 36 deletions(-)
6405db
 create mode 100644 dirsrvtests/tests/suites/cos/__init__.py
6405db
 create mode 100644 dirsrvtests/tests/suites/cos/indirect_cos_test.py
6405db
6405db
diff --git a/dirsrvtests/tests/suites/cos/__init__.py b/dirsrvtests/tests/suites/cos/__init__.py
6405db
new file mode 100644
6405db
index 0000000..e69de29
6405db
diff --git a/dirsrvtests/tests/suites/cos/indirect_cos_test.py b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
6405db
new file mode 100644
6405db
index 0000000..1aac6b8
6405db
--- /dev/null
6405db
+++ b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
6405db
@@ -0,0 +1,191 @@
6405db
+import logging
6405db
+import pytest
6405db
+import os
6405db
+import ldap
6405db
+import time
6405db
+import subprocess
6405db
+
6405db
+from lib389 import Entry
6405db
+from lib389.idm.user import UserAccounts
6405db
+from lib389.topologies import topology_st as topo
6405db
+from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD, HOST_STANDALONE,
6405db
+                               SERVERID_STANDALONE, PORT_STANDALONE)
6405db
+
6405db
+
6405db
+DEBUGGING = os.getenv("DEBUGGING", default=False)
6405db
+if DEBUGGING:
6405db
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
6405db
+else:
6405db
+    logging.getLogger(__name__).setLevel(logging.INFO)
6405db
+log = logging.getLogger(__name__)
6405db
+
6405db
+TEST_USER_DN = "uid=test_user,ou=people,dc=example,dc=com"
6405db
+OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
6405db
+
6405db
+PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,' \
6405db
+                        'ou=people,dc=example,dc=com",' \
6405db
+                        'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
6405db
+
6405db
+PW_POLICY_CONT_PEOPLE2 = 'cn="cn=nsPwPolicyEntry,' \
6405db
+                        'dc=example,dc=com",' \
6405db
+                        'cn=nsPwPolicyContainerdc=example,dc=com'
6405db
+
6405db
+
6405db
+def check_user(inst):
6405db
+    """Search the test user and make sure it has the execpted attrs
6405db
+    """
6405db
+    try:
6405db
+        entries = inst.search_s('dc=example,dc=com', ldap.SCOPE_SUBTREE, "uid=test_user")
6405db
+        log.debug('user: \n' + str(entries[0]))
6405db
+        assert entries[0].hasAttr('ou'), "Entry is missing ou cos attribute"
6405db
+        assert entries[0].hasAttr('x-department'), "Entry is missing description cos attribute"
6405db
+        assert entries[0].hasAttr('x-en-ou'), "Entry is missing givenname cos attribute"
6405db
+    except ldap.LDAPError as e:
6405db
+        log.fatal('Failed to search for user: ' + str(e))
6405db
+        raise e
6405db
+
6405db
+
6405db
+def setup_subtree_policy(topo):
6405db
+    """Set up subtree password policy
6405db
+    """
6405db
+    try:
6405db
+        topo.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE,
6405db
+                                                'nsslapd-pwpolicy-local',
6405db
+                                                'on')])
6405db
+    except ldap.LDAPError as e:
6405db
+        log.error('Failed to set fine-grained policy: error {}'.format(
6405db
+            e.message['desc']))
6405db
+        raise e
6405db
+
6405db
+    log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
6405db
+    try:
6405db
+        subprocess.call(['%s/ns-newpwpolicy.pl' % topo.standalone.get_sbin_dir(),
6405db
+                         '-D', DN_DM, '-w', PASSWORD,
6405db
+                         '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
6405db
+                         '-S', DEFAULT_SUFFIX, '-Z', SERVERID_STANDALONE])
6405db
+    except subprocess.CalledProcessError as e:
6405db
+        log.error('Failed to create pw policy policy for {}: error {}'.format(
6405db
+            OU_PEOPLE, e.message['desc']))
6405db
+        raise e
6405db
+
6405db
+    log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
6405db
+    try:
6405db
+        topo.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_REPLACE,
6405db
+                                                   'pwdpolicysubentry',
6405db
+                                                   PW_POLICY_CONT_PEOPLE2)])
6405db
+    except ldap.LDAPError as e:
6405db
+        log.error('Failed to pwdpolicysubentry pw policy '
6405db
+                  'policy for {}: error {}'.format(OU_PEOPLE, e.message['desc']))
6405db
+        raise e
6405db
+    time.sleep(1)
6405db
+
6405db
+
6405db
+def setup_indirect_cos(topo):
6405db
+    """Setup indirect COS definition and template
6405db
+    """
6405db
+    cosDef = Entry(('cn=cosDefinition,dc=example,dc=com',
6405db
+                    {'objectclass': ['top', 'ldapsubentry',
6405db
+                                     'cossuperdefinition',
6405db
+                                     'cosIndirectDefinition'],
6405db
+                     'cosAttribute': ['ou merge-schemes',
6405db
+                                      'x-department merge-schemes',
6405db
+                                      'x-en-ou merge-schemes'],
6405db
+                     'cosIndirectSpecifier': 'seeAlso',
6405db
+                     'cn': 'cosDefinition'}))
6405db
+
6405db
+    cosTemplate = Entry(('cn=cosTemplate,dc=example,dc=com',
6405db
+                         {'objectclass': ['top',
6405db
+                                          'extensibleObject',
6405db
+                                          'cosTemplate'],
6405db
+                          'ou': 'My COS Org',
6405db
+                          'x-department': 'My COS x-department',
6405db
+                          'x-en-ou': 'my COS x-en-ou',
6405db
+                          'cn': 'cosTemplate'}))
6405db
+    try:
6405db
+        topo.standalone.add_s(cosDef)
6405db
+        topo.standalone.add_s(cosTemplate)
6405db
+    except ldap.LDAPError as e:
6405db
+        log.fatal('Failed to add cos: error ' + str(e))
6405db
+        raise e
6405db
+    time.sleep(1)
6405db
+
6405db
+
6405db
+@pytest.fixture(scope="module")
6405db
+def setup(topo, request):
6405db
+    """Add schema, and test user
6405db
+    """
6405db
+    log.info('Add custom schema...')
6405db
+    try:
6405db
+        ATTR_1 = ("( 1.3.6.1.4.1.409.389.2.189 NAME 'x-department' " +
6405db
+                  "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
6405db
+        ATTR_2 = ("( 1.3.6.1.4.1.409.389.2.187 NAME 'x-en-ou' " +
6405db
+                  "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
6405db
+        OC = ("( xPerson-oid NAME 'xPerson' DESC '' SUP person STRUCTURAL MAY " +
6405db
+              "( x-department $ x-en-ou ) X-ORIGIN 'user defined' )")
6405db
+        topo.standalone.modify_s("cn=schema", [(ldap.MOD_ADD, 'attributeTypes', ATTR_1),
6405db
+                                               (ldap.MOD_ADD, 'attributeTypes', ATTR_2),
6405db
+                                               (ldap.MOD_ADD, 'objectClasses', OC)])
6405db
+    except ldap.LDAPError as e:
6405db
+        log.fatal('Failed to add custom schema')
6405db
+        raise e
6405db
+    time.sleep(1)
6405db
+
6405db
+    log.info('Add test user...')
6405db
+    users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
6405db
+
6405db
+    user_properties = {
6405db
+        'uid': 'test_user',
6405db
+        'cn': 'test user',
6405db
+        'sn': 'user',
6405db
+        'uidNumber': '1000',
6405db
+        'gidNumber': '2000',
6405db
+        'homeDirectory': '/home/test_user',
6405db
+        'seeAlso': 'cn=cosTemplate,dc=example,dc=com'
6405db
+    }
6405db
+    users.create(properties=user_properties)
6405db
+    try:
6405db
+        topo.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_ADD,
6405db
+                                                 'objectclass',
6405db
+                                                 'xPerson')])
6405db
+    except ldap.LDAPError as e:
6405db
+        log.fatal('Failed to add objectclass to user')
6405db
+        raise e
6405db
+
6405db
+    # Setup COS
6405db
+    log.info("Setup indirect COS...")
6405db
+    setup_indirect_cos(topo)
6405db
+
6405db
+
6405db
+def test_indirect_cos(topo, setup):
6405db
+    """Test indirect cos
6405db
+
6405db
+    :id: 890d5929-7d52-4a56-956e-129611b4649a
6405db
+    :setup: standalone
6405db
+    :steps:
6405db
+        1. Test cos is working for test user
6405db
+        2. Add subtree password policy
6405db
+        3. Test cos is working for test user
6405db
+    :expectedresults:
6405db
+        1. User has expected cos attrs
6405db
+        2. Substree password policy setup is successful
6405db
+        3  User still has expected cos attrs
6405db
+    """
6405db
+
6405db
+    # Step 1 - Search user and see if the COS attrs are included
6405db
+    log.info('Checking user...')
6405db
+    check_user(topo.standalone)
6405db
+
6405db
+    # Step 2 - Add subtree password policy (Second COS - operational attribute)
6405db
+    setup_subtree_policy(topo)
6405db
+
6405db
+    # Step 3 - Check user again now hat we have a mix of vattrs
6405db
+    log.info('Checking user...')
6405db
+    check_user(topo.standalone)
6405db
+
6405db
+
6405db
+if __name__ == '__main__':
6405db
+    # Run isolated
6405db
+    # -s for DEBUG mode
6405db
+    CURRENT_FILE = os.path.realpath(__file__)
6405db
+    pytest.main("-s %s" % CURRENT_FILE)
6405db
+
6405db
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
6405db
index 66c6c7f..87d4890 100644
6405db
--- a/ldap/servers/plugins/cos/cos_cache.c
6405db
+++ b/ldap/servers/plugins/cos/cos_cache.c
6405db
@@ -2190,48 +2190,44 @@ bail:
6405db
 static int cos_cache_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,
6405db
 							vattr_type_list_context *type_context,int flags)
6405db
 {
6405db
-	int ret = 0;
6405db
-	int index = 0;
6405db
-	cosCache *pCache;
6405db
-	char *lastattr = "thisisfakeforcos";
6405db
-	int props = 0;
6405db
-
6405db
-	slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
6405db
-	
6405db
-	if(cos_cache_getref((cos_cache **)&pCache) < 1)
6405db
-	{
6405db
-		/* problems we are hosed */
6405db
-		slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
6405db
-		goto bail;
6405db
-	}
6405db
-
6405db
-	while(index < pCache->attrCount )
6405db
-	{
6405db
-		if(slapi_utf8casecmp(
6405db
-				(unsigned char *)pCache->ppAttrIndex[index]->pAttrName, 
6405db
-				(unsigned char *)lastattr))
6405db
-		{
6405db
-			lastattr = pCache->ppAttrIndex[index]->pAttrName;
6405db
+    int ret = 0;
6405db
+    int index = 0;
6405db
+    cosCache *pCache;
6405db
+    char *lastattr = "thisisfakeforcos";
6405db
 
6405db
-			if(1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
6405db
-											 NULL, &props, NULL))
6405db
-			{
6405db
-				/* entry contains this attr */
6405db
-				vattr_type_thang thang = {0};
6405db
+    slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
6405db
 
6405db
-				thang.type_name = lastattr;
6405db
-				thang.type_flags = props;
6405db
+    if (cos_cache_getref((cos_cache **)&pCache) < 1) {
6405db
+        /* problems we are hosed */
6405db
+        slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
6405db
+        goto bail;
6405db
+    }
6405db
 
6405db
-				slapi_vattrspi_add_type(type_context,&thang,0);
6405db
-			}
6405db
-		}
6405db
-		index++;
6405db
-	}
6405db
-	cos_cache_release(pCache);
6405db
+    while (index < pCache->attrCount) {
6405db
+        int props = 0;
6405db
+        if (slapi_utf8casecmp(
6405db
+                (unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
6405db
+                (unsigned char *)lastattr)) {
6405db
+            lastattr = pCache->ppAttrIndex[index]->pAttrName;
6405db
+
6405db
+            if (1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
6405db
+                                          NULL, &props, NULL)) {
6405db
+                /* entry contains this attr */
6405db
+                vattr_type_thang thang = {0};
6405db
+
6405db
+                thang.type_name = lastattr;
6405db
+                thang.type_flags = props;
6405db
+
6405db
+                slapi_vattrspi_add_type(type_context, &thang, 0);
6405db
+            }
6405db
+        }
6405db
+        index++;
6405db
+    }
6405db
+    cos_cache_release(pCache);
6405db
 
6405db
 bail:
6405db
 
6405db
-slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
6405db
+    slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
6405db
 	return ret;
6405db
 }
6405db
 
6405db
-- 
6405db
2.9.5
6405db