andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame SOURCES/0094-Ticket-48862-At-startup-DES-to-AES-password-conversi.patch

f5000e
From 72562d03b0f758902e0ee858fd43d5bcfbef379b Mon Sep 17 00:00:00 2001
f5000e
From: Mark Reynolds <mreynolds@redhat.com>
f5000e
Date: Tue, 7 Jun 2016 10:02:42 -0400
f5000e
Subject: [PATCH] Ticket 48862 - At startup DES to AES password conversion
f5000e
 causes timeout in start script
f5000e
f5000e
Bug Description:  At server start all the backends are searches for entries that contain
f5000e
                  DES password attributes as defined in the plugin.  These are typically
f5000e
                  unindexed searches, and if there is a very large backend this can cause
f5000e
                  the server startup to timeout.
f5000e
f5000e
Fix Description:  At startup only check "cn=config" for entries with DES password attributes.
f5000e
                  A new "conversion" task has been created that can be run after startup
f5000e
                  to search all backends(if a suffix is not specified), or specific backends.
f5000e
f5000e
                      dn: cn=convertPasswords, cn=des2aes,cn=tasks,cn=config
f5000e
                      objectclass: top
f5000e
                      objectclass: extensibleObject
f5000e
                      suffix: dc=example,dc=com
f5000e
                      suffix: dc=other,dc=suffix
f5000e
f5000e
                  Another bug was discovered in pw_rever_encode() in pw.c where a "for" loop
f5000e
                  counter was accidentially reused by a second "for" loop.  This could lead
f5000e
                  to an infinite loop/hang.
f5000e
f5000e
                  Updated the CI test to perform the conversion task.
f5000e
f5000e
https://fedorahosted.org/389/ticket/48862
f5000e
f5000e
Reviewed by: nhosoi(Thanks!)
f5000e
f5000e
(cherry picked from commit 11f55f3dd2a2c44ddf7b5be54273401add13b1bc)
f5000e
(cherry picked from commit c0ad918939c40779e463b71c41ab106e7ee890e2)
f5000e
---
f5000e
 dirsrvtests/tickets/ticket47462_test.py | 133 ++++++++----
f5000e
 ldap/servers/slapd/daemon.c             | 195 +++++-------------
f5000e
 ldap/servers/slapd/pw.c                 |   4 +-
f5000e
 ldap/servers/slapd/task.c               | 346 +++++++++++++++++++++++++++++++-
f5000e
 4 files changed, 493 insertions(+), 185 deletions(-)
f5000e
f5000e
diff --git a/dirsrvtests/tickets/ticket47462_test.py b/dirsrvtests/tickets/ticket47462_test.py
f5000e
index 17854fa..2d2c507 100644
f5000e
--- a/dirsrvtests/tickets/ticket47462_test.py
f5000e
+++ b/dirsrvtests/tickets/ticket47462_test.py
f5000e
@@ -32,6 +32,7 @@ AGMT_DN = ''
f5000e
 USER_DN = 'cn=test_user,' + DEFAULT_SUFFIX
f5000e
 USER1_DN = 'cn=test_user1,' + DEFAULT_SUFFIX
f5000e
 TEST_REPL_DN = 'cn=test repl,' + DEFAULT_SUFFIX
f5000e
+DES2AES_TASK_DN = 'cn=convert,cn=des2aes,cn=tasks,cn=config'
f5000e
 
f5000e
 
f5000e
 class TopologyMaster1Master2(object):
f5000e
@@ -134,6 +135,11 @@ def topology(request):
f5000e
     # clear the tmp directory
f5000e
     master1.clearTmpDir(__file__)
f5000e
 
f5000e
+    def fin():
f5000e
+        master1.delete()
f5000e
+        master2.delete()
f5000e
+    request.addfinalizer(fin)
f5000e
+
f5000e
     return TopologyMaster1Master2(master1, master2)
f5000e
 
f5000e
 
