diff options
-rw-r--r-- | doc/doc-txt/experimental-spec.txt | 7 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 19 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 30 | ||||
-rw-r--r-- | src/src/transports/smtp.h | 1 | ||||
-rw-r--r-- | src/src/verify.c | 22 | ||||
-rw-r--r-- | test/confs/5850 | 3 | ||||
-rw-r--r-- | test/scripts/5850-DANE-OpenSSL/5850 | 2 |
7 files changed, 54 insertions, 30 deletions
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 333307b74..6eeb5092c 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -1224,10 +1224,9 @@ for fast revocation of certificates (which would otherwise be limited by the DNS TTL on the TLSA records). -For client-side DANE there is a new smtp transport option, -hosts_try_dane. It does the obvious thing. -[ may add a hosts_require_dane, too? ] -[ should it be domain-based rather than host-based? ] +For client-side DANE there are two new smtp transport options, +hosts_try_dane and hosts_require_dane. They do the obvious thing. +[ should they be domain-based rather than host-based? ] DANE will only be usable if the target host has DNSSEC-secured MX, A and TLSA records. diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 201636db0..0bd23ac63 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1618,15 +1618,8 @@ BOOL dane_required; #endif #ifdef EXPERIMENTAL_DANE -/*XXX TBD: test for transport options, and for TLSA records */ -/*dane = TRUE;*/ - -# ifdef notyet dane_required = verify_check_this_host(&ob->hosts_require_dane, NULL, host->name, host->address, NULL) == OK; -# else -dane_required = FALSE; -#endif if (host->dnssec == DS_YES) { @@ -1637,11 +1630,10 @@ if (host->dnssec == DS_YES) { /* move this out to host.c given the similarity to dns_lookup() ? */ uschar buffer[300]; - int prefix_length; /* why do we want this? */ uschar * fullname = buffer; /* TLSA lookup string */ - (void)sprintf(CS buffer, "_%d._tcp.%n%.256s", host->port, &prefix_length, + (void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name); switch (rc = dns_lookup(&tlsa_dnsa, buffer, T_TLSA, &fullname)) @@ -1653,7 +1645,7 @@ if (host->dnssec == DS_YES) case DNS_FAIL: if (dane_required) { - /* log that TLSA lookup failed */ + log_write(0, LOG_MAIN, "DANE error: TLSA lookup failed"); return FAIL; } break; @@ -1661,7 +1653,7 @@ if (host->dnssec == DS_YES) case DNS_SUCCEED: if (!dns_is_secure(&tlsa_dnsa)) { - /*log it - tlsa should never be non-dnssec */ + log_write(0, LOG_MAIN, "DANE error: TLSA lookup not DNSSEC"); return DEFER; } dane = TRUE; @@ -1669,9 +1661,10 @@ if (host->dnssec == DS_YES) } } } -else if (dane_required && !dane) +else if (dane_required) { - /* log that dnssec pre-req failed. Hmm - what? */ + /* Hmm - what lookup, precisely? */ + log_write(0, LOG_MAIN, "DANE error: previous lookup not DNSSEC"); return FAIL; } diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 2e3a6ced4..9abc69d51 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -109,6 +109,10 @@ optionlist smtp_transport_options[] = { { "hosts_require_auth", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_require_auth) }, #ifdef SUPPORT_TLS +# ifdef EXPERIMENTAL_DANE + { "hosts_require_dane", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, hosts_require_dane) }, +# endif # ifndef DISABLE_OCSP { "hosts_require_ocsp", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_require_ocsp) }, @@ -118,7 +122,7 @@ optionlist smtp_transport_options[] = { #endif { "hosts_try_auth", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_try_auth) }, -#ifdef EXPERIMENTAL_DANE +#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE) { "hosts_try_dane", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_try_dane) }, #endif @@ -206,6 +210,7 @@ smtp_transport_options_block smtp_transport_option_defaults = { NULL, /* hosts_require_auth */ #ifdef EXPERIMENTAL_DANE NULL, /* hosts_try_dane */ + NULL, /* hosts_require_dane */ #endif #ifndef DISABLE_PRDR NULL, /* hosts_try_prdr */ @@ -1571,8 +1576,13 @@ if (tls_out.active >= 0) /* If the host is required to use a secure channel, ensure that we have one. */ -else if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, - host->address, NULL) == OK) +else if ( verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, + host->address, NULL) == OK +#ifdef EXPERIMENTAL_DANE + || verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name, + host->address, NULL) == OK +#endif + ) { save_errno = ERRNO_TLSREQUIRED; message = string_sprintf("a TLS session is required for %s [%s], but %s", @@ -3268,10 +3278,16 @@ for (cutoff_retry = 0; expired && happens inside smtp_deliver().] */ #ifdef SUPPORT_TLS - if (rc == DEFER && first_addr->basic_errno == ERRNO_TLSFAILURE && - ob->tls_tempfail_tryclear && - verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, - host->address, NULL) != OK) + if ( rc == DEFER + && first_addr->basic_errno == ERRNO_TLSFAILURE + && ob->tls_tempfail_tryclear + && verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, + host->address, NULL) != OK +#ifdef EXPERIMENTAL_DANE + && verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name, + host->address, NULL) != OK +#endif + ) { log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted " "to %s [%s] (not in hosts_require_tls)", host->name, host->address); diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 018f9cfef..d968a4d54 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -23,6 +23,7 @@ typedef struct { uschar *hosts_require_auth; #ifdef EXPERIMENTAL_DANE uschar *hosts_try_dane; + uschar *hosts_require_dane; #endif #ifndef DISABLE_PRDR uschar *hosts_try_prdr; diff --git a/src/src/verify.c b/src/src/verify.c index b1b9f29a4..c2ee47892 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -644,9 +644,16 @@ else if the options permit it for this host. */ if (rc != OK) { - if (rc == DEFER && ob->tls_tempfail_tryclear && !smtps && - verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, - host->address, NULL) != OK) + if ( rc == DEFER + && ob->tls_tempfail_tryclear + && !smtps + && verify_check_this_host(&(ob->hosts_require_tls), NULL, + host->name, host->address, NULL) != OK +#ifdef EXPERIMENTAL_DANE + && verify_check_this_host(&(ob->hosts_require_dane), NULL, + host->name, host->address, NULL) != OK +#endif + ) { (void)close(inblock.sock); log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted " @@ -676,8 +683,13 @@ else /* If the host is required to use a secure channel, ensure that we have one. */ if (tls_out.active < 0) - if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, - host->address, NULL) == OK) + if ( verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name, + host->address, NULL) == OK +#ifdef EXPERIMENTAL_DANE + || verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name, + host->address, NULL) == OK +#endif + ) { /*save_errno = ERRNO_TLSREQUIRED;*/ log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s", diff --git a/test/confs/5850 b/test/confs/5850 index ac967fcb8..53cb78ae1 100644 --- a/test/confs/5850 +++ b/test/confs/5850 @@ -60,6 +60,9 @@ send_to_server: # tls_privatekey = DIR/aux-fixed/cert2 # tls_verify_certificates = DIR/aux-fixed/cert2 +# hosts_try_dane = * + hosts_require_dane = * + # ----- Retry ----- diff --git a/test/scripts/5850-DANE-OpenSSL/5850 b/test/scripts/5850-DANE-OpenSSL/5850 index 419930e11..0776fb6b4 100644 --- a/test/scripts/5850-DANE-OpenSSL/5850 +++ b/test/scripts/5850-DANE-OpenSSL/5850 @@ -5,7 +5,7 @@ exim -DSERVER=server -bd -oX PORT_D exim CALLER@test.ex Testing **** -exim -qf +exim -d+all -qf **** killdaemon exim -DSERVER=server -DNOTDAEMON -qf |