Description
The following code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo openssl_get_cert_locations()['default_cert_file'] . "<br>";
echo openssl_get_cert_locations()['default_cert_dir'] . "<br>";
$domain="<hidden for public>";
$ldaphost="<hidden for public>". ".". $domain;
$ldaps=true;
$ldapport=($ldaps ? 636 : 389);
$ldapconn = ldap_connect(($ldaps ? "ldaps://" : "ldap://") . $ldaphost . ":" . $ldapport)
or die("No connection to LDAP server!<br>");
if($ldapconn) {
echo "Connect success<br>";
}
ldap_get_option($ldapconn, LDAP_OPT_DIAGNOSTIC_MESSAGE, $diag);
echo "Diagnostic: " . $diag . "<br>";
$User="<hidden for public>";
$ldappass="<hidden for public>";
$ldaprdn=$User. "@". $domain;
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ldapconn, LDAP_OPT_DEBUG_LEVEL, 255);
$ldapbind = @ldap_bind($ldapconn, $ldaprdn, $ldappass);
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
ldap_get_option($ldapconn, LDAP_OPT_DIAGNOSTIC_MESSAGE, $diag);
echo "Diagnostic: " . $diag . "<br>";
echo "LDAP Error: " . ldap_error($ldapconn) . "<br>";
echo "LDAP Errno: " . ldap_errno($ldapconn) . "<br>";
// OpenSSL error chain
while ($msg = openssl_error_string()) {
echo "OpenSSL: " . $msg . "<br>";
}
}
ldap_close($ldapconn);
Resulted in this output:
C:\Program Files\Common Files\SSL/cert.pem
C:\Program Files\Common Files\SSL/certs
Connect success
Diagnostic:
Diagnostic: error:0A000086:SSL routines::certificate verify failed (unable to get local issuer certificate)
LDAP Error: Can't contact LDAP server
LDAP Errno: -1
OpenSSL: error:0A000
But I expected this output instead:
C:\Program Files\Common Files\SSL/cert.pem
C:\Program Files\Common Files\SSL/certs
Connect success
Diagnostic:
LDAP bind successful...
To make this work, the directory C:\openldap was created, containing the subdirectory certs, which holds the required certificates, and the subdirectory sysconf, which contains the file ladap.conf with the entry “TLS_CACERT C:\openldap\certs\DF_PUB_CA_Bundle.crt”.
This code worked fine with PHP 8.4.20 and fails after update to 8.4.21. Going back to 8.4.20 it works again.
I have analyzed that behavior with Claude AI and the result was:
This is a known PHP bug with a regression chain
In PHP 8.4.7, bug GH-17776 was fixed (LDAP_OPT_X_TLS_* options cannot be overridden). However, this fix caused a regression: In PHP 8.4.8, bug GH-18529 was then fixed — “ldap no longer respects TLS_CACERT from ldaprc in ldap_start_tls()” — explicitly marked as a regression of the GH-17776 fix. PHP.(https://php.watch/versions/8.4/releases/8.4.8)
So the pattern is: The fix from 8.4.7 broke ldap.conf detection. 8.4.8 corrected this for ldap_start_tls(). Apparently, the same regression has reappeared in 8.4.21 for LDAPS (port 636) or was never fully fixed.
A specific workaround from the GitHub issue: In 8.4.7, it was necessary to explicitly set the CA file using ldap_set_option($connection, LDAP_OPT_X_TLS_CACERTFILE, “/path/to/my/ca-bundle.crt”) instead of defining it in ldap.conf — the configuration file setting was simply ignored. (https://github.com/php/php-src/issues/18529)
The workaround is to add the following lines before the call of ldap_connect:
ldap_set_option(null, LDAP_OPT_X_TLS_CACERTFILE, 'C:\\openldap\\certs\\DF_PUB_CA_Bundle.crt');
ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND);
This requires adapting code to system configuration and is not the "real solution".
PHP Version
PHP 8.4.21 (cli) (built: May 6 2026 09:30:47) (ZTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Built by The PHP Group
Zend Engine v4.4.21, Copyright (c) Zend Technologies
with Zend OPcache v8.4.21, Copyright (c), by Zend Technologies
with Xdebug v3.4.5, Copyright (c) 2002-2025, by Derick Rethans
Operating System
Windows 11 64Bit
Description
The following code:
Resulted in this output:
But I expected this output instead:
To make this work, the directory C:\openldap was created, containing the subdirectory certs, which holds the required certificates, and the subdirectory sysconf, which contains the file ladap.conf with the entry “TLS_CACERT C:\openldap\certs\DF_PUB_CA_Bundle.crt”.
This code worked fine with PHP 8.4.20 and fails after update to 8.4.21. Going back to 8.4.20 it works again.
I have analyzed that behavior with Claude AI and the result was:
The workaround is to add the following lines before the call of ldap_connect:
This requires adapting code to system configuration and is not the "real solution".
PHP Version
Operating System
Windows 11 64Bit