[Pkg-fedora-ds-maintainers] 389-ds-base: Changes to 'upstream'

Timo Aaltonen tjaalton at moszumanska.debian.org
Mon Aug 29 07:56:43 UTC 2016


 Makefile.am                                                  |    3 
 Makefile.in                                                  |    3 
 VERSION.sh                                                   |    2 
 dirsrvtests/create_test.py                                   |  171 +
 dirsrvtests/tests/suites/paged_results/paged_results_test.py | 1138 ++++++++++-
 dirsrvtests/tests/suites/paged_results/sss_control.py        |  127 +
 dirsrvtests/tests/suites/password/pwp_history_test.py        |  264 ++
 dirsrvtests/tests/tickets/ticket1347760_test.py              |  440 ++++
 dirsrvtests/tests/tickets/ticket47462_test.py                |  160 +
 dirsrvtests/tests/tickets/ticket48109_test.py                |   41 
 dirsrvtests/tests/tickets/ticket48497_test.py                |    4 
 dirsrvtests/tests/tickets/ticket48745_test.py                |    2 
 dirsrvtests/tests/tickets/ticket48746_test.py                |    2 
 dirsrvtests/tests/tickets/ticket48755_test.py                |  261 ++
 dirsrvtests/tests/tickets/ticket48798_test.py                |  141 +
 dirsrvtests/tests/tickets/ticket48799_test.py                |  170 +
 dirsrvtests/tests/tickets/ticket48808_test.py                |  337 +++
 ldap/admin/src/logconv.pl                                    |   60 
 ldap/admin/src/scripts/91reindex.pl.in                       |  103 
 ldap/admin/src/scripts/91subtreereindex.pl                   |    8 
 ldap/admin/src/scripts/repl-monitor.pl.in                    |   72 
 ldap/admin/src/scripts/setup-ds.res.in                       |    1 
 ldap/ldif/template-dse.ldif.in                               |    1 
 ldap/schema/01core389.ldif                                   |    6 
 ldap/servers/plugins/replication/cl5_api.c                   |  171 -
 ldap/servers/plugins/replication/cl5_clcache.c               |  292 +-
 ldap/servers/plugins/replication/cl5_clcache.h               |    2 
 ldap/servers/plugins/replication/repl5.h                     |   14 
 ldap/servers/plugins/replication/repl5_inc_protocol.c        |  106 -
 ldap/servers/plugins/replication/repl5_plugins.c             |    3 
 ldap/servers/plugins/replication/repl5_replica.c             |  137 +
 ldap/servers/plugins/replication/repl5_replica_config.c      |   32 
 ldap/servers/plugins/replication/repl5_tot_protocol.c        |  169 +
 ldap/servers/plugins/replication/repl_globals.c              |    1 
 ldap/servers/slapd/back-ldbm/back-ldbm.h                     |    6 
 ldap/servers/slapd/back-ldbm/dblayer.c                       |    5 
 ldap/servers/slapd/back-ldbm/dn2entry.c                      |   17 
 ldap/servers/slapd/back-ldbm/filterindex.c                   |   21 
 ldap/servers/slapd/back-ldbm/findentry.c                     |  139 +
 ldap/servers/slapd/back-ldbm/idl_new.c                       |   87 
 ldap/servers/slapd/back-ldbm/import-threads.c                |    7 
 ldap/servers/slapd/back-ldbm/index.c                         |   22 
 ldap/servers/slapd/back-ldbm/init.c                          |    2 
 ldap/servers/slapd/back-ldbm/ldbm_add.c                      |   21 
 ldap/servers/slapd/back-ldbm/ldbm_attr.c                     |   18 
 ldap/servers/slapd/back-ldbm/ldbm_bind.c                     |   11 
 ldap/servers/slapd/back-ldbm/ldbm_compare.c                  |    2 
 ldap/servers/slapd/back-ldbm/ldbm_delete.c                   |    9 
 ldap/servers/slapd/back-ldbm/ldbm_index_config.c             |    6 
 ldap/servers/slapd/back-ldbm/ldbm_modify.c                   |   30 
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c                   |   17 
 ldap/servers/slapd/back-ldbm/ldbm_search.c                   |   35 
 ldap/servers/slapd/back-ldbm/misc.c                          |    3 
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h               |   14 
 ldap/servers/slapd/back-ldbm/vlv_srch.c                      |    2 
 ldap/servers/slapd/bind.c                                    |  126 -
 ldap/servers/slapd/daemon.c                                  |  226 --
 ldap/servers/slapd/defbackend.c                              |   82 
 ldap/servers/slapd/entry.c                                   |    4 
 ldap/servers/slapd/modify.c                                  |    4 
 ldap/servers/slapd/opshared.c                                |   11 
 ldap/servers/slapd/pagedresults.c                            |    5 
 ldap/servers/slapd/pblock.c                                  |   13 
 ldap/servers/slapd/proto-slap.h                              |    1 
 ldap/servers/slapd/pw.c                                      |   33 
 ldap/servers/slapd/result.c                                  |   27 
 ldap/servers/slapd/saslbind.c                                |    4 
 ldap/servers/slapd/schema.c                                  |   66 
 ldap/servers/slapd/slap.h                                    |    5 
 ldap/servers/slapd/slapi-plugin.h                            |    9 
 ldap/servers/slapd/slapi-private.h                           |    1 
 ldap/servers/slapd/ssl.c                                     |   77 
 ldap/servers/slapd/task.c                                    |  346 +++
 ldap/servers/slapd/tools/ldclt/ldcltU.c                      |    2 
 man/man1/ldclt.1                                             |    2 
 man/man1/repl-monitor.1                                      |   58 
 wrappers/systemd.template.sysconfig                          |    3 
 77 files changed, 5054 insertions(+), 969 deletions(-)

