On Oct 16, 2017, at 12:53 PM, Michael Ströder <michael@stroeder.com> wrote:
What do you mean by "initialize" and "has to guess"?
Disclaimer: I did not look at FreeRADIUS code.
It isn't in the FreRADIUS code. It's in the OpenLDAP code. If you go through the OpenLDAP client code, you'll see global variables, and all kinds of magic to determine if the LDAP library is initialized. That's bad.
No news that OpenLDAP API (with its roots in RFC 1823) has real deficiencies. Everybody involved agrees on that.
But most issues developers experience are caused by the lazy connect in libldap: ldap_initialize() and friends do *not* to the LDAP server. You have send the first LDAP operation to really connect and handle connection errors *after* that.
Yes, we've had issues with that ourselves.
In multi-threaded software with a persistent connection (pool) I usually use a lock to ensure that ldap_initialize() and bind (simple or SASL) were successfully done before the connection can be used by another thread. That's also the reason why I usually avoid a code path with anon-search-without-bind because I want to provoke a connect error with an explicit bind right from the beginning.
FreeRADIUS doesn't do a search until the LDAP connection is initialized. FreeRADIUS has a connection manager which handles all of that. The connections can move between threads, but only after a connection is explicitly released by a thread. So there is no multi-threaded usage of LDAP connections. Each thread uses a connection, and when it's done using the connection, the connection is released back to the connection manager for use by another thread.
This also might get tricky when the OpenLDAP server drops idle connections or was simply restarted and your multi-threaded LDAP client has to re-connect.
The connection manager (src/main/connection.c) handles all of that. Alan DeKok.