mail/exim: import exim-4.94+fixes branch as state of 2020.09.09

Used git diffs:

[27/37] Fix spelling of local_part_data in docs and debug output
[27/37] Fix spelling of local_part_data in docs and debug output
[28/37] Fix ${readsocket } eol-replacement.  Bug 2630
[29/37] Taint: fix off-by-one in is_tainted().  Bug 2634
[30/37] Build: ifdef guard for EXPERIMENTAL_QUEUEFILE
[31/37] Taint: fix off-by-one in is_tainted().  Bug 2634
[32/37] DANE: force SNI to use $domain.  Bug 2265
[33/37] DANE: Fix 2-rcpt message, diff domins case.  Bug 2265
[34/37] Fix non-DANE build
[35/37] DANE: Fix 2 messages from queue case
[36/37] Fix non-DANE build

While here, make SPF option turned on by default

MFH:		2020Q3
This commit is contained in:
Dima Panov 2020-09-09 12:09:34 +00:00
parent cf2795d11d
commit 6d61cf0e62
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=548081
12 changed files with 1433 additions and 1 deletions

View file

@ -3,7 +3,7 @@
PORTNAME= exim
PORTVERSION?= ${EXIM_VERSION}
PORTREVISION?= 1
PORTREVISION?= 2
CATEGORIES= mail
MASTER_SITES= EXIM:exim
MASTER_SITE_SUBDIR= /exim4/:exim \

View file

@ -0,0 +1,54 @@
From d08a4ba2c5216195c107b123842da17bc1b0559f Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Sun, 9 Aug 2020 01:38:00 +0100
Subject: [PATCH 27/37] Fix spelling of local_part_data in docs and debug
output
(cherry picked from commit ccec2d82e2fda6d764f6cd1a9dd21c4f6285b614)
---
doc/ChangeLog | 2 +-
doc/NewStuff | 2 +-
src/routers/rf_queue_add.c | 2 +-
diff --git doc/ChangeLog doc/ChangeLog
index aaea04caf..703f4b9ee 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -6700,7 +6700,7 @@ Exim version 4.31
same list, then the first domain was re-checked, the value of $domain_data
after the final check could be wrong. In particular, if the second check
failed, it could be set empty. This bug probably also applied to
- $localpart_data.
+ $local_part_data.
41. The strip_trailing_dot option was not being applied to the address given
with the -f command-line option.
diff --git doc/NewStuff doc/NewStuff
index 43e170e11..16dec8808 100644
--- doc/NewStuff
+++ doc/NewStuff
@@ -57,7 +57,7 @@ Version 4.94
16. An option on all single-key lookups, to return (on a hit) a de-tainted
version of the lookup key rather than the looked-up data.
-17. $domain_data and $localpart_data are now set by all list-match successes.
+17. $domain_data and $local_part_data are now set by all list-match successes.
Previously only list items that performed lookups did so.
Also, matching list items that are tail-match or RE-match now set the
numeric variables $0 (etc) in the same way os other RE matches.
diff --git src/routers/rf_queue_add.c src/routers/rf_queue_add.c
index 938eee30a..4dab60dfe 100644
--- src/routers/rf_queue_add.c
+++ src/routers/rf_queue_add.c
@@ -98,7 +98,7 @@ DEBUG(D_route)
" errors_to=%s\n",
addr->transport ? addr->transport->name : US"<unset>",
addr->local_part, addr->domain, addr->prop.errors_address);
- debug_printf(" domain_data=%s localpart_data=%s\n", addr->prop.domain_data,
+ debug_printf(" domain_data=%s local_part_data=%s\n", addr->prop.domain_data,
addr->prop.localpart_data);
}
--
2.28.0

View file