New commits:
commit 695f0b73e9a4e6ce682526265fb1ec7f18ba7970
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Thu Aug 11 15:11:57 2016 -0700

    bump version to 1.3.4.14

diff --git a/VERSION.sh b/VERSION.sh
index 42e3e7e..0309bf5 100644
--- a/VERSION.sh
+++ b/VERSION.sh
@@ -10,7 +10,7 @@ vendor="389 Project"
 # PACKAGE_VERSION is constructed from these
 VERSION_MAJOR=1
 VERSION_MINOR=3
-VERSION_MAINT=4.13
+VERSION_MAINT=4.14
 # if this is a PRERELEASE, set VERSION_PREREL
 # otherwise, comment it out
 # be sure to include the dot prefix in the prerel

commit c5521864b2996db2ae18f24ef34acb6aec92ad78
Author: Ludwig Krispenz <lkrispen at redhat.com>
Date:   Thu Aug 4 11:45:49 2016 -0700

    Bug 1347760 - CVE-2016-4992 389-ds-base: Information disclosure via repeated use of LDAP ADD operation, etc.
    
    Description: do not overwrite rc used to decide if bind was successful.
    When the bind is through ldapi/autobind, an entry does not exist to be
    checked with slapi_check_account_lock.  In that case, a variable rc is
    not supposed to be modified which confuses the following code path.
    
    Reviewed by nhosoi at redhat.com.
    
    (cherry picked from commit caa351ae0cc81cbf2309a43c5f74b359cda152d0)

diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 8f5375a..399eaf7 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -775,10 +775,12 @@ do_bind( Slapi_PBlock *pb )
                      */
                     if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
                         bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(sdn));
-                        rc = slapi_check_account_lock(pb, bind_target_entry, pw_response_requested, 1, 1);
-                        if (1 == rc) { /* account is locked */
+                        myrc = slapi_check_account_lock(pb, bind_target_entry, pw_response_requested, 1, 1);
+                        if (1 == myrc) { /* account is locked */
+                            rc = myrc;
                             goto account_locked;
                         }
+                        myrc = 0;
                     }
                     if (!auto_bind) {
                         /* 

commit e88a1ba32ec1b02f278e7febef6024f4e6bf9f55
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Tue Jul 26 18:08:38 2016 -0700

    Bug 1347760 - CVE-2016-4992 389-ds-base: Information disclosure via repeated use of LDAP ADD operation, etc.
    
    Description:
    1. When an account is inactivated, the error UNWILLING_TO_PERFORM with
       the inactivated message should be returned only when the bind is
       successful.
    2. When SASL bind fails, instead of returning the cause of the failure
       directly to the client, but logging it in the access log.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1347760
    
    Reviewed by wibrown at redhat.com (Thank you, William!)
    
    (cherry picked from commit b8767d510d11c7cbfede24daaae3348b9f028f47)

diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 6763fc3..8f5375a 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -720,25 +720,6 @@ do_bind( Slapi_PBlock *pb )
                     }
                 }
             }
-
-            /*
-             * Is this account locked ?
-             *	could be locked through the account inactivation
-             *	or by the password policy
-             *
-             * rc=0: account not locked
-             * rc=1: account locked, can not bind, result has been sent
-             * rc!=0 and rc!=1: error. Result was not sent, lets be_bind
-             * 		deal with it.
-             *
-             */
-
-            /* get the entry now, so that we can give it to slapi_check_account_lock and reslimit_update_from_dn */
-            if (! slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
-                bind_target_entry = get_entry(pb,  slapi_sdn_get_ndn(sdn));
-                rc = slapi_check_account_lock ( pb, bind_target_entry, pw_response_requested, 1, 1);
-            }
-
             slapi_pblock_set( pb, SLAPI_PLUGIN, be->be_database );
             set_db_default_result_handlers(pb);
             if ( (rc != 1) && 
@@ -777,6 +758,28 @@ do_bind( Slapi_PBlock *pb )
 
                 if ( rc == SLAPI_BIND_SUCCESS ) {
                     int myrc = 0;
+                    /* 
+                     * The bind is successful.
+                     * We can give it to slapi_check_account_lock and reslimit_update_from_dn.
+                     */
+                    /*
+                     * Is this account locked ?
+                     *	could be locked through the account inactivation
+                     *	or by the password policy
+                     *
+                     * rc=0: account not locked
+                     * rc=1: account locked, can not bind, result has been sent
+                     * rc!=0 and rc!=1: error. Result was not sent, lets be_bind
+                     * 		deal with it.
+                     *
+                     */
+                    if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
+                        bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(sdn));
+                        rc = slapi_check_account_lock(pb, bind_target_entry, pw_response_requested, 1, 1);
+                        if (1 == rc) { /* account is locked */
+                            goto account_locked;
+                        }
+                    }
                     if (!auto_bind) {
                         /* 
                          * There could be a race that bind_target_entry was not added 
@@ -787,13 +790,7 @@ do_bind( Slapi_PBlock *pb )
                         if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA) && 
                             !bind_target_entry) {
                             bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(sdn));
-                            if (bind_target_entry) {
-                                myrc = slapi_check_account_lock(pb, bind_target_entry,
-                                                              pw_response_requested, 1, 1);
-                                if (1 == myrc) { /* account is locked */
-                                    goto account_locked;
-                                }
-                            } else {
+                            if (!bind_target_entry) {
                                 slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "No such entry");
                                 send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, "", 0, NULL);
                                 goto free_and_return;
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index 76294ac..d56f0ed 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -1049,8 +1049,8 @@ sasl_check_result:
         errstr = sasl_errdetail(sasl_conn);
 
         PR_ExitMonitor(pb->pb_conn->c_mutex); /* BIG LOCK */
