Hi,
For a long time our company has been planning to implement one-time password authentication as a LDAP SIMPLE auth mechanism. The goal behind that is to enable unified OTP authentication for a wide range of server applications that are capable of LDAP SIMPLE auth. The list of most important applications includes (but is not limited too): a Dovecot IMAP + RoundCube tandem; third-party JavaEE applications, like Atlassian Confluence and JIRA; in-house web-applications; etc. OATH HOTP [1] has been chosen as the actual OTP mechanism, due to its openness and wide availability of cheap hardware HOTP-compliant tokens, as well as software "tokens" for mobile phones. Implementing OTP on a LDAP server side will not only provide unified OTP auth, but also will allow to centralize authentication-related information (user database + token database) and will let us benefit from OpenLDAP out-of-the box features like replication. Right now we are entering the actual implementation phase, and I will be very glad to hear general architectural considerations as well as answers to my questions that already arose.
1. We have chosen to use SLAPI, not overlay API, to make our authentication plugin portable to other LDAP servers; but still our main target is OpenLDAP and we're not going to migrate to any other LDAP server (but our clients might). In terms of SLAPI, this will be a "preoperation bind plugin". If somebody thinks our choice is awfully bad, please don't hesitate to share your considerations.
2. Another reason for choosing SLAPI was much clearer API and, most importantly, availability of simple, synchronous functions for performing internal operations (searches, modifications). It seemed to me that overlay API provides only complex, callback-based functions for internal operations. Please let me know if I've overlooked that in the documentation (or, better say, source code, since overlay API is actually undocumented, opposite to SLAPI [2]).
3. Current state of SLAPI support in OpenLDAP completely lacks functions like slapi_is_root_suffix(), slapi_dn_isroot(), as well as the whole slapi_be_* function family. This makes impossible to determine root DN for authenticating principal. If we decide to actually implement those functions, what is the preferred way to submit the code to mainstream? To open an ITS issue and attach a patch to it?
4. For SLAPI plugins, is there a preferred way of obtaining plugin configuration, other than parsing ARGV? I know that in RedHat Directory server plugins often use their corresponding cn=plugins,cn=config entries to store config, but what about OpenLDAP?
5. HOTP algorithm uses SHA1 cryptographic hash. We clearly understand that if using SLAPI we won't be able to use OpenLDAP SHA1 implementation available via lutil_sha1.h. In order not to implement SHA1 ourselves, is it okay to introduce a dependency on OpenSSL/GnuTLS/NSS? For example, two RedHat plugins from their distribution (namely "http" and "pwdstorage" [3]) do use NSS and hence include ssl.h.
6. We decided to store token information in its dedicated subtree, like "ou=Tokens,dc=example,dc=com" (configurable). Each token will have its own entry that will store its serial number, seed, counter, PIN and its current owner (a single DN of user that this token has been assigned to), thus introducing a many-to-one relationship between tokens and users. Entries with absent "owner" attribute will form a pool of tokens available for assignment. Token synchronization (computing actual counter value from two successive passwords) will be implemented as an extended operation. A preliminary version of schema is available and we can publish it right now for review. Again, if there are any considerations and/or critical remarks, don't hesitate to share them.
That's all for the first post; I beg my pardon for a long and verbose text. We will be very thankful for any feedback on the topic.
Thanks! Dimitri CargoSoft LLC, Russia
[1] OATH HOTP: http://tools.ietf.org/html/rfc4226 [2] RedHat Directory Server Plugin Guide: http://docs.redhat.com/docs/en-US/Red_Hat_Directory_Server/8.2/html/Plug-in_... [3] http://git.fedorahosted.org/git/?p=389/ds.git;a=tree;f=ldap/servers/plugins;...
--On Tuesday, October 04, 2011 10:27 PM +0400 Dimitri mitya@cargosoft.ru wrote:
- Current state of SLAPI support in OpenLDAP completely lacks functions
like slapi_is_root_suffix(), slapi_dn_isroot(), as well as the whole slapi_be_* function family. This makes impossible to determine root DN for authenticating principal. If we decide to actually implement those functions, what is the preferred way to submit the code to mainstream? To open an ITS issue and attach a patch to it?
This is answered directly on the web site:
http://www.openldap.org/devel/contributing.html
--Quanah
--
Quanah Gibson-Mount Sr. Member of Technical Staff Zimbra, Inc A Division of VMware, Inc. -------------------- Zimbra :: the leader in open source messaging and collaboration
(Copying some of this from an IRC conversation)
Dimitri writes:
- We have chosen to use SLAPI, not overlay API, to make our
authentication plugin portable to other LDAP servers; but still our main target is OpenLDAP and we're not going to migrate to any other LDAP server (but our clients might). In terms of SLAPI, this will be a "preoperation bind plugin". If somebody thinks our choice is awfully bad, please don't hesitate to share your considerations.
Normally the simplest way would be to make new password scheme, maybe {OATH-HOTP} which takes the user name as a value. Then put userPassword: {OATH-HOTP}mitya in your entry. See contrib/slapd-modules/passwd/README.
Except I'm not sure how to best make a password plugin look up anyting in LDAP, like you are planning (your point 6). The right way is presumably via slapd internals - retrieve the thread and memory context, create a fake (internal) operation, use be_search. Or I suppose you could make it a regular LDAP client which talks to slapd over the LDAP protocol (maybe over ldapi://), but that seems rather weird. I wonder if that could potentially freeze all threads in a deadlock if you do it wrong. In OpenLDAP, each active LDAP request uses one thread. But I think SASL can do the same, so maybe it's OK.
I don't know slapi if you stay with that, but anyway:
- Another reason for choosing SLAPI was much clearer API and, most
importantly, availability of simple, synchronous functions for performing internal operations (searches, modifications). It seemed to me that overlay API provides only complex, callback-based functions for internal operations. Please let me know if I've overlooked that in the documentation (or, better say, source code, since overlay API is actually undocumented, opposite to SLAPI [2]).
See above. But for slapi vs overlays, not really. Some of the small overlays can be used for templates, and there are postings floating around with slapd internals. E.g. this one (now somewhat obsolete): http://www.openldap.org/lists/openldap-devel/200803/msg00054.html
- Current state of SLAPI support in OpenLDAP completely lacks functions
like slapi_is_root_suffix(), slapi_dn_isroot(), as well as the whole slapi_be_* function family. This makes impossible to determine root DN for authenticating principal.
slapi code is supposed to be portable to other servers, which might not have a concept like root DN.
- (SLAPI plugins configuration)
Don't know.
- HOTP algorithm uses SHA1 cryptographic hash. We clearly understand
that if using SLAPI we won't be able to use OpenLDAP SHA1 implementation available via lutil_sha1.h. In order not to implement SHA1 ourselves, is it okay to introduce a dependency on OpenSSL/GnuTLS/NSS? For example, two RedHat plugins from their distribution (namely "http" and "pwdstorage" [3]) do use NSS and hence include ssl.h.
Should work fine, unless you are linking a different library version of what OpenLDAP uses. Or sometimes even then, depending on how well the OS isolates linked library namespaces from each other.
However this may complicate things for your users: How to get a library to load another library requires OS-dependent linker options. You might prefer to copy someone's sha1 code. E.g. the one in OpenLDAP. Along with any COPYING file or whatever their copyright might require.
Or use lutil_sha1.h anyway as long as you're only using slapi for its simple interface, and worry about porting to other servers when the time comes when someone wants to do that.
Avoid GnuTLS: GnuTLS considered harmful http://www.openldap.org/lists/openldap-devel/200802/msg00072.html It has been cleaned up somewhat since then, but nothing I've heard suggests it's now good enough to trust it.
openldap-technical@openldap.org