summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/experimental-spec.txt7
-rw-r--r--src/src/tls-openssl.c19
-rw-r--r--src/src/transports/smtp.c30
-rw-r--r--src/src/transports/smtp.h1
-rw-r--r--src/src/verify.c22
-rw-r--r--test/confs/58503
-rw-r--r--test/scripts/5850-DANE-OpenSSL/58502
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