-        send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL,
-                         (char*)errstr, 0, NULL);
+        slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, (void *)errstr);
+        send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
         break;
     }
 

commit 5e810f82fd36d606f48d9a1218d2b8937bdf04ef
Author: Mark Reynolds <mreynolds at redhat.com>
Date:   Tue Jul 26 15:31:32 2016 -0400

    Ticket 48935 - Update dirsrv.systemd file
    
    BUg Description:  Two issues here.  First the default system startup timeout
                      is set to 1 minute 30 seconds.  But in the start-dirsrv script
                      it attempts to use a 10 minute timeout.
    
                      Second, starting in F23 systemd does not work well with valgrind.
                      systemd does not accept the notification once the DS starts.
                      So the start command actually fails after it times out.
    
    Fix Description:  For the first issue set the system startup timeout to match the
                      start-dirsrv script by setting:
    
                            TimeoutStartSecs=10min
    
                      Second, allow valgrind's startup success message to be
                      recognized/accepted we set:
    
                            NotifyAccess=all
    
    https://fedorahosted.org/389/ticket/48935
    
    Reviewed by: nhosoi(Thanks!)
    
    (cherry picked from commit ce44176803aa52ab8001113136bfbb7ff4a50972)

diff --git a/wrappers/systemd.template.sysconfig b/wrappers/systemd.template.sysconfig
index d88bdcd..e653c86 100644
--- a/wrappers/systemd.template.sysconfig
+++ b/wrappers/systemd.template.sysconfig
@@ -1,3 +1,6 @@
 [Service]
+TimeoutStartSec=10m
+NotifyAccess=all
+
 # uncomment this line to raise the file descriptor limit
 # LimitNOFILE=8192

commit c8e7fc567ca9b00969e3911bf3aa6245ebdffe5b
Author: Mark Reynolds <mreynolds at redhat.com>
Date:   Tue Jul 19 18:28:06 2016 -0400

    Ticket 48930 - Paged result search can hang the server
    
    Bug Description:  If a pages result has sent all its entry it's possible that
                      the connection lock/monitor is not exited.  This can lead
                      to a deadlock when a new connection comes in.
    
    Fix Description:  Move the monitor exit to the proper location, and also set
                      the result to success if all the entries have been sent.
    
    https://fedorahosted.org/389/ticket/48930
    
    Reviewed by: nhosoi(Thanks!)
    
    (cherry picked from commit bff1dd433f5de807ded1114e5961d66e2c0494e2)

diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 84e4c71..93334a1 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -694,11 +694,12 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
           /* search result could be reset in the backend/dse */
           slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
           pagedresults_set_search_result(pb->pb_conn, operation, sr, 1/*locked*/, pr_idx);
-          PR_ExitMonitor(pb->pb_conn->c_mutex);
         }
       } else {
         pr_stat = PAGEDRESULTS_SEARCH_END;
+        rc = LDAP_SUCCESS;
       }
