PHPverse 2025

Voting

: eight plus one?
(Example: nine)

The Note You're Voting On

Andrew (a.whyte at cqu.edu.au)
21 years ago
To be able to make modifications to Active Directory via the LDAP connector you must bind to the LDAP service over SSL. Otherwise Active Directory provides a mostly readonly connection. You cannot add objects or modify certain properties without LDAPS, e.g. passwords can only be changed using LDAPS connections to Active Directory.

Therefore, for those wishing to securely connect to Active Directory, from a Unix host using PHP+OpenLDAP+OpenSSL I spent some time getting this going myself, and came across a few gotcha's. Hope this proves fruitfull for others like me when you couldn't find answers out there.

Make sure you compile OpenLDAP with OpenSSL support, and that you compile PHP with OpenLDAP and OpenSSL.

This provides PHP with what it needs to make use of ldaps:// connections.

Configure OpenSSL:

Extract your Root CA certificate from Active Directory, this is achived through the use of Certificate Services, a startard component of Windows 2000 Server, but may not be installed by default, (The usual Add/Remove Software method will work here). I extracted this in Base64 not DER format.

Place the extracted CAcert into the certs folder for openssl. (e.g. /usr/local/ssl/certs) and setup the hashed symlinks. This is easily done by simply running:

/usr/local/ssl/bin/c_rehash

Once this is done you can test it is worked by running:

/usr/local/ssl/bin/openssl verify -verbose -CApath /usr/local/ssl/certs /tmp/exported_cacert.pem

(Should return: OK).

Configure OpenLDAP:

Add the following to your ldap.conf file.
(found as /usr/local/openldap/etc/openldap/ldap.conf)

#--begin--

# Instruct client to NOT request a server's cert.
#
# WARNING: This will open up the server vor Man-in-the-middle
# attacs and should *not* be used on production systems or outside
# of test-scenarios!
#
# If you use this setting you will not need any other settings as
# no certificate is requested and therefore will not be validated
#
# For a proper solution check out https://andreas.heigl.org/2020/01/31/handle-self-signed-certificates-with-phps-ldap-extension/
TLS_REQCERT never

# Define location of CA Cert
TLS_CACERT /usr/local/ssl/certs/AD_CA_CERT.pem
TLS_CACERTDIR /usr/local/ssl/certs

#--end--

You also need to place those same settings in a file within the Apache Web user homedir called .ldaprc

e.g.:

cp /usr/local/openldap/etc/openldap/ldap.conf ~www/.ldaprc )

You can then test that you're able to establish a LDAPS connection to Active Directory from the OpenLDAP command tools:

/usr/local/openldap/bin/ldapsearch -H "ldaps://adserver.ad.com"

This should return some output in extended LDIF format and will indicate no matching objects, but it proves the connection works.

The name of the server you're connecting to is important. If they server name you specify in the "ldaps://" URI does not match the name of the server in it's certificate, it will complain like so:

ldap_bind: Can't contact LDAP server (81)
additional info: TLS: hostname does not match CN in peer certificate

Once you've gotten the ldapsearch tool working correctly PHP should work also.

One important gotcha however is that the Web user must be able to locate it's HOME folder. You must check that Apache is providing a HOME variable set to the Web users home directory, so that php can locate the .ldaprc file and the settings contained within. This may well be different between Unix variants but it is such a simple and stupid thing if you miss it and it causes you grief. Simply use a SetEnv directive in Apache's httpd.conf:

SetEnv HOME /usr/local/www

With all that done, you can now code up a simple connect function:

function connect_AD()
{
$ldap_server = "ldaps://adserver.ad.com" ;
$ldap_user = "CN=web service account,OU=Service Accounts,DC=ad,DC=com" ;
$ldap_pass = "password" ;

$ad = ldap_connect($ldap_server) ;
ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) ;
$bound = ldap_bind($ad, $ldap_user, $ldap_pass);

return $ad ;
}

Optionally you can avoid the URI style server string and use something like ldap_connect("adserver.ad.com", 636) ; But work fine with Active Directory servers.

Hope this proves usefull.

<< Back to user notes page

To Top