Ability to reject invalid client certificate at TLS handshake time

Gert van Dijk gertvdijk+dovecot at gmail.com
Sat May 1 15:04:29 EEST 2021


Hi,

After a bit of struggling I've been able to set up TLS client
certificate authentication with Dovecot for both IMAP and Submission.
Users are required to present a valid certificate, cool so far!

What I noticed however on non-StartTLS listeners IMAPS (993) and SMTPS
(465), is that during the TLS handhake presenting a valid client
certificate is seemingly optional and is only checked later at time of
protocol-level login (external auth in my case). I'd like to change
that for security purposes and also a bit of obscurity. Not having the
ability to interact with Dovecot on protocol level lowers the attack
vector as well as the ease of checking my network security. Also, it
would prevent (anonymous) network scanners to easily detect what kind
of service is running on the port as they can see the IMAP/SMTP banner
without presenting a valid TLS client certificate currently.

Is it possible in any version of Dovecot to configure it to set up a
TLS server listening context that requires a handshake with a valid
client certificate?

I'm using Dovecot 2.3.4.1 (actual Debian Buster version
2.3.4.1-5+deb10u6), but willing to upgrade to any newer version when
this is offered. Going through some newer revisions changelog this
seems not the case, so I didn't spend time on upgrading yet.

Relevant config snippets for IMAP authenticating proxy that I use
(something similar for Submission):

# Opens 143 on StartTLS and 993 in wrapped TLS-only mode.
# Only 993 is exposed to the internet.
protocols = imap
passdb {
 driver = static
 args = proxy=y host=10.1.2.3 port=1143 pass=masterpass nopassword=y
}
auth_username_format = %n
ssl = required
ssl_cert = </etc/dovecot-ssl/cert.crt
ssl_key = </etc/dovecot-ssl/key.pem
ssl_prefer_server_ciphers = yes
ssl_min_protocol = TLSv1.2
ssl_cipher_list = [omitted for brevity]
ssl_ca = </etc/dovecot-ssl/client-ca.crt
ssl_verify_client_cert = yes
# Required to set this to 'no' if no CRL is set up yet
ssl_require_crl = no
auth_ssl_require_client_cert = yes
# Take the username from the client certificate (CN)
auth_mechanisms = external
auth_ssl_username_from_cert = yes
ssl_cert_username_field = commonName

Current behaviour from a client when deliberately not presenting a
client certificate shows the IMAP banner:
$ openssl s_client -connect myserver:993
CONNECTED(00000003)
---
Certificate chain
 0 [...]
---
Server certificate
-----BEGIN CERTIFICATE-----
[...]
---
Acceptable client certificate CA names
C = NL, O = Gert van Dijk, [...]
---
SSL handshake has read 1096 bytes and written 413 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 384 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE
LITERAL+ LOGINDISABLED AUTH=EXTERNAL] Dovecot (Debian) ready.


Expected:
TLS alert during handshake, e.g. on my Apache TLS client certificate
required configured instance:
$ openssl s_client -connect myserver:443
139676785239360:error:14094410:SSL routines:ssl3_read_bytes:sslv3
alert handshake failure:../ssl/record/rec_layer_s3.c:1543:SSL alert
number 40


IOW, I was hoping for something like this to exist:
ssl_verify_client_cert = required
OR
service imap-login {
 inet_listener imaps {
   port = 993
   ssl = client-cert-required
 }
}


Thanks,

Gert


More information about the dovecot mailing list