@ -0,0 +1,216 @@
From 18a352ae8a799bb7be3a03b14bbf3ce9e0ba4945 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Fri, 14 Aug 2020 13:09:53 +0100
Subject: [PATCH 28/37] Fix ${readsocket } eol-replacement. Bug 2630
(cherry picked from commit 7f83b348ccf4cd815e9758ab9ca1012e66324e9d)
---
doc/ChangeLog | 4 ++++
src/expand.c | 11 +++++++----
src/functions.h | 2 +-
src/lookups/readsock.c | 6 ++++--
src/macros.h | 6 ++++--
src/readconf.c | 4 ++--
src/string.c | 30 +++++++++++++++++-----------
diff --git doc/ChangeLog doc/ChangeLog
index 703f4b9ee..2d2dc1f9f 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -78,6 +78,10 @@ JH/18 Bug 2617: Fix a taint trap in parse_fix_phrase(). Previously when the
rewrite with the "h" flag, by using the "-F" command-line option, or
by using a "name=" option on a control=submission ACL modifier.
+JH/21 Bug 2630: Fix eol-replacement string for the ${readsocket } expansion.
+ Previously when a whitespace character was specified it was not inserted
+ after removing the newline.
+
Exim version 4.94
-----------------
diff --git src/expand.c src/expand.c
index 791222324..bb9fd79ef 100644
--- src/expand.c
+++ src/expand.c
@@ -4920,7 +4920,7 @@ while (*s != 0)
{
expand_string_message =
string_sprintf("lookup of \"%s\" gave DEFER: %s",
- string_printing2(key, FALSE), search_error_message);
+ string_printing2(key, SP_TAB), search_error_message);
goto EXPAND_FAILED;
}
if (expand_setup > 0) expand_nmax = expand_setup;
@@ -5334,11 +5334,14 @@ while (*s != 0)
while ((item = string_nextinlist(&list, &sep, NULL, 0)))
g = string_append_listele(g, ',', item);
- /* possibly plus an EOL string */
+ /* possibly plus an EOL string. Process with escapes, to protect
+ from list-processing. The only current user of eol= in search
+ options is the readsock expansion. */
+
if (sub_arg[3] && *sub_arg[3])
g = string_append_listele(g, ',',
- string_sprintf("eol=%s", sub_arg[3]));
-
+ string_sprintf("eol=%s",
+ string_printing2(sub_arg[3], SP_TAB|SP_SPACE)));
}
/* Gat a (possibly cached) handle for the connection */
diff --git src/functions.h src/functions.h
index f4d1622dc..51bb17a09 100644
--- src/functions.h
+++ src/functions.h
@@ -529,7 +529,7 @@ extern int string_is_ip_address(const uschar *, int *);
#ifdef SUPPORT_I18N
extern BOOL string_is_utf8(const uschar *);
#endif
-extern const uschar *string_printing2(const uschar *, BOOL);
+extern const uschar *string_printing2(const uschar *, int);
extern uschar *string_split_message(uschar *);
extern uschar *string_unprinting(uschar *);
#ifdef SUPPORT_I18N
diff --git src/lookups/readsock.c src/lookups/readsock.c
index c2088b7a5..cfc9b4ad8 100644
--- src/lookups/readsock.c
+++ src/lookups/readsock.c
@@ -186,7 +186,9 @@ FILE * fp;
gstring * yield;
int ret = DEFER;
-DEBUG(D_lookup) debug_printf_indent("readsock: file=\"%s\" key=\"%s\" len=%d opts=\"%s\"\n", filename, keystring, length, opts);
+DEBUG(D_lookup)
+ debug_printf_indent("readsock: file=\"%s\" key=\"%s\" len=%d opts=\"%s\"\n",
+ filename, keystring, length, opts);
/* Parse options */
@@ -200,7 +202,7 @@ if (opts) for (uschar * s; s = string_nextinlist(&opts, &sep, NULL, 0); )
lf.do_tls = TRUE;
#endif
else if (Ustrncmp(s, "eol=", 4) == 0)
- eol = s + 4;
+ eol = string_unprinting(s + 4);
else if (Ustrcmp(s, "cache=yes") == 0)
lf.cache = TRUE;
else if (Ustrcmp(s, "send=no") == 0)
diff --git src/macros.h src/macros.h
index a507bbf83..2378773cb 100644
--- src/macros.h
+++ src/macros.h
@@ -41,9 +41,11 @@ manipulate them. */
/* For almost all calls to convert things to printing characters, we want to
-allow tabs. A macro just makes life a bit easier. */
+allow tabs & spaces. A macro just makes life a bit easier. */
-#define string_printing(s) string_printing2((s), TRUE)
+#define string_printing(s) string_printing2((s), 0)
+#define SP_TAB BIT(0)
+#define SP_SPACE BIT(1)
/* We need a special return code for "no recipients and failed to send an error
diff --git src/readconf.c src/readconf.c
index 0d0769c88..948fa2403 100644
--- src/readconf.c
+++ src/readconf.c
@@ -1546,7 +1546,7 @@ if (flags & opt_fn_print)
{
if (flags & opt_fn_print_label) printf("%s = ", name);
printf("%s\n", smtp_receive_timeout_s
- ? string_printing2(smtp_receive_timeout_s, FALSE)
+ ? string_printing2(smtp_receive_timeout_s, SP_TAB)
: readconf_printtime(smtp_receive_timeout));
}
else if (*str == '$')
@@ -2463,7 +2463,7 @@ switch(ol->type & opt_mask)
case opt_rewrite: /* Show the text value */
s = *(USS value);
if (!no_labels) printf("%s = ", name);
- printf("%s\n", s ? string_printing2(s, FALSE) : US"");
+ printf("%s\n", s ? string_printing2(s, SP_TAB) : US"");
break;
case opt_int:
diff --git src/string.c src/string.c
index 5acee1b00..f91a6a428 100644
--- src/string.c
+++ src/string.c
@@ -281,17 +281,17 @@ return ch;
/* This function is called for critical strings. It checks for any
non-printing characters, and if any are found, it makes a new copy
of the string with suitable escape sequences. It is most often called by the
-macro string_printing(), which sets allow_tab TRUE.
+macro string_printing(), which sets flags to 0.
Arguments:
s the input string
- allow_tab TRUE to allow tab as a printing character
+ flags Bit 0: convert tabs. Bit 1: convert spaces.
Returns: string with non-printers encoded as printing sequences
*/
const uschar *
-string_printing2(const uschar *s, BOOL allow_tab)
+string_printing2(const uschar *s, int flags)
{
int nonprintcount = 0;
int length = 0;
@@ -301,7 +301,10 @@ uschar *ss, *tt;
while (*t != 0)
{
int c = *t++;
- if (!mac_isprint(c) || (!allow_tab && c == '\t')) nonprintcount++;
+ if ( !mac_isprint(c)
+ || flags & SP_TAB && c == '\t'
+ || flags & SP_SPACE && c == ' '
+ ) nonprintcount++;
length++;
}
@@ -310,17 +313,19 @@ if (nonprintcount == 0) return s;
/* Get a new block of store guaranteed big enough to hold the
expanded string. */
-ss = store_get(length + nonprintcount * 3 + 1, is_tainted(s));
+tt = ss = store_get(length + nonprintcount * 3 + 1, is_tainted(s));
/* Copy everything, escaping non printers. */
-t = s;
-tt = ss;
-
-while (*t != 0)
+for (t = s; *t; )
{
int c = *t;
- if (mac_isprint(c) && (allow_tab || c != '\t')) *tt++ = *t++; else
+ if ( mac_isprint(c)
+ && (!(flags & SP_TAB) || c != '\t')
+ && (!(flags & SP_SPACE) || c != ' ')
+ )
+ *tt++ = *t++;
+ else
{
*tt++ = '\\';
switch (*t)
@@ -947,7 +952,10 @@ else
s = ss;
if (!*s || *++s != sep || sep_is_special) break;
}
- while (g->ptr > 0 && isspace(g->s[g->ptr-1])) g->ptr--;
+ /* while (g->ptr > 0 && isspace(g->s[g->ptr-1])) g->ptr--; */
+ while ( g->ptr > 0 && isspace(g->s[g->ptr-1])
+ && (g->ptr == 1 || g->s[g->ptr-2] != '\\') )
+ g->ptr--;
buffer = string_from_gstring(g);
gstring_release_unused(g);
}
--
2.28.0

View file

@ -0,0 +1,51 @@
From d2671b04d025dee3b8311d2d83e0a0342c670f52 Mon Sep 17 00:00:00 2001
From: Gavan <gavan@coolfactor.org>
Date: Fri, 21 Aug 2020 15:46:01 +0100
Subject: [PATCH 29/37] Taint: fix off-by-one in is_tainted(). Bug 2634
(cherry picked from commit e0ae68c8ee6788508da4989ee0d6fcbaf40c7b97)
---
doc/ChangeLog | 5 +++++
src/store.c | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index 2d2dc1f9f..6d944f204 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -82,6 +82,11 @@ JH/21 Bug 2630: Fix eol-replacement string for the ${readsocket } expansion.
Previously when a whitespace character was specified it was not inserted
after removing the newline.
+JH/24 Bug 2634: Fix a taint trap seen on NetBSD: the testing coded for
+ is_tainted() had an off-by-one error in the overenthusiastic direction.
+ Find and fix by Gavan. Although NetBSD is not a supported platform for
+ 4.94 this bug could affect other platforms.
+
Exim version 4.94
-----------------
diff --git src/store.c src/store.c
index c460ba383..7d08c9804 100644
--- src/store.c
+++ src/store.c
@@ -188,14 +188,14 @@ for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
if ((b = current_block[pool]))
{
uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
- if (US p >= bc && US p <= bc + b->length) return TRUE;
+ if (US p >= bc && US p < bc + b->length) return TRUE;
}
for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
for (b = chainbase[pool]; b; b = b->next)
{
uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
- if (US p >= bc && US p <= bc + b->length) return TRUE;
+ if (US p >= bc && US p < bc + b->length) return TRUE;
}
return FALSE;
}
--
2.28.0

View file

