This is an automated email from the git hooks/post-receive script.
tbordaz pushed a commit to branch 389-ds-base-1.4.0
in repository 389-ds-base.
The following commit(s) were added to refs/heads/389-ds-base-1.4.0 by this push:
new 6d2b128 Ticket 50581 - ns-slapd crashes during ldapi search
6d2b128 is described below
commit 6d2b1282de97c0790ea2db4bfbe6c83641eaec81
Author: Thierry Bordaz <tbordaz(a)redhat.com>
AuthorDate: Mon Sep 2 16:48:45 2019 +0200
Ticket 50581 - ns-slapd crashes during ldapi search
Bug Description:
Using ldapi, if the length of the socket file path exceeds
46 bytes it triggers a buffer overflow while reseting a connection.
Reset happens at open/close/error.
Fix Description:
Use a buffer sized for a PRNetAddr.local.path (~100bytes)
Use of MAXPATHLEN (4kb) is too much.
https://pagure.io/389-ds-base/issue/50581
Reviewed by: William Brown, Alexander Bokovoy, Mark Reynolds, Simon Pichugi
Platforms tested: F30 (thanks !!)
Flag Day: no
Doc impact: no
---
dirsrvtests/tests/suites/basic/basic_test.py | 114 +++++++++++++++++++++++++++
ldap/servers/slapd/connection.c | 39 +++++----
2 files changed, 136 insertions(+), 17 deletions(-)
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py
b/dirsrvtests/tests/suites/basic/basic_test.py
index d926f64..5e738c1 100644
--- a/dirsrvtests/tests/suites/basic/basic_test.py
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
@@ -12,6 +12,7 @@
"""
from subprocess import check_output, Popen
+from lib389 import DirSrv
from lib389.idm.user import UserAccounts
import pytest
from lib389.tasks import *
@@ -21,6 +22,16 @@ from lib389.dbgen import dbgen
from lib389.idm.organizationalunit import OrganizationalUnits
from lib389._constants import DN_DM, PASSWORD, PW_DM
from lib389.topologies import topology_st
+from lib389.paths import Paths
+from lib389.idm.directorymanager import DirectoryManager
+from lib389.config import LDBMConfig
+from lib389.dseldif import DSEldif
+from lib389.rootdse import RootDSE
+
+
+pytestmark = pytest.mark.tier0
+
+default_paths = Paths()
log = logging.getLogger(__name__)
@@ -1247,6 +1258,109 @@ sample_entries = yes
request.addfinalizer(fin)
+(a)pytest.fixture(scope="module")
+def dscreate_ldapi_instance(request):
+ template_file = "/tmp/dssetup.inf"
+ longname_serverid =
"test_longname_deadbeef_deadbeef_deadbeef_deadbeef_deadbeef"
+ template_text = """[general]
+config_version = 2
+# This invalid hostname ...
+full_machine_name = localhost.localdomain
+# Means we absolutely require this.
+strict_host_checking = False
+# In tests, we can be run in containers, NEVER trust
+# that systemd is there, or functional in any capacity
+systemd = False
+
+[slapd]
+instance_name = %s
+root_dn = cn=directory manager
+root_password = someLongPassword_123
+# We do not have access to high ports in containers,
+# so default to something higher.
+port = 38999
+secure_port = 63699
+
+
+[backend-userroot]
+suffix = dc=example,dc=com
+sample_entries = yes
+""" % longname_serverid
+
+ with open(template_file, "w") as template_fd:
+ template_fd.write(template_text)
+
+ # Unset PYTHONPATH to avoid mixing old CLI tools and new lib389
+ tmp_env = os.environ
+ if "PYTHONPATH" in tmp_env:
+ del tmp_env["PYTHONPATH"]
+ try:
+ subprocess.check_call([
+ 'dscreate',
+ 'from-file',
+ template_file
+ ], env=tmp_env)
+ except subprocess.CalledProcessError as e:
+ log.fatal("dscreate failed! Error ({}) {}".format(e.returncode,
e.output))
+ assert False
+
+ inst = DirSrv(verbose=True, external_log=log)
+ dse_ldif = DSEldif(inst,
+ serverid=longname_serverid)
+
+ socket_path = dse_ldif.get("cn=config", "nsslapd-ldapifilepath")
+ inst.local_simple_allocate(
+ serverid=longname_serverid,
+ ldapuri=f"ldapi://{socket_path[0].replace('/',
'%2f')}",
+ password="someLongPassword_123"
+ )
+ inst.ldapi_enabled = 'on'
+ inst.ldapi_socket = socket_path
+ inst.ldapi_autobind = 'off'
+ try:
+ inst.open()
+ except:
+ log.fatal("Failed to connect via ldapi to %s instance" %
longname_serverid)
+ os.remove(template_file)
+ try:
+ subprocess.check_call(['dsctl', longname_serverid, 'remove',
'--do-it'])
+ except subprocess.CalledProcessError as e:
+ log.fatal("Failed to remove test instance Error ({})
{}".format(e.returncode, e.output))
+
+ def fin():
+ os.remove(template_file)
+ try:
+ subprocess.check_call(['dsctl', longname_serverid, 'remove',
'--do-it'])
+ except subprocess.CalledProcessError as e:
+ log.fatal("Failed to remove test instance Error ({})
{}".format(e.returncode, e.output))
+
+ request.addfinalizer(fin)
+
+ return inst
+
+
+(a)pytest.mark.skipif(not get_user_is_root() or not default_paths.perl_enabled or
ds_is_older('1.4.0.0'),
+ reason="This test is only required with new admin cli, and
requires root.")
+(a)pytest.mark.bz1748016
+(a)pytest.mark.ds50581
+def test_dscreate_longname(dscreate_ldapi_instance):
+ """Test that an instance with a long name can
+ handle ldapi connection using a long socket name
+
+ :id: 5d72d955-aff8-4741-8c9a-32c1c707cf1f
+ :setup: None
+ :steps:
+ 1. create an instance with a long serverId name, that open a ldapi connection
+ 2. Connect with ldapi, that hit 50581 and crash the instance
+ :expectedresults:
+ 1. Should succeeds
+ 2. Should succeeds
+ """
+
+ root_dse = RootDSE(dscreate_ldapi_instance)
+ log.info(root_dse.get_supported_ctrls())
+
+
if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 81d49e0..acdbdb3 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -253,6 +253,8 @@ connection_reset(Connection *conn, int ns, PRNetAddr *from, int
fromLen __attrib
char *pTmp = is_SSL ? "SSL " : "";
char *str_ip = NULL, *str_destip;
char buf_ip[256], buf_destip[256];
+ char buf_ldapi[sizeof(from->local.path) + 1] = {0};
+ char buf_destldapi[sizeof(from->local.path) + 1] = {0};
char *str_unknown = "unknown";
int in_referral_mode = config_check_referral_mode();
@@ -272,18 +274,18 @@ connection_reset(Connection *conn, int ns, PRNetAddr *from, int
fromLen __attrib
slapi_ch_free((void **)&conn->cin_addr); /* just to be conservative */
if (from->raw.family == PR_AF_LOCAL) { /* ldapi */
conn->cin_addr = (PRNetAddr *)slapi_ch_malloc(sizeof(PRNetAddr));
- PL_strncpyz(buf_ip, from->local.path, sizeof(from->local.path));
+ PL_strncpyz(buf_ldapi, from->local.path, sizeof(from->local.path));
memcpy(conn->cin_addr, from, sizeof(PRNetAddr));
- if (!buf_ip[0]) {
+ if (!buf_ldapi[0]) {
PR_GetPeerName(conn->c_prfd, from);
- PL_strncpyz(buf_ip, from->local.path, sizeof(from->local.path));
+ PL_strncpyz(buf_ldapi, from->local.path, sizeof(from->local.path));
memcpy(conn->cin_addr, from, sizeof(PRNetAddr));
- if (!buf_ip[0]) {
+ if (!buf_ldapi[0]) {
/* Cannot derive local address, need something for logging */
- PL_strncpyz(buf_ip, "local", sizeof(buf_ip));
+ PL_strncpyz(buf_ldapi, "local", sizeof(buf_ldapi));
}
}
- str_ip = buf_ip;
+ str_ip = buf_ldapi;
} else if (((from->ipv6.ip.pr_s6_addr32[0] != 0) || /* from contains non zeros */
(from->ipv6.ip.pr_s6_addr32[1] != 0) ||
(from->ipv6.ip.pr_s6_addr32[2] != 0) ||
@@ -346,21 +348,24 @@ connection_reset(Connection *conn, int ns, PRNetAddr *from, int
fromLen __attrib
memset(conn->cin_destaddr, 0, sizeof(PRNetAddr));
if (PR_GetSockName(conn->c_prfd, conn->cin_destaddr) == 0) {
if (conn->cin_destaddr->raw.family == PR_AF_LOCAL) { /* ldapi */
- PL_strncpyz(buf_destip, conn->cin_destaddr->local.path,
+ PL_strncpyz(buf_destldapi, conn->cin_destaddr->local.path,
sizeof(conn->cin_destaddr->local.path));
- if (!buf_destip[0]) {
- PL_strncpyz(buf_destip, "unknown local file",
sizeof(buf_destip));
+ if (!buf_destldapi[0]) {
+ PL_strncpyz(buf_destldapi, "unknown local file",
sizeof(buf_destldapi));
}
- } else if (PR_IsNetAddrType(conn->cin_destaddr, PR_IpAddrV4Mapped)) {
- PRNetAddr v4destaddr = {{0}};
- v4destaddr.inet.family = PR_AF_INET;
- v4destaddr.inet.ip = conn->cin_destaddr->ipv6.ip.pr_s6_addr32[3];
- PR_NetAddrToString(&v4destaddr, buf_destip, sizeof(buf_destip));
+ str_destip = buf_destldapi;
} else {
- PR_NetAddrToString(conn->cin_destaddr, buf_destip,
sizeof(buf_destip));
+ if (PR_IsNetAddrType(conn->cin_destaddr, PR_IpAddrV4Mapped)) {
+ PRNetAddr v4destaddr = {{0}};
+ v4destaddr.inet.family = PR_AF_INET;
+ v4destaddr.inet.ip =
conn->cin_destaddr->ipv6.ip.pr_s6_addr32[3];
+ PR_NetAddrToString(&v4destaddr, buf_destip, sizeof
(buf_destip));
+ } else {
+ PR_NetAddrToString(conn->cin_destaddr, buf_destip, sizeof
(buf_destip));
+ }
+ buf_destip[sizeof (buf_destip) - 1] = '\0';
+ str_destip = buf_destip;
}
- buf_destip[sizeof(buf_destip) - 1] = '\0';
- str_destip = buf_destip;
} else {
str_destip = str_unknown;
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.