f5000e
@@ -144,11 +150,9 @@ def test_ticket47462(topology):
f5000e
     """
f5000e
 
f5000e
     #
f5000e
-    # First set config as if it's an older version.  Set DES to use libdes-plugin,
f5000e
-    # MMR to depend on DES, delete the existing AES plugin, and set a DES password
f5000e
-    # for the replication agreement.
f5000e
-    #
f5000e
-
f5000e
+    # First set config as if it's an older version.  Set DES to use
f5000e
+    # libdes-plugin, MMR to depend on DES, delete the existing AES plugin,
f5000e
+    # and set a DES password for the replication agreement.
f5000e
     #
f5000e
     # Add an extra attribute to the DES plugin args
f5000e
     #
f5000e
@@ -168,7 +172,9 @@ def test_ticket47462(topology):
f5000e
 
f5000e
     try:
f5000e
         topology.master1.modify_s(MMR_PLUGIN,
f5000e
-                      [(ldap.MOD_DELETE, 'nsslapd-plugin-depends-on-named', 'AES')])
f5000e
+                      [(ldap.MOD_DELETE,
f5000e
+                        'nsslapd-plugin-depends-on-named',
f5000e
+                        'AES')])
f5000e
 
f5000e
     except ldap.NO_SUCH_ATTRIBUTE:
f5000e
         pass
f5000e
@@ -194,7 +200,8 @@ def test_ticket47462(topology):
f5000e
     # Get the agmt dn, and set the password
f5000e
     #
f5000e
     try:
f5000e
-        entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'objectclass=nsDS5ReplicationAgreement')
f5000e
+        entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE,
f5000e
+                                          'objectclass=nsDS5ReplicationAgreement')
f5000e
         if entry:
f5000e
             agmt_dn = entry[0].dn
f5000e
             log.info('Found agmt dn (%s)' % agmt_dn)
f5000e
@@ -207,7 +214,8 @@ def test_ticket47462(topology):
f5000e
 
f5000e
     try:
f5000e
         properties = {RA_BINDPW: "password"}
f5000e
-        topology.master1.agreement.setProperties(None, agmt_dn, None, properties)
f5000e
+        topology.master1.agreement.setProperties(None, agmt_dn, None,
f5000e
+                                                 properties)
f5000e
         log.info('Successfully modified replication agreement')
f5000e
     except ValueError:
f5000e
         log.error('Failed to update replica agreement: ' + AGMT_DN)
f5000e
@@ -220,12 +228,14 @@ def test_ticket47462(topology):
f5000e
         topology.master1.add_s(Entry((USER1_DN,
f5000e
                                       {'objectclass': "top person".split(),
f5000e
                                        'sn': 'sn',
f5000e
+                                       'description': 'DES value to convert',
f5000e
                                        'cn': 'test_user'})))
f5000e
         loop = 0
f5000e
         ent = None
f5000e
         while loop <= 10:
f5000e
             try:
f5000e
-                ent = topology.master2.getEntry(USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)")
f5000e
+                ent = topology.master2.getEntry(USER1_DN, ldap.SCOPE_BASE,
f5000e
+                                                "(objectclass=*)")
f5000e
                 break
f5000e
             except ldap.NO_SUCH_OBJECT:
f5000e
                 time.sleep(1)
f5000e
@@ -250,7 +260,8 @@ def test_ticket47462(topology):
f5000e
     # Check that the restart converted existing DES credentials
f5000e
     #
f5000e
     try:
f5000e
-        entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE, 'nsDS5ReplicaCredentials=*')
f5000e
+        entry = topology.master1.search_s('cn=config', ldap.SCOPE_SUBTREE,
f5000e
+                                          'nsDS5ReplicaCredentials=*')
f5000e
         if entry:
f5000e
             val = entry[0].getValue('nsDS5ReplicaCredentials')
f5000e
             if val.startswith('{AES-'):
f5000e
@@ -259,22 +270,25 @@ def test_ticket47462(topology):
f5000e
                 log.fatal('Failed to convert credentials from DES to AES!')
f5000e
                 assert False
f5000e
         else:
f5000e
-            log.fatal('Failed to find any entries with nsDS5ReplicaCredentials ')
f5000e
+            log.fatal('Failed to find entries with nsDS5ReplicaCredentials')
f5000e
             assert False
f5000e
     except ldap.LDAPError, e:
f5000e
         log.fatal('Failed to search for replica credentials: ' + e.message['desc'])
f5000e
         assert False
f5000e
 
f5000e
     #
f5000e
-    # Check that the AES plugin exists, and has all the attributes listed in DES plugin.
f5000e
-    # The attributes might not be in the expected order so check all the attributes.
f5000e
+    # Check that the AES plugin exists, and has all the attributes listed in
f5000e
+    # DES plugin.  The attributes might not be in the expected order so check
f5000e
+    # all the attributes.
f5000e
     #
f5000e
     try:
f5000e
-        entry = topology.master1.search_s(AES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
f5000e
+        entry = topology.master1.search_s(AES_PLUGIN, ldap.SCOPE_BASE,
f5000e
+                                          'objectclass=*')
f5000e
         if not entry[0].hasValue('nsslapd-pluginarg0', 'description') and \
f5000e
            not entry[0].hasValue('nsslapd-pluginarg1', 'description') and \
f5000e
            not entry[0].hasValue('nsslapd-pluginarg2', 'description'):
f5000e
-            log.fatal('The AES plugin did not have the DES attribute copied over correctly')
f5000e
+            log.fatal('The AES plugin did not have the DES attribute copied ' +
f5000e
+                      'over correctly')
f5000e
             assert False
f5000e
         else:
f5000e
             log.info('The AES plugin was correctly setup')
f5000e
@@ -286,7 +300,8 @@ def test_ticket47462(topology):
f5000e
     # Check that the MMR plugin was updated
f5000e
     #
f5000e
     try:
f5000e
-        entry = topology.master1.search_s(MMR_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
f5000e
+        entry = topology.master1.search_s(MMR_PLUGIN, ldap.SCOPE_BASE,
f5000e
+                                          'objectclass=*')
f5000e
         if not entry[0].hasValue('nsslapd-plugin-depends-on-named', 'AES'):
f5000e
             log.fatal('The MMR Plugin was not correctly updated')
f5000e
             assert False
f5000e
@@ -300,7 +315,8 @@ def test_ticket47462(topology):
f5000e
     # Check that the DES plugin was correctly updated
f5000e
     #
f5000e
     try:
f5000e
-        entry = topology.master1.search_s(DES_PLUGIN, ldap.SCOPE_BASE, 'objectclass=*')
f5000e
+        entry = topology.master1.search_s(DES_PLUGIN, ldap.SCOPE_BASE,
f5000e
+                                          'objectclass=*')
f5000e
         if not entry[0].hasValue('nsslapd-pluginPath', 'libpbe-plugin'):
f5000e
             log.fatal('The DES Plugin was not correctly updated')
f5000e
             assert False
f5000e
@@ -322,7 +338,8 @@ def test_ticket47462(topology):
f5000e
         ent = None
f5000e
         while loop <= 10:
f5000e
             try:
f5000e
-                ent = topology.master2.getEntry(USER_DN, ldap.SCOPE_BASE, "(objectclass=*)")
f5000e
+                ent = topology.master2.getEntry(USER_DN, ldap.SCOPE_BASE,
f5000e
+                                                "(objectclass=*)")
f5000e
                 break
f5000e
             except ldap.NO_SUCH_OBJECT:
f5000e
                 time.sleep(1)
f5000e
@@ -336,30 +353,66 @@ def test_ticket47462(topology):
f5000e
         log.fatal('Failed to add test user: ' + e.message['desc'])
f5000e
         assert False
f5000e
 
f5000e
+    # Check the entry
f5000e
+    log.info('Entry before running task...')
f5000e
+    try:
f5000e
+        entry = topology.master1.search_s(USER1_DN,
f5000e
+                                          ldap.SCOPE_BASE,
f5000e
+                                          'objectclass=*')
f5000e
+        if entry:
f5000e
+            print(str(entry))
f5000e
+        else:
f5000e
+            log.fatal('Failed to find entries')
f5000e
+            assert False
f5000e
+    except ldap.LDAPError as e:
f5000e
+        log.fatal('Failed to search for entries: ' +
f5000e
+                  e.message['desc'])
f5000e
+        assert False
f5000e
 
f5000e
-def test_ticket47462_final(topology):
f5000e
-    topology.master1.delete()
f5000e
-    topology.master2.delete()
f5000e
-    log.info('Testcase PASSED')
f5000e
-
f5000e
-
f5000e
-def run_isolated():
f5000e
-    '''
f5000e
-        run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
f5000e
-        To run isolated without py.test, you need to
f5000e
-            - edit this file and comment '@pytest.fixture' line before 'topology' function.
f5000e
-            - set the installation prefix
f5000e
-            - run this program
f5000e
-    '''
f5000e
-    global installation1_prefix
f5000e
-    global installation2_prefix
f5000e
-    installation1_prefix = None
f5000e
-    installation2_prefix = None
f5000e
+    #
f5000e
+    # Test the DES2AES Task on USER1_DN
f5000e
+    #
f5000e
+    try:
f5000e
+        topology.master1.add_s(Entry((DES2AES_TASK_DN,
f5000e
+                                      {'objectclass': ['top',
f5000e
+                                                       'extensibleObject'],
f5000e
+                                       'suffix': DEFAULT_SUFFIX,
f5000e
+                                       'cn': 'convert'})))
f5000e
+    except ldap.LDAPError as e:
f5000e
+        log.fatal('Failed to add task entry: ' + e.message['desc'])
f5000e
+        assert False
f5000e
 
f5000e
-    topo = topology(True)
f5000e
-    test_ticket47462(topo)
f5000e
-    test_ticket47462_final(topo)
f5000e
+    # Wait for task
f5000e
+    task_entry = Entry(DES2AES_TASK_DN)
f5000e
+    (done, exitCode) = topology.master1.tasks.checkTask(task_entry, True)
f5000e
+    if exitCode:
f5000e
+        log.fatal("Error: des2aes task exited with %d" % (exitCode))
f5000e
+        assert False
f5000e
 
f5000e
+    # Check the entry
f5000e
+    try:
f5000e
+        entry = topology.master1.search_s(USER1_DN,
f5000e
+                                          ldap.SCOPE_BASE,
f5000e
+                                          'objectclass=*')
f5000e
+        if entry:
f5000e
+            val = entry[0].getValue('description')
f5000e
+            print(str(entry[0]))
f5000e
+            if val.startswith('{AES-'):
f5000e
+                log.info('Task: DES credentials have been converted to AES')
f5000e
+            else:
f5000e
+                log.fatal('Task: Failed to convert credentials from DES to ' +
f5000e
+                          'AES! (%s)' % (val))
f5000e
+                assert False
f5000e
+        else:
f5000e
+            log.fatal('Failed to find entries')
f5000e
+            assert False
f5000e
+    except ldap.LDAPError as e:
f5000e
+        log.fatal('Failed to search for entries: ' +
f5000e
+                  e.message['desc'])
f5000e
+        assert False
f5000e
 
f5000e
 if __name__ == '__main__':
f5000e
-    run_isolated()
f5000e
+    # Run isolated
f5000e
+    # -s for DEBUG mode
f5000e
+    CURRENT_FILE = os.path.realpath(__file__)
f5000e
+    pytest.main("-s %s" % CURRENT_FILE)
f5000e
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
f5000e
index d702129..29562ae 100644
f5000e
--- a/ldap/servers/slapd/daemon.c
f5000e
+++ b/ldap/servers/slapd/daemon.c
f5000e
@@ -692,14 +692,12 @@ convert_pbe_des_to_aes()
f5000e
     Slapi_Entry **entries = NULL;
f5000e
     struct slapdplugin *plugin = NULL;
f5000e
     char **attrs = NULL;
f5000e
-    char **backends = NULL;
f5000e
     char *val = NULL;
f5000e
     int converted_des_passwd = 0;
f5000e
-    int disable_des = 1;
f5000e
     int result = -1;
f5000e
     int have_aes = 0;
f5000e
     int have_des = 0;
f5000e
-    int i = 0, ii = 0, be_idx = 0;
f5000e
+    int i = 0, ii = 0;
f5000e
 
f5000e
     /*
f5000e
      * Check that AES plugin is enabled, and grab all the unique
f5000e
@@ -733,94 +731,56 @@ convert_pbe_des_to_aes()
f5000e
 
f5000e
     if(have_aes && have_des){
f5000e
         /*
f5000e
-         * Build a list of all the backend dn's
f5000e
+         * Find any entries in cn=config that contain DES passwords and convert
f5000e
+         * them to AES
f5000e
          */
f5000e
-        Slapi_Backend *be = NULL;
f5000e
-        struct suffixlist *list;
f5000e
-        char *cookie = NULL;
f5000e
-
f5000e
-        LDAPDebug(LDAP_DEBUG_ANY, "convert_pbe_des_to_aes:  "
f5000e
-                "Checking for DES passwords to convert to AES...\n",0,0,0);
f5000e
-
f5000e
-        be = slapi_get_first_backend(&cookie);
f5000e
-        while (be){
f5000e
-            int suffix_idx = 0;
f5000e
-            int count = slapi_counter_get_value(be->be_suffixcounter);
f5000e
-
f5000e
-            list = be->be_suffixlist;
f5000e
-            for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) {
f5000e
-                char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix);
f5000e
-                if(charray_inlist(backends, suffix) || strlen(suffix) == 0){
f5000e
-                    list = list->next;
f5000e
-                    continue;
f5000e
-                }
f5000e
-                charray_add(&backends, slapi_ch_strdup(suffix));
f5000e
-                list = list->next;
f5000e
-            }
f5000e
-            be = slapi_get_next_backend (cookie);
f5000e
-        }
f5000e
-        slapi_ch_free ((void **)&cookie);
f5000e
+        slapi_log_error(SLAPI_LOG_HOUSE,  "convert_pbe_des_to_aes",
f5000e
+                "Converting DES passwords to AES...\n");
f5000e
 
f5000e
-        /*
f5000e
-         * Search for the password attributes
f5000e
-         */
f5000e
         for (i = 0; attrs && attrs[i]; i++){
f5000e
             char *filter = PR_smprintf("%s=*", attrs[i]);
f5000e
-            /*
f5000e
-             * Loop over all the backends looking for the password attribute
f5000e
-             */
f5000e
-            for(be_idx = 0; backends && backends[be_idx]; be_idx++){
f5000e
-                pb = slapi_pblock_new();
f5000e
-                slapi_search_internal_set_pb(pb, backends[be_idx],
f5000e
-                        LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
f5000e
-                        (void *)plugin_get_default_component_id(),
f5000e
-                        SLAPI_OP_FLAG_IGNORE_UNINDEXED);
f5000e
-                slapi_search_internal_pb(pb);
f5000e
-                slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
f5000e
-                if (LDAP_SUCCESS != result) {
f5000e
-                    slapi_log_error(SLAPI_LOG_TRACE, "convert_pbe_des_to_aes: ",
f5000e
-                        "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
f5000e
-                        attrs[i], result, backends[be_idx]);
f5000e
-                    slapi_free_search_results_internal(pb);
f5000e
-                    slapi_pblock_destroy(pb);
f5000e
-                    pb = NULL;
f5000e
-                    continue;
f5000e
-                }
f5000e
-                slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
f5000e
-                for (ii = 0; entries && entries[ii]; ii++){
f5000e
-                    if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
f5000e
-                        if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
f5000e
-                            /*
f5000e
-                             * We have a DES encoded password, convert it AES
f5000e
-                             */
f5000e
-                            Slapi_PBlock *mod_pb = NULL;
f5000e
-                            Slapi_Value *sval = NULL;
f5000e
-                            LDAPMod mod_replace;
f5000e
-                            LDAPMod *mods[2];
f5000e
-                            char *replace_val[2];
f5000e
-                            char *passwd = NULL;
f5000e
-
f5000e
-                            /* decode the DES password */
f5000e
-                            if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
f5000e
-                                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
-                                        "Failed to decode existing DES password for (%s)\n",
f5000e
-                                        slapi_entry_get_dn(entries[ii]), 0, 0);
f5000e
-                                disable_des = 0;
f5000e
-                                goto done;
f5000e
-                            }
f5000e
 
f5000e
-                            /* encode the password */
f5000e
+            pb = slapi_pblock_new();
f5000e
+            slapi_search_internal_set_pb(pb, "cn=config",
f5000e
+                LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
f5000e
+                (void *)plugin_get_default_component_id(),
f5000e
+                SLAPI_OP_FLAG_IGNORE_UNINDEXED);
f5000e
+            slapi_search_internal_pb(pb);
f5000e
+            slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
f5000e
+            for (ii = 0; entries && entries[ii]; ii++){
f5000e
+                if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
f5000e
+                    if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
f5000e
+                        /*
f5000e
+                         * We have a DES encoded password, convert it to AES
f5000e
+                         */
f5000e
+                        Slapi_PBlock *mod_pb = NULL;
f5000e
+                        Slapi_Value *sval = NULL;
f5000e
+                        LDAPMod mod_replace;
f5000e
+                        LDAPMod *mods[2];
f5000e
+                        char *replace_val[2];
f5000e
+                        char *passwd = NULL;
f5000e
+                        int rc = 0;
f5000e
+
f5000e
+                        /* decode the DES password */
f5000e
+                        if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
f5000e
+                            slapi_log_error(SLAPI_LOG_FATAL ,"convert_pbe_des_to_aes",
f5000e
+                                    "Failed to decode existing DES password for (%s)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]));
f5000e
+                            rc = -1;
f5000e
+                        }
f5000e
+
f5000e
+                        /* encode the password */
f5000e
+                        if (rc == 0){
f5000e
                             sval = slapi_value_new_string(passwd);
f5000e
                             if(pw_rever_encode(&sval, attrs[i]) == -1){
f5000e
-                                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes",
f5000e
                                         "failed to encode AES password for (%s)\n",
f5000e
-                                        slapi_entry_get_dn(entries[ii]), 0, 0);
f5000e
-                                slapi_ch_free_string(&passwd);
f5000e
-                                slapi_value_free(&sval);
f5000e
-                                disable_des = 0;
f5000e
-                                goto done;
f5000e
+                                        slapi_entry_get_dn(entries[ii]));
f5000e
+                                rc = -1;
f5000e
                             }
f5000e
+                        }
f5000e
 
f5000e
+                        if (rc == 0){
f5000e
                             /* replace the attribute in the entry */
f5000e
                             replace_val[0] = (char *)slapi_value_get_string(sval);
f5000e
                             replace_val[1] = NULL;
f5000e
@@ -837,83 +797,34 @@ convert_pbe_des_to_aes()
f5000e
 
f5000e
                             slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
f5000e
                             if (LDAP_SUCCESS != result) {
f5000e
-                                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes"
f5000e
                                         "Failed to convert password for (%s) error (%d)\n",
f5000e
-                                        slapi_entry_get_dn(entries[ii]), result, 0);
f5000e
-                                disable_des = 0;
f5000e
+                                        slapi_entry_get_dn(entries[ii]), result);
f5000e
                             } else {
f5000e
-                                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
+                                slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes",
f5000e
                                         "Successfully converted password for (%s)\n",
f5000e
-                                         slapi_entry_get_dn(entries[ii]), result, 0);
f5000e
+                                         slapi_entry_get_dn(entries[ii]));
f5000e
                                 converted_des_passwd = 1;
f5000e
                             }
f5000e
-                            slapi_ch_free_string(&passwd);
f5000e
-                            slapi_value_free(&sval);
f5000e
-                            slapi_pblock_destroy(mod_pb);
f5000e
                         }
f5000e
-                        slapi_ch_free_string(&val;;
f5000e
+                        slapi_ch_free_string(&passwd);
f5000e
+                        slapi_value_free(&sval);
f5000e
+                        slapi_pblock_destroy(mod_pb);
f5000e
                     }
f5000e
+                    slapi_ch_free_string(&val;;
f5000e
                 }
f5000e
-                slapi_free_search_results_internal(pb);
f5000e
-                slapi_pblock_destroy(pb);
f5000e
-                pb = NULL;
f5000e
             }
f5000e
+            slapi_free_search_results_internal(pb);
f5000e
+            slapi_pblock_destroy(pb);
f5000e
+            pb = NULL;
f5000e
             slapi_ch_free_string(&filter);
f5000e
         }
f5000e
         if (!converted_des_passwd){
f5000e
-            slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes",
f5000e
+            slapi_log_error(SLAPI_LOG_HOUSE, "convert_pbe_des_to_aes",
f5000e
                 "No DES passwords found to convert.\n");
f5000e
         }
f5000e
     }
f5000e
-
f5000e
-done:
f5000e
     charray_free(attrs);
f5000e
-    charray_free(backends);
f5000e
-    slapi_free_search_results_internal(pb);
f5000e
-    slapi_pblock_destroy(pb);
f5000e
-
f5000e
-    if (have_aes && have_des){
f5000e
-        /*
f5000e
-         * If a conversion attempt did not fail then we can disable the DES plugin
f5000e
-         */
f5000e
-        if(converted_des_passwd && disable_des){
f5000e
-            /*
f5000e
-             * Disable the DES plugin - this also prevents potentially expensive
f5000e
-             * searches at every server startup.
f5000e
-             */
f5000e
-            LDAPMod mod_replace;
f5000e
-            LDAPMod *mods[2];
f5000e
-            char *replace_val[2];
f5000e
-            char *des_dn = "cn=DES,cn=Password Storage Schemes,cn=plugins,cn=config";
f5000e
-
f5000e
-            replace_val[0] = "off";
f5000e
-            replace_val[1] = NULL;
f5000e
-            mod_replace.mod_op = LDAP_MOD_REPLACE;
f5000e
-            mod_replace.mod_type = "nsslapd-pluginEnabled";
f5000e
-            mod_replace.mod_values = replace_val;
f5000e
-            mods[0] = &mod_replace;
f5000e
-            mods[1] = 0;
f5000e
-
f5000e
-            pb = slapi_pblock_new();
f5000e
-            slapi_modify_internal_set_pb(pb, des_dn, mods, 0, 0,
f5000e
-                    (void *)plugin_get_default_component_id(), 0);
f5000e
-            slapi_modify_internal_pb(pb);
f5000e
-            slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
f5000e
-            if (LDAP_SUCCESS != result) {
f5000e
-                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
-                        "Failed to disable DES plugin (%s), error (%d)\n",
f5000e
-                        des_dn, result, 0);
f5000e
-            } else {
f5000e
-                LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
-                        "Successfully disabled DES plugin (%s)\n",
f5000e
-                        des_dn, 0, 0);
f5000e
-            }
f5000e
-            slapi_pblock_destroy(pb);
f5000e
-            LDAPDebug(LDAP_DEBUG_ANY,"convert_pbe_des_to_aes: "
f5000e
-                      "All DES passwords have been converted to AES.\n",
f5000e
-                      0, 0, 0);
f5000e
-        }
f5000e
-    }
f5000e
 }
f5000e
 
f5000e
 #ifdef ENABLE_NUNC_STANS
f5000e
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
f5000e
index 4e222d7..883ef80 100644
f5000e
--- a/ldap/servers/slapd/pw.c
f5000e
+++ b/ldap/servers/slapd/pw.c
f5000e
@@ -516,10 +516,10 @@ pw_rever_encode(Slapi_Value **vals, char * attr_name)
f5000e
 	for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
f5000e
 	{
f5000e
 		char *L_attr = NULL;
f5000e
-		int i = 0;
f5000e
+		int i = 0, ii = 0;
f5000e
 
f5000e
 		/* Get the appropriate encoding function */
f5000e
-		for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
f5000e
+		for ( L_attr = p->plg_argv[ii]; ii<p->plg_argc; L_attr = p->plg_argv[++ii] )
f5000e
 		{
f5000e
 			if (slapi_attr_types_equivalent(L_attr, attr_name))
f5000e
 			{
f5000e
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
f5000e
index db3c222..405f0bf 100644
f5000e
--- a/ldap/servers/slapd/task.c
f5000e
+++ b/ldap/servers/slapd/task.c
f5000e
@@ -53,6 +53,8 @@ static int shutting_down = 0;
f5000e
 #define TASK_TOMBSTONE_FIXUP_BACKEND "backend"
f5000e
 #define TASK_TOMBSTONE_FIXUP_SUFFIX "suffix"
f5000e
 #define TASK_TOMBSTONE_FIXUP_STRIPCSN "stripcsn"
f5000e
+#define TASK_DES2AES "des2aes task"
f5000e
+
f5000e
 
f5000e
 #define LOG_BUFFER              256
f5000e
 /* if the cumul. log gets larger than this, it's truncated: */
f5000e
@@ -83,8 +85,10 @@ static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
f5000e
                               const char *default_val);
f5000e
 static Slapi_Entry *get_internal_entry(Slapi_PBlock *pb, char *dn);
f5000e
 static void modify_internal_entry(char *dn, LDAPMod **mods);
f5000e
-
f5000e
 static void fixup_tombstone_task_destructor(Slapi_Task *task);
f5000e
+static void task_des2aes_thread(void *arg);
f5000e
+static void des2aes_task_destructor(Slapi_Task *task);
f5000e
+
f5000e
 
f5000e
 /***********************************
f5000e
  * Public Functions
f5000e
@@ -2425,6 +2429,345 @@ fixup_tombstone_task_destructor(Slapi_Task *task)
f5000e
                     "fixup_tombstone_task_destructor <--\n" );
f5000e
 }
f5000e
 
f5000e
+/*
f5000e
+ * des2aes Task
f5000e
+ *
f5000e
+ * Convert any DES passwords to AES
f5000e
+ *
f5000e
+ * dn: cn=convertPasswords, cn=des2aes,cn=tasks,cn=config
f5000e
+ * objectclass: top
f5000e
+ * objectclass: extensibleObject
f5000e
+ * suffix: dc=example,dc=com (If empty all backends are checked)
f5000e
+ * suffix: dc=other,dc=suffix
f5000e
+ */
f5000e
+struct task_des2aes_data
f5000e
+{
f5000e
+    char **suffixes;
f5000e
+    Slapi_Task *task;
f5000e
+};
f5000e
+
f5000e
+static int
f5000e
+task_des2aes(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
f5000e
+             int *returncode, char *returntext, void *arg)
f5000e
+{
f5000e
+    struct task_des2aes_data *task_data = NULL;
f5000e
+    PRThread *thread = NULL;
f5000e
+    Slapi_Task *task = NULL;
f5000e
+    char **suffix = NULL;
f5000e
+    char **bases = NULL;
f5000e
+    int rc = SLAPI_DSE_CALLBACK_OK;
f5000e
+
f5000e
+    /* Get the suffixes */
f5000e
+    if((suffix = slapi_entry_attr_get_charray(e, "suffix"))){
f5000e
+        int i;
f5000e
+        for (i = 0; suffix && suffix[i]; i++){
f5000e
+            /* Make sure "suffix" is NUL terminated string */
f5000e
+            char *dn = slapi_create_dn_string("%s", suffix[i]);
f5000e
+
f5000e
+            if(dn){
f5000e
+                if(slapi_dn_syntax_check(pb, dn, 1)){
f5000e
+                    /* invalid suffix name */
f5000e
+                    PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f5000e
+                        "Invalid DN syntax (%s) specified for \"suffix\"\n",
f5000e
+                        suffix[i]);
f5000e
+                    *returncode = LDAP_INVALID_DN_SYNTAX;
f5000e
+                    slapi_ch_free_string(&dn;;
f5000e
+                    rc = SLAPI_DSE_CALLBACK_ERROR;
f5000e
+                    goto error;
f5000e
+                } else {
f5000e
+                    slapi_ch_array_add(&bases, dn);
f5000e
+                }
f5000e
+            } else{
f5000e
+                PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f5000e
+                    "Invalid DN (%s) specified for \"suffix\"\n", suffix[i]);
f5000e
+                    *returncode = LDAP_INVALID_DN_SYNTAX;
f5000e
+                rc = SLAPI_DSE_CALLBACK_ERROR;
f5000e
+                goto error;
f5000e
+            }
f5000e
+        }
f5000e
+    }
f5000e
+
f5000e
+    /* Build the task data and fire off a thread to perform the conversion */
f5000e
+    task = slapi_new_task(slapi_entry_get_ndn(e));
f5000e
+
f5000e
+    /* register our destructor for cleaning up our private data */
f5000e
+    slapi_task_set_destructor_fn(task, des2aes_task_destructor);
f5000e
+    task_data = (struct task_des2aes_data *)slapi_ch_calloc(1, sizeof(struct task_des2aes_data));
f5000e
+    task_data->suffixes = bases;
f5000e
+    task_data->task = task;
f5000e
+
f5000e
+    /* Start the conversion thread */
f5000e
+    thread = PR_CreateThread(PR_USER_THREAD, task_des2aes_thread,
f5000e
+                             (void *)task_data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
f5000e
+                             PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
f5000e
+    if (thread == NULL) {
f5000e
+        PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
f5000e
+                "unable to create des2aes thread!\n");
f5000e
+        slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                        "unable to create des2aes thread!\n");
f5000e
+        *returncode = LDAP_OPERATIONS_ERROR;
f5000e
+        slapi_task_finish(task, *returncode);
f5000e
+        rc = SLAPI_DSE_CALLBACK_ERROR;
f5000e
+    }
f5000e
+
f5000e
+error:
f5000e
+    if (rc == SLAPI_DSE_CALLBACK_ERROR){
f5000e
+        slapi_ch_array_free(bases);
f5000e
+        slapi_ch_array_free(suffix);
f5000e
+        slapi_ch_free((void **)&task_data);
f5000e
+    }
f5000e
+    return rc;
f5000e
+}
f5000e
+
f5000e
+static void
f5000e
+task_des2aes_thread(void *arg)
f5000e
+{
f5000e
+    struct task_des2aes_data *task_data = arg;
f5000e
+    Slapi_PBlock *pb = NULL;
f5000e
+    Slapi_Entry **entries = NULL;
f5000e
+    Slapi_Task *task = task_data->task;
f5000e
+    struct slapdplugin *plugin = NULL;
f5000e
+    char **attrs = NULL;
f5000e
+    char **backends = NULL;
f5000e
+    char *val = NULL;
f5000e
+    int converted_des_passwd = 0;
f5000e
+    int result = -1;
f5000e
+    int have_aes = 0;
f5000e
+    int have_des = 0;
f5000e
+    int i = 0, ii = 0, be_idx = 0;
f5000e
+    int rc = 0;
f5000e
+
f5000e
+    /*
f5000e
+     * Check that AES plugin is enabled, and grab all the unique
f5000e
+     * password attributes.
f5000e
+     */
f5000e
+    for ( plugin = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME);
f5000e
+          plugin != NULL;
f5000e
+          plugin = plugin->plg_next )
f5000e
+    {
f5000e
+        char *plugin_arg = NULL;
f5000e
+
f5000e
+        if(plugin->plg_started && strcasecmp(plugin->plg_name, "AES") == 0){
f5000e
+            /* We have the AES plugin, and its enabled */
f5000e
+            have_aes = 1;
f5000e
+        }
f5000e
+        if(plugin->plg_started && strcasecmp(plugin->plg_name, "DES") == 0){
f5000e
+            /* We have the DES plugin, and its enabled */
f5000e
+            have_des = 1;
f5000e
+        }
f5000e
+        /* Gather all the unique password attributes from all the PBE plugins */
f5000e
+        for ( i = 0, plugin_arg = plugin->plg_argv[i];
f5000e
+              i < plugin->plg_argc;
f5000e
+              plugin_arg = plugin->plg_argv[++i] )
f5000e
+        {
f5000e
+            if(charray_inlist(attrs, plugin_arg)){
f5000e
+                continue;
f5000e
+            }
f5000e
+            charray_add(&attrs, slapi_ch_strdup(plugin_arg));
f5000e
+        }
f5000e
+    }
f5000e
+
f5000e
+    if(have_aes && have_des){
f5000e
+        if(task_data->suffixes == NULL){
f5000e
+            /*
f5000e
+             * Build a list of all the backend dn's
f5000e
+             */
f5000e
+            Slapi_Backend *be = NULL;
f5000e
+            struct suffixlist *list;
f5000e
+            char *cookie = NULL;
f5000e
+
f5000e
+            slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                "Checking for DES passwords to convert to AES...\n");
f5000e
+            slapi_task_log_notice(task,
f5000e
+                "Checking for DES passwords to convert to AES...\n");
f5000e
+
f5000e
+            be = slapi_get_first_backend(&cookie);
f5000e
+            while (be){
f5000e
+                int suffix_idx = 0;
f5000e
+                int count = slapi_counter_get_value(be->be_suffixcounter);
f5000e
+
f5000e
+                list = be->be_suffixlist;
f5000e
+                for (suffix_idx = 0; list && suffix_idx < count; suffix_idx++) {
f5000e
+                    char *suffix = (char *)slapi_sdn_get_ndn(list->be_suffix);
f5000e
+                    if(charray_inlist(backends, suffix) || strlen(suffix) == 0){
f5000e
+                        list = list->next;
f5000e
+                        continue;
f5000e
+                    }
f5000e
+                    charray_add(&backends, slapi_ch_strdup(suffix));
f5000e
+                    list = list->next;
f5000e
+                }
f5000e
+                be = slapi_get_next_backend (cookie);
f5000e
+            }
f5000e
+            slapi_ch_free ((void **)&cookie);
f5000e
+        } else {
f5000e
+            backends = task_data->suffixes;
f5000e
+        }
f5000e
+
f5000e
+        /*
f5000e
+         * Search for the password attributes
f5000e
+         */
f5000e
+        for (i = 0; attrs && attrs[i]; i++){
f5000e
+            char *filter = PR_smprintf("%s=*", attrs[i]);
f5000e
+            /*
f5000e
+             * Loop over all the backends looking for the password attribute
f5000e
+             */
f5000e
+            for(be_idx = 0; backends && backends[be_idx]; be_idx++){
f5000e
+                pb = slapi_pblock_new();
f5000e
+                slapi_search_internal_set_pb(pb, backends[be_idx],
f5000e
+                        LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
f5000e
+                        (void *)plugin_get_default_component_id(),
f5000e
+                        SLAPI_OP_FLAG_IGNORE_UNINDEXED);
f5000e
+                slapi_search_internal_pb(pb);
f5000e
+                slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
f5000e
+                if (LDAP_SUCCESS != result) {
f5000e
+                    slapi_log_error(SLAPI_LOG_FATAL, "convert_pbe_des_to_aes: ",
f5000e
+                        "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
f5000e
+                        attrs[i], result, backends[be_idx]);
f5000e
+                    slapi_task_log_notice(task,
f5000e
+                        "Failed to search for password attribute (%s) error (%d), skipping suffix (%s)\n",
f5000e
+                        attrs[i], result, backends[be_idx]);
f5000e
+                    slapi_free_search_results_internal(pb);
f5000e
+                    slapi_pblock_destroy(pb);
f5000e
+                    pb = NULL;
f5000e
+                    continue;
f5000e
+                }
f5000e
+                slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
f5000e
+                for (ii = 0; entries && entries[ii]; ii++){
f5000e
+                    if((val = slapi_entry_attr_get_charptr(entries[ii], attrs[i]))){
f5000e
+                        if(strlen(val) >= 5 && strncmp(val,"{DES}", 5) == 0){
f5000e
+                            /*
f5000e
+                             * We have a DES encoded password, convert it AES
f5000e
+                             */
f5000e
+                            Slapi_PBlock *mod_pb = NULL;
f5000e
+                            Slapi_Value *sval = NULL;
f5000e
+                            LDAPMod mod_replace;
f5000e
+                            LDAPMod *mods[2];
f5000e
+                            char *replace_val[2];
f5000e
+                            char *passwd = NULL;
f5000e
+
f5000e
+                            /* Decode the DES password */
f5000e
+                            if(pw_rever_decode(val, &passwd, attrs[i]) == -1){
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                                        "Failed to decode existing DES password for (%s)\n",
f5000e
+                                        slapi_entry_get_dn(entries[ii]));
f5000e
+                                slapi_task_log_notice(task,
f5000e
+                                    "Failed to decode existing DES password for (%s)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]));
f5000e
+                                rc = 1;
f5000e
+                                goto done;
f5000e
+                            }
f5000e
+
f5000e
+                            /* Encode the password */
f5000e
+                            sval = slapi_value_new_string(passwd);
f5000e
+                            if(pw_rever_encode(&sval, attrs[i]) == -1){
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                                    "failed to encode AES password for (%s)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]));
f5000e
+                                slapi_task_log_notice(task,
f5000e
+                                    "failed to encode AES password for (%s)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]));
f5000e
+                                slapi_ch_free_string(&passwd);
f5000e
+                                slapi_value_free(&sval);
f5000e
+                                rc = 1;
f5000e
+                                goto done;
f5000e
+                            }
f5000e
+
f5000e
+                            /* Replace the attribute in the entry */
f5000e
+                            replace_val[0] = (char *)slapi_value_get_string(sval);
f5000e
+                            replace_val[1] = NULL;
f5000e
+                            mod_replace.mod_op = LDAP_MOD_REPLACE;
f5000e
+                            mod_replace.mod_type = attrs[i];
f5000e
+                            mod_replace.mod_values = replace_val;
f5000e
+                            mods[0] = &mod_replace;
f5000e
+                            mods[1] = 0;
f5000e
+
f5000e
+                            mod_pb = slapi_pblock_new();
f5000e
+                            slapi_modify_internal_set_pb(mod_pb, slapi_entry_get_dn(entries[ii]),
f5000e
+                                    mods, 0, 0, (void *)plugin_get_default_component_id(), 0);
f5000e
+                            slapi_modify_internal_pb(mod_pb);
f5000e
+
f5000e
+                            slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
f5000e
+                            if (LDAP_SUCCESS != result) {
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                                    "Failed to convert password for (%s) error (%d)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]), result);
f5000e
+                                slapi_task_log_notice(task,
f5000e
+                                    "Failed to convert password for (%s) error (%d)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]), result);
f5000e
+                                rc = 1;
f5000e
+                            } else {
f5000e
+                                slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                                    "Successfully converted password for (%s)\n",
f5000e
+                                     slapi_entry_get_dn(entries[ii]));
f5000e
+                                slapi_task_log_notice(task,
f5000e
+                                   "Successfully converted password for (%s)\n",
f5000e
+                                    slapi_entry_get_dn(entries[ii]));
f5000e
+                                converted_des_passwd = 1;
f5000e
+                            }
f5000e
+                            slapi_ch_free_string(&passwd);
f5000e
+                            slapi_value_free(&sval);
f5000e
+                            slapi_pblock_destroy(mod_pb);
f5000e
+                        }
f5000e
+                        slapi_ch_free_string(&val;;
f5000e
+                    }
f5000e
+                }
f5000e
+                slapi_free_search_results_internal(pb);
f5000e
+                slapi_pblock_destroy(pb);
f5000e
+                pb = NULL;
f5000e
+            }
f5000e
+            slapi_ch_free_string(&filter);
f5000e
+        }
f5000e
+        if (!converted_des_passwd){
f5000e
+            slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                "No DES passwords found to convert.\n");
f5000e
+            slapi_task_log_notice(task, "No DES passwords found to convert.\n");
f5000e
+        }
f5000e
+    } else {
f5000e
+        /* No AES/DES */
f5000e
+        if (!have_des){
f5000e
+            slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                            "DES plugin not enabled\n");
f5000e
+            slapi_task_log_notice(task, "DES plugin not enabled\n");
f5000e
+        }
f5000e
+        if (!have_aes){
f5000e
+            slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+                        "AES plugin not enabled\n");
f5000e
+            slapi_task_log_notice(task, "AES plugin not enabled\n");
f5000e
+        }
f5000e
+        slapi_log_error(SLAPI_LOG_FATAL, TASK_DES2AES,
f5000e
+            "Unable to convert passwords\n");
f5000e
+        slapi_task_log_notice(task, "Unable to convert passwords\n");
f5000e
+        rc = 1;
f5000e
+    }
f5000e
+
f5000e
+done:
f5000e
+    charray_free(attrs);
f5000e
+    charray_free(backends);
f5000e
+    slapi_free_search_results_internal(pb);
f5000e
+    slapi_pblock_destroy(pb);
f5000e
+    slapi_task_finish(task, rc);
f5000e
+}
f5000e
+
f5000e
+static void
f5000e
+des2aes_task_destructor(Slapi_Task *task)
f5000e
+{
f5000e
+    slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES,
f5000e
+                    "des2aes_task_destructor -->\n" );
f5000e
+    if (task) {
f5000e
+        struct task_des2aes_data *task_data = (struct task_des2aes_data *)slapi_task_get_data(task);
f5000e
+        while (slapi_task_get_refcount(task) > 0) {
f5000e
+            /* Yield to wait for the task to finish. */
f5000e
+            DS_Sleep (PR_MillisecondsToInterval(100));
f5000e
+        }
f5000e
+        if (task_data) {
f5000e
+            slapi_ch_array_free(task_data->suffixes);
f5000e
+            slapi_ch_free((void **)&task_data);
f5000e
+        }
f5000e
+    }
f5000e
+    slapi_log_error(SLAPI_LOG_TRACE, TASK_DES2AES,
f5000e
+                    "des2aes_task_destructor <--\n" );
f5000e
+}
f5000e
+
f5000e
 /* cleanup old tasks that may still be in the DSE from a previous session
f5000e
  * (this can happen if the server crashes [no matter how unlikely we like
f5000e
  * to think that is].)
f5000e
@@ -2506,6 +2849,7 @@ void task_init(void)
f5000e
     slapi_task_register_handler("upgradedb", task_upgradedb_add);
f5000e
     slapi_task_register_handler("sysconfig reload", task_sysconfig_reload_add);
f5000e
     slapi_task_register_handler("fixup tombstones", task_fixup_tombstones_add);
f5000e
+    slapi_task_register_handler("des2aes", task_des2aes);
f5000e
 }
f5000e
 
f5000e
 /* called when the server is shutting down -- abort all existing tasks */
f5000e
-- 
f5000e
2.4.11
f5000e