@ -0,0 +1,32 @@
From 4970c58b394eb0778542c97e3f86b565f9e3daa7 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Mon, 24 Aug 2020 20:14:34 +0100
Subject: [PATCH 30/37] Build: ifdef guard for EXPERIMENTAL_QUEUEFILE
(cherry picked from commit 1f5d0a9551205febf6729c7ee36c27626a76b4a4)
---
src/transports/queuefile.c | 4 ++++
diff --git src/transports/queuefile.c src/transports/queuefile.c
index 21ed3527f..97218548b 100644
--- src/transports/queuefile.c
+++ src/transports/queuefile.c
@@ -8,7 +8,10 @@
/* See the file NOTICE for conditions of use and distribution. */
+
#include "../exim.h"
+
+#ifdef EXPERIMENTAL_QUEUEFILE /* whole file */
#include "queuefile.h"
/* Options specific to the appendfile transport. They must be in alphabetic
@@ -276,3 +279,4 @@ return FALSE;
}
#endif /*!MACRO_PREDEF*/
+#endif /*EXPERIMENTAL_QUEUEFILE*/
--
2.28.0

View file

@ -0,0 +1,28 @@
From 976ef0e5fa7896394fe045e824dfb3e7d7502a68 Mon Sep 17 00:00:00 2001
From: Gavan <gavan@coolfactor.org>
Date: Fri, 21 Aug 2020 15:46:01 +0100
Subject: [PATCH 31/37] Taint: fix off-by-one in is_tainted(). Bug 2634
(cherry picked from commit e0ae68c8ee6788508da4989ee0d6fcbaf40c7b97)
---
doc/ChangeLog | 5 +++++
diff --git doc/ChangeLog doc/ChangeLog
index 6d944f204..ae4050322 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -87,6 +87,11 @@ JH/24 Bug 2634: Fix a taint trap seen on NetBSD: the testing coded for
Find and fix by Gavan. Although NetBSD is not a supported platform for
4.94 this bug could affect other platforms.
+JH/24 Bug 2634: Fix a taint trap seen on NetBSD: the testing coded for
+ is_tainted() had an off-by-one error in the overenthusiastic direction.
+ Find and fix by Gavan. Although NetBSD is not a supported platform for
+ 4.94 this bug could affect other platforms.
+
Exim version 4.94
-----------------
--
2.28.0

View file

