|
|
b8da0b |
From 7b7217538908ae58df864ef5cd82e1d3303c189f Mon Sep 17 00:00:00 2001
|
|
|
b8da0b |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
b8da0b |
Date: Mon, 7 Jun 2021 12:58:42 -0400
|
|
|
b8da0b |
Subject: [PATCH] Issue 4447 - Crash when the Referential Integrity log is
|
|
|
b8da0b |
manually edited
|
|
|
b8da0b |
|
|
|
b8da0b |
Bug Description: If the referint log is manually edited with a string
|
|
|
b8da0b |
that is not a DN the server will crash when processing
|
|
|
b8da0b |
the log.
|
|
|
b8da0b |
|
|
|
b8da0b |
Fix Description: Check for NULL pointers when strtoking the file line.
|
|
|
b8da0b |
|
|
|
b8da0b |
relates: https://github.com/389ds/389-ds-base/issues/4447
|
|
|
b8da0b |
|
|
|
b8da0b |
Reviewed by: firstyear(Thanks!)
|
|
|
b8da0b |
---
|
|
|
b8da0b |
.../tests/suites/plugins/referint_test.py | 72 +++++++++++++++----
|
|
|
b8da0b |
ldap/servers/plugins/referint/referint.c | 7 ++
|
|
|
b8da0b |
src/lib389/lib389/plugins.py | 15 ++++
|
|
|
b8da0b |
3 files changed, 80 insertions(+), 14 deletions(-)
|
|
|
b8da0b |
|
|
|
b8da0b |
diff --git a/dirsrvtests/tests/suites/plugins/referint_test.py b/dirsrvtests/tests/suites/plugins/referint_test.py
|
|
|
b8da0b |
index 02b985767..fda602545 100644
|
|
|
b8da0b |
--- a/dirsrvtests/tests/suites/plugins/referint_test.py
|
|
|
b8da0b |
+++ b/dirsrvtests/tests/suites/plugins/referint_test.py
|
|
|
b8da0b |
@@ -1,5 +1,5 @@
|
|
|
b8da0b |
# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
b8da0b |
-# Copyright (C) 2016 Red Hat, Inc.
|
|
|
b8da0b |
+# Copyright (C) 2021 Red Hat, Inc.
|
|
|
b8da0b |
# All rights reserved.
|
|
|
b8da0b |
#
|
|
|
b8da0b |
# License: GPL (version 3 or any later version).
|
|
|
b8da0b |
@@ -12,13 +12,11 @@ Created on Dec 12, 2019
|
|
|
b8da0b |
@author: tbordaz
|
|
|
b8da0b |
'''
|
|
|
b8da0b |
import logging
|
|
|
b8da0b |
-import subprocess
|
|
|
b8da0b |
import pytest
|
|
|
b8da0b |
from lib389 import Entry
|
|
|
b8da0b |
-from lib389.utils import *
|
|
|
b8da0b |
-from lib389.plugins import *
|
|
|
b8da0b |
-from lib389._constants import *
|
|
|
b8da0b |
-from lib389.idm.user import UserAccounts, UserAccount
|
|
|
b8da0b |
+from lib389.plugins import ReferentialIntegrityPlugin
|
|
|
b8da0b |
+from lib389._constants import DEFAULT_SUFFIX
|
|
|
b8da0b |
+from lib389.idm.user import UserAccounts
|
|
|
b8da0b |
from lib389.idm.group import Groups
|
|
|
b8da0b |
from lib389.topologies import topology_st as topo
|
|
|
b8da0b |
|
|
|
b8da0b |
@@ -29,21 +27,27 @@ log = logging.getLogger(__name__)
|
|
|
b8da0b |
ESCAPED_RDN_BASE = "foo\\,oo"
|
|
|
b8da0b |
def _user_get_dn(no):
|
|
|
b8da0b |
uid = '%s%d' % (ESCAPED_RDN_BASE, no)
|
|
|
b8da0b |
- dn = 'uid=%s,%s' % (uid, SUFFIX)
|
|
|
b8da0b |
+ dn = 'uid=%s,%s' % (uid, DEFAULT_SUFFIX)
|
|
|
b8da0b |
return (uid, dn)
|
|
|
b8da0b |
|
|
|
b8da0b |
def add_escaped_user(server, no):
|
|
|
b8da0b |
(uid, dn) = _user_get_dn(no)
|
|
|
b8da0b |
log.fatal('Adding user (%s): ' % dn)
|
|
|
b8da0b |
- server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson'],
|
|
|
b8da0b |
- 'uid': [uid],
|
|
|
b8da0b |
- 'sn' : [uid],
|
|
|
b8da0b |
- 'cn' : [uid]})))
|
|
|
b8da0b |
+ users = UserAccounts(server, DEFAULT_SUFFIX, None)
|
|
|
b8da0b |
+ user_properties = {
|
|
|
b8da0b |
+ 'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount'],
|
|
|
b8da0b |
+ 'uid': uid,
|
|
|
b8da0b |
+ 'cn' : uid,
|
|
|
b8da0b |
+ 'sn' : uid,
|
|
|
b8da0b |
+ 'uidNumber' : '1000',
|
|
|
b8da0b |
+ 'gidNumber' : '2000',
|
|
|
b8da0b |
+ 'homeDirectory' : '/home/testuser',
|
|
|
b8da0b |
+ }
|
|
|
b8da0b |
+ users.create(properties=user_properties)
|
|
|
b8da0b |
return dn
|
|
|
b8da0b |
|
|
|
b8da0b |
-@pytest.mark.ds50020
|
|
|
b8da0b |
def test_referential_false_failure(topo):
|
|
|
b8da0b |
- """On MODRDN referential integrity can erronously fail
|
|
|
b8da0b |
+ """On MODRDN referential integrity can erroneously fail
|
|
|
b8da0b |
|
|
|
b8da0b |
:id: f77aeb80-c4c4-471b-8c1b-4733b714778b
|
|
|
b8da0b |
:setup: Standalone Instance
|
|
|
b8da0b |
@@ -100,6 +104,46 @@ def test_referential_false_failure(topo):
|
|
|
b8da0b |
inst.restart()
|
|
|
b8da0b |
|
|
|
b8da0b |
# Here if the bug is fixed, referential is able to update the member value
|
|
|
b8da0b |
- inst.rename_s(user1.dn, 'uid=new_test_user_1001', newsuperior=SUFFIX, delold=0)
|
|
|
b8da0b |
+ user1.rename('uid=new_test_user_1001', newsuperior=DEFAULT_SUFFIX, deloldrdn=False)
|
|
|
b8da0b |
|
|
|
b8da0b |
|
|
|
b8da0b |
+def test_invalid_referint_log(topo):
|
|
|
b8da0b |
+ """If there is an invalid log line in the referint log, make sure the server
|
|
|
b8da0b |
+ does not crash at startup
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ :id: 34807b5a-ab17-4281-ae48-4e3513e19145
|
|
|
b8da0b |
+ :setup: Standalone Instance
|
|
|
b8da0b |
+ :steps:
|
|
|
b8da0b |
+ 1. Set the referint log delay
|
|
|
b8da0b |
+ 2. Create invalid log
|
|
|
b8da0b |
+ 3. Start the server (no crash)
|
|
|
b8da0b |
+ :expectedresults:
|
|
|
b8da0b |
+ 1. Success
|
|
|
b8da0b |
+ 2. Success
|
|
|
b8da0b |
+ 3. Success
|
|
|
b8da0b |
+ """
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ inst = topo.standalone
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Set delay - required for log parsing at server startup
|
|
|
b8da0b |
+ plugin = ReferentialIntegrityPlugin(inst)
|
|
|
b8da0b |
+ plugin.enable()
|
|
|
b8da0b |
+ plugin.set_update_delay('2')
|
|
|
b8da0b |
+ logfile = plugin.get_log_file()
|
|
|
b8da0b |
+ inst.restart()
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Create invalid log
|
|
|
b8da0b |
+ inst.stop()
|
|
|
b8da0b |
+ with open(logfile, 'w') as log_fh:
|
|
|
b8da0b |
+ log_fh.write("CRASH\n")
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Start the instance
|
|
|
b8da0b |
+ inst.start()
|
|
|
b8da0b |
+ assert inst.status()
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+if __name__ == '__main__':
|
|
|
b8da0b |
+ # Run isolated
|
|
|
b8da0b |
+ # -s for DEBUG mode
|
|
|
b8da0b |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
b8da0b |
+ pytest.main("-s %s" % CURRENT_FILE)
|
|
|
b8da0b |
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
|
|
|
b8da0b |
index fd5356d72..28240c1f6 100644
|
|
|
b8da0b |
--- a/ldap/servers/plugins/referint/referint.c
|
|
|
b8da0b |
+++ b/ldap/servers/plugins/referint/referint.c
|
|
|
b8da0b |
@@ -1447,6 +1447,13 @@ referint_thread_func(void *arg __attribute__((unused)))
|
|
|
b8da0b |
sdn = slapi_sdn_new_normdn_byref(ptoken);
|
|
|
b8da0b |
ptoken = ldap_utf8strtok_r(NULL, delimiter, &iter);
|
|
|
b8da0b |
|
|
|
b8da0b |
+ if (ptoken == NULL) {
|
|
|
b8da0b |
+ /* Invalid line in referint log, skip it */
|
|
|
b8da0b |
+ slapi_log_err(SLAPI_LOG_ERR, REFERINT_PLUGIN_SUBSYSTEM,
|
|
|
b8da0b |
+ "Skipping invalid referint log line: (%s)\n", thisline);
|
|
|
b8da0b |
+ slapi_sdn_free(&sdn;;
|
|
|
b8da0b |
+ continue;
|
|
|
b8da0b |
+ }
|
|
|
b8da0b |
if (!strcasecmp(ptoken, "NULL")) {
|
|
|
b8da0b |
tmprdn = NULL;
|
|
|
b8da0b |
} else {
|
|
|
b8da0b |
diff --git a/src/lib389/lib389/plugins.py b/src/lib389/lib389/plugins.py
|
|
|
b8da0b |
index 2d88e60bd..b07e80022 100644
|
|
|
b8da0b |
--- a/src/lib389/lib389/plugins.py
|
|
|
b8da0b |
+++ b/src/lib389/lib389/plugins.py
|
|
|
b8da0b |
@@ -518,6 +518,21 @@ class ReferentialIntegrityPlugin(Plugin):
|
|
|
b8da0b |
|
|
|
b8da0b |
self.set('referint-update-delay', str(value))
|
|
|
b8da0b |
|
|
|
b8da0b |
+ def get_log_file(self):
|
|
|
b8da0b |
+ """Get referint log file"""
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ return self.get_attr_val_utf8('referint-logfile')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ def get_log_file_formatted(self):
|
|
|
b8da0b |
+ """Get referint log file"""
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ return self.display_attr('referint-logfile')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ def set_log_file(self, value):
|
|
|
b8da0b |
+ """Set referint log file"""
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ self.set('referint-logfile', value)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
def get_membership_attr(self, formatted=False):
|
|
|
b8da0b |
"""Get referint-membership-attr attribute"""
|
|
|
b8da0b |
|
|
|
b8da0b |
--
|
|
|
b8da0b |
2.31.1
|
|
|
b8da0b |
|