Opportunistic TLS or mandatory TLS?
In most cases, mail platforms use opportunistic TLS, sometimes even without the mail administrator knowing this. For example a default setup of the Sendmail Opensource MTA is likely to use opportunistic TLS as a client (when sending mail), and you don’t need to do anything for this. Opportunistic TLS brings encryption of your communication up to the next hop. It does not provide any form of authentication: you may still be sending your mail to the wrong server, just that the communication will be encrypted!
On the other hand, mandatory TLS is when you need to ensure you’re speaking to the right server, and this works both ways: inbound and outbound. Policy configuration will ensure that you speak to the right server, i.e. when the MTA has decided to send a message to, say, the host relay.wolfhugel.eu, you want to make sure that this host shows a X.509 certificate which is adequate and which you trust.
Mandatory TLS makes sense from the moment you need to be sure who you’re talking to, or who is connecting to your mail server. This policy enforcement can be partial: most real life situations use standard Internet mail routing (MX records), eventually opportunistic TLS, and mandatory TLS to/from just a few remote sites.
Current implementation in the Sendmail MTA
Thanks to the use of rulesets to handle TLS enforcement, site administrators have a vast choice of what they can do with respect to validating a TLS connection. The only limitations are:
- The information coming from the certificate and provided by the MTA to the ruleset engine
- The ability of the rulesets to do things (and this is quite a large set of things).
The TLS_Srv and TLS_Clt tags are used respectivement when the Sendmail MTA sends (TLS_Srv) or receives (TLS_Clt) mail and it allows defining one or several actions. These filters apply when selecting the actual name of the server we’re talking to (or the domain of it), this means whatever appears in the MX. For fining control based on the recipient’s address there is a TLS_Rcpt keyword which is applied per recipient, regardless of the server we’re talking to. There is no such rule, sender address based, for incoming mail.
A few examples:
TLS_Srv:wolfhugel.eu VERIFY:128+CN TLS_Rcpt:wolfhugel.eu VERIFY:128+CN++CI:/C=GB/.../O=MyCAThe first line means that when talking to any server called “wolfhugel.eu” or within this domain (mail.wolfhugel.eu, relay.wolfhugel.eu, …), we want the TLS connection to be shown with a certificate whose Certification Authority is trusted by our system, with at least a 128 bit encryption algorithm and in addition we will check the CN of the presented certificate to ensure it corresponds to the one we’re actually talking to. So if our MX record is “relay.wolfhugel.eu” and we send a mail to this server, we want the certificate to be trusted and to have “relay.wolfhugel.eu” in its CN field.
The second line applies to any mail going to someone within the wolfhugel.eu domain, regardless of the mail server we’re actually sending the mail to. We do all verifications described above and in addition we want that the Certificate Issuer (this can be an intermediate certification authority) has a Subject line of “/C=GB/…/O=MyCA”, i.e. we indicate clearly which CA we trust for this domain.
Full documentation is provided in the Opensource Sendmail MTA package in the cf/README file.
Another use of TLS authentication is to permit, or not, relaying, i.e. the goal is to say that if you show a given certificate you may use this SMTP server to send mail anywhere (typically you would use the MSA submission port, 587/tcp). I do use this when I’m roaming: regardless of the IP address I show, my home MTA with allow me to send messages to anyone if I can prove, by ways of the adequate certificate, it’s me.
The verification is again done in two steps by using the “access_db” map: first we check if the certificate issuer is authorized, and then eventually we check the certificate itself, like in following example:
CertIssuer:/C=GB/.../O=MyCA RELAY CertIssuer:/C=GB/.../O=AnotherCA SUBJECT CertSubject:/C=GB/.../CN=CWOLF RELAYThe first line means that we will trust anyone showing a certificate issued by the certification authority “/C=GB/…/O=MyCA” (which again can be an intermediate authority). The second line says that if a certificate is presented signed by “/C=GB/…/O=AnotherCA” then we’ll check the Subject of the certificate itself, and we will authorize any listed entry with the adequate “CertSubject” entry.
Anything else? Just write your own rules, and this article won’t go into this. You can write any rules using the “sendmail.cf” language and the values provided for certificates. Following macros are available (taken from the documentation):
- ${cert_issuer} holds the DN of the CA (the cert issuer).
- ${cert_subject} holds the DN of the cert (called the cert subject).
- ${cn_issuer} holds the CN of the CA (the cert issuer).
- ${cn_subject} holds the CN of the cert (called the cert subject).
- ${tls_version} the TLS/SSL version used for the connection, e.g., TLSv1, TLSv1/SSLv3, SSLv3, SSLv2.
- ${cipher} the cipher used for the connection, e.g., EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CBC-SHA, DES-CBC-MD5, DES-CBC3-SHA.
- ${cipher_bits} the keylength (in bits) of the symmetric encryption algorithm used for the connection.
- ${verify} holds the result of the verification of the presented cert.
Possible values are:OK verification succeeded. NO no cert presented. NOT no cert requested. FAIL cert presented but could not be verified,
e.g., the cert of the signing CA is missing.NONE STARTTLS has not been performed. TEMP temporary error occurred. PROTOCOL protocol error occurred (SMTP level). SOFTWARE STARTTLS handshake failed. - ${server_name} the name of the server of the current outgoing SMTP connection.
- ${server_addr} the address of the server of the current outgoing SMTP connection.
The provided primitives already allow a lot of flexibility, but I feel there are a few limitations which are worth being discussed and which could lead to improvements.
An important limitation I came across when setting up TLS recently is that the Sendmail MTA does not handle the X509v3 “Subject Alternative Name” extension which allows specifying more than one host name in a certificate: my certificate could have a CN=tea.wolfhugel.eu and the extension would list this and all other names I do use the certificate for (“DNS:mail.wolfhugel.eu”, “DNS:relay.wolfhugel.eu”, …). Also one could argue that when doing name matching in certificate validation the current rules do not support the use of wildcard certificates (i.e. “CN=*.wolfhugel.eu”, “DNS:*.wolfhugel.eu”).
It seems like the Sendmail MTA it is somewhat difficult to define rules with intermediary certification authorities when trusting or accepting certificates.
Some proposals to improve the current handling in Sendmail MTA
Here are a few proposals to hopefully improve the way the Sendmail MTA uses certificates in STARTTLS connections and how to decide about giving, or not, authorization to connect or to relay. Comments on this are more than welcome, as users’ feedback is essential for improving the product!
Implement X509v3 Subject Alternative Names
This is a significant change and it requires source code changes in the MTA, but I feel it is probably the most needed extension: the Sendmail MTA would extract the DNS Subject Alternative Names from the presented certificates and expose them to the configuration file in macros $&{altname_subject} and $&{altname_issuer}. These macros can later be used in any rule where they are available for deciding to give, or not, access to the SMTP service.
Create new rules to use the Subject Alternative Names
The two new macros defined with the new names extracted from the certificates can be used to extend the current way the MTA gives authorization. Here is a proposal to extend the current rules.
For the TLS_Srv/TLS_Rcpt entries in the access DB we would add a new attribute called “CA” (as Cert Altnames) who behaves identically to the “CN” attribute but would mean match the CN or any alternative name, and the example given in the beginning of this article would become:
TLS_Srv:wolfhugel.eu VERIFY:128+CA TLS_Rcpt:wolfhugel.eu VERIFY:128+CA++CI:/C=GB/.../O=MyCAThis would mean the the host we’re connecting to must be found either in the CN of the certificate or in any DNS value of the alternative names for the verification to be successful.
Similarly when authorizing a remote party to relay, with the CertIssuer/CertSubject tags, we would add a new value to the access database: “ALTNAMES:xxx” would create an indirection telling to search for a key called “SubjAltName:xxx:value” in the access map which in turn would authorize or prevent access as shown in this example:
CertIssuer:/C=GB/.../O=MyCA ALTNAMES:SMI SubjAltName:SMI:cwolf@sendmail.com RELAYThe meaning of the above would be that whenever a connection is made with a certificate issues by “/C=GB/…/O=MyCA” we will be checking the alternative names and our key for the lookup is “SMI”. If any of the alternative names is “cwolf@sendmail.com” relaying will be authorized, and yes here we do allow Email addresses as alternative names.
Implement the wildcard certificates
Another point which has not been implemented in supporting wildcard certificates, i.e. a certificate whose CN or alternative name contains a star, like “*.wolfhugel.eu” meaning this certificate covers any host within the “wolfhugel.eu” domain name. This implementation would be transparent, i.e. no changes in the access map would be required.
Hi,
ReplyDeleteI wish to implement wildcard CN matching, on the (I thought simple) premise that the companies I want to send to have several servers, and that for specially sensitive correspondents (@example.com) in the absence of DNSSEC it should be good enough that I know that the MX for example.com has a valid certificate of the form *.example.com.
I asked on serverfault (http://serverfault.com/questions/734919/how-can-i-use-wildcards-for-sendmail-tls-rcpt) and the only help was a point to this post.
I think it should be possible to hack the TLS_req stanza from sendmail.cf to get what I want, I think it might even be easy for someone who is already familiar with the rather cryptic sendmail $ variables. For matching a cert whose CN ends in .example.com one could take CN:.example.com or even create a new CX:example.com, it seems from the stanza I quoted on serverfault that all is there in the .cf.
Does this seem doable to you?