|
|
b69e47 |
From 2741a6db134ad40662cfa0233c4542d2d4148997 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 ++++++++++++++++++++++
|
|
|
b69e47 |
ldap/servers/plugins/cos/cos_cache.c | 68 ++++----
|
|
|
b69e47 |
3 files changed, 223 insertions(+), 36 deletions(-)
|
|
|
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
|
|
|
b69e47 |
index 0000000..e69de29
|
|
|
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
|
|
|
b69e47 |
index 0000000..1aac6b8
|
|
|
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
|
|
|
b69e47 |
index 66c6c7f..87d4890 100644
|
|
|
b69e47 |
--- a/ldap/servers/plugins/cos/cos_cache.c
|
|
|
b69e47 |
+++ b/ldap/servers/plugins/cos/cos_cache.c
|
|
|
b69e47 |
@@ -2190,48 +2190,44 @@ bail:
|
|
|
b69e47 |
static int cos_cache_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,
|
|
|
b69e47 |
vattr_type_list_context *type_context,int flags)
|
|
|
b69e47 |
{
|
|
|
b69e47 |
- int ret = 0;
|
|
|
b69e47 |
- int index = 0;
|
|
|
b69e47 |
- cosCache *pCache;
|
|
|
b69e47 |
- char *lastattr = "thisisfakeforcos";
|
|
|
b69e47 |
- int props = 0;
|
|
|
b69e47 |
-
|
|
|
b69e47 |
- slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
|
|
|
b69e47 |
-
|
|
|
b69e47 |
- if(cos_cache_getref((cos_cache **)&pCache) < 1)
|
|
|
b69e47 |
- {
|
|
|
b69e47 |
- /* problems we are hosed */
|
|
|
b69e47 |
- slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
|
|
|
b69e47 |
- goto bail;
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
-
|
|
|
b69e47 |
- while(index < pCache->attrCount )
|
|
|
b69e47 |
- {
|
|
|
b69e47 |
- if(slapi_utf8casecmp(
|
|
|
b69e47 |
- (unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
|
|
|
b69e47 |
- (unsigned char *)lastattr))
|
|
|
b69e47 |
- {
|
|
|
b69e47 |
- lastattr = pCache->ppAttrIndex[index]->pAttrName;
|
|
|
b69e47 |
+ int ret = 0;
|
|
|
b69e47 |
+ int index = 0;
|
|
|
b69e47 |
+ cosCache *pCache;
|
|
|
b69e47 |
+ char *lastattr = "thisisfakeforcos";
|
|
|
b69e47 |
|
|
|
b69e47 |
- if(1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
|
|
|
b69e47 |
- NULL, &props, NULL))
|
|
|
b69e47 |
- {
|
|
|
b69e47 |
- /* entry contains this attr */
|
|
|
b69e47 |
- vattr_type_thang thang = {0};
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
|
|
|
b69e47 |
|
|
|
b69e47 |
- thang.type_name = lastattr;
|
|
|
b69e47 |
- thang.type_flags = props;
|
|
|
b69e47 |
+ if (cos_cache_getref((cos_cache **)&pCache) < 1) {
|
|
|
b69e47 |
+ /* problems we are hosed */
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
|
|
|
b69e47 |
+ goto bail;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
|
|
|
b69e47 |
- slapi_vattrspi_add_type(type_context,&thang,0);
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
- index++;
|
|
|
b69e47 |
- }
|
|
|
b69e47 |
- cos_cache_release(pCache);
|
|
|
b69e47 |
+ while (index < pCache->attrCount) {
|
|
|
b69e47 |
+ int props = 0;
|
|
|
b69e47 |
+ if (slapi_utf8casecmp(
|
|
|
b69e47 |
+ (unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
|
|
|
b69e47 |
+ (unsigned char *)lastattr)) {
|
|
|
b69e47 |
+ lastattr = pCache->ppAttrIndex[index]->pAttrName;
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ if (1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
|
|
|
b69e47 |
+ NULL, &props, NULL)) {
|
|
|
b69e47 |
+ /* entry contains this attr */
|
|
|
b69e47 |
+ vattr_type_thang thang = {0};
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ thang.type_name = lastattr;
|
|
|
b69e47 |
+ thang.type_flags = props;
|
|
|
b69e47 |
+
|
|
|
b69e47 |
+ slapi_vattrspi_add_type(type_context, &thang, 0);
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+ index++;
|
|
|
b69e47 |
+ }
|
|
|
b69e47 |
+ cos_cache_release(pCache);
|
|
|
b69e47 |
|
|
|
b69e47 |
bail:
|
|
|
b69e47 |
|
|
|
b69e47 |
-slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
|
|
|
b69e47 |
+ slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
|
|
|
b69e47 |
return ret;
|
|
|
b69e47 |
}
|
|
|
b69e47 |
|
|
|
b69e47 |
--
|
|
|
b69e47 |
2.9.5
|
|
|
b69e47 |
|