I recently moved a PHP web application from a server running PHP 5.3 on Mac OS X 10.6 to a newer one with PHP 5.4 on Mac OS X 10.9. This caused the following code sample, run against an Active Directory server, to hang at the ldap_search() call:
$conn = ldap_connect('ldaps://' . $LDAPSERVER); ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3); $bind = @ldap_bind($conn, $LDAPUSER, $LDAPPW); $result = ldap_search($conn, $LDAPSEARCHBASE, '(&(samaccountname=' . $searchuser . '))'); $info = ldap_get_entries($conn, $result); ldap_close($conn);
Wiresharking the connection between web server and LDAP server (after replacing ldaps:// with ldap://) showed:
bindRequest(1) "$LDAPUSER" simplebindResponse(1) success searchRequest82) "$LDAPSEARCHBASE" wholeSubtree searchResEntry(2) "CN=$searchuser,...,$LDAPSEARCHBASE" | searchResRef(2) | searchResDone(2) success [1 result] bindRequest(4) "" simple bindResponse(4) success searchRequest(3) "DC=DomainDnsZones,$LDAPSEARCHBASE" wholeSubtree searchResDone(3) operationsError (000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be complete on the connection., data0,
So it’s binding, receiving a success response, searching and then receiving a response and a referrer to DC=DomainDnsZones,$LDAPSEARCHBASE. Next, it opens a new TCP connection and follows the referrer, but does an anonymous bind.
The solution is simple: just add
ldap_set_option($conn, LDAP_OPT_REFERRALS, FALSE);
after line 2. If for some reason you actually need to follow the referrer, have a look at ldap_set_rebind_proc, which lets you specify a callback which then does the authentication upon rebind.
Update August 2015: Same goes when using Net_LDAP3, which is used e.g. by Roundcube’s LDAP integration. Here you need to add the following:
$config['ldap_public']['public'] = array( [...] 'referrals' => false, );