diff options
-rw-r--r-- | src/src/tls-openssl.c | 2 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 14 | ||||
-rw-r--r-- | src/src/verify.c | 43 |
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; |