Re: [exim-dev] DANE SRV(/MX): mixed mode; multiple certs

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Phil Pennock
Ημερομηνία:  
Προς: exim-dev
Υ/ο: Tony Finch
Αντικείμενο: Re: [exim-dev] DANE SRV(/MX): mixed mode; multiple certs
> I'm going to add to this an optional "/strict" modifier.

I meant to not call it that, fighting off the propaganda that strictness
requires CAs, was in a rush to leave for gym. Went for /castrict
instead. Still time for a better name.

Here, attached, are the file comments in dane.c; no code (waiting for
this weekend, or perhaps next: I got confused over dates).

File comments guide the code that gets written.

Absent reasoned discourse leading to a change of heart, this is what I
intend to implement.

Thanks,
-Phil
/*************************************************
*     Exim - an Internet mail transport agent    *
*************************************************/


/* Copyright (c) University of Cambridge 1995 - 2013 */
/* See the file NOTICE for conditions of use and distribution. */

/* Copyright (c) Apcera, Inc. 2013
Author: Phil Pennock <pdp@???> */

/* Logic for handle DANE trust anchors for Exim */

/* Theory

Required background reading:
  RFC 6698
    The DNS-Based Authentication of Named Entities (DANE)
    Transport Layer Security (TLS) Protocol: TLSA


Loosely based on:
<https://datatracker.ietf.org/doc/draft-ietf-dane-smtp/?include_text=1> v01
<https://datatracker.ietf.org/doc/draft-ietf-dane-srv/?include_text=1> v02

However, we prefer a more secure approach to MX filtering by default, which
works within compatibility of MX intent instead of traditional MX ordering.

Routers gain an option "security = dane" or "security = dane/modifiers".

If "dane" is set, this does not turn on need_dnssec, but if the MX results are
secure, and if _$port._tcp.$host exists with a TLSA record for any one of the
results from the MX lookup, then in the Transport:

  * unless tls_verify_certificates is also set on the Transport, only
    usage 2 or 3 of TLSA apply, usage 0 or 1 will be equivalent to
    usage 2 or 3.
  * need_dnssec is coerced on (Router & Transport)
  * tls_sni defaults to $host (if not explicitly set)
  * hosts_require_tls is coerced on (if not explicitly set)
  * if /castrict modifier is set then:
    * tls_verify_hosts=* is set
  * else if TLSA is present, and contains a full certificate:
    * tls_verify_hosts=* is set, using the certificate from the TLSA record
      either as the expected peer cert or as a trust anchor
  * else without TLSA present and without /castrict:
    * tls_try_verify_hosts=* is set
  * the trust-anchor from the TLSA record is written to
    spool_directory/tlsa/$something
  * for non-PKIX usages (2,3) we just use the trust-anchor directly in
    TLS setup
  * for PKIX usages (0,1), we first use the tls_verify_certificates to
    confirm a path to the TLSA trust-anchor; then, if either that succeeds
    or /castrict is not set, then use the TLSA trust-anchor for TLS setup, just
    as for usages 2/3.


security = dane/prefertlsa
security = dane/prefersecure
security = dane/prefermxfirst
security = dane/preservemxorder

  * /prefertlsa -- prefer TLSA-present records, then DNSSEC-AD records,
    then the Insecure; within each of the three bands, sort by MX
  * /prefersecure -- just prefer DNSSEC-AD and then Insecure; within
    each of the two bands, sort by MX
  * /prefermxfirst -- aka Insecurity Prevails, first use MX ordering
    but within an MX level, prefer TLSA/Secure to Insecure
  * /preservemxorder -- aka Insecurity Prevails, only use MX ordering


MX records potentially result in multiple MX priorities, multiple hostnames at
each priority, and multiple IPs per hostname. TLSA security is at the hostname
level, so we can ignore the IPs. Within an MX priority, we're free to order as
we wish, although some people might depend upon round robin balancing. It's
easy to argue that if you want equal treatment, then provide DNSSEC for both or
neither, and provide TLSA records for both or neither.

Not using the MX ordering as the default primary key for sorting is more
contentious.

In order to not drop out of trusted resolution, if there exists a secure path
to a host identity, we need to take that. If there exists a secure path to
anchor information which we can process, we need to take that. If we allow
Insecure to intermix freely with Secure then the downgrade attack paths require
a lot of careful reasoning to try to convince ourselves we might get away with
it.

Against that, all MX hosts for a domain are supposed to be able to handle the
mail, so we simply treat security failures to some hosts as equivalent to a
network partition and the host being unreachable. That has to be handled
already anyway.

In the cases where a mail administrator is trying to be "clever" with semantic
meaning for their MX levels, in some kind of crude honeypot system which
assumes no network splits, then our answer is "don't secure your honeypots
first".

The "dane/preservemxorder" preserves all previous MX rules and DANE does not
change any ordering. Purists who don't accept that security is a reasonable
cause to change previous practice, as long as it can be done sufficiently
compatibly with previous specifications to not break things, can set this.

security = dane/castrict
security = dane/((prefer|preserve)*)/castrict

Without an explicit trust anchor present in a TLSA record, in most deployments
the lack of direct channel back to the human responsible for sending an email
means that errors can't be handled with a question. This results in anything
that tries to require CA certs be present on the sender side results in
delivery failures; tempting as it might be to claim "they cut off delivery to
themselves", back in the real world, postmasters would come under pressure to
trust Yet Another CA. Since the overhead of managing CAs-per-recipient-domain
is likely to create bureaucracy that is a losing battle, we avoid that.

If the client really wants to always be able to verify a certificate, even when
the recipient doesn't include a certificate in a TLSA record, we provide the
/castrict modifier, which can occur at any place.

Of note: if there is a certificate in a TLSA record (rather than just a
fingerprint) then the TLS verification is always absolute, and the
TLS-presented certificate must either anchor in (usage=(0,2)) or be
(usage=(1,3)) that TLSA certificate. A lack of trust path, with /castrict
false, merely converts TLSA usages 0=>2 and 1=>3, after at least _trying_
to verify, so that there are useful logs.
*/

/* For now, we only accept X00 certificates, ignoring the rest as unusable
per RFC 6698 section 4.1. */