1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-18529: additional inheriting of TLS int options

This is for LDAP_OPT_X_TLS_PROTOCOL_MIN and LDAP_OPT_X_TLS_PROTOCOL_MAX

It also adds a test that uses LDAPCONF with TLS max version lower than
the minimum TLS server version so it should always fail. However it
does not fial for the second case without this change which confirms
that the change works as expected.

Closes GH-18676
This commit is contained in:
Jakub Zelenka
2025-05-27 19:03:56 +02:00
parent faf833bffc
commit eade5c17ea
6 changed files with 110 additions and 6 deletions

View File

@@ -72,6 +72,9 @@ olcTLSCertificateKeyFile: /etc/ldap/ssl/server.key
add: olcTLSVerifyClient
olcTLSVerifyClient: never
-
add: olcTLSProtocolMin
olcTLSProtocolMin: 3.3
-
add: olcAuthzRegexp
olcAuthzRegexp: uid=usera,cn=digest-md5,cn=auth cn=usera,dc=my-domain,dc=com
-

6
NEWS
View File

@@ -2,7 +2,11 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.3.25
OpenSSL:
- LDAP:
. Fixed bug GH-18529 (additional inheriting of TLS int options).
(Jakub Zelenka)
- OpenSSL:
. Fixed bug GH-18986 (OpenSSL backend: incorrect RAND_{load,write}_file()
return value check). (nielsdos, botovq)
. Fix error return check of EVP_CIPHER_CTX_ctrl(). (nielsdos)

View File

@@ -3732,7 +3732,8 @@ PHP_FUNCTION(ldap_rename_ext)
*/
static int _php_ldap_tls_newctx(LDAP *ld)
{
int val = 0, i, opts[] = {
int val = 0, i;
int str_opts[] = {
#if (LDAP_API_VERSION > 2000)
LDAP_OPT_X_TLS_CACERTDIR,
LDAP_OPT_X_TLS_CACERTFILE,
@@ -3752,21 +3753,42 @@ static int _php_ldap_tls_newctx(LDAP *ld)
#endif
0};
for (i=0 ; opts[i] ; i++) {
for (i=0 ; str_opts[i] ; i++) {
char *path = NULL;
ldap_get_option(ld, opts[i], &path);
ldap_get_option(ld, str_opts[i], &path);
if (path) { /* already set locally */
ldap_memfree(path);
} else {
ldap_get_option(NULL, opts[i], &path);
ldap_get_option(NULL, str_opts[i], &path);
if (path) { /* set globally, inherit */
ldap_set_option(ld, opts[i], path);
ldap_set_option(ld, str_opts[i], path);
ldap_memfree(path);
}
}
}
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
int int_opts[] = {
LDAP_OPT_X_TLS_PROTOCOL_MIN,
#ifdef LDAP_OPT_X_TLS_PROTOCOL_MAX
LDAP_OPT_X_TLS_PROTOCOL_MAX,
#endif
0
};
for (i=0 ; int_opts[i] ; i++) {
int value = 0;
ldap_get_option(ld, int_opts[i], &value);
if (value <= 0) { /* if value is not set already */
ldap_get_option(NULL, int_opts[i], &value);
if (value > 0) { /* set globally, inherit */
ldap_set_option(ld, int_opts[i], &value);
}
}
}
#endif
return ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &val);
}

View File

@@ -0,0 +1 @@
TLS_PROTOCOL_MAX 3.2

View File

@@ -0,0 +1,41 @@
--TEST--
ldap_start_tls() - Basic ldap_start_tls test
--EXTENSIONS--
ldap
--ENV--
LDAPCONF={PWD}/ldap_start_tls_rc_max_version.conf
--SKIPIF--
<?php
$require_vendor = [
"name" => "OpenLDAP",
"min_version" => 20600,
];
require_once __DIR__ .'/skipifbindfailure.inc';
?>
--FILE--
<?php
require_once "connect.inc";
// CI uses self signed certificate
// No cert option - fails
$link = ldap_connect($uri);
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
var_dump(@ldap_start_tls($link));
// No cert check - should pass but due to ldaps check, it fails as well
$link = ldap_connect($uri);
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
ldap_set_option($link, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
var_dump(@ldap_start_tls($link));
// With cert check - fails
$link = ldap_connect($uri);
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
ldap_set_option($link, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND);
var_dump(@ldap_start_tls($link));
?>
--EXPECT--
bool(false)
bool(false)
bool(false)

View File

@@ -10,4 +10,37 @@ if ($skip_on_bind_failure) {
ldap_unbind($link);
}
if (isset($require_vendor)) {
ob_start();
phpinfo(INFO_MODULES);
$phpinfo = ob_get_clean();
// Extract the LDAP section specifically
if (preg_match('/^ldap\s*$(.*?)^[a-z_]+\s*$/ims', $phpinfo, $ldap_section_match)) {
$ldap_section = $ldap_section_match[1];
// Extract vendor info from the LDAP section only
if (preg_match('/Vendor Name\s*=>\s*(.+)/i', $ldap_section, $name_match) &&
preg_match('/Vendor Version\s*=>\s*(\d+)/i', $ldap_section, $version_match)) {
$vendor_name = trim($name_match[1]);
$vendor_version = (int)$version_match[1];
// Check vendor name if specified
if (isset($require_vendor['name']) && $vendor_name !== $require_vendor['name']) {
die("skip Requires {$require_vendor['name']} (detected: $vendor_name)");
}
// Check minimum version if specified
if (isset($require_vendor['min_version']) && $vendor_version < $require_vendor['min_version']) {
die("skip Requires minimum version {$require_vendor['min_version']} (detected: $vendor_version)");
}
} else {
die("skip Cannot determine LDAP vendor information");
}
} else {
die("skip LDAP extension information not found");
}
}
?>