|
|
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 |
|