ZF-8274: No ability to specify URI when connecting to LDAP server using Zend_Ldap

Description

The current Zend_Ldap implementation expects host, portnumber, ssl and tls settings to connect to a directory server. However, this doesn't allow to connect to a socket (when running OpenLDAP on the same server for instance). Also, there's quite some lines of code figuring out the URI that one could specify immediately, but after those lines is an if that discards it all if there was no SLL used.

Personally I'd like to give an URI to ldap_connect, because it also allows failover to other servers. I currently specify 5 servers when connecting to LDAP, so I made my own class that extends Zend_Ldap and overrides the connect function.

I think there must be a sane way to implement this without dropping backwards compatibility, for instance by adding an URI option and using connect with URI when the option is set. Also, ldap_connect should connect to the default server specified in the ldap config files if no arguments are given, it seems to me this currently isn't possible either.

Comments

I don't understand why the ability to specify the LDAP URI directly would have any effect on the possibility of using a failover configuration.

Would it OK for your use-case (using a socket connection to the LDAP server via {{ldapi://}} if there was another {{socket}} option that allows you to specify the path to the underlying socket?

Regarding your comment about using ldap config files: this will not be possible as e.g. there are no such files with Windows installations of PHP. It also shouldn't be that much work to include the default failover server in the application itself - without relying on external files (whose location is also not very consistent).

As for the failover: $resource = ldap_connect('ldapi:/// ldapi:///var/run/slapd.sock ldap://localhost ldaps://localhost ldaps://nearbyserver ldaps://farawayserver'); This will only fail if all of the servers can't be reached. Of course there are other possibilities to provide a similar failover system, by connecting to the first server and then checking if it is available and so on, but this is already possible to use at a lower level, without having to implement anything for it yourself.

I think the socket option would only partly solve the missing URI option, but at least it would allow people to connect over a socket instead of via a hostname (and everything that comes with that).

Regarding the config files: It's not that there's a default failover server, there's a default server (or default list of servers). I don't know how it works on Windows, whether it's not possible to create such a config file (I believe it is, but the location is awkward, otherwise it would also not be possible to verify certificates). Either way, allowing for it to work as it should on linux doesn't break anything.

Would this be worth it if I can tell you how to set up a similar configuration file for Windows?

Fixed in trunk (r18924).

Added option to provide one or more LDAP URI(s) (ldap://, ldaps:// or ldapi://) in the $host parameter (either via options or via {{Zend_Ldap::connect()}}.

Could you please test if this works as expected?

Regarding the thing about reading the ldap.conf: how would you propose to locate the correct ldap.conf? Some distribution have /etc/ldap.conf some have /etc/ldap/ldap.conf... Or how do you think we could handle user-specific config files? On Windows the path to ldap.conf is hard-coded within the extension; it's always {{C:\OpenLDAP\sysconf\ldap.conf}}. So I think the problem will rather be finding the correct file on *nix systems.

I will comment about testing the code later, but in response to your config question:

I actually thought the LDAP libraries took care of loading defaults when not specifying any arguments, but I was wrong. The config file in *nix can be in a few places, but according to pam_ldap (which is very much one of the technically best LDAP implementations as far as I know) the default is /etc/ldap.conf (and this is the default I know off for the distributions I've used).

After rediscovering that the config has to be read at application level, I'm in doubt as to how and if it should be implemented. Personally I'd say implement a config reader, create a mapping from config values to values needed for Zend_Ldap and use the system default path (known for windows and *nix) with an option to override.

This would pretty much allow similar behaviour to what is possible now with loading configs and setOptions().

Also, I'm not saying you have to implement this functionality, I'm very happy the URI support is there, which is way more important in my opinion, but for future reference it might be nice that the issue was at least discussed (in depth?).

URI support works as expected (tested with trunk), thank you very much!