Today sees another important fix for Kolab — in the SASL authentication daemon we ship, to be precise.
Our version of the SASL authentication daemon is a necessity for multi-domain environments. email@example.com may need to be authenticated against ldap://ldap.example.org/?dc=example,dc=org, while firstname.lastname@example.org may need to be authenticated against ldap://ldap.company.com/?o=company,c=ch.
The Kolab SASL authentication daemon performs this task based on discovery — but to discover time and time again for every single authentication request creates too many connections, too many searches and basically overloads the LDAP servers for larger deployments.
The chicken way out would be to cache the username and a one-way hash of the password — but Kolab is no chicken. We like LDAP to remain completely authoritative for authentication (so you can apply account suspension policies in a centralized manner).
So, instead, for each search we have performed in the past, save a base dn, filter and the resulting object entry DN. This makes us quick to resolve what root dn is used for @example.org, namely dc=example,dc=org, and which one is used for @company.com, namely o=company,c=ch. We do the actual search for email@example.com once, and we save (&(objectclass=kolabinetorgperson)(firstname.lastname@example.org)) having previously resulted in uid=doe,ou=People,dc=example,dc=org. We can then perform a fast bind using the object entry DN to verify the password, and update the timestamp on the cache entry every time it is successful.
So far, so good. However:
For a user however (a particularly volatile object), the position in the tree might change. When the object entry DN changes, the cached entry (that holds the bind DN) is no longer valid, and the cache would first need to expire before a new search is executed, and authentication would start to succeed once more — not good.
I originally implemented the cache for a particular use-case in which the object entry DN could not change, but repeated searches were too expensive, and had not taken the volatile object entry DN use-case — most other organizations running Kolab, probably.
The fix includes a couple of items, including only purging a cached entry before re-attempting authentication if the actual response to the original authentication attempt (against the cached bind DN) failed with a NO_SUCH_OBJECT error (code 32).
Welcome to the complexities of doing a little bit of coding on the side.