I'm trying to connect to Google's LDAP server with a cert, the basic code is
ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7);
$ldap = ldap_connect('ldaps://ldap.google.com', 636);
putenv('LDAPTLS_REQCERT=demand');
putenv("LDAPTLS_CACERT=/etc/ssl/certs/ca-certificates.crt");
putenv("LDAPTLS_CERT=" . path('Google_2024_01_22_49615.crt'));
putenv("LDAPTLS_KEY=" . path('Google_2024_01_22_49615.key'));
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_start_tls($ldap);
ldap_sasl_bind($ldap, null, '', 'EXTERNAL');
$resuts = ldap_search($ldap, 'dc=foo,dc=com', 'uid=*');
print_r(ldap_get_entries($ldap, $searchResults));
It fails on ldap_start_tls
with Unable to start TLS: Can't contact LDAP serer
, looking into this further I can see the real error is TLS: peer cert untrusted or revoked (0x42)
which is caused by hostname (ldap.google.com) does not match common name in certificate (invalid2.invalid)
. Google returns this cert to indicate that SNI isn't supported (https://support.google.com/a/answer/9190869)
But my PHP version is 7.1.33 compiled in Dec 2020 on Ubuntu 20.04, with OpenLDAP 20449 (SASL Support enabled) and OpenSSL 1.1.1i. So why would I not have SNI supported? Elsewhere I see people using LDAPTLS_REQCERT=never
to bypass this problem, but as Google requires a TLS cert & SASL I need to use LDAPTLS_REQCERT=demand
or PHP won't let me use the SASL EXTERNAL auth mechanism (https://gist.github.com/heiglandreas/8a299a6f47a13ba463c3f2da41c679f7) and I won't be able to authenticate
It's worth noting on the same machine the following command works perfectly, authenticates with SASL EXTERNAL and lists users LDAPTLS_CERT=Google_2024_01_22_49615.crt LDAPTLS_KEY=Google_2024_01_22_49615.key ldapsearch -X -W -D uid=MyUUID,ou=Users,dc=foo,dc=com -H ldaps://ldap.google.com:636 -b dc=foo,dc=com
I have also tried using the PHP options LDAP_OPT_X_TLS_REQUIRE_CERT
, LDAP_OPT_X_TLS_CACERTDIR
, LDAP_OPT_X_TLS_CACERTFILE
, LDAP_OPT_X_TLS_KEYFILE
and LDAP_OPT_X_TLS_CERTFILE
but they don't make a difference
My problem here was using ldap_start_tls
and ldap_sasl_bind
(or ldap_bind
) at the same time when you only need one to open the connection, as-well as using ldap_set_option
with the resource like ldap_set_option($ldap, LDAP_OPT_X_TLS_KEYFILE, $keyFilePath);
when it should be used on null like ldap_set_option(null, LDAP_OPT_X_TLS_KEYFILE, $keyFilePath);
since it's overriding a /etc/ldap/ldap.conf variable.
Following https://www.php.net/manual/en/function.ldap-get-option.php#124601 was useful to figuring this out