
Description
Description
The following code:
<?php
// Test case for PHP bug: https://bugs.php.net/bug.php?id=73558
//
// The two commands below work totally fine:
//
// OpenSSL:
// $ openssl s_client -verifyCAfile ca.crt -cert ldap-client.crt -key ldap-client.key -connect ldap.home.arpa:636
//
// ldapsearch:
// $ LDAPTLS_CACERT=ca.crt LDAPTLS_CERT=ldap-client.crt LDAPTLS_KEY=ldap-client.key ldapwhoami -H ldaps://ldap.home.arpa -x
// anonymous
$ldapUri = 'ldaps://ldap.home.arpa';
$caFile = __DIR__.'/ca.crt';
$certFile = __DIR__.'/ldap-client.crt';
$keyFile = __DIR__.'/ldap-client.key';
//putenv(sprintf('LDAPTLS_CACERT=%s', $caFile));
//putenv(sprintf('LDAPTLS_CERT=%s', $certFile));
//putenv(sprintf('LDAPTLS_KEY=%s', $keyFile));
$ldapResource = ldap_connect($ldapUri);
$ldapOptions = [
LDAP_OPT_PROTOCOL_VERSION => 3,
LDAP_OPT_REFERRALS => 0,
LDAP_OPT_X_TLS_CACERTFILE => $caFile,
LDAP_OPT_X_TLS_CERTFILE => $certFile,
LDAP_OPT_X_TLS_KEYFILE => $keyFile,
];
foreach($ldapOptions as $k => $v) {
ldap_set_option($ldapResource, $k, $v);
}
if(false === ldap_bind($ldapResource)) {
ldap_get_option($ldapResource, LDAP_OPT_DIAGNOSTIC_MESSAGE, $errMsg);
echo sprintf(
"%s (%d): %s\n",
ldap_error($ldapResource),
ldap_errno($ldapResource),
$errMsg
);
}
var_dump(
ldap_exop_whoami($ldapResource)
);
Resulted in this output:
PHP Warning: ldap_bind(): Unable to bind to server: Can't contact LDAP server in /home/fkooman/ldap.home.arpa/ldap_test.php on line 36
Can't contact LDAP server (-1): error:0A000086:SSL routines::certificate verify failed (self-signed certificate in certificate chain)
PHP Warning: ldap_exop_whoami(): Whoami extended operation failed: Can't contact LDAP server (-1) in /home/fkooman/ldap.home.arpa/ldap_test.php on line 47
bool(false)
But I expected this output instead (anonymous bind):
string(0) ""
Workaround
When you enable the three putenv
lines, things start working, but this probably not how it should be :)
Additional details
It seems the options LDAP_OPT_X_TLS_CACERTFILE
, LDAP_OPT_X_TLS_CERTFILE
and LDAP_OPT_X_TLS_KEYFILE
are somehow ignored.
We tested this on Fedora 38 (PHP 8.2.9 (cli) (built: Aug 3 2023 11:39:08) (NTS gcc x86_64)
):
LDAP Support => enabled
Total Links => 0/unlimited
API Version => 3001
Vendor Name => OpenLDAP
Vendor Version => 20604
SASL Support => Enabled
Directive => Local Value => Master Value
ldap.max_links => Unlimited => Unlimited
And on Debian 12 (PHP 8.2.7 (cli) (built: Jun 9 2023 19:37:27) (NTS)
):
LDAP Support => enabled
Total Links => 0/unlimited
API Version => 3001
Vendor Name => OpenLDAP
Vendor Version => 20513
SASL Support => Enabled
Directive => Local Value => Master Value
ldap.max_links => Unlimited => Unlimited
See also: https://bugs.php.net/bug.php?id=73558
Test Setup without LDAP server
If you do not have an LDAP server, you can also use openssl
to create a test server that results in the exact same error message in the PHP script as the problem is in the TLS setup, not the actual LDAP connection:
$ openssl s_server -CAfile ca.crt -cert ldap.home.arpa.crt -key ldap.home.arpa.key
All you need is the client cert/key, server cert/key and CA and connect to port 4433 (the default of s_server
).
PHP Version
PHP 8.2.9 / 8.2.7
Operating System
Fedora 38 / Debian 12