+      PR_ExitMonitor(pb->pb_conn->c_mutex);
       pagedresults_unlock(pb->pb_conn, pr_idx);
 
       if ((PAGEDRESULTS_SEARCH_END == pr_stat) || (0 == pnentries)) {

commit 7738a00e7334c191421be274bae3ada964e4279a
Author: Simon Pichugin <spichugi at redhat.com>
Date:   Thu Jul 14 14:14:12 2016 +0200

    Ticket 48752 - Add CI test
    
    Description: Test that search with simple paged result control works
    properly on two suffixes (one is parent of the other) and the logs
    show right pr_cookie values.
    
    https://fedorahosted.org/389/ticket/48752
    
    Reviewed by: mreynolds (Thanks!)
    
    (cherry picked from commit fc97900fc6637d888a103c69adbf303f6e78e233)

diff --git a/dirsrvtests/tests/suites/paged_results/paged_results_test.py b/dirsrvtests/tests/suites/paged_results/paged_results_test.py
index 6fec5c7..2248fd2 100644
--- a/dirsrvtests/tests/suites/paged_results/paged_results_test.py
+++ b/dirsrvtests/tests/suites/paged_results/paged_results_test.py
@@ -12,8 +12,7 @@ import logging
 import pytest
 from random import sample
 from ldap.controls import SimplePagedResultsControl
-from lib389 import DirSrv, Entry, tools, tasks
-from lib389.tools import DirSrvTools
+from lib389 import DirSrv, Entry
 from lib389._constants import *
 from lib389.properties import *
 from lib389.tasks import *
@@ -24,8 +23,14 @@ logging.getLogger(__name__).setLevel(logging.DEBUG)
 log = logging.getLogger(__name__)
 
 TEST_USER_NAME = 'simplepaged_test'
-TEST_USER_DN = 'uid=%s,%s' % (TEST_USER_NAME, DEFAULT_SUFFIX)
+TEST_USER_DN = 'uid={},{}'.format(TEST_USER_NAME, DEFAULT_SUFFIX)
 TEST_USER_PWD = 'simplepaged_test'
+NEW_SUFFIX_1_NAME = 'test_parent'
+NEW_SUFFIX_1 = 'o={}'.format(NEW_SUFFIX_1_NAME)
+NEW_SUFFIX_2_NAME = 'child'
+NEW_SUFFIX_2 = 'ou={},{}'.format(NEW_SUFFIX_2_NAME, NEW_SUFFIX_1)
+NEW_BACKEND_1 = 'parent_base'
+NEW_BACKEND_2 = 'child_base'
 
 
 class TopologyStandalone(object):
@@ -62,9 +67,10 @@ def topology(request):
 
 
 @pytest.fixture(scope="module")
-def test_user(topology):
+def test_user(topology, request):
     """User for binding operation"""
 
+    log.info('Adding user {}'.format(TEST_USER_DN))
     try:
         topology.standalone.add_s(Entry((TEST_USER_DN, {
                                         'objectclass': 'top person'.split(),
@@ -81,8 +87,63 @@ def test_user(topology):
                                                            e.message['desc']))
         raise e
 
+    def fin():
+        log.info('Deleting user {}'.format(TEST_USER_DN))
+        topology.standalone.delete_s(TEST_USER_DN)
+    request.addfinalizer(fin)
+
+
+ at pytest.fixture(scope="module")
+def new_suffixes(topology):
+    """Add two suffixes with backends, one is a parent
+    of the another
+    """
+
+    log.info('Adding suffix:{} and backend: {}'.format(NEW_SUFFIX_1, NEW_BACKEND_1))
+    topology.standalone.backend.create(NEW_SUFFIX_1,
+                                       {BACKEND_NAME: NEW_BACKEND_1})
+    topology.standalone.mappingtree.create(NEW_SUFFIX_1,
+                                           bename=NEW_BACKEND_1)
+    try:
+        topology.standalone.add_s(Entry((NEW_SUFFIX_1, {
+                                        'objectclass': 'top',
+                                        'objectclass': 'organization',
+                                        'o': NEW_SUFFIX_1_NAME
+                                        })))
+    except ldap.LDAPError as e:
+        log.error('Failed to add suffix ({}): error ({})'.format(NEW_SUFFIX_1,
+                                                                 e.message['desc']))
+        raise
 
-def add_users(topology, users_num):
+    log.info('Adding suffix:{} and backend: {}'.format(NEW_SUFFIX_2, NEW_BACKEND_2))
+    topology.standalone.backend.create(NEW_SUFFIX_2,
+                                       {BACKEND_NAME: NEW_BACKEND_2})
+    topology.standalone.mappingtree.create(NEW_SUFFIX_2,
+                                           bename=NEW_BACKEND_2,
+                                           parent=NEW_SUFFIX_1)
+
+    try:
+        topology.standalone.add_s(Entry((NEW_SUFFIX_2, {
+                                        'objectclass': 'top',
+                                        'objectclass': 'organizationalunit',
+                                        'ou': NEW_SUFFIX_2_NAME
+                                        })))
+    except ldap.LDAPError as e:
+        log.error('Failed to add suffix ({}): error ({})'.format(NEW_SUFFIX_2,
+                                                                 e.message['desc']))
+        raise
+
+    log.info('Adding ACI to allow our test user to search')
+    ACI_TARGET = '(targetattr != "userPassword || aci")'
+    ACI_ALLOW = '(version 3.0; acl "Enable anonymous access";allow (read, search, compare)'
+    ACI_SUBJECT = '(userdn = "ldap:///anyone");)'
+    ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
+
+    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+    topology.standalone.modify_s(NEW_SUFFIX_1, mod)
+
+
+def add_users(topology, users_num, suffix):
     """Add users to the default suffix
 
     Return the list of added user DNs.
@@ -93,7 +154,7 @@ def add_users(topology, users_num):
     for num in sample(range(1000), users_num):
         num_ran = int(round(num))
         USER_NAME = 'test%05d' % num_ran
-        USER_DN = 'uid=%s,%s' % (USER_NAME, DEFAULT_SUFFIX)
+        USER_DN = 'uid=%s,%s' % (USER_NAME, suffix)
         users_list.append(USER_DN)
         try:
             topology.standalone.add_s(Entry((USER_DN, {
@@ -154,7 +215,7 @@ def change_conf_attr(topology, suffix, attr_name, attr_value):
     return attr_value_bck
 
 
-def paged_search(topology, controls, search_flt, searchreq_attrlist):
+def paged_search(topology, suffix, controls, search_flt, searchreq_attrlist):
     """Search at the DEFAULT_SUFFIX with ldap.SCOPE_SUBTREE
     using Simple Paged Control(should the first item in the
     list controls.
@@ -167,7 +228,7 @@ def paged_search(topology, controls, search_flt, searchreq_attrlist):
     pctrls = []
     all_results = []
     req_ctrl = controls[0]
-    msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
+    msgid = topology.standalone.search_ext(suffix,
                                            ldap.SCOPE_SUBTREE,
                                            search_flt,
                                            searchreq_attrlist,
@@ -187,7 +248,7 @@ def paged_search(topology, controls, search_flt, searchreq_attrlist):
             if pctrls[0].cookie:
                 # Copy cookie from response control to request control
                 req_ctrl.cookie = pctrls[0].cookie
-                msgid = topology.standalone.search_ext(DEFAULT_SUFFIX,
+                msgid = topology.standalone.search_ext(suffix,
                                                        ldap.SCOPE_SUBTREE,
                                                        search_flt,
                                                        searchreq_attrlist,
@@ -219,7 +280,7 @@ def test_search_success(topology, test_user, page_size, users_num):
     @Assert: All users should be found
     """
 
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -230,7 +291,7 @@ def test_search_success(topology, test_user, page_size, users_num):
         log.info('Create simple paged results control instance')
         req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
 
-        all_results = paged_search(topology, [req_ctrl],
+        all_results = paged_search(topology, DEFAULT_SUFFIX, [req_ctrl],
                                    search_flt, searchreq_attrlist)
 
         log.info('%d results' % len(all_results))
@@ -272,7 +333,7 @@ def test_search_limits_fail(topology, test_user, page_size, users_num,
     @Assert: Should fail with appropriate exception
     """
 
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     attr_value_bck = change_conf_attr(topology, suffix, attr_name, attr_value)
     conf_param_dict = {attr_name: attr_value}
     search_flt = r'(uid=test*)'
@@ -362,7 +423,7 @@ def test_search_sort_success(topology, test_user):
 
     users_num = 50
     page_size = 5
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -377,7 +438,7 @@ def test_search_sort_success(topology, test_user):
         log.info('Initiate ldapsearch with created control instance')
         log.info('Collect data with sorting')
         controls = [req_ctrl, sort_ctrl]
-        results_sorted = paged_search(topology, controls,
+        results_sorted = paged_search(topology, DEFAULT_SUFFIX, controls,
                                       search_flt, searchreq_attrlist)
 
         log.info('Substring numbers from user DNs')
@@ -411,7 +472,7 @@ def test_search_abandon(topology, test_user):
 
     users_num = 10
     page_size = 2
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -464,7 +525,7 @@ def test_search_with_timelimit(topology, test_user):
     users_num = 100
     page_size = 50
     timelimit = 5
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -547,7 +608,7 @@ def test_search_dns_ip_aci(topology, test_user, aci_subject):
 
     users_num = 100
     page_size = 5
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -578,7 +639,7 @@ def test_search_dns_ip_aci(topology, test_user, aci_subject):
         log.info('Initiate three searches with a paged results control')
         for ii in range(3):
             log.info('%d search' % (ii + 1))
-            all_results = paged_search(topology, controls,
+            all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                        search_flt, searchreq_attrlist)
             log.info('%d results' % len(all_results))
             assert len(all_results) == len(users_list)
@@ -618,7 +679,7 @@ def test_search_multiple_paging(topology, test_user):
 
     users_num = 100
     page_size = 30
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -679,7 +740,7 @@ def test_search_invalid_cookie(topology, test_user, invalid_cookie):
 
     users_num = 100
     page_size = 50
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -732,7 +793,7 @@ def test_search_abandon_with_zero_size(topology, test_user):
 
     users_num = 10
     page_size = 0
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -787,7 +848,7 @@ def test_search_pagedsizelimit_success(topology, test_user):
     attr_value = '20'
     attr_value_bck = change_conf_attr(topology, DN_CONFIG,
                                       attr_name, attr_value)
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
 
@@ -799,7 +860,7 @@ def test_search_pagedsizelimit_success(topology, test_user):
         req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
         controls = [req_ctrl]
 
-        all_results = paged_search(topology, controls,
+        all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                    search_flt, searchreq_attrlist)
 
         log.info('%d results' % len(all_results))
@@ -846,7 +907,7 @@ def test_search_nspagedsizelimit(topology, test_user,
 
     users_num = 10
     page_size = 10
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
     conf_attr_bck = change_conf_attr(topology, DN_CONFIG,
@@ -865,11 +926,11 @@ def test_search_nspagedsizelimit(topology, test_user,
         if expected_rs == ldap.SIZELIMIT_EXCEEDED:
             log.info('Expect to fail with SIZELIMIT_EXCEEDED')
             with pytest.raises(expected_rs):
-                all_results = paged_search(topology, controls,
+                all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                            search_flt, searchreq_attrlist)
         elif expected_rs == 'PASS':
             log.info('Expect to pass')
-            all_results = paged_search(topology, controls,
+            all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                        search_flt, searchreq_attrlist)
             log.info('%d results' % len(all_results))
             assert len(all_results) == len(users_list)
@@ -917,7 +978,7 @@ def test_search_paged_limits(topology, test_user, conf_attr_values, expected_rs)
 
     users_num = 101
     page_size = 10
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
     size_attr_bck = change_conf_attr(topology, DN_CONFIG,
@@ -940,11 +1001,11 @@ def test_search_paged_limits(topology, test_user, conf_attr_values, expected_rs)
         if expected_rs == ldap.ADMINLIMIT_EXCEEDED:
             log.info('Expect to fail with ADMINLIMIT_EXCEEDED')
             with pytest.raises(expected_rs):
-                all_results = paged_search(topology, controls,
+                all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                            search_flt, searchreq_attrlist)
         elif expected_rs == 'PASS':
             log.info('Expect to pass')
-            all_results = paged_search(topology, controls,
+            all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                        search_flt, searchreq_attrlist)
             log.info('%d results' % len(all_results))
             assert len(all_results) == len(users_list)
@@ -996,7 +1057,7 @@ def test_search_paged_user_limits(topology, test_user, conf_attr_values, expecte
 
     users_num = 101
     page_size = 10
-    users_list = add_users(topology, users_num)
+    users_list = add_users(topology, users_num, DEFAULT_SUFFIX)
     search_flt = r'(uid=test*)'
     searchreq_attrlist = ['dn', 'sn']
     lookthrough_attr_bck = change_conf_attr(topology, 'cn=config,%s' % DN_LDBM,
@@ -1019,11 +1080,11 @@ def test_search_paged_user_limits(topology, test_user, conf_attr_values, expecte
         if expected_rs == ldap.ADMINLIMIT_EXCEEDED:
             log.info('Expect to fail with ADMINLIMIT_EXCEEDED')
             with pytest.raises(expected_rs):
-                all_results = paged_search(topology, controls,
+                all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                            search_flt, searchreq_attrlist)
         elif expected_rs == 'PASS':
             log.info('Expect to pass')
-            all_results = paged_search(topology, controls,
+            all_results = paged_search(topology, DEFAULT_SUFFIX, controls,
                                        search_flt, searchreq_attrlist)
             log.info('%d results' % len(all_results))
             assert len(all_results) == len(users_list)
@@ -1041,6 +1102,62 @@ def test_search_paged_user_limits(topology, test_user, conf_attr_values, expecte
                          'nsPagedLookthroughLimit', user_lookthrough_attr_bck)
 
 
+def test_multi_suffix_search(topology, test_user, new_suffixes):
+    """Verify that page result search returns empty cookie
+    if there is no returned entry.
+
+    :Feature: Simple paged results
+
+    :Setup: Standalone instance, test user for binding,
+            two suffixes with backends, one is inserted into another,
+            10 users for the search base within each suffix
+
+    :Steps: 1. Bind as test user
+            2. Search through all 20 added users with a simple paged control
+               using page_size = 4
+            3. Wait some time logs to be updated
+            3. Check access log
+
+    :Assert: All users should be found, the access log should contain
+             the pr_cookie for each page request and it should be equal 0,
+             except the last one should be equal -1
+    """
+
+    search_flt = r'(uid=test*)'
+    searchreq_attrlist = ['dn', 'sn']
+    page_size = 4
+    users_num = 20
+
+    users_list_1 = add_users(topology, users_num / 2, NEW_SUFFIX_1)
+    users_list_2 = add_users(topology, users_num / 2, NEW_SUFFIX_2)
+
+    try:
+        log.info('Set DM bind')
+        topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+        log.info('Create simple paged results control instance')
+        req_ctrl = SimplePagedResultsControl(True, size=page_size, cookie='')
+
+        all_results = paged_search(topology, NEW_SUFFIX_1, [req_ctrl],
+                                search_flt, searchreq_attrlist)
+
+        log.info('{} results'.format(len(all_results)))
+        assert len(all_results) == users_num
+
+        log.info('Waiting for logs to be updated')
+        time.sleep(30)
+        access_log_lines = topology.standalone.ds_access_log.match('.*pr_cookie=.*')
+        pr_cookie_list = ([line.rsplit('=', 1)[-1] for line in access_log_lines])
+        pr_cookie_list = [int(pr_cookie) for pr_cookie in pr_cookie_list]
+        log.info('Assert that last pr_cookie == -1 and others pr_cookie == 0')
+        assert all((pr_cookie == 0 for pr_cookie in pr_cookie_list[0:-1]))
+        assert pr_cookie_list[-1] == -1
+    finally:
+        log.info('Remove added users')
+        del_users(topology, users_list_1)
+        del_users(topology, users_list_2)
+
+
 if __name__ == '__main__':
     # Run isolated
     # -s for DEBUG mode

commit 42fcf976d9c8bc223a9c7a6c0a0857b3fd9463e6
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Fri Jul 15 14:19:16 2016 -0700

    bump version to 1.3.4.13

diff --git a/VERSION.sh b/VERSION.sh
index f4a1fda..42e3e7e 100644
--- a/VERSION.sh
+++ b/VERSION.sh
@@ -10,7 +10,7 @@ vendor="389 Project"
 # PACKAGE_VERSION is constructed from these
 VERSION_MAJOR=1
 VERSION_MINOR=3
-VERSION_MAINT=4.12
+VERSION_MAINT=4.13
 # if this is a PRERELEASE, set VERSION_PREREL
 # otherwise, comment it out
 # be sure to include the dot prefix in the prerel

commit b338616f66d4d51536b94edd9ae7f0dd10fbebd0
Author: Noriko Hosoi <nhosoi at redhat.com>
Date:   Tue Jul 12 14:33:17 2016 -0700

    Bug 1347760 - CI test: test case for bug 1347760
    
    Description: Information disclosure via repeated use of LDAP ADD operation, etc.
    (cherry picked from commit 8bfe4bbf3d61d4eaf4abac6515c95b38ac39b195)

diff --git a/dirsrvtests/tests/tickets/ticket1347760_test.py b/dirsrvtests/tests/tickets/ticket1347760_test.py
new file mode 100644
index 0000000..d2e9e37
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket1347760_test.py
@@ -0,0 +1,440 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+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 *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+CONFIG_DN = 'cn=config'
+BOU = 'BOU'
+BINDOU = 'ou=%s,%s' % (BOU, DEFAULT_SUFFIX)
+BUID = 'buser123'
+TUID = 'tuser0'
+BINDDN = 'uid=%s,%s' % (BUID, BINDOU)
+BINDPW = BUID
+TESTDN = 'uid=%s,ou=people,%s' % (TUID, DEFAULT_SUFFIX)
+TESTPW = TUID
+BOGUSDN = 'uid=bogus,%s' % DEFAULT_SUFFIX
+BOGUSDN2 = 'uid=bogus,ou=people,%s' % DEFAULT_SUFFIX
+BOGUSSUFFIX = 'uid=bogus,ou=people,dc=bogus'
+GROUPOU = 'ou=groups,%s' % DEFAULT_SUFFIX
+BOGUSOU = 'ou=OU,%s' % DEFAULT_SUFFIX
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+class TopologyStandalone(object):
+    def __init__(self, standalone):
+        standalone.open()
+        self.standalone = standalone
+
+
+ at pytest.fixture(scope="module")
+def topology(request):
+    global installation1_prefix
+    if installation1_prefix:
+        args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+    # Creating standalone instance ...
+    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()
+
+    # Delete each instance in the end
+#    def fin():
+#        standalone.delete()
+#    request.addfinalizer(fin)
+
+    # Clear out the tmp dir
+    standalone.clearTmpDir(__file__)
+
+    return TopologyStandalone(standalone)
+
+def pattern_accesslog(file, log_pattern):
+    try:
+        pattern_accesslog.last_pos += 1
+    except AttributeError:
+        pattern_accesslog.last_pos = 0
+
+    found = None
+    file.seek(pattern_accesslog.last_pos)
+
+    # Use a while true iteration because 'for line in file: hit a
+    # python bug that break file.tell()
+    while True:
+        line = file.readline()
+        found = log_pattern.search(line)
+        if ((line == '') or (found)):
+            break
+
+    pattern_accesslog.last_pos = file.tell()
+    if found:
+        return line
+    else:
+        return None
+
+def check_op_result(server, op, dn, superior, exists, rc):
+    targetdn = dn
+    if op == 'search':
+        if exists:
+            opstr = 'Searching existing entry'
+        else:
+            opstr = 'Searching non-existing entry'
+    elif op == 'add':
+        if exists:
+            opstr = 'Adding existing entry'
+        else:
+            opstr = 'Adding non-existing entry'
+    elif op == 'modify':
+        if exists:
+            opstr = 'Modifying existing entry'
+        else:
+            opstr = 'Modifying non-existing entry'
+    elif op == 'modrdn':
+        if superior != None:
+            targetdn = superior
+            if exists:
+                opstr = 'Moving to existing superior'
+            else:
+                opstr = 'Moving to non-existing superior'
+        else:
+            if exists:
+                opstr = 'Renaming existing entry'
+            else:
+                opstr = 'Renaming non-existing entry'
+    elif op == 'delete':
+        if exists:
+            opstr = 'Deleting existing entry'
+        else:
+            opstr = 'Deleting non-existing entry'
+
+    if ldap.SUCCESS == rc:
+        expstr = 'be ok'
+    else:
+        expstr = 'fail with %s' % rc.__name__
+
+    log.info('%s %s, which should %s.' % (opstr, targetdn, expstr))
+    hit = 0
+    try:
+        if op == 'search':
+            centry = server.search_s(dn, ldap.SCOPE_BASE, 'objectclass=*')
+        elif op == 'add':
+            server.add_s(Entry((dn, {'objectclass': 'top extensibleObject'.split(),
+                                     'cn': 'test entry'})))
+        elif op == 'modify':
+            server.modify_s(dn, [(ldap.MOD_REPLACE, 'description', 'test')])
+        elif op == 'modrdn':
+            if superior != None:
+                server.rename_s(dn, 'uid=new', newsuperior=superior, delold=1)
+            else:
+                server.rename_s(dn, 'uid=new', delold=1)
+        elif op == 'delete':
+            server.delete_s(dn)
+        else:
+            log.fatal('Unknown operation %s' % op)
+            assert False
+    except ldap.LDAPError as e:
+        hit = 1
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc ' + e.message['desc'])
+        assert isinstance(e, rc)
+        if e.message.has_key('matched'):
+            log.info('Matched is returned: ' + e.message['matched'])
+            if rc != ldap.NO_SUCH_OBJECT:
+                assert False
+
+    if ldap.SUCCESS == rc:
+        if op == 'search':
+            log.info('Search should return none')
+            assert len(centry) == 0
+    else:
+        if 0 == hit:
+            log.info('Expected to fail with %s, but passed' % rc.__name__)
+            assert False
+
+    log.info('PASSED\n')
+
+def test_ticket1347760(topology):
+    """
+    Prevent revealing the entry info to whom has no access rights.
+    """
+    log.info('Testing Bug 1347760 - Information disclosure via repeated use of LDAP ADD operation, etc.')
+
+    log.info('Disabling accesslog logbuffering')
+    topology.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-accesslog-logbuffering', 'off')])
+
+    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
+    topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    log.info('Adding ou=%s a bind user belongs to.' % BOU)
+    topology.standalone.add_s(Entry((BINDOU, {
+                              'objectclass': 'top organizationalunit'.split(),
+                              'ou': BOU})))
+
+    log.info('Adding a bind user.')
+    topology.standalone.add_s(Entry((BINDDN,
+                                     {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+                                      'cn': 'bind user',
+                                      'sn': 'user',
+                                      'userPassword': BINDPW})))
+
+    log.info('Adding a test user.')
+    topology.standalone.add_s(Entry((TESTDN,
+                                     {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+                                      'cn': 'test user',
+                                      'sn': 'user',
+                                      'userPassword': TESTPW})))
+
+    log.info('Deleting aci in %s.' % DEFAULT_SUFFIX)
+    topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_DELETE, 'aci', None)])
+
+    log.info('Bind case 1. the bind user has no rights to read the entry itself, bind should be successful.')
+    log.info('Bind as {%s,%s} who has no access rights.' % (BINDDN, BINDPW))
+    try:



More information about the Pkg-fedora-ds-maintainers mailing list