Blob Blame Raw
From 3d1a6717b4b8c11dda68dd3d1a923acb2e6c5eeb Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Wed, 17 Aug 2016 16:46:47 +0200
Subject: [PATCH 35/35] Ticket 48956 ns-accountstatus.pl showing "activated"
 user even if it is inactivated

Bug Description:
    If the account policy DN is long (suffix is long), it is fold on several lines.
    So when looking for it, the base DN is invalid and fail to retrieve it and the limit value.

Fix Description:
    Change the DSutil search to be in no fold

https://fedorahosted.org/389/ticket/48956

Reviewed by: Noriko Hosoi (Thanks Noriko)

Platforms tested: F23

Flag Day: no

Doc impact: no

(cherry picked from commit 3cce9f9188a38e1a5043c9659ecbc5955ddb0242)
---
 dirsrvtests/tests/tickets/ticket48956_test.py | 167 ++++++++++++++++++++++++++
 ldap/admin/src/scripts/DSUtil.pm.in           |  34 +++---
 2 files changed, 185 insertions(+), 16 deletions(-)
 create mode 100644 dirsrvtests/tests/tickets/ticket48956_test.py

diff --git a/dirsrvtests/tests/tickets/ticket48956_test.py b/dirsrvtests/tests/tickets/ticket48956_test.py
new file mode 100644
index 0000000..291dd4e
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket48956_test.py
@@ -0,0 +1,167 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+import subprocess
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+
+
+DEBUGGING = False
+
+RDN_LONG_SUFFIX = 'this'
+LONG_SUFFIX = "dc=%s,dc=is,dc=a,dc=very,dc=long,dc=suffix,dc=so,dc=long,dc=suffix,dc=extremely,dc=long,dc=suffix" % RDN_LONG_SUFFIX
+LONG_SUFFIX_BE = 'ticket48956'
+
+
+ACCT_POLICY_PLUGIN_DN = 'cn=%s,cn=plugins,cn=config' % PLUGIN_ACCT_POLICY
+ACCT_POLICY_CONFIG_DN = 'cn=config,%s' % ACCT_POLICY_PLUGIN_DN
+
+
+INACTIVITY_LIMIT = '9'
+SEARCHFILTER = '(objectclass=*)'
+
+TEST_USER = 'ticket48956user'
+TEST_USER_PW = '%s' % TEST_USER
+
+if DEBUGGING:
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+    logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+
+class TopologyStandalone(object):
+    """The DS Topology Class"""
+    def __init__(self, standalone):
+        """Init"""
+        standalone.open()
+        self.standalone = standalone
+
+
+@pytest.fixture(scope="module")
+def topology(request):
+    """Create DS Deployment"""
+
+    # Creating standalone instance ...
+    if DEBUGGING:
+        standalone = DirSrv(verbose=True)
+    else:
+        standalone = DirSrv(verbose=False)
+    args_instance[SER_HOST] = HOST_STANDALONE
+    args_instance[SER_PORT] = PORT_STANDALONE
+    args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+    args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+    args_standalone = args_instance.copy()
+    standalone.allocate(args_standalone)
+    instance_standalone = standalone.exists()
+    if instance_standalone:
+        standalone.delete()
+    standalone.create()
+    standalone.open()
+
+    def fin():
+        """If we are debugging just stop the instances, otherwise remove them
+        """
+        if DEBUGGING:
+            standalone.stop()
+        else:
+            standalone.delete()
+    request.addfinalizer(fin)
+
+    return TopologyStandalone(standalone)
+
+def _check_status(topology, user, expected):
+    nsaccountstatus = '%s/sbin/ns-accountstatus.pl' % topology.standalone.prefix
+    proc = subprocess.Popen([nsaccountstatus, '-Z', 'standalone', '-D', DN_DM, '-w', PASSWORD, '-p', str(topology.standalone.port), '-I', user], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+    found = False
+    while True:
+        l = proc.stdout.readline()
+        log.info("output: %s" % l)
+        if l == "":
+            break
+        if expected in l:
+            found = True
+            break
+    return found
+
+def _check_inactivity(topology, mysuffix):
+    ACCT_POLICY_DN = 'cn=Account Inactivation Policy,%s' % mysuffix
+    log.info("\n######################### Adding Account Policy entry: %s ######################\n" % ACCT_POLICY_DN)
+    topology.standalone.add_s(Entry((ACCT_POLICY_DN, {'objectclass': "top ldapsubentry extensibleObject accountpolicy".split(),
+                                                      'accountInactivityLimit': INACTIVITY_LIMIT})))
+    TEST_USER_DN = 'uid=%s,%s' % (TEST_USER, mysuffix)
+    log.info("\n######################### Adding Test User entry: %s ######################\n" % TEST_USER_DN)
+    topology.standalone.add_s(Entry((TEST_USER_DN, {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+                                                    'cn': TEST_USER,
+                                                    'sn': TEST_USER,
+                                                    'givenname': TEST_USER,
+                                                    'userPassword': TEST_USER_PW,
+                                                    'acctPolicySubentry': ACCT_POLICY_DN})))
+
+    # Setting the lastLoginTime
+    try:
+        topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PW)
+    except ldap.CONSTRAINT_VIOLATION as e:
+        log.error('CONSTRAINT VIOLATION ' + e.message['desc'])
+    topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+
+    assert(_check_status(topology, TEST_USER_DN, '- activated'))
+
+    time.sleep(int(INACTIVITY_LIMIT) + 5)
+    assert(_check_status(topology, TEST_USER_DN, '- inactivated (inactivity limit exceeded'))
+
+def test_ticket48956(topology):
+    """Write your testcase here...
+
+    Also, if you need any testcase initialization,
+    please, write additional fixture for that(include finalizer).
+
+    """
+
+    topology.standalone.modify_s(ACCT_POLICY_PLUGIN_DN, [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', ACCT_POLICY_CONFIG_DN)])
+
+    topology.standalone.modify_s(ACCT_POLICY_CONFIG_DN, [(ldap.MOD_REPLACE, 'alwaysrecordlogin', 'yes'),
+                                                         (ldap.MOD_REPLACE, 'stateattrname', 'lastLoginTime'),
+                                                         (ldap.MOD_REPLACE, 'altstateattrname', 'createTimestamp'),
+                                                         (ldap.MOD_REPLACE, 'specattrname', 'acctPolicySubentry'),
+                                                         (ldap.MOD_REPLACE, 'limitattrname', 'accountInactivityLimit')])
+
+    # Enable the plugins
+    topology.standalone.plugins.enable(name=PLUGIN_ACCT_POLICY)
+
+    topology.standalone.restart(timeout=10)
+
+    # Check inactivity on standard suffix (short)
+    _check_inactivity(topology, SUFFIX)
+
+    # Check inactivity on a long suffix
+    topology.standalone.backend.create(LONG_SUFFIX, {BACKEND_NAME: LONG_SUFFIX_BE})
+    topology.standalone.mappingtree.create(LONG_SUFFIX, bename=LONG_SUFFIX_BE)
+    topology.standalone.add_s(Entry((LONG_SUFFIX, {
+                                            'objectclass': "top domain".split(),
+                                            'dc': RDN_LONG_SUFFIX})))
+    _check_inactivity(topology, LONG_SUFFIX)
+
+
+    if DEBUGGING:
+        # Add debugging steps(if any)...
+        pass
+
+    log.info('Test PASSED')
+
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
+
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
index f53f0c0..756d6ea 100644
--- a/ldap/admin/src/scripts/DSUtil.pm.in
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
@@ -1201,8 +1201,10 @@ sub get_info {
     my $toollib = `ldapsearch -V 2>&1`;
     if ($toollib =~ /OpenLDAP/) { 
         $info{openldap} = "yes";
+        $info{nofold} = "-o ldif-wrap=no";
     } else {
         $info{openldap} = "no";
+        $info{nofold} = "-T";
     }
     
     #
@@ -1537,10 +1539,10 @@ sub ldapsrch {
             print "STARTTLS)\n";
         }
         if($info{openldap} eq "yes"){
-            $search = "ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw " .
+            $search = "ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
                       "$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         } else {
-            $search = "ldapsearch -ZZZ -P \"$info{certdir}\" -p $info{port} -h $info{host} -D \"$info{rootdn}\" " .
+            $search = "ldapsearch -ZZZ -P \"$info{certdir}\" -p $info{port} -h $info{host} -D \"$info{rootdn}\" $info{nofold} " .
                       "-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         }  
     } elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){ 
@@ -1551,10 +1553,10 @@ sub ldapsrch {
             print "LDAPS)\n";
         }
         if($info{openldap} eq "yes"){
-            $search = "ldapsearch -x -LLL -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" " .
+            $search = "ldapsearch -x -LLL -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" $info{nofold} " .
                       "-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         } else {
-            $search = "ldapsearch -Z -P \"$info{certdir}\" -p $info{secure_port} -h $info{host} -D \"$info{rootdn}\" " .
+            $search = "ldapsearch -Z -P \"$info{certdir}\" -p $info{secure_port} -h $info{host} -D \"$info{rootdn}\" $info{nofold} " .
                       "-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         } 
     } elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){  
@@ -1562,10 +1564,10 @@ sub ldapsrch {
         # LDAPI
         #
         if ($< == 0 && $info{autobind} eq "on"){
-            $search = "ldapsearch  -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL " .
+            $search = "ldapsearch  -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL $info{nofold} " .
                   "$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} 2>/dev/null";
         } else {
-            $search = "ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw " .
+            $search = "ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
                   "$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         }
     } else {
@@ -1576,10 +1578,10 @@ sub ldapsrch {
             print "LDAP)\n";
         }
         if($info{openldap} eq "yes"){
-            $search = "ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw " .
+            $search = "ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
                   "$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         } else {
-            $search = "ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw " .
+            $search = "ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
                   "$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
         }
     }
@@ -1611,9 +1613,9 @@ sub ldapsrch_ext {
             print "STARTTLS)\n";
         }
         if($info{openldap} eq "yes"){
-            return `ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         } else {
-            return `ldapsearch -ZZZ -P $info{certdir} -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -ZZZ -P $info{certdir} -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         }     
     } elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){ 
         # 
@@ -1623,18 +1625,18 @@ sub ldapsrch_ext {
             print "LDAPS)\n";
         }
         if($info{openldap} eq "yes"){
-            return `ldapsearch -x -LLL -H ldaps://$info{host}:$info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -x -LLL -H ldaps://$info{host}:$info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args}  -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         } else {
-            return `ldapsearch -Z -P $info{certdir} -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -Z -P $info{certdir} -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         }
     } elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){  
         # 
         # LDAPI
         #
         if ($< == 0 && $info{autobind} eq "on"){
-            return `ldapsearch -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect} 2>/dev/null`;
+            return `ldapsearch -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect} 2>/dev/null`;
         } else {
-            return `ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         }
     } else {
         # 
@@ -1644,9 +1646,9 @@ sub ldapsrch_ext {
             print "LDAP)\n";
         }
         if($info{openldap} eq "yes"){
-            return `ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         } else {
-            return `ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
+            return `ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
         }
     }
 }
-- 
2.4.11