Soon after the release of Kolab 3 — the original, 2012 edition– the SASL Authentication daemon that Kolab provides to facilitate distributing LDAP hierarchies over multiple root DNs or even separate LDAP servers has assisted the speed of authentication with a cache.
Not the kind of cache you may be thinking about, though. The information contained within the cache does not (and won’t ever) contain full sets of credentials.
I have some provided some quick details on caching on the kolab users mailing list recently, but it was not really clearly articulated nor as well-explanatory, and people seem to be interested in these sorts of musings, so here’s a more detailed explanation of what the Kolab SASL Authentication daemon cache does, and why;
Suppose a user authenticates as firstname.lastname@example.org. Note that by default, thanks to login username canonification, Kolab allows this same user to use doe, john.doe, jdoe, both with @example.org as well as without, as the login username while ending up with email@example.com ultimately.
The authentication routines implemented in the Kolab SASL Authentication daemon need to find out;
Q: What is the root DN for the example.org domain?
This is mostly considered a multi-domain environment capability, and I have mentioned there’s more to that as well. Here, however, I’m going to stick to explaining the caching strategy 😉
By default, the domain base DN is cn=kolab,cn=config. This is a hierarchy that lives outside any LDAP database however, and without a database, there’s no indexes, and querying can be considered rather expensive.
Should an LDAP object entry be found, it’ll look for a domain result attribute. Usually, this is inetDomainBaseDN, and is supposed to contain the base DN — the highest level in the hierarchy at which the LDAP object entries related to the domain in question start. In a default Kolab Groupware installation, this inetDomainBaseDN corresponds to the domain root DN.
In our example, example.org would resolve to dc=example,dc=org. This result can be cached, shaving off one search otherwise performed relatively frequently.
Q: What entries can we find?
This is where the SASL authentication daemon searches the hierarchy for versions of the login username value in number of authentication attributes, namely uid, mail, and alias.
In our example, possible values (again, this is by default) may include john.doe, or firstname.lastname@example.org.
This searches potentially many entries for multiple versions of multiple attribute values. It will enforce to find only one entry (not zero nor more than one). The resulting entry’s DN is cached as a filter against a base dn with the one result entry DN:
- Searching for (&(objectclass=kolabinetorgperson)(|(uid=john.doe)(email@example.com)(firstname.lastname@example.org)(email@example.com)))
- against dc=example,dc=org
- results in uid=doe,ou=People,dc=example,dc=org
Since the filter is composed and the base DN is derived (from cache), the result is bound to remain valid for a period of time. Using the cached result entry DN rather than to search for it for every authentication request allows skipping another number of searches.
Q: Does a bind operation succeed?
This is where the supplied user credentials are validated. A bind() operation is performed using the result entry DN and the original supplied login credential.
Depending on the nature of a failure, the SASL authentication daemon can invalidate its result entry DN cache entry and re-iterate the searches necessary, such as when uid=doe has been moved to uid=doe,ou=Finance,ou=People,dc=example,dc=org resulting in the recognizable ‘NO_SUCH_OBJECT’ (32).
I hope this clarifies this part of Kolab’s caching. Perhaps I can find some time next week to write up some notes on the inner workings of the SMTP Access Policy.