SASL authentication against LDAP w/ client certs, supposed to work?
Hi all
I'm currently testing Dovecot 2.4, considering a migration from 2.3, and all works fine except authentication against LDAP (openldap slapd) with client certificates. Which I had no problem with on 2.3 for seven years or so.
Versions: Linux Alpine 3.22 Dovecot 2.4.1-4 (7d8c0e5759) Alpine package, but patched with https://github.com/dovecot/core/commit/431e328b3b035ddb187526cd13bccf29833ae...
Now, first a Dovecot configuration that does work, unencrypted simple bind against Unix domain socket:
ldap_version = 3 ldap_uris = ldapi:/// ldap_base = ou=users,dc=mydomain,dc=internal ldap_auth_dn = cn=dovecot,dc=mydomain,dc=internal ldap_auth_dn_password = secret passdb ldap { bind = no default_password_scheme = SSHA ldap_filter = (&(objectClass=posixAccount)(uid=%{user})) fields { user = %{ldap:uid} password = %{ldap:userPassword} } }
Meaning I'm doing password lookups, IMAP users can authenticate against Dovecot, Postfix correctly delivers incoming emails, everything works flawlessly.
Now the setup I'm talking about, which does not work:
ldap_version = 3 ldap_uris = ldaps://localhost.mydomain.internal ldap_base = ou=users,dc=mydomain,dc=internal ldap_auth_sasl_mechanisms = external ssl_client_cert_file = /etc/ssl/ldap/dovecot.crt ssl_client_key_file = /etc/ssl/ldap/dovecot.key
this just as a precaution during testing, validation *does* work
ssl_client_require_valid_cert = no ssl_client_ca_dir = /etc/ssl/certs passdb ldap { bind = no default_password_scheme = SSHA ldap_filter = (&(objectClass=posixAccount)(uid=%{user})) fields { user = %{ldap:uid} password = %{ldap:userPassword} } }
What happens here, as far as I can see, is Dovecot connects to slapd, initiates a SASL session but then fails to send the client certificate. slapd realizes the cert isn't coming, asserts there's no other SASL "external" method to fall back to and disconnects Dovecot. Game over.
Now, before somebody thinks 'maybe something wrong with the certs or so', the very same setup on the very same machine works perfectly with two other client types, namely
- openldap standard utils
- postfix (recipient lookup)
With the utils I have this setup, with the same client cert
URI ldaps://localhost.mydomain.internal BASE ou=users,dc=mydomain,dc=internal SASL_MECH external TLS_REQCERT demand TLS_CACERT /root/ssl/ca.crt TLS_CERT /etc/ssl/ldap/dovecot.crt TLS_KEY /etc/ssl/ldap/dovecot.key
and ldapwhoami connects without problem, and with ldapsearch I can perform the very same searches Dovecot is supposed to do.
Postfix, for recipient lookups, I have configured like this:
version = 3 server_host = ldaps://localhost.mydomain.internal search_base = ou=users,dc=mydomain,dc=internal query_filter = (&(mail=%s)) result_attribute = uid bind = sasl sasl_mechs = external tls_require_cert = demand tls_ca_cert_dir = /etc/ssl/certs tls_cert = /etc/ssl/ldap/dovecot.crt tls_key = /etc/ssl/ldap/dovecot.key
Again, no problem to authenticate agains LDAP with the very same client certificate. The CA is correctly installed into /etc/ssl/certs , by the way, with update-ca-certificates.
So out of 3 client types with the very same setup only Dovecot fails to successfully negotiate the client cert SASL session, while, after a good look through the docs, I really don't see any other settings I could tweak.
Thoughts?
Greetings, Bruno
On 26/06/2025 09:10 EEST Bruno Hertz via dovecot <dovecot@dovecot.org> wrote:
Hi all
I'm currently testing Dovecot 2.4, considering a migration from 2.3, and all works fine except authentication against LDAP (openldap slapd) with client certificates. Which I had no problem with on 2.3 for seven years or so.
Versions: Linux Alpine 3.22 Dovecot 2.4.1-4 (7d8c0e5759) Alpine package, but patched with https://github.com/dovecot/core/commit/431e328b3b035ddb187526cd13bccf29833ae...
Now, first a Dovecot configuration that does work, unencrypted simple bind against Unix domain socket:
ldap_version = 3 ldap_uris = ldapi:/// ldap_base = ou=users,dc=mydomain,dc=internal ldap_auth_dn = cn=dovecot,dc=mydomain,dc=internal ldap_auth_dn_password = secret passdb ldap { bind = no default_password_scheme = SSHA ldap_filter = (&(objectClass=posixAccount)(uid=%{user})) fields { user = %{ldap:uid} password = %{ldap:userPassword} } }
Meaning I'm doing password lookups, IMAP users can authenticate against Dovecot, Postfix correctly delivers incoming emails, everything works flawlessly.
Now the setup I'm talking about, which does not work:
ldap_version = 3 ldap_uris = ldaps://localhost.mydomain.internal ldap_base = ou=users,dc=mydomain,dc=internal ldap_auth_sasl_mechanisms = external ssl_client_cert_file = /etc/ssl/ldap/dovecot.crt ssl_client_key_file = /etc/ssl/ldap/dovecot.key
this just as a precaution during testing, validation *does* work
ssl_client_require_valid_cert = no ssl_client_ca_dir = /etc/ssl/certs passdb ldap { bind = no default_password_scheme = SSHA ldap_filter = (&(objectClass=posixAccount)(uid=%{user})) fields { user = %{ldap:uid} password = %{ldap:userPassword} } }
What happens here, as far as I can see, is Dovecot connects to slapd, initiates a SASL session but then fails to send the client certificate. slapd realizes the cert isn't coming, asserts there's no other SASL "external" method to fall back to and disconnects Dovecot. Game over.
Now, before somebody thinks 'maybe something wrong with the certs or so', the very same setup on the very same machine works perfectly with two other client types, namely
- openldap standard utils
- postfix (recipient lookup)
With the utils I have this setup, with the same client cert
URI ldaps://localhost.mydomain.internal BASE ou=users,dc=mydomain,dc=internal SASL_MECH external TLS_REQCERT demand TLS_CACERT /root/ssl/ca.crt TLS_CERT /etc/ssl/ldap/dovecot.crt TLS_KEY /etc/ssl/ldap/dovecot.key
and ldapwhoami connects without problem, and with ldapsearch I can perform the very same searches Dovecot is supposed to do.
Postfix, for recipient lookups, I have configured like this:
version = 3 server_host = ldaps://localhost.mydomain.internal search_base = ou=users,dc=mydomain,dc=internal query_filter = (&(mail=%s)) result_attribute = uid bind = sasl sasl_mechs = external tls_require_cert = demand tls_ca_cert_dir = /etc/ssl/certs tls_cert = /etc/ssl/ldap/dovecot.crt tls_key = /etc/ssl/ldap/dovecot.key
Again, no problem to authenticate agains LDAP with the very same client certificate. The CA is correctly installed into /etc/ssl/certs , by the way, with update-ca-certificates.
So out of 3 client types with the very same setup only Dovecot fails to successfully negotiate the client cert SASL session, while, after a good look through the docs, I really don't see any other settings I could tweak.
Thoughts?
Greetings, Bruno
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leae@dovecot.org
Dovecot uses openldap library, so it should respect what you have set in openldap config file. Can you run with ldap_debug_level = 9 to see if there is something that would explain this?
Aki
On Thu Jun 26, 2025 at 8:21 AM CEST, Aki Tuomi wrote:
On 26/06/2025 09:10 EEST Bruno Hertz via dovecot <dovecot@dovecot.org> wrote:
Hi all
I'm currently testing Dovecot 2.4, considering a migration from 2.3, and all works fine except authentication against LDAP (openldap slapd) with client certificates. Which I had no problem with on 2.3 for seven years or so.
[ .. snip .. ]
Thoughts?
Greetings, Bruno
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leae@dovecot.org
Dovecot uses openldap library, so it should respect what you have set in openldap config file. Can you run with ldap_debug_level = 9 to see if there is something that would explain this?
Aki
Hello Aki,
thanks for your reply. Did as you requested, and I hope something useful can be gleaned from it.
First, dovecot gives plenty of: dovecot: auth: Error: TLS trace: SSL_connect:error in SSLv3/TLS write client hello
Then, from slapd, TLS connection established: slapd[2439]: conn=1001 fd=18 TLS established tls_ssf=256 ssf=256 tls_proto=TLSv1.3 tls_cipher=TLS_AES_256_GCM_SHA384
Then, from dovecot, the handshake: dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS write client hello dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS read server hello dovecot: auth: Error: TLS trace: SSL_connect:TLSv1.3 read encrypted extensions
Then plenty of: dovecot: auth: Error: TLS trace: SSL_connect:error in SSLv3/TLS read server certificate request
Then, finally, we're coming to the point: dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS read server certificate request dovecot: auth: Error: TLS certificate verification: depth: 1, err: 0, subject: /O=Mydomain Internal/CN=Root CA, issuer: /O=Mydomain Internal/CN=Root CA dovecot: auth: Error: TLS certificate verification: depth: 0, err: 0, subject: /CN=*.mydomain.internal, issuer: /O=Mydomain Internal/CN=Root CA dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS read server certificate dovecot: auth: Error: TLS trace: SSL_connect:TLSv1.3 read server certificate verify dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS read finished dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS write change cipher spec dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS write client certificate dovecot: auth: Error: TLS trace: SSL_connect:SSLv3/TLS write finished dovecot: auth: Error: ldap_int_sasl_open: host=ldaptest dovecot: auth: Error: ldap_msgfree dovecot: auth: Error: ldap_err2string dovecot: auth: Error: ldap(ldaps://localhost.mydomain.internal:636): binding failed (dn (none)): Unknown authentication method, SASL(-4): no mechanism available: dovecot: auth: Error: ldap_sasl_interactive_bind: user selected: external dovecot: auth: Error: ldap_int_sasl_bind: external dovecot: auth: Error: ldap_int_sasl_open: host=ldaptest dovecot: auth: Error: ldap_msgfree dovecot: auth: Error: ldap_err2string dovecot: auth: Error: ldap(ldaps://localhost.mydomain.internal:636): binding failed (dn (none)): Unknown authentication method, SASL(-4): no mechanism available: dovecot: imap-login : Login aborted: Logged out (auth service reported temporary failure, 1 attempts in 3 secs) (temp_fail): user=<testuser>, method=PLAIN, rip=192.168.0.2, lip=192.168.0.11, TLS, session=<606v3XM46t3AqAAC> dovecot: auth: Error: ldap_free_connection 1 1 dovecot: auth: Error: ldap_send_unbind dovecot: auth: Error: TLS trace: SSL3 alert write:warning:close notify dovecot: auth: Error: ldap_free_connection: actually freed
So it does connect, does say it writes the client certificate, but then I don't know how to read this.
For comparison the other end, slapd. First a simple ldapwhoami client connection, which succeeds:
conn=1000 fd=18 TLS established tls_ssf=256 ssf=256 tls_proto=TLSv1.3 tls_cipher=TLS_AES_256_GCM_SHA384
tls_read: want=5, got=5
0000: 17 03 03 00 2b ....+
tls_read: want=43, got=43
0000: 63 a8 39 c4 f1 0c 75 53 9b 2e a9 7b b3 24 84 62 c.9...uS...{.$.b
0010: bb 01 32 0a 88 9d 39 c2 2f 06 1b ab 0d 59 a1 3b ..2...9./....Y.;
0020: 9d 71 e6 f2 a1 c1 dc 09 cc 1a 51 .q........Q
ldap_read: want=8, got=8
0000: 30 18 02 01 01 60 13 02 0....`..
ldap_read: want=18, got=18
0000: 01 03 04 00 a3 0c 04 08 45 58 54 45 52 4e 41 4c ........EXTERNAL
0010: 04 00 ..
tls_read: want=5 error=Resource temporarily unavailable
ldap_read: want=8 error=Resource temporarily unavailable
conn=1000 op=0 BIND dn="" method=163
So there we see the EXTERNAL request and the successful bind.
Now the dovecot client connection:
conn=1000 fd=18 TLS established tls_ssf=256 ssf=256 tls_proto=TLSv1.3 tls_cipher=TLS_AES_256_GCM_SHA384
tls_read: want=5, got=5
0000: 17 03 03 00 18 .....
tls_read: want=24, got=24
0000: 9c 7b cf 62 bf 11 3e 0c 30 db cf 5c 53 97 80 69 .{.b..>.0..\S..i
0010: 9f 97 cc d8 bf 53 87 f9 .....S..
ldap_read: want=8, got=7
0000: 30 05 02 01 01 42 00 0....B.
tls_read: want=5, got=5
0000: 17 03 03 00 13 .....
tls_read: want=19, got=19
0000: 44 f5 34 d2 cf cb 6f 9a 9d c6 38 c3 f0 34 9a 13 D.4...o...8..4..
0010: 77 8a 24 w.$
ldap_read: want=8, got=0
conn=1000 op=0 UNBIND
No EXTERNAL request and unbind after some timeout. So something appears to go wrong with the SASL setup, but what exactly, and why?
Greeting, Bruno
On 26/06/2025 11:03 EEST Bruno Hertz via dovecot <dovecot@dovecot.org> wrote: On Thu Jun 26, 2025 at 8:21 AM CEST, Aki Tuomi wrote: > >> On 26/06/2025 09:10 EEST Bruno Hertz via dovecot <dovecot@dovecot.org> wrote: >> >> >> Hi all >> >> I'm currently testing Dovecot 2.4, considering a migration from 2.3, and all >> works fine except authentication against LDAP (openldap slapd) with client >> certificates. Which I had no problem with on 2.3 for seven years or so. >> [ .. snip .. ] >> >> Thoughts? >> >> Greetings, Bruno >> _______________________________________________ >> dovecot mailing list -- dovecot@dovecot.org >> To unsubscribe send an email to dovecot-leae@dovecot.org > Dovecot uses openldap library, so it should respect what you have set in openldap config file. Can you run with ldap_debug_level = 9 to see if there is something that would explain this? Aki Hello Aki, thanks for your reply. Did as you requested, and I hope something useful can be gleaned from it. Can you try ldap_sasl_mechanism = EXTERNAL? As in, try upper casing it. Aki
On Thu Jun 26, 2025 at 10:32 AM CEST, Aki Tuomi wrote:
[snip]
Can you try ldap_sasl_mechanism = EXTERNAL?
As in, try upper casing it.
Aki
Certainly, Aki, thanks for the suggestion. I tried that before though without success (actually spent some time tweaking settings, even did straces and so forth to see if the certificate is actually read, simply because the authentication process did work in 2.3).
So I tried again now, applied the change to /etc/dovecot/dovecot.conf, restartet the dovecot service and did a quick fetchmail authentication test. The result is exactly the same as before:
slapd reports the incoming connection slapd[590]: conn=1006 fd=18 ACCEPT from IP=[::1]:38730 (IP=[::]:636) but dovecot logs the same message as it previously did, and fetchmail times out dovecot: auth: Error: ldap(ldaps://localhost.quasi.internal:636): binding failed (dn (none)): Unknown authentication method, SASL(-4): no mechanism available:
So the behavior is completely independent from the capitalization of the word external.
Greetings, Bruno
On 26/06/2025 12:05 EEST Bruno Hertz via dovecot <dovecot@dovecot.org> wrote:
On Thu Jun 26, 2025 at 10:32 AM CEST, Aki Tuomi wrote:
[snip]
Can you try ldap_sasl_mechanism = EXTERNAL?
As in, try upper casing it.
Aki
Certainly, Aki, thanks for the suggestion. I tried that before though without success (actually spent some time tweaking settings, even did straces and so forth to see if the certificate is actually read, simply because the authentication process did work in 2.3).
So I tried again now, applied the change to /etc/dovecot/dovecot.conf, restartet the dovecot service and did a quick fetchmail authentication test. The result is exactly the same as before:
slapd reports the incoming connection slapd[590]: conn=1006 fd=18 ACCEPT from IP=[::1]:38730 (IP=[::]:636) but dovecot logs the same message as it previously did, and fetchmail times out dovecot: auth: Error: ldap(ldaps://localhost.quasi.internal:636): binding failed (dn (none)): Unknown authentication method, SASL(-4): no mechanism available:
So the behavior is completely independent from the capitalization of the word external.
Greetings, Bruno
dovecot mailing list -- dovecot@dovecot.org To unsubscribe send an email to dovecot-leave@dovecot.org
The problem here is that the error is coming from your LDAP server. It does not want to do SASL EXTERNAL. Are you able to run your LDAP server in debug mode to see why it refuses this?
Aki
On Thu Jun 26, 2025 at 11:14 AM CEST, Aki Tuomi wrote:
[snip]
The problem here is that the error is coming from your LDAP server. It does not want to do SASL EXTERNAL. Are you able to run your LDAP server in debug mode to see why it refuses this?
Aki
Hello Aki,
I did that a number of times already, at various debug levels. In particular, slapd does not refuse to do SASL external, because, as said, it flawlessly works with the openldap tools (ldapwhoami, ldapsearch, ...) and Postfix, with the very same setup. Same certificate, same SASL mech settings, I documented all that in my very first email. So slapd is perfectly willing to do client certificate based authentication.
I emailed a slapd log example previously, by the way, comparing ldadwhoami to dovecot. Here it is again:
(1) successful connect with ldapwhoami (on host ldaptest)
conn=1000 fd=18 TLS established tls_ssf=256 ssf=256 tls_proto=TLSv1.3 tls_cipher=TLS_AES_256_GCM_SHA384
tls_read: want=5, got=5
0000: 17 03 03 00 2b ....+
tls_read: want=43, got=43
0000: 63 a8 39 c4 f1 0c 75 53 9b 2e a9 7b b3 24 84 62 c.9...uS...{.$.b
0010: bb 01 32 0a 88 9d 39 c2 2f 06 1b ab 0d 59 a1 3b ..2...9./....Y.;
0020: 9d 71 e6 f2 a1 c1 dc 09 cc 1a 51 .q........Q
ldap_read: want=8, got=8
0000: 30 18 02 01 01 60 13 02 0....`..
ldap_read: want=18, got=18
0000: 01 03 04 00 a3 0c 04 08 45 58 54 45 52 4e 41 4c ........EXTERNAL
0010: 04 00 ..
tls_read: want=5 error=Resource temporarily unavailable
ldap_read: want=8 error=Resource temporarily unavailable
conn=1000 op=0 BIND dn="" method=163
(2) unsuccessful connect with dovecot (on host ldaptest, same as above)
conn=1000 fd=18 TLS established tls_ssf=256 ssf=256 tls_proto=TLSv1.3 tls_cipher=TLS_AES_256_GCM_SHA384
tls_read: want=5, got=5
0000: 17 03 03 00 18 .....
tls_read: want=24, got=24
0000: 9c 7b cf 62 bf 11 3e 0c 30 db cf 5c 53 97 80 69 .{.b..>.0..\S..i
0010: 9f 97 cc d8 bf 53 87 f9 .....S..
ldap_read: want=8, got=7
0000: 30 05 02 01 01 42 00 0....B.
tls_read: want=5, got=5
0000: 17 03 03 00 13 .....
tls_read: want=19, got=19
0000: 44 f5 34 d2 cf cb 6f 9a 9d c6 38 c3 f0 34 9a 13 D.4...o...8..4..
0010: 77 8a 24 w.$
ldap_read: want=8, got=0
conn=1000 op=0 UNBIND
Note that these are packet logs taken at the very same stage. In the first case you see an 'EXTERNAL' reported by the function ldap_read, so I very strongly assume that's a packet coming from the client. Meaning the client says 'I want to do external'.
That very same announcement is missing in the second, the dovecot case. Dovecot does not say 'I want to do external', is what I'm bound to understand looking at those logs. And that's, presumably, where the problem lies.
slapd, I'm as good as certain, is not the problem here. All those programs - openldap tools, Postfix, Dovecot - link against the very same ldap and sasl libraries, is what I would think. Two out of three work. One does not.
Greetings, Bruno
participants (2)
-
Aki Tuomi
-
Bruno Hertz