Blame SOURCES/0005-Ticket-49389-unable-to-retrieve-specific-cosAttribut.patch

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