How to acces secure LDAP server via SSL from PHP on Linux

First, obtain SSL certificate of your LDAP server:

cd /etc/openldap/cacerts
openssl s_client -showcerts -connect 172.16.1.1:636 > ldapsrv1.crt
^D
<

If you connection times out, check whether port is accessible:

telnet 172.16.1.1 636
<

Edit the file and leave just lines between the first section delimited by the "BEGIN CERTIFICATE" and "END CERTIFICATE" lines.

Decode the certificate content

openssl x509 -in ldapsrv1.crt -text > ldapsrv1.pem
<

Now see canonical host name (subject) and certificate authority identifier (subject):

egrep 'Issuer:|Subject:' ldapsrv1.pem
<

If issuer and subject are the same, this is a self-signed certificate and it is enough to add it to the list of CA certificates recognized by OpenSSL.

OpenSSL uses two methods to verify a CA certificate: bundle file or hashed directory.

The CA bundle file consists of concatenated certificate texts. Usually OpenLDAP uses the file /etc/openldap/cacerts.pem, but your mileage can vary. Add your certificate as follows:

cat ldapsrv1.pem >> /etc/openldap/cacerts.pem
<

OpenLDAP by default uses /etc/openldap/cacerts directory for hashed CA certificates. Files (or symbolic links to actual certificate files) should have their names of the form "xxxxx.0", where "xxxxx" is x509 hash of the certificate. Add your certificate as follows:

cp /path/to/ldapsrv1.pem /etc/openldap/cacerts/
cd /etc/openldap/cacerts
ln -s ldapsrv1.pem `openssl x509 -noout -hash -in ldapsrv1.pem`.0
<

If issuer and subject are different, you have to somehow obtain the issuer CA certificate and add it to the list of recognized certificates. See links below for how to obtain CA certificate of an Active Directory server or OpenLDAP server.

The part after "CN=" in the Subject field denotes canonical server name. If the server will be accessed by a different name, the "hostname does not match CN in peer certificate" error will result. Check wether server is accessible by this name:

ping ldapsrv1.com<

If ping does not work, verify DNS settings. As a last resort, add this host name to /etc/hosts.

Now you can verify your certificate:

openssl s_client -connect ldapsrv1.com:636 -CApath /etc/openldap/cacerts
^D

openssl s_client -connect ldapsrv1.com:636 -CAfile /etc/openldap/cacerts.pem
^D<

In case of success the output should contain line "Verify return code: 0 (ok)".

Now tell OpenLDAP about your certificate verification means. Edit the /etc/openldap/ldap.conf file and add lines like these:

TLS_CACERTDIR /etc/openldap/cacerts
TLS_CACERT /etc/openldap/cacerts.pem
<

You are not required to use both bundle file and hashed directory at the same time, either method is sufficient.

Now verify that OpenLDAP command-line utilities use this configuration:

ldapsearch -H ldaps://ldapsrv1.com:636 -D bind_dn -x -w bind_pass -LLL -b cn=x dn
<

Take care of canonical host name. If connection is successful, the only error will be "Operations error (1)", since we used a dummy base path.

The LDAP implementation in PHP uses the same OpenLDAP library and consequently reads the same configuration file /etc/openldap/ldap.conf. However, the file is parsed only once when PHP server is started. Thus, restart your PHP container (Apache or PHP FPM or whatever).

Now create the following simple PHP script:

<?php
$conn = ldap_connect("ldapsrv1.com", 636)
  or die("cannot connect");
$link = ldap_bind($conn, "bind_dn", "bind_pass")
  or die("cannot bind: " . ldap_error($conn));
$res = ldap_search($link, "cn=x", "(objectClass=*)");
echo("count=" . count($res) . "\n");
?>
<

Run the script:

php test.php
<

Good luck!