Commit 6287a9b8 authored by Rocky Automation's avatar Rocky Automation 📺
Browse files

import 389-ds-base-1.4.3.28-6.module+el8.6.0+14129+983ceada

parents
9274c7088190993255749ea90bbb770c5c5e0f5c SOURCES/389-ds-base-1.4.3.28.tar.bz2
9e06b5cc57fd185379d007696da153893cf73e30 SOURCES/jemalloc-5.2.1.tar.bz2
c6875530163f0e217ed2e0e5b768506db3d07447 SOURCES/vendor-1.4.3.28-1.tar.gz
SOURCES/389-ds-base-1.4.3.28.tar.bz2
SOURCES/jemalloc-5.2.1.tar.bz2
SOURCES/vendor-1.4.3.28-1.tar.gz
From 957ffd53b041c19d27753a028e6f514dcc75dfbd Mon Sep 17 00:00:00 2001
From: Simon Pichugin <spichugi@redhat.com>
Date: Tue, 26 Oct 2021 15:51:24 -0700
Subject: [PATCH 03/12] Issue 3584 - Fix PBKDF2_SHA256 hashing in FIPS mode
(#4949)
Issue Description: Use PK11_Decrypt function to get hash data
because PK11_ExtractKeyValue function is forbidden in FIPS mode.
We can't extract keys while in FIPS mode. But we use PK11_ExtractKeyValue
for hashes, and it's not forbidden.
We can't use OpenSSL's PBKDF2-SHA256 implementation right now because
we need to support an upgrade procedure while in FIPS mode (update
hash on bind). For that, we should fix existing PBKDF2 usage, and we can
switch to OpenSSL's PBKDF2-SHA256 in the following versions.
Fix Description: Use PK11_Decrypt function to get the data.
Enable TLS on all CI test topologies while in FIPS because without
that we don't set up the NSS database correctly.
Add PBKDF2-SHA256 (OpenSSL) to ldif templates, so the password scheme is
discoverable by internal functions.
https://github.com/389ds/389-ds-base/issues/3584
Reviewed by: @progier389, @mreynolds389, @Firstyear, @tbordaz (Thanks!!)
---
.../healthcheck/health_security_test.py | 10 ---
ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c | 62 ++++++++++++++++---
ldap/servers/slapd/main.c | 12 ++++
src/lib389/lib389/__init__.py | 4 ++
src/lib389/lib389/topologies.py | 6 +-
src/lib389/lib389/utils.py | 13 ++++
6 files changed, 86 insertions(+), 21 deletions(-)
diff --git a/dirsrvtests/tests/suites/healthcheck/health_security_test.py b/dirsrvtests/tests/suites/healthcheck/health_security_test.py
index 6c0d27aaa..c1dc7938c 100644
--- a/dirsrvtests/tests/suites/healthcheck/health_security_test.py
+++ b/dirsrvtests/tests/suites/healthcheck/health_security_test.py
@@ -40,16 +40,6 @@ else:
log = logging.getLogger(__name__)
-def is_fips():
- if os.path.exists('/proc/sys/crypto/fips_enabled'):
- with open('/proc/sys/crypto/fips_enabled', 'r') as f:
- state = f.readline().strip()
- if state == '1':
- return True
- else:
- return False
-
-
def run_healthcheck_and_flush_log(topology, instance, searched_code, json, searched_code2=None):
args = FakeArgs()
args.instance = instance.serverid
diff --git a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
index d310dc792..dcac4fcdd 100644
--- a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
@@ -91,10 +91,11 @@ pbkdf2_sha256_extract(char *hash_in, SECItem *salt, uint32_t *iterations)
SECStatus
pbkdf2_sha256_hash(char *hash_out, size_t hash_out_len, SECItem *pwd, SECItem *salt, uint32_t iterations)
{
- SECItem *result = NULL;
SECAlgorithmID *algid = NULL;
PK11SlotInfo *slot = NULL;
PK11SymKey *symkey = NULL;
+ SECItem *wrapKeyData = NULL;
+ SECStatus rv = SECFailure;
/* We assume that NSS is already started. */
algid = PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA256, SEC_OID_HMAC_SHA256, hash_out_len, iterations, salt);
@@ -104,7 +105,6 @@ pbkdf2_sha256_hash(char *hash_out, size_t hash_out_len, SECItem *pwd, SECItem *s
slot = PK11_GetBestSlotMultiple(mechanism_array, 2, NULL);
if (slot != NULL) {
symkey = PK11_PBEKeyGen(slot, algid, pwd, PR_FALSE, NULL);
- PK11_FreeSlot(slot);
if (symkey == NULL) {
/* We try to get the Error here but NSS has two or more error interfaces, and sometimes it uses none of them. */
int32_t status = PORT_GetError();
@@ -123,18 +123,60 @@ pbkdf2_sha256_hash(char *hash_out, size_t hash_out_len, SECItem *pwd, SECItem *s
return SECFailure;
}
- if (PK11_ExtractKeyValue(symkey) == SECSuccess) {
- result = PK11_GetKeyData(symkey);
- if (result != NULL && result->len <= hash_out_len) {
- memcpy(hash_out, result->data, result->len);
- PK11_FreeSymKey(symkey);
+ /*
+ * First, we need to generate a wrapped key for PK11_Decrypt call:
+ * slot is the same slot we used in PK11_PBEKeyGen()
+ * 256 bits / 8 bit per byte
+ */
+ PK11SymKey *wrapKey = PK11_KeyGen(slot, CKM_AES_ECB, NULL, 256/8, NULL);
+ PK11_FreeSlot(slot);
+ if (wrapKey == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "pbkdf2_sha256_hash", "Unable to generate a wrapped key.\n");
+ return SECFailure;
+ }
+
+ wrapKeyData = (SECItem *)PORT_Alloc(sizeof(SECItem));
+ /* Align the wrapped key with 32 bytes. */
+ wrapKeyData->len = (PK11_GetKeyLength(symkey) + 31) & ~31;
+ /* Allocate the aligned space for pkc5PBE key plus AESKey block */
+ wrapKeyData->data = (unsigned char *)slapi_ch_calloc(wrapKeyData->len, sizeof(unsigned char));
+
+ /* Get symkey wrapped with wrapKey - required for PK11_Decrypt call */
+ rv = PK11_WrapSymKey(CKM_AES_ECB, NULL, wrapKey, symkey, wrapKeyData);
+ if (rv != SECSuccess) {
+ PK11_FreeSymKey(symkey);
+ PK11_FreeSymKey(wrapKey);
+ SECITEM_FreeItem(wrapKeyData, PR_TRUE);
+ slapi_log_err(SLAPI_LOG_ERR, "pbkdf2_sha256_hash", "Unable to wrap the symkey. (%d)\n", rv);
+ return SECFailure;
+ }
+
+ /* Allocate the space for our result */
+ void *result = (char *)slapi_ch_calloc(wrapKeyData->len, sizeof(char));
+ unsigned int result_len = 0;
+
+ /* User wrapKey to decrypt the wrapped contents.
+ * result is the hash that we need;
+ * result_len is the actual lengh of the data;
+ * has_out_len is the maximum (the space we allocted for hash_out)
+ */
+ rv = PK11_Decrypt(wrapKey, CKM_AES_ECB, NULL, result, &result_len, hash_out_len, wrapKeyData->data, wrapKeyData->len);
+ PK11_FreeSymKey(symkey);
+ PK11_FreeSymKey(wrapKey);
+ SECITEM_FreeItem(wrapKeyData, PR_TRUE);
+
+ if (rv == SECSuccess) {
+ if (result != NULL && result_len <= hash_out_len) {
+ memcpy(hash_out, result, result_len);
+ slapi_ch_free((void **)&result);
} else {
- PK11_FreeSymKey(symkey);
- slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to retrieve (get) hash output.\n");
+ slapi_log_err(SLAPI_LOG_ERR, "pbkdf2_sha256_hash", "Unable to retrieve (get) hash output.\n");
+ slapi_ch_free((void **)&result);
return SECFailure;
}
} else {
- slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to extract hash output.\n");
+ slapi_log_err(SLAPI_LOG_ERR, "pbkdf2_sha256_hash", "Unable to extract hash output. (%d)\n", rv);
+ slapi_ch_free((void **)&result);
return SECFailure;
}
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 61ed40b7d..04d0494f8 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -2895,9 +2895,21 @@ slapd_do_all_nss_ssl_init(int slapd_exemode, int importexport_encrypt, int s_por
* is enabled or not. We use NSS for random number generation and
* other things even if we are not going to accept SSL connections.
* We also need NSS for attribute encryption/decryption on import and export.
+ *
+ * It's important to remember that while in FIPS mode the administrator should always enable
+ * the security, otherwise we don't call slapd_pk11_authenticate which is a requirement for FIPS mode
*/
+ PRBool isFIPS = slapd_pk11_isFIPS();
int init_ssl = config_get_security();
+ if (isFIPS && !init_ssl) {
+ slapi_log_err(SLAPI_LOG_WARNING, "slapd_do_all_nss_ssl_init",
+ "ERROR: TLS is not enabled, and the machine is in FIPS mode. "
+ "Some functionality won't work correctly (for example, "
+ "users with PBKDF2_SHA256 password scheme won't be able to log in). "
+ "It's highly advisable to enable TLS on this instance.\n");
+ }
+
if (slapd_exemode == SLAPD_EXEMODE_SLAPD) {
init_ssl = init_ssl && (0 != s_port) && (s_port <= LDAP_PORT_MAX);
} else {
diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py
index 29ee5245a..e0299c5b4 100644
--- a/src/lib389/lib389/__init__.py
+++ b/src/lib389/lib389/__init__.py
@@ -1588,6 +1588,10 @@ class DirSrv(SimpleLDAPObject, object):
:param post_open: Open the server connection after restart.
:type post_open: bool
"""
+ if self.config.get_attr_val_utf8_l("nsslapd-security") == 'on':
+ self.restart(post_open=post_open)
+ return
+
# If it doesn't exist, create a cadb.
ssca = NssSsl(dbpath=self.get_ssca_dir())
if not ssca._db_exists():
diff --git a/src/lib389/lib389/topologies.py b/src/lib389/lib389/topologies.py
index e9969f524..e7d56582d 100644
--- a/src/lib389/lib389/topologies.py
+++ b/src/lib389/lib389/topologies.py
@@ -15,7 +15,7 @@ import socket
import pytest
from lib389 import DirSrv
-from lib389.utils import generate_ds_params
+from lib389.utils import generate_ds_params, is_fips
from lib389.mit_krb5 import MitKrb5
from lib389.saslmap import SaslMappings
from lib389.replica import ReplicationManager, Replicas
@@ -108,6 +108,10 @@ def _create_instances(topo_dict, suffix):
if role == ReplicaRole.HUB:
hs[instance.serverid] = instance
instances.update(hs)
+ # We should always enable TLS while in FIPS mode because otherwise NSS database won't be
+ # configured in a FIPS compliant way
+ if is_fips():
+ instance.enable_tls()
log.info("Instance with parameters {} was created.".format(args_instance))
if "standalone1" in instances and len(instances) == 1:
diff --git a/src/lib389/lib389/utils.py b/src/lib389/lib389/utils.py
index b270784ce..5ba0c6676 100644
--- a/src/lib389/lib389/utils.py
+++ b/src/lib389/lib389/utils.py
@@ -1430,3 +1430,16 @@ def is_valid_hostname(hostname):
hostname = hostname[:-1] # strip exactly one dot from the right, if present
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
+
+
+def is_fips():
+ if os.path.exists('/proc/sys/crypto/fips_enabled'):
+ with open('/proc/sys/crypto/fips_enabled', 'r') as f:
+ state = f.readline().strip()
+ if state == '1':
+ return True
+ else:
+ return False
+ else:
+ return False
+
--
2.31.1
From d037688c072c4cb84fbf9b2a6cb24927f7950605 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 20 Oct 2021 10:04:06 -0400
Subject: [PATCH 04/12] Issue 4956 - Automember allows invalid regex, and does
not log proper error
Bug Description: The server was detecting an invalid automember
regex, but it did not reject it, and it did not
log which regex rule was invalid.
Fix Description: By properly rejecting the invalid regex will also
trigger the proper error logging to occur.
relates: https://github.com/389ds/389-ds-base/issues/4956
Reviewed by: tbordaz & spichugi(Thanks!!)
---
.../automember_plugin/configuration_test.py | 49 +++++++++++++++++--
ldap/servers/plugins/automember/automember.c | 1 +
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/dirsrvtests/tests/suites/automember_plugin/configuration_test.py b/dirsrvtests/tests/suites/automember_plugin/configuration_test.py
index 0f9cc49dc..4a6b596db 100644
--- a/dirsrvtests/tests/suites/automember_plugin/configuration_test.py
+++ b/dirsrvtests/tests/suites/automember_plugin/configuration_test.py
@@ -1,21 +1,20 @@
# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2019 Red Hat, Inc.
+# Copyright (C) 2021 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details.
# --- END COPYRIGHT BLOCK ---
+import ldap
import os
import pytest
-
from lib389.topologies import topology_st as topo
from lib389.plugins import AutoMembershipPlugin, AutoMembershipDefinitions, MemberOfPlugin
-import ldap
+from lib389._constants import DEFAULT_SUFFIX
pytestmark = pytest.mark.tier1
-
@pytest.mark.bz834056
def test_configuration(topo):
"""
@@ -52,6 +51,48 @@ def test_configuration(topo):
'"cn=SuffDef1,ou=autouserGroups,cn=config" '
'can not be a child of the plugin config area "cn=config"')
+def test_invalid_regex(topo):
+ """Test invalid regex is properly reportedin the error log
+
+ :id: a6d89f84-ec76-4871-be96-411d051800b1
+ :setup: Standalone Instance
+ :steps:
+ 1. Setup automember
+ 2. Add invalid regex
+ 3. Error log reports useful message
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ """
+ REGEX_DN = "cn=regex1,cn=testregex,cn=auto membership plugin,cn=plugins,cn=config"
+ REGEX_VALUE = "cn=*invalid*"
+ REGEX_ESC_VALUE = "cn=\\*invalid\\*"
+ GROUP_DN = "cn=demo_group,ou=groups," + DEFAULT_SUFFIX
+
+ AutoMembershipPlugin(topo.standalone).remove_all("nsslapd-pluginConfigArea")
+ automemberplugin = AutoMembershipPlugin(topo.standalone)
+
+ automember_prop = {
+ 'cn': 'testRegex',
+ 'autoMemberScope': 'ou=People,' + DEFAULT_SUFFIX,
+ 'autoMemberFilter': 'objectclass=*',
+ 'autoMemberDefaultGroup': GROUP_DN,
+ 'autoMemberGroupingAttr': 'member:dn',
+ }
+ automember_defs = AutoMembershipDefinitions(topo.standalone, "cn=Auto Membership Plugin,cn=plugins,cn=config")
+ automember_def = automember_defs.create(properties=automember_prop)
+ automember_def.add_regex_rule("regex1", GROUP_DN, include_regex=[REGEX_VALUE])
+
+ automemberplugin.enable()
+ topo.standalone.restart()
+
+ # Check errors log for invalid message
+ ERR_STR1 = "automember_parse_regex_rule - Unable to parse regex rule"
+ ERR_STR2 = f"Skipping invalid inclusive regex rule in rule entry \"{REGEX_DN}\" \\(rule = \"{REGEX_ESC_VALUE}\"\\)"
+ assert topo.standalone.searchErrorsLog(ERR_STR1)
+ assert topo.standalone.searchErrorsLog(ERR_STR2)
+
if __name__ == "__main__":
CURRENT_FILE = os.path.realpath(__file__)
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index 39350ad53..b92b89bd5 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -1217,6 +1217,7 @@ automember_parse_regex_rule(char *rule_string)
"automember_parse_regex_rule - Unable to parse "
"regex rule (invalid regex). Error \"%s\".\n",
recomp_result ? recomp_result : "unknown");
+ goto bail;
}
/* Validation has passed, so create the regex rule struct and fill it in.
--
2.31.1
From 9c08a053938eb28821fad7d0850c046ef2ed44c4 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 9 Dec 2020 16:16:30 -0500
Subject: [PATCH 05/12] Issue 4092 - systemd-tmpfiles warnings
Bug Description:
systemd-tmpfiles warns about legacy paths in our tmpfiles configs.
Using /var/run also introduces a race condition, see the following
issue https://pagure.io/389-ds-base/issue/47429
Fix Description:
Instead of using @localstatedir@/run use @localrundir@ which was
introduced in #850.
Relates: https://github.com/389ds/389-ds-base/issues/766
Fixes: https://github.com/389ds/389-ds-base/issues/4092
Reviewed by: vashirov & firstyear(Thanks!)
---
Makefile.am | 4 ++--
configure.ac | 10 ++++++++--
dirsrvtests/tests/suites/basic/basic_test.py | 3 ++-
ldap/admin/src/defaults.inf.in | 8 ++++----
ldap/servers/snmp/main.c | 8 ++++----
src/lib389/lib389/__init__.py | 3 +++
src/lib389/lib389/instance/options.py | 7 ++++++-
src/lib389/lib389/instance/remove.py | 13 ++++++++-----
src/lib389/lib389/instance/setup.py | 10 ++++++++--
9 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 36434cf17..fc5a6a7d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -141,8 +141,8 @@ PATH_DEFINES = -DLOCALSTATEDIR="\"$(localstatedir)\"" -DSYSCONFDIR="\"$(sysconfd
-DLIBDIR="\"$(libdir)\"" -DBINDIR="\"$(bindir)\"" \
-DDATADIR="\"$(datadir)\"" -DDOCDIR="\"$(docdir)\"" \
-DSBINDIR="\"$(sbindir)\"" -DPLUGINDIR="\"$(serverplugindir)\"" \
- -DTEMPLATEDIR="\"$(sampledatadir)\"" -DSYSTEMSCHEMADIR="\"$(systemschemadir)\""
-
+ -DTEMPLATEDIR="\"$(sampledatadir)\"" -DSYSTEMSCHEMADIR="\"$(systemschemadir)\"" \
+ -DLOCALRUNDIR="\"$(localrundir)\""
# Now that we have all our defines in place, setup the CPPFLAGS
# These flags are the "must have" for all components
diff --git a/configure.ac b/configure.ac
index 61bf35e4a..9845beb7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -418,7 +418,14 @@ fi
m4_include(m4/fhs.m4)
-localrundir='/run'
+# /run directory path
+AC_ARG_WITH([localrundir],
+ AS_HELP_STRING([--with-localrundir=DIR],
+ [Runtime data directory]),
+ [localrundir=$with_localrundir],
+ [localrundir="/run"])
+AC_SUBST([localrundir])
+
cockpitdir=/389-console
# installation paths - by default, we store everything
@@ -899,7 +906,6 @@ AC_SUBST(ldaplib_defs)
AC_SUBST(ldaptool_bindir)
AC_SUBST(ldaptool_opts)
AC_SUBST(plainldif_opts)
-AC_SUBST(localrundir)
AC_SUBST(brand)
AC_SUBST(capbrand)
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
index 41726f073..7e80c443b 100644
--- a/dirsrvtests/tests/suites/basic/basic_test.py
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
@@ -901,7 +901,8 @@ def test_basic_ldapagent(topology_st, import_example_ldif):
# Remember, this is *forking*
check_output([os.path.join(topology_st.standalone.get_sbin_dir(), 'ldap-agent'), config_file])
# First kill any previous agents ....
- pidpath = os.path.join(var_dir, 'run/ldap-agent.pid')
+ run_dir = topology_st.standalone.get_run_dir()
+ pidpath = os.path.join(run_dir, 'ldap-agent.pid')
pid = None
with open(pidpath, 'r') as pf:
pid = pf.readlines()[0].strip()
diff --git a/ldap/admin/src/defaults.inf.in b/ldap/admin/src/defaults.inf.in
index d5f504591..e02248b89 100644
--- a/ldap/admin/src/defaults.inf.in
+++ b/ldap/admin/src/defaults.inf.in
@@ -35,12 +35,12 @@ sysconf_dir = @sysconfdir@
initconfig_dir = @initconfigdir@
config_dir = @instconfigdir@/slapd-{instance_name}
local_state_dir = @localstatedir@
-run_dir = @localstatedir@/run/dirsrv
+run_dir = @localrundir@
# This is the expected location of ldapi.
-ldapi = @localstatedir@/run/slapd-{instance_name}.socket
+ldapi = @localrundir@/slapd-{instance_name}.socket
+pid_file = @localrundir@/slapd-{instance_name}.pid
ldapi_listen = on
ldapi_autobind = on
-pid_file = @localstatedir@/run/dirsrv/slapd-{instance_name}.pid
inst_dir = @serverdir@/slapd-{instance_name}
plugin_dir = @serverplugindir@
system_schema_dir = @systemschemadir@
@@ -54,7 +54,7 @@ root_dn = cn=Directory Manager
schema_dir = @instconfigdir@/slapd-{instance_name}/schema
cert_dir = @instconfigdir@/slapd-{instance_name}
-lock_dir = @localstatedir@/lock/dirsrv/slapd-{instance_name}
+lock_dir = @localrundir@/lock/dirsrv/slapd-{instance_name}
log_dir = @localstatedir@/log/dirsrv/slapd-{instance_name}
access_log = @localstatedir@/log/dirsrv/slapd-{instance_name}/access
audit_log = @localstatedir@/log/dirsrv/slapd-{instance_name}/audit
diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c
index 88a4d532a..e6271a8a9 100644
--- a/ldap/servers/snmp/main.c
+++ b/ldap/servers/snmp/main.c
@@ -287,14 +287,14 @@ load_config(char *conf_path)
}
/* set pidfile path */
- if ((pidfile = malloc(strlen(LOCALSTATEDIR) + strlen("/run/") +
+ if ((pidfile = malloc(strlen(LOCALRUNDIR) + strlen("/") +
strlen(LDAP_AGENT_PIDFILE) + 1)) != NULL) {
- strncpy(pidfile, LOCALSTATEDIR, strlen(LOCALSTATEDIR) + 1);
+ strncpy(pidfile, LOCALRUNDIR, strlen(LOCALRUNDIR) + 1);
/* The above will likely not be NULL terminated, but we need to
* be sure that we're properly NULL terminated for the below
* strcat() to work properly. */
- pidfile[strlen(LOCALSTATEDIR)] = (char)0;
- strcat(pidfile, "/run/");
+ pidfile[strlen(LOCALRUNDIR)] = (char)0;
+ strcat(pidfile, "/");
strcat(pidfile, LDAP_AGENT_PIDFILE);
} else {
printf("ldap-agent: malloc error processing config file\n");
diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py
index e0299c5b4..2a0b83913 100644
--- a/src/lib389/lib389/__init__.py
+++ b/src/lib389/lib389/__init__.py
@@ -1709,6 +1709,9 @@ class DirSrv(SimpleLDAPObject, object):
def get_bin_dir(self):
return self.ds_paths.bin_dir
+ def get_run_dir(self):
+ return self.ds_paths.run_dir
+
def get_plugin_dir(self):
return self.ds_paths.plugin_dir
diff --git a/src/lib389/lib389/instance/options.py b/src/lib389/lib389/instance/options.py
index 4e083618c..d5b95e6df 100644
--- a/src/lib389/lib389/instance/options.py
+++ b/src/lib389/lib389/instance/options.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2019 Red Hat, Inc.
+# Copyright (C) 2021 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
@@ -32,6 +32,7 @@ format_keys = [
'backup_dir',
'db_dir',
'db_home_dir',
+ 'ldapi',
'ldif_dir',
'lock_dir',
'log_dir',
@@ -233,6 +234,10 @@ class Slapd2Base(Options2):
self._helptext['local_state_dir'] = "Sets the location of Directory Server variable data. Only set this parameter in a development environment."
self._advanced['local_state_dir'] = True
+ self._options['ldapi'] = ds_paths.ldapi
+ self._type['ldapi'] = str
+ self._helptext['ldapi'] = "Sets the location of socket interface of the Directory Server."
+
self._options['lib_dir'] = ds_paths.lib_dir
self._type['lib_dir'] = str
self._helptext['lib_dir'] = "Sets the location of Directory Server shared libraries. Only set this parameter in a development environment."
diff --git a/src/lib389/lib389/instance/remove.py b/src/lib389/lib389/instance/remove.py
index d7bb48ce0..1a35ddc07 100644
--- a/src/lib389/lib389/instance/remove.py
+++ b/src/lib389/lib389/instance/remove.py
@@ -78,13 +78,16 @@ def remove_ds_instance(dirsrv, force=False):
_log.debug("Found instance marker at %s! Proceeding to remove ..." % dse_ldif_path)
- # Stop the instance (if running) and now we know it really does exist
- # and hopefully have permission to access it ...
- _log.debug("Stopping instance %s" % dirsrv.serverid)
- dirsrv.stop()
-
### ANY NEW REMOVAL ACTION MUST BE BELOW THIS LINE!!!
+ # Remove LDAPI socket file
+ ldapi_path = os.path.join(dirsrv.ds_paths.run_dir, "slapd-%s.socket" % dirsrv.serverid)
+ if os.path.exists(ldapi_path):
+ try:
+ os.remove(ldapi_path)
+ except OSError as e:
+ _log.debug(f"Failed to remove LDAPI socket ({ldapi_path}) Error: {str(e)}")
+
# Remove these paths:
# for path in ('backup_dir', 'cert_dir', 'config_dir', 'db_dir',
# 'ldif_dir', 'lock_dir', 'log_dir', 'run_dir'):
diff --git a/src/lib389/lib389/instance/setup.py b/src/lib389/lib389/instance/setup.py
index ab7a2da85..57e7a9fd4 100644
--- a/src/lib389/lib389/instance/setup.py
+++ b/src/lib389/lib389/instance/setup.py
@@ -732,7 +732,10 @@ class SetupDs(object):
dse += line.replace('%', '{', 1).replace('%', '}', 1)
with open(os.path.join(slapd['config_dir'], 'dse.ldif'), 'w') as file_dse:
- ldapi_path = os.path.join(slapd['local_state_dir'], "run/slapd-%s.socket" % slapd['instance_name'])
+ if os.path.exists(os.path.dirname(slapd['ldapi'])):
+ ldapi_path = slapd['ldapi']
+ else:
+ ldapi_path = os.path.join(slapd['run_dir'], "slapd-%s.socket" % slapd['instance_name'])
dse_fmt = dse.format(
schema_dir=slapd['schema_dir'],
lock_dir=slapd['lock_dir'],
@@ -902,10 +905,13 @@ class SetupDs(object):
self.log.info("Perform SELinux labeling ...")
selinux_paths = ('backup_dir', 'cert_dir', 'config_dir', 'db_dir',
'ldif_dir', 'lock_dir', 'log_dir', 'db_home_dir',
- 'run_dir', 'schema_dir', 'tmp_dir')
+ 'schema_dir', 'tmp_dir')
for path in selinux_paths:
selinux_restorecon(slapd[path])
+ # Don't run restorecon on the entire /run directory
+ selinux_restorecon(slapd['run_dir'] + '/dirsrv')
+
selinux_label_port(slapd['port'])
# Start the server
--
2.31.1