summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/src/tls-openssl.c2
-rw-r--r--src/src/transports/smtp.c14
-rw-r--r--src/src/verify.c43
3 files changed, 44 insertions, 15 deletions
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index ce6b47832..24ae3ea7e 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1764,7 +1764,7 @@ if (found)
return OK;
log_write(0, LOG_MAIN, "DANE error: No usable TLSA records");
-return FAIL;
+return DEFER;
}
#endif /*EXPERIMENTAL_DANE*/
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 094353415..087b10cda 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1279,6 +1279,7 @@ BOOL prdr_active;
BOOL dsn_all_lasthop = TRUE;
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
BOOL dane = FALSE;
+BOOL dane_required;
dns_answer tlsa_dnsa;
#endif
smtp_inblock inblock;
@@ -1365,8 +1366,6 @@ if (continue_hostname == NULL)
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
{
- BOOL dane_required;
-
tls_out.dane_verified = FALSE;
tls_out.tlsa_usage = 0;
@@ -1605,6 +1604,17 @@ if ( tls_offered
if (rc != OK)
{
+# ifdef EXPERIMENTAL_DANE
+ if (rc == DEFER && dane && !dane_required)
+ {
+ log_write(0, LOG_MAIN, "DANE attempt failed;"
+ " trying CA-root TLS to %s [%s] (not in hosts_require_dane)",
+ host->name, host->address);
+ dane = FALSE;
+ goto TLS_NEGOTIATE;
+ }
+# endif
+
save_errno = ERRNO_TLSFAILURE;
message = US"failure while setting up TLS session";
send_quit = FALSE;
diff --git a/src/src/verify.c b/src/src/verify.c
index bdd4b8b0a..a22bb7d5b 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -535,6 +535,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount.
uschar *interface = NULL; /* Outgoing interface to use; NULL => any */
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
BOOL dane = FALSE;
+ BOOL dane_required;
dns_answer tlsa_dnsa;
#endif
uschar inbuffer[4096];
@@ -592,7 +593,6 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount.
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
{
- BOOL dane_required;
int rc;
tls_out.dane_verified = FALSE;
@@ -797,6 +797,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount.
int oldtimeout = ob->command_timeout;
int rc;
+ tls_negotiate:
ob->command_timeout = callout;
rc = tls_client_start(inblock.sock, host, addr, addr->transport
# ifdef EXPERIMENTAL_DANE
@@ -805,26 +806,44 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount.
);
ob->command_timeout = oldtimeout;
- /* TLS negotiation failed; give an error. Try in clear on a new connection,
- if the options permit it for this host. */
+ /* TLS negotiation failed; give an error. Try in clear on a new
+ connection, if the options permit it for this host. */
if (rc != OK)
{
- if ( rc == DEFER
- && ob->tls_tempfail_tryclear
- && !smtps
- && verify_check_given_host(&ob->hosts_require_tls, host) != OK
- )
+ if (rc == DEFER)
{
(void)close(inblock.sock);
# ifdef EXPERIMENTAL_EVENT
(void) event_raise(addr->transport->event_action,
US"tcp:close", NULL);
# endif
- log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
- "to %s [%s] (not in hosts_require_tls)", host->name, host->address);
- suppress_tls = TRUE;
- goto tls_retry_connection;
+# ifdef EXPERIMENTAL_DANE
+ if (dane)
+ {
+ if (!dane_required)
+ {
+ log_write(0, LOG_MAIN, "DANE attempt failed;"
+ " trying CA-root TLS to %s [%s] (not in hosts_require_dane)",
+ host->name, host->address);
+ dane = FALSE;
+ goto tls_negotiate;
+ }
+ }
+ else
+# endif
+ if ( ob->tls_tempfail_tryclear
+ && !smtps
+ && verify_check_given_host(&ob->hosts_require_tls, host) != OK
+ )
+ {
+ log_write(0, LOG_MAIN, "TLS session failure:"
+ " delivering unencrypted to %s [%s] (not in hosts_require_tls)",
+ host->name, host->address);
+ suppress_tls = TRUE;
+ goto tls_retry_connection;
+ }
}
+
/*save_errno = ERRNO_TLSFAILURE;*/
/*message = US"failure while setting up TLS session";*/
send_quit = FALSE;