phpsslldapgoogle-workspacesni

SNI issues connecting to Google LDAP server


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


Solution

  • 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