[Dovecot] "nopassword" extra field useless with LDAP passdb
Hi,
We are trying to implement a highly secure mail server with user authentication restricted to SSL certificates only (not using passwords at all). Still, user information is stored in a LDAP directory. In this configuration LDAP is used to check whether the user is registered (and probably supply quota and other info), and actual authentication is done by SSL layer.
According to wiki, a "nopassword" extra field should be supplied, together with empty password. But there is no way to return an empty password from LDAP, as LDAP simply does not allow "empty attributes"; if an attribute is present, it is not empty. Supplying empty password as a static field (like this: pass_attrs = uid=user,=password=,nopassword) works an odd way, allowing empty password only, not "any password", and most MUAs (including our target Thunderbird) do not allow empty passwords.
Log excerpt follows ("1" was entered as a password during POP3 session; static empty password was configured as above):
Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): pass search: base=ou=People,dc=example,dc=com scope=subtree filter=(&(objectClass=inetOrgPerson)(uid=user1)) fields=uid,nopassword Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): result: uid(user)=user1 Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): Password mismatch Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): PLAIN(1) != '' Dec 9 02:11:17 localhost dovecot: auth(default): client out: FAIL 1 user=user1 Dec 9 02:11:19 localhost dovecot: pop3-login: Aborted login (auth failed, 1 attempts): user=<user1>, method=PLAIN, rip=127 .0.0.1, lip=127.0.0.1, secured
That's why we now have to maintain a separate passwd-like file with the following contents:
user1:::::::nopassword user2:::::::nopassword ...
and so on (updating it each time manually as users are added/removed), and use it as passdb. Only this allows true "any password" policy.
In fact, the problem seems to be a little bit deeper. In our setup user/password challenge is not needed at all. This is exactly what RFC 4959, "IMAP Extension for Simple Authentication and Security Layer (SASL) Initial Client Response", is about (http://tools.ietf.org/html/rfc4959 , see SASL EXTERNAL example). Are there any plans to implement SASL EXTERNAL mechanism in Dovecot?
Thank you! Zohan
First, I don't see why you would want to let your users logon with any password. A user with a valid certificate could logon as any user, as long as you don't actually somehow check who is the certificates' owner.
And i don't think there's a big chance that EXTERNAL will be implemented in the next time (though this post is a bit outdated): http://archives.neohapsis.com/archives/postfix/2005-12/1323.html Also, there's no further information at Roadmap: http://wiki.dovecot.org/Roadmap
Maybe you could use "auth external" with couriers authlib, as it recently started to support AUTH EXTERNAL: http://sourceforge.net/project/shownotes.php?group_id=5404&release_id=296342 The problem is that I don't see how authlib would be able to access the the certificate.
-----Original Message----- From: dovecot-bounces+siebert+lists=et.rub.de@dovecot.org [mailto:dovecot-bounces+siebert+lists=et.rub.de@dovecot.org] On Behalf Of Zohan Sent: Tuesday, December 09, 2008 12:45 AM To: dovecot@dovecot.org Subject: [Dovecot] "nopassword" extra field useless with LDAP passdb
Hi,
We are trying to implement a highly secure mail server with user authentication restricted to SSL certificates only (not using passwords at all). Still, user information is stored in a LDAP directory. In this configuration LDAP is used to check whether the user is registered (and probably supply quota and other info), and actual authentication is done by SSL layer.
According to wiki, a "nopassword" extra field should be supplied, together with empty password. But there is no way to return an empty password from LDAP, as LDAP simply does not allow "empty attributes"; if an attribute is present, it is not empty. Supplying empty password as a static field (like this: pass_attrs = uid=user,=password=,nopassword) works an odd way, allowing empty password only, not "any password", and most MUAs (including our target Thunderbird) do not allow empty passwords.
Log excerpt follows ("1" was entered as a password during POP3 session; static empty password was configured as above):
Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): pass search: base=ou=People,dc=example,dc=com scope=subtree filter=(&(objectClass=inetOrgPerson)(uid=user1)) fields=uid,nopassword Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): result: uid(user)=user1 Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): Password mismatch Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): PLAIN(1) != '' Dec 9 02:11:17 localhost dovecot: auth(default): client out: FAIL 1 user=user1 Dec 9 02:11:19 localhost dovecot: pop3-login: Aborted login (auth failed, 1 attempts): user=<user1>, method=PLAIN, rip=127 .0.0.1, lip=127.0.0.1, secured
That's why we now have to maintain a separate passwd-like file with the following contents:
user1:::::::nopassword user2:::::::nopassword ...
and so on (updating it each time manually as users are added/removed), and use it as passdb. Only this allows true "any password" policy.
In fact, the problem seems to be a little bit deeper. In our setup user/password challenge is not needed at all. This is exactly what RFC 4959, "IMAP Extension for Simple Authentication and Security Layer (SASL) Initial Client Response", is about (http://tools.ietf.org/html/rfc4959 , see SASL EXTERNAL example). Are there any plans to implement SASL EXTERNAL mechanism in Dovecot?
Thank you! Zohan
On Tue, 2008-12-09 at 02:44 +0300, Zohan wrote:
Dec 9 02:11:15 localhost dovecot: auth(default): ldap(user1,127.0.0.1): pass search: base=ou=People,dc=example,dc=com scope=subtree filter=(&(objectClass=inetOrgPerson)(uid=user1)) fields=uid,nopassword
Do you have a "nopassword" field in LDAP? If not, then it doesn't get set. Perhaps what you want is:
pass_attrs = uid=user, =nopassword=1
Do you have a "nopassword" field in LDAP? If not, then it doesn't get set. Perhaps what you want is:
pass_attrs = uid=user, =nopassword=1
Timo,
Thank you for your tip. The correct dovecot-ldap.conf line should look like:
pass_attrs = uid=user, =password=, =nopassword=1
But even in this case we get:
dovecot: auth(default): ldap(user1,127.0.0.1): pass search: base=ou=People,dc=example,dc=local scope=subtree filter=(&(objectClass=inetOrgPerson)(uid=user1)) fields=uid dovecot: auth(default): ldap(user1,127.0.0.1): result: uid(user)=user1 dovecot: auth(default): ldap(user1,127.0.0.1): No password in reply dovecot: auth(default): client out: FAIL 1 user=user1 temp
in our logs. I beleive this is due to the way attribute templates/static fields are processed in db-ldap.c.
Thanks in advance!
P.S. By the way, could you please share your opinion about possible SASL EXTERNAL usage in this case? Do you think this is the appropriate use case?
Timo,
Seems that "nopassword" extra field (more exactly, auth_request->no_password condition) is completely ignored in passdb-ldap.c, due to (line 112 as of Dovecot 1.1.7):
=== if (auth_request->passdb_password == NULL) { auth_request_log_error(auth_request, "ldap", "No password in reply"); } else if (ldap_next_entry(conn->ld, entry) != NULL) { auth_request_log_error(auth_request, "ldap", "pass_filter matched multiple objects, aborting"); } else if (auth_request->passdb_password == NULL && !auth_request->no_password) { auth_request_log_info(auth_request, "ldap", "Empty password returned without nopassword"); passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH; } else { /* passdb_password may change on the way, so we'll need to strdup. */ password = t_strdup(auth_request->passdb_password); passdb_result = PASSDB_RESULT_OK; }
As we see, the first "if" block intercepts auth_request->passdb_password == NULL condition, ignoring auth_request->no_password and making line 127 (passdb_result = PASSDB_RESULT_OK) unreachable even if auth_request->no_password is set. For my local installation I've just removed the first "if" block (see patch in attachment), and it seems to fix the problem.
On Fri, 2008-12-19 at 02:53 +0300, Zohan wrote:
As we see, the first "if" block intercepts auth_request->passdb_password == NULL condition, ignoring auth_request->no_password and making line 127 (passdb_result = PASSDB_RESULT_OK) unreachable even if auth_request->no_password is set. For my local installation I've just removed the first "if" block (see patch in attachment), and it seems to fix the problem.
I was originally thinking that passdb_password should be "" there, but I guess it's not necessary. Fixed the code the way pretty much like you did: http://hg.dovecot.org/dovecot-1.1/rev/a47ddd8a67a4
participants (3)
-
Thomas Siebert
-
Timo Sirainen
-
Zohan