@ -0,0 +1,102 @@
From d8e99d6047e709b35eabb1395c2046100d1a1dda Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Wed, 19 Aug 2020 21:09:04 +0100
Subject: [PATCH 32/37] DANE: force SNI to use $domain. Bug 2265
Note: this is not a complete fix for the issue
(cherry picked from commit 7044dd8fd62e215572ecf5a2c7f1bb9581cf6628)
---
doc/ChangeLog | 10 ++++++++++
src/receive.c | 2 +-
src/smtp_in.c | 2 +-
src/tls-gnu.c | 2 +-
src/tls-openssl.c | 1 +
src/transports/smtp.c | 1 +
diff --git doc/ChangeLog doc/ChangeLog
index ae4050322..ec1b03304 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -91,6 +91,16 @@ JH/24 Bug 2634: Fix a taint trap seen on NetBSD: the testing coded for
is_tainted() had an off-by-one error in the overenthusiastic direction.
Find and fix by Gavan. Although NetBSD is not a supported platform for
4.94 this bug could affect other platforms.
+JH/21 Bug 2630: Fix eol-replacement string for the ${readsocket } expansion.
+ Previously when a whitespace character was specified it was not inserted
+ after removing the newline.
+
+JH/22 Bug 2265: Force SNI usage for smtp transport DANE'd connections, to be
+ the domain part of the recipient address. This overrides any tls_sni
+ option set, which was previously used.
+
+JH/23 Logging: with the +tls_sni log_selector, do not wrap the received SNI
+ in quotes.
Exim version 4.94
diff --git src/receive.c src/receive.c
index 0db897e9e..ec90e93cd 100644
--- src/receive.c
+++ src/receive.c
@@ -4004,7 +4004,7 @@ if (LOGGING(tls_certificate_verified) && tls_in.cipher)
if (LOGGING(tls_peerdn) && tls_in.peerdn)
g = string_append(g, 3, US" DN=\"", string_printing(tls_in.peerdn), US"\"");
if (LOGGING(tls_sni) && tls_in.sni)
- g = string_append(g, 3, US" SNI=\"", string_printing(tls_in.sni), US"\"");
+ g = string_append(g, 2, US" SNI=", string_printing2(tls_in.sni, SP_TAB|SP_SPACE));
#endif
if (sender_host_authenticated)
diff --git src/smtp_in.c src/smtp_in.c
index 526164c46..a13f0ed63 100644
--- src/smtp_in.c
+++ src/smtp_in.c
@@ -1811,7 +1811,7 @@ if (LOGGING(tls_certificate_verified) && tls_in.cipher)
if (LOGGING(tls_peerdn) && tls_in.peerdn)
g = string_append(g, 3, US" DN=\"", string_printing(tls_in.peerdn), US"\"");
if (LOGGING(tls_sni) && tls_in.sni)
- g = string_append(g, 3, US" SNI=\"", string_printing(tls_in.sni), US"\"");
+ g = string_append(g, 2, US" SNI=", string_printing2(tls_in.sni, SP_TAB|SP_SPACE));
return g;
}
#endif
diff --git src/tls-gnu.c src/tls-gnu.c
index 875c82efa..a34633390 100644
--- src/tls-gnu.c
+++ src/tls-gnu.c
@@ -2863,7 +2863,7 @@ DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", cctx->so
/* If dane is flagged, have either request or require dane for this host, and
a TLSA record found. Therefore, dane verify required. Which implies cert must
be requested and supplied, dane verify must pass, and cert verify irrelevant
-(incl. hostnames), and (caller handled) require_tls */
+(incl. hostnames), and (caller handled) require_tls and sni=$domain */
if (conn_args->dane && ob->dane_require_tls_ciphers)
{
diff --git src/tls-openssl.c src/tls-openssl.c
index a62322928..054b23d0c 100644
--- src/tls-openssl.c
+++ src/tls-openssl.c
@@ -3197,6 +3197,7 @@ tlsp->tlsa_usage = 0;
#ifndef DISABLE_OCSP
{
# ifdef SUPPORT_DANE
+ /*XXX this should be moved to caller, to be common across gnutls/openssl */
if ( conn_args->dane
&& ob->hosts_request_ocsp[0] == '*'
&& ob->hosts_request_ocsp[1] == '\0'
diff --git src/transports/smtp.c src/transports/smtp.c
index 8492a7f25..28dd8ff24 100644
--- src/transports/smtp.c
+++ src/transports/smtp.c
@@ -2020,6 +2020,7 @@ if (!continue_hostname)
{
case OK: sx->conn_args.dane = TRUE;
ob->tls_tempfail_tryclear = FALSE;
+ ob->tls_sni = sx->addrlist->domain;
break;
case FAIL_FORCED: break;
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
--
2.28.0

View file

@ -0,0 +1,217 @@
From a505cf777f90755bce69ab53a899b284a304127b Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Sun, 23 Aug 2020 15:32:48 +0100
Subject: [PATCH 33/37] DANE: Fix 2-rcpt message, diff domins case. Bug 2265
(cherry picked from commit 99350dede64ad634300ddf15d0d97a81fd75d330)
---
src/debug.c | 11 ++++-
src/deliver.c | 3 ++
src/macros.h | 1 +
src/transports/smtp.c | 71 ++++++++++++++++++++++++----
src/verify.c | 2 +-
diff --git src/debug.c src/debug.c
index 6d6132e39..819e83331 100644
--- src/debug.c
+++ src/debug.c
@@ -30,7 +30,16 @@ const uschar * rc_names[] = { /* Mostly for debug output */
[UNEXPECTED] = US"UNEXPECTED",
[CANCELLED] = US"CANCELLED",
[FAIL_SEND] = US"FAIL_SEND",
- [FAIL_DROP] = US"FAIL_DROP"
+ [FAIL_DROP] = US"FAIL_DROP",
+ [DANE] = US"DANE",
+};
+
+const uschar * dns_rc_names[] = {
+ [DNS_SUCCEED] = US"DNS_SUCCEED",
+ [DNS_NOMATCH] = US"DNS_NOMATCH",
+ [DNS_NODATA] = US"DNS_NODATA",
+ [DNS_AGAIN] = US"DNS_AGAIN",
+ [DNS_FAIL] = US"DNS_FAIL",
};
diff --git src/deliver.c src/deliver.c
index 40db50084..f5e28941f 100644
--- src/deliver.c
+++ src/deliver.c
@@ -460,6 +460,9 @@ TRUE if the lists refer to the same hosts in the same order, except that
This enables Exim to use a single SMTP transaction for sending to two entirely
different domains that happen to end up pointing at the same hosts.
+We do not try to batch up different A-record host names that refer to the
+same IP.
+
Arguments:
one points to the first host list
two points to the second host list
diff --git src/macros.h src/macros.h
index 2378773cb..6fd5db94c 100644
--- src/macros.h
+++ src/macros.h
@@ -304,6 +304,7 @@ Use rc_names[] for debug strings. */
#define CANCELLED 13 /* Authentication cancelled */
#define FAIL_SEND 14 /* send() failed in authenticator */
#define FAIL_DROP 15 /* Fail and drop connection (used in ACL) */
+#define DANE 16 /* Deferred for domain mismatch (used in transport) */
/* Returns from the deliver_message() function */
diff --git src/transports/smtp.c src/transports/smtp.c
index 28dd8ff24..6ca4552a6 100644
--- src/transports/smtp.c
+++ src/transports/smtp.c
@@ -2019,11 +2019,12 @@ if (!continue_hostname)
switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required))
{
case OK: sx->conn_args.dane = TRUE;
- ob->tls_tempfail_tryclear = FALSE;
- ob->tls_sni = sx->addrlist->domain;
+ ob->tls_tempfail_tryclear = FALSE; /* force TLS */
+ ob->tls_sni = sx->first_addr->domain; /* force SNI */
break;
case FAIL_FORCED: break;
- default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
+ default:
+ set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
rc_to_string(rc)),
rc, FALSE, &sx->delivery_start);
@@ -3430,6 +3431,7 @@ BOOL pass_message = FALSE;
uschar *message = NULL;
uschar new_message_id[MESSAGE_ID_LENGTH + 1];
smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */
+BOOL dane_held;
suppress_tls = suppress_tls; /* stop compiler warning when no TLS support */
*message_defer = FALSE;
@@ -3446,13 +3448,36 @@ sx->conn_args.tblock = tblock;
gettimeofday(&sx->delivery_start, NULL);
sx->sync_addr = sx->first_addr = addrlist;
-/* Get the channel set up ready for a message (MAIL FROM being the next
-SMTP command to send */
+DANE_DOMAINS:
+dane_held = FALSE;
+
+/* Get the channel set up ready for a message, MAIL FROM being the next
+SMTP command to send. */
if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
{
timesince(&addrlist->delivery_time, &sx->delivery_start);
- return rc;
+ yield = rc;
+ goto TIDYUP;
+ }
+
+/*XXX*/
+/* If the connection used DANE, ignore for now any addresses with incompatible
+domains. The SNI has to be the domain. Arrange a whole new TCP conn later,
+just in case only TLS isn't enough. */
+
+if (sx->conn_args.dane)
+ {
+ const uschar * dane_domain = sx->first_addr->domain;
+
+ for (address_item * a = sx->first_addr->next; a; a = a->next)
+ if ( a->transport_return == PENDING_DEFER
+ && Ustrcmp(dane_domain, a->domain) != 0)
+ {
+ DEBUG(D_transport) debug_printf("DANE: holding %s for later\n", a->domain);
+ dane_held = TRUE;
+ a->transport_return = DANE;
+ }
}
/* If there is a filter command specified for this transport, we can now
@@ -4203,7 +4228,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
if (sx->first_addr != NULL) /* More addresses still to be sent */
- { /* in this run of the transport */
+ { /* on this connection */
continue_sequence++; /* Causes * in logging */
pipelining_active = sx->pipelining_used; /* was cleared at DATA */
goto SEND_MESSAGE;
@@ -4235,7 +4260,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
'2', ob->command_timeout);
if (sx->ok && f.continue_more)
- return yield; /* More addresses for another run */
+ goto TIDYUP; /* More addresses for another run */
}
else
{
@@ -4255,7 +4280,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
else
#endif
if (f.continue_more)
- return yield; /* More addresses for another run */
+ goto TIDYUP; /* More addresses for another run */
/* If the socket is successfully passed, we mustn't send QUIT (or
indeed anything!) from here. */
@@ -4295,7 +4320,7 @@ propagate it from the initial
sx->cctx.sock = -1;
continue_transport = NULL;
continue_hostname = NULL;
- return yield;
+ goto TIDYUP;
}
log_write(0, LOG_PANIC_DIE, "fork failed");
}
@@ -4370,9 +4395,35 @@ if (sx->send_quit)
(void) event_raise(tblock->event_action, US"tcp:close", NULL);
#endif
+/*XXX*/
+if (dane_held)
+ {
+ sx->first_addr = NULL;
+ for (address_item * a = sx->addrlist->next; a; a = a->next)
+ if (a->transport_return == DANE)
+ {
+ a->transport_return = PENDING_DEFER;
+ if (!sx->first_addr)
+ {
+ /* Remember the new start-point in the addrlist, for smtp_setup_conn()
+ to get the domain string for SNI */
+
+ sx->first_addr = a;
+ DEBUG(D_transport) debug_printf("DANE: go-around for %s\n", a->domain);
+ }
+ }
+ goto DANE_DOMAINS;
+ }
+
continue_transport = NULL;
continue_hostname = NULL;
return yield;
+
+TIDYUP:
+if (dane_held) for (address_item * a = sx->addrlist->next; a; a = a->next)
+ if (a->transport_return == DANE)
+ a->transport_return = PENDING_DEFER;
+return yield;
}
diff --git src/verify.c src/verify.c
index 5f4181de9..43343a646 100644
--- src/verify.c
+++ src/verify.c
@@ -674,7 +674,7 @@ coding means skipping this whole loop and doing the append separately. */
if (!sx) sx = store_get(sizeof(*sx), TRUE); /* tainted buffers */
memset(sx, 0, sizeof(*sx));
- sx->addrlist = addr;
+ sx->addrlist = sx->first_addr = addr;
sx->conn_args.host = host;
sx->conn_args.host_af = host_af,
sx->port = port;
--
2.28.0

View file

@ -0,0 +1,92 @@
From 7dad62cced33eebd10d13fd1f6cd59696175fa44 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Sun, 23 Aug 2020 17:27:30 +0100
Subject: [PATCH 34/37] Fix non-DANE build
(cherry picked from commit 79b19a30d9fc64a7b7f70928cdefe4f51064280b)
---
src/transports/smtp.c | 15 +++++++++++----
diff --git src/transports/smtp.c src/transports/smtp.c
index 6ca4552a6..d63379e37 100644
--- src/transports/smtp.c
+++ src/transports/smtp.c
@@ -2023,8 +2023,7 @@ if (!continue_hostname)
ob->tls_sni = sx->first_addr->domain; /* force SNI */
break;
case FAIL_FORCED: break;
- default:
- set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
+ default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
rc_to_string(rc)),
rc, FALSE, &sx->delivery_start);
@@ -3431,7 +3430,9 @@ BOOL pass_message = FALSE;
uschar *message = NULL;
uschar new_message_id[MESSAGE_ID_LENGTH + 1];
smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */
+#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
BOOL dane_held;
+#endif
suppress_tls = suppress_tls; /* stop compiler warning when no TLS support */
*message_defer = FALSE;
@@ -3448,8 +3449,10 @@ sx->conn_args.tblock = tblock;
gettimeofday(&sx->delivery_start, NULL);
sx->sync_addr = sx->first_addr = addrlist;
+#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
DANE_DOMAINS:
dane_held = FALSE;
+#endif
/* Get the channel set up ready for a message, MAIL FROM being the next
SMTP command to send. */
@@ -3461,7 +3464,7 @@ if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
goto TIDYUP;
}
-/*XXX*/
+#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
/* If the connection used DANE, ignore for now any addresses with incompatible
domains. The SNI has to be the domain. Arrange a whole new TCP conn later,
just in case only TLS isn't enough. */
@@ -3479,6 +3482,7 @@ if (sx->conn_args.dane)
a->transport_return = DANE;
}
}
+#endif
/* If there is a filter command specified for this transport, we can now
set it up. This cannot be done until the identity of the host is known. */
@@ -4395,7 +4399,7 @@ if (sx->send_quit)
(void) event_raise(tblock->event_action, US"tcp:close", NULL);
#endif
-/*XXX*/
+#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
if (dane_held)
{
sx->first_addr = NULL;
@@ -4414,15 +4418,18 @@ if (dane_held)
}
goto DANE_DOMAINS;
}
+#endif
continue_transport = NULL;
continue_hostname = NULL;
return yield;
TIDYUP:
+#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
if (dane_held) for (address_item * a = sx->addrlist->next; a; a = a->next)
if (a->transport_return == DANE)
a->transport_return = PENDING_DEFER;
+#endif
return yield;
}
--
2.28.0

View file

@ -0,0 +1,525 @@
From 569be4bc51fd4806edcf6b3abcf550dbbba90df5 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Wed, 26 Aug 2020 23:43:54 +0100
Subject: [PATCH 35/37] DANE: Fix 2 messages from queue case
(cherry picked from commit b6054898ace169a0e5143117397a4f666a5e7283)
---
src/deliver.c | 12 +++-
src/exim.c | 14 +++-
src/globals.c | 2 +
src/globals.h | 2 +
src/spool_in.c | 24 +++----
src/tls-gnu.c | 6 +-
src/transport.c | 32 ++++++---
src/transports/smtp.c | 89 ++++++++++++++++++++---
src/transports/smtp.h | 2 +-
diff --git src/deliver.c src/deliver.c
index f5e28941f..8f21c607e 100644
--- src/deliver.c
+++ src/deliver.c
@@ -1195,7 +1195,7 @@ else
if (addr->host_used)
{
g = d_hostlog(g, addr);
- if (continue_sequence > 1)
+ if (continue_sequence > 1) /*XXX this is wrong for a dropped proxyconn. Would have to pass back from transport */
g = string_catn(g, US"*", 1);
#ifndef DISABLE_EVENT
@@ -4275,6 +4275,10 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
}
}
+/*XXX need to defeat this when DANE is used - but we don't know that yet.
+So look out for the place it gets used.
+*/
+
/* Get the flag which specifies whether the transport can handle different
domains that nevertheless resolve to the same set of hosts. If it needs
expanding, get variables set: $address_data, $domain_data, $localpart_data,
@@ -4353,6 +4357,11 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
/************************************************************************/
+/*XXX don't know yet if DANE will be used. So tpt will have to
+check at the point if gets next addr from list, and skip/defer any
+nonmatch domains
+*/
+
/* Pick off all addresses which have the same transport, errors address,
destination, and extra headers. In some cases they point to the same host
list, but we also need to check for identical host lists generated from
@@ -4499,6 +4508,7 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
if (continue_transport)
{
BOOL ok = Ustrcmp(continue_transport, tp->name) == 0;
+/*XXX do we need to check for a DANEd conn vs. a change of domain? */
/* If the transport is about to override the host list do not check
it here but take the cost of running the transport process to discover
diff --git src/exim.c src/exim.c
index ac0ff5523..630ac4038 100644
--- src/exim.c
+++ src/exim.c
@@ -2806,10 +2806,22 @@ on the second character (the one after '-'), to save some effort. */
case 'S': smtp_peer_options |= OPTION_SIZE; break;
#ifndef DISABLE_TLS
+ /* -MCs: used with -MCt; SNI was sent */
+ /* -MCr: ditto, DANE */
+
+ case 'r':
+ case 's': if (++i < argc)
+ {
+ continue_proxy_sni = string_copy_taint(argv[i], TRUE);
+ if (argrest[1] == 'r') continue_proxy_dane = TRUE;
+ }
+ else badarg = TRUE;
+ break;
+
/* -MCt: similar to -MCT below but the connection is still open
via a proxy process which handles the TLS context and coding.
Require three arguments for the proxied local address and port,
- and the TLS cipher. */
+ and the TLS cipher. */
case 't': if (++i < argc)
sending_ip_address = string_copy_taint(argv[i], TRUE);
diff --git src/globals.c src/globals.c
index fc3086f72..c34ac9ddd 100644
--- src/globals.c
+++ src/globals.c
@@ -729,6 +729,8 @@ uid_t config_uid = 0;
int connection_max_messages= -1;
uschar *continue_proxy_cipher = NULL;
+BOOL continue_proxy_dane = FALSE;
+uschar *continue_proxy_sni = NULL;
uschar *continue_hostname = NULL;
uschar *continue_host_address = NULL;
int continue_sequence = 1;
diff --git src/globals.h src/globals.h
index c80c8532f..a4c1143b7 100644
--- src/globals.h
+++ src/globals.h
@@ -425,6 +425,8 @@ extern uschar *config_main_filename; /* File name actually used */
extern uschar *config_main_directory; /* Directory where the main config file was found */
extern uid_t config_uid; /* Additional owner */
extern uschar *continue_proxy_cipher; /* TLS cipher for proxied continued delivery */
+extern BOOL continue_proxy_dane; /* proxied conn is DANE */
+extern uschar *continue_proxy_sni; /* proxied conn SNI */
extern uschar *continue_hostname; /* Host for continued delivery */
extern uschar *continue_host_address; /* IP address for ditto */
extern int continue_sequence; /* Sequence num for continued delivery */
diff --git src/spool_in.c src/spool_in.c
index a0147d5ee..1b4cefdb2 100644
--- src/spool_in.c
+++ src/spool_in.c
@@ -55,7 +55,7 @@ for (int i = 0; i < 2; i++)
set_subdir_str(message_subdir, id, i);
fname = spool_fname(US"input", message_subdir, id, US"-D");
- DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
+ DEBUG(D_deliver) debug_printf_indent("Trying spool file %s\n", fname);
/* We protect against symlink attacks both in not propagating the
* file-descriptor to other processes as we exec, and also ensuring that we
@@ -367,7 +367,7 @@ for (int n = 0; n < 2; n++)
errno = 0;
#ifndef COMPILE_UTILITY
-DEBUG(D_deliver) debug_printf("reading spool file %s\n", name);
+DEBUG(D_deliver) debug_printf_indent("reading spool file %s\n", name);
#endif /* COMPILE_UTILITY */
/* The first line of a spool file contains the message id followed by -H (i.e.
@@ -430,7 +430,7 @@ if (f.running_in_test_harness)
#endif
#ifndef COMPILE_UTILITY
-DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
+DEBUG(D_deliver) debug_printf_indent("user=%s uid=%ld gid=%ld sender=%s\n",
originator_login, (long int)originator_uid, (long int)originator_gid,
sender_address);
#endif
@@ -715,7 +715,7 @@ host_build_sender_fullhost();
#ifndef COMPILE_UTILITY
DEBUG(D_deliver)
- debug_printf("sender_local=%d ident=%s\n", f.sender_local,
+ debug_printf_indent("sender_local=%d ident=%s\n", f.sender_local,
sender_ident ? sender_ident : US"unset");
#endif /* COMPILE_UTILITY */
@@ -743,7 +743,7 @@ if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
goto SPOOL_FORMAT_ERROR;
#ifndef COMPILE_UTILITY
-DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
+DEBUG(D_deliver) debug_printf_indent("recipients_count=%d\n", rcount);
#endif /* COMPILE_UTILITY */
recipients_list_max = rcount;
@@ -814,7 +814,7 @@ for (recipients_count = 0; recipients_count < rcount; recipients_count++)
{
int dummy;
#if !defined (COMPILE_UTILITY)
- DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim 3 spool file\n");
+ DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - Exim 3 spool file\n");
#endif
while (isdigit(*(--p)) || *p == ',');
if (*p == ' ')
@@ -829,7 +829,7 @@ for (recipients_count = 0; recipients_count < rcount; recipients_count++)
else if (*p == ' ')
{
#if !defined (COMPILE_UTILITY)
- DEBUG(D_deliver) debug_printf("**** SPOOL_IN - early Exim 4 spool file\n");
+ DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - early Exim 4 spool file\n");
#endif
*p++ = 0;
(void)sscanf(CS p, "%d", &pno);
@@ -842,7 +842,7 @@ for (recipients_count = 0; recipients_count < rcount; recipients_count++)
int flags;
#if !defined (COMPILE_UTILITY)
- DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim standard format spoolfile\n");
+ DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - Exim standard format spoolfile\n");
#endif
(void)sscanf(CS p+1, "%d", &flags);
@@ -878,13 +878,13 @@ for (recipients_count = 0; recipients_count < rcount; recipients_count++)
}
#if !defined(COMPILE_UTILITY)
else
- { DEBUG(D_deliver) debug_printf("**** SPOOL_IN - No additional fields\n"); }
+ { DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - No additional fields\n"); }
if (orcpt || dsn_flags)
- DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: <%s> orcpt: <%s> dsn_flags: 0x%x\n",
+ DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - address: <%s> orcpt: <%s> dsn_flags: 0x%x\n",
big_buffer, orcpt, dsn_flags);
if (errors_to)
- DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: <%s> errorsto: <%s>\n",
+ DEBUG(D_deliver) debug_printf_indent("**** SPOOL_IN - address: <%s> errorsto: <%s>\n",
big_buffer, errors_to);
#endif
@@ -956,7 +956,7 @@ line count by adding the body linecount to the header linecount. Close the file
and give a positive response. */
#ifndef COMPILE_UTILITY
-DEBUG(D_deliver) debug_printf("body_linecount=%d message_linecount=%d\n",
+DEBUG(D_deliver) debug_printf_indent("body_linecount=%d message_linecount=%d\n",
body_linecount, message_linecount);
#endif /* COMPILE_UTILITY */
diff --git src/tls-gnu.c src/tls-gnu.c
index a34633390..dafe1be0c 100644
--- src/tls-gnu.c
+++ src/tls-gnu.c
@@ -545,7 +545,10 @@ else
/* peercert is set in peer_status() */
tlsp->peerdn = state->peerdn;
-tlsp->sni = state->received_sni;
+
+/* do not corrupt sni sent by client; record sni rxd by server */
+if (!state->host)
+ tlsp->sni = state->received_sni;
/* record our certificate */
{
@@ -2890,6 +2893,7 @@ if (!cipher_list)
cipher_list, &state, tlsp, errstr) != OK)
return FALSE;
+
#ifdef MEASURE_TIMING
report_time_since(&t0, US"client tls_init (delta)");
#endif
diff --git src/transport.c src/transport.c
index 2d8426f29..b1cda55fd 100644
--- src/transport.c
+++ src/transport.c
@@ -1661,6 +1661,7 @@ DEBUG(D_transport)
debug_printf("transport_check_waiting entered\n");
debug_printf(" sequence=%d local_max=%d global_max=%d\n",
continue_sequence, local_message_max, connection_max_messages);
+ acl_level++;
}
/* Do nothing if we have hit the maximum number that can be send down one
@@ -1670,23 +1671,23 @@ if (connection_max_messages >= 0) local_message_max = connection_max_messages;
if (local_message_max > 0 && continue_sequence >= local_message_max)
{
DEBUG(D_transport)
- debug_printf("max messages for one connection reached: returning\n");
- return FALSE;
+ debug_printf_indent("max messages for one connection reached: returning\n");
+ goto retfalse;
}
/* Open the waiting information database. */
if (!(dbm_file = dbfn_open(string_sprintf("wait-%.200s", transport_name),
O_RDWR, &dbblock, TRUE, TRUE)))
- return FALSE;
+ goto retfalse;
/* See if there is a record for this host; if not, there's nothing to do. */
if (!(host_record = dbfn_read(dbm_file, hostname)))
{
dbfn_close(dbm_file);
- DEBUG(D_transport) debug_printf("no messages waiting for %s\n", hostname);
- return FALSE;
+ DEBUG(D_transport) debug_printf_indent("no messages waiting for %s\n", hostname);
+ goto retfalse;
}
/* If the data in the record looks corrupt, just log something and
@@ -1697,7 +1698,7 @@ if (host_record->count > WAIT_NAME_MAX)
dbfn_close(dbm_file);
log_write(0, LOG_MAIN|LOG_PANIC, "smtp-wait database entry for %s has bad "
"count=%d (max=%d)", hostname, host_record->count, WAIT_NAME_MAX);
- return FALSE;
+ goto retfalse;
}
/* Scan the message ids in the record from the end towards the beginning,
@@ -1835,8 +1836,8 @@ while (1)
if (host_length <= 0)
{
dbfn_close(dbm_file);
- DEBUG(D_transport) debug_printf("waiting messages already delivered\n");
- return FALSE;
+ DEBUG(D_transport) debug_printf_indent("waiting messages already delivered\n");
+ goto retfalse;
}
/* we were not able to find an acceptable message, nor was there a
@@ -1847,7 +1848,7 @@ while (1)
{
Ustrcpy(new_message_id, message_id);
dbfn_close(dbm_file);
- return FALSE;
+ goto retfalse;
}
} /* we need to process a continuation record */
@@ -1865,7 +1866,12 @@ if (host_length > 0)
}
dbfn_close(dbm_file);
+DEBUG(D_transport) {acl_level--; debug_printf("transport_check_waiting: TRUE\n"); }
return TRUE;
+
+retfalse:
+DEBUG(D_transport) {acl_level--; debug_printf("transport_check_waiting: FALSE\n"); }
+return FALSE;
}
/*************************************************
@@ -1877,7 +1883,7 @@ void
transport_do_pass_socket(const uschar *transport_name, const uschar *hostname,
const uschar *hostaddress, uschar *id, int socket_fd)
{
-int i = 20;
+int i = 22;
const uschar **argv;
/* Set up the calling arguments; use the standard function for the basics,
@@ -1898,6 +1904,12 @@ if (smtp_peer_options & OPTION_TLS)
argv[i++] = sending_ip_address;
argv[i++] = string_sprintf("%d", sending_port);
argv[i++] = tls_out.active.sock >= 0 ? tls_out.cipher : continue_proxy_cipher;
+
+ if (tls_out.sni)
+ {
+ argv[i++] = tls_out.dane_verified ? US"-MCr" : US"-MCs";
+ argv[i++] = tls_out.sni;
+ }
}
else
argv[i++] = US"-MCT";
diff --git src/transports/smtp.c src/transports/smtp.c
index d63379e37..7fc2a48bb 100644
--- src/transports/smtp.c
+++ src/transports/smtp.c
@@ -1620,8 +1620,8 @@ return FALSE;
typedef struct smtp_compare_s
{
- uschar *current_sender_address;
- struct transport_instance *tblock;
+ uschar * current_sender_address;
+ struct transport_instance * tblock;
} smtp_compare_t;
@@ -1991,6 +1991,74 @@ if (sx->smtps)
}
#endif
+#ifdef SUPPORT_DANE
+/* If we have a proxied TLS connection, check usability for this message */
+
+if (continue_hostname && continue_proxy_cipher)
+ {
+ int rc;
+ const uschar * sni = US"";
+
+ /* Check if the message will be DANE-verified; if so force its SNI */
+
+ smtp_port_for_connect(sx->conn_args.host, sx->port);
+ if ( sx->conn_args.host->dnssec == DS_YES
+ && ( sx->dane_required
+ || verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK
+ ) )
+ switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required))
+ {
+ case OK: sx->conn_args.dane = TRUE;
+ ob->tls_tempfail_tryclear = FALSE; /* force TLS */
+ ob->tls_sni = sx->first_addr->domain; /* force SNI */
+ break;
+ case FAIL_FORCED: break;
+ default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
+ string_sprintf("DANE error: tlsa lookup %s",
+ rc_to_string(rc)),
+ rc, FALSE, &sx->delivery_start);
+# ifndef DISABLE_EVENT
+ (void) event_raise(sx->conn_args.tblock->event_action,
+ US"dane:fail", sx->dane_required
+ ? US"dane-required" : US"dnssec-invalid");
+# endif
+ return rc;
+ }
+
+ /* If the SNI required for the new message differs from the existing conn
+ drop the connection to force a new one. */
+
+ if (ob->tls_sni && !(sni = expand_cstring(ob->tls_sni)))
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "<%s>: failed to expand transport's tls_sni value: %s",
+ sx->addrlist->address, expand_string_message);
+
+ if ( (continue_proxy_sni ? (Ustrcmp(continue_proxy_sni, sni) == 0) : !*sni)
+ && continue_proxy_dane == sx->conn_args.dane)
+ {
+ tls_out.sni = US sni;
+ if ((tls_out.dane_verified = continue_proxy_dane))
+ sx->conn_args.host->dnssec = DS_YES;
+ }
+ else
+ {
+ DEBUG(D_transport)
+ debug_printf("Closing proxied-TLS connection due to SNI mismatch\n");
+
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> QUIT\n");
+ write(0, "QUIT\r\n", 6);
+ close(0);
+ tls_out.dane_verified = FALSE;
+ continue_hostname = continue_proxy_cipher = NULL;
+ f.continue_more = FALSE;
+ continue_sequence = 1; /* Unfortunately, this process cannot affect success log
+ which is done by delivery proc. Would have to pass this
+ back through reporting pipe. */
+ }
+ }
+#endif
+
+
/* Make a connection to the host if this isn't a continued delivery, and handle
the initial interaction and HELO/EHLO/LHLO. Connect timeout errors are handled
specially so they can be identified for retries. */
@@ -3430,7 +3498,7 @@ BOOL pass_message = FALSE;
uschar *message = NULL;
uschar new_message_id[MESSAGE_ID_LENGTH + 1];
smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */
-#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
BOOL dane_held;
#endif
@@ -3449,7 +3517,7 @@ sx->conn_args.tblock = tblock;
gettimeofday(&sx->delivery_start, NULL);
sx->sync_addr = sx->first_addr = addrlist;
-#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
DANE_DOMAINS:
dane_held = FALSE;
#endif
@@ -3464,7 +3532,7 @@ if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
goto TIDYUP;
}
-#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
/* If the connection used DANE, ignore for now any addresses with incompatible
domains. The SNI has to be the domain. Arrange a whole new TCP conn later,
just in case only TLS isn't enough. */
@@ -4184,8 +4252,8 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
t_compare.tblock = tblock;
t_compare.current_sender_address = sender_address;
- if ( sx->first_addr != NULL
- || f.continue_more
+ if ( sx->first_addr != NULL /* more addrs for this message */
+ || f.continue_more /* more addrs for coninued-host */
|| (
#ifndef DISABLE_TLS
( tls_out.active.sock < 0 && !continue_proxy_cipher
@@ -4232,7 +4300,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
if (sx->first_addr != NULL) /* More addresses still to be sent */
- { /* on this connection */
+ { /* for this message */
continue_sequence++; /* Causes * in logging */
pipelining_active = sx->pipelining_used; /* was cleared at DATA */
goto SEND_MESSAGE;
@@ -4256,6 +4324,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_WAIT);
sx->cctx.tls_ctx = NULL;
+ tls_out.active.sock = -1;
smtp_peer_options = smtp_peer_options_wrap;
sx->ok = !sx->smtps
&& smtp_write_command(sx, SCMD_FLUSH, "EHLO %s\r\n", sx->helo_data)
@@ -4399,7 +4468,7 @@ if (sx->send_quit)
(void) event_raise(tblock->event_action, US"tcp:close", NULL);
#endif
-#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
if (dane_held)
{
sx->first_addr = NULL;
@@ -4425,7 +4494,7 @@ continue_hostname = NULL;
return yield;
TIDYUP:
-#if !defined(DISABLE_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
if (dane_held) for (address_item * a = sx->addrlist->next; a; a = a->next)
if (a->transport_return == DANE)
a->transport_return = PENDING_DEFER;
diff --git src/transports/smtp.h src/transports/smtp.h
index 6e63a002d..213bca1a8 100644
--- src/transports/smtp.h
+++ src/transports/smtp.h
@@ -87,7 +87,7 @@ typedef struct {
# ifdef EXPERIMENTAL_TLS_RESUME
uschar *tls_resumption_hosts;
# endif
- uschar *tls_sni;
+ const uschar *tls_sni;
uschar *tls_verify_certificates;
int tls_dh_min_bits;
BOOL tls_tempfail_tryclear;
--
2.28.0

View file

@ -0,0 +1,114 @@
From 6742503035564e057edc7d3eba88b108f7d3d74c Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Wed, 26 Aug 2020 23:59:28 +0100
Subject: [PATCH 36/37] Fix non-DANE build
(cherry picked from commit 651946cbf8e3849687332049730e5fa23d42b4b7)
---
src/smtp_out.c | 2 +-
src/transport.c | 6 +++++-
src/transports/smtp.c | 15 ++++++++++-----
diff --git src/smtp_out.c src/smtp_out.c
index 86c3e4127..c4c409677 100644
--- src/smtp_out.c
+++ src/smtp_out.c
@@ -375,7 +375,7 @@ smtp_port_for_connect(host_item * host, int port)
{
if (host->port != PORT_NONE)
{
- HDEBUG(D_transport|D_acl|D_v)
+ HDEBUG(D_transport|D_acl|D_v) if (port != host->port)
debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
host->port);
port = host->port;
diff --git src/transport.c src/transport.c
index b1cda55fd..609fd128c 100644
--- src/transport.c
+++ src/transport.c
@@ -1907,7 +1907,11 @@ if (smtp_peer_options & OPTION_TLS)
if (tls_out.sni)
{
- argv[i++] = tls_out.dane_verified ? US"-MCr" : US"-MCs";
+ argv[i++] =
+#ifdef SUPPORT_DANE
+ tls_out.dane_verified ? US"-MCr" :
+#endif
+ US"-MCs";
argv[i++] = tls_out.sni;
}
}
diff --git src/transports/smtp.c src/transports/smtp.c
index 7fc2a48bb..77335af09 100644
--- src/transports/smtp.c
+++ src/transports/smtp.c
@@ -1991,7 +1991,6 @@ if (sx->smtps)
}
#endif
-#ifdef SUPPORT_DANE
/* If we have a proxied TLS connection, check usability for this message */
if (continue_hostname && continue_proxy_cipher)
@@ -1999,8 +1998,10 @@ if (continue_hostname && continue_proxy_cipher)
int rc;
const uschar * sni = US"";
+#ifdef SUPPORT_DANE
/* Check if the message will be DANE-verified; if so force its SNI */
+ tls_out.dane_verified = FALSE;
smtp_port_for_connect(sx->conn_args.host, sx->port);
if ( sx->conn_args.host->dnssec == DS_YES
&& ( sx->dane_required
@@ -2024,15 +2025,17 @@ if (continue_hostname && continue_proxy_cipher)
# endif
return rc;
}
+#endif
- /* If the SNI required for the new message differs from the existing conn
- drop the connection to force a new one. */
+ /* If the SNI or the DANE status required for the new message differs from the
+ existing conn drop the connection to force a new one. */
if (ob->tls_sni && !(sni = expand_cstring(ob->tls_sni)))
log_write(0, LOG_MAIN|LOG_PANIC,
"<%s>: failed to expand transport's tls_sni value: %s",
sx->addrlist->address, expand_string_message);
+#ifdef SUPPORT_DANE
if ( (continue_proxy_sni ? (Ustrcmp(continue_proxy_sni, sni) == 0) : !*sni)
&& continue_proxy_dane == sx->conn_args.dane)
{
@@ -2040,6 +2043,10 @@ if (continue_hostname && continue_proxy_cipher)
if ((tls_out.dane_verified = continue_proxy_dane))
sx->conn_args.host->dnssec = DS_YES;
}
+#else
+ if ((continue_proxy_sni ? (Ustrcmp(continue_proxy_sni, sni) == 0) : !*sni))
+ tls_out.sni = US sni;
+#endif
else
{
DEBUG(D_transport)
@@ -2048,7 +2055,6 @@ if (continue_hostname && continue_proxy_cipher)
HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> QUIT\n");
write(0, "QUIT\r\n", 6);
close(0);
- tls_out.dane_verified = FALSE;
continue_hostname = continue_proxy_cipher = NULL;
f.continue_more = FALSE;
continue_sequence = 1; /* Unfortunately, this process cannot affect success log
@@ -2056,7 +2062,6 @@ if (continue_hostname && continue_proxy_cipher)
back through reporting pipe. */
}
}
-#endif
/* Make a connection to the host if this isn't a continued delivery, and handle
--
2.28.0

View file

@ -50,6 +50,7 @@ OPTIONS_DEFAULT+= AUTH_CRAM_MD5 \
PAM \
PASSWD \
PRDR \
SPF \
SUID \
TLS