[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#987924: unblock: exim4/4.94-19



... forgot the debdiff.

cu Andreas
diff -Nru exim4-4.94/debian/changelog exim4-4.94/debian/changelog
--- exim4-4.94/debian/changelog	2021-03-18 13:54:47.000000000 +0100
+++ exim4-4.94/debian/changelog	2021-04-26 18:35:43.000000000 +0200
@@ -1,3 +1,42 @@
+exim4 (4.94-19) unstable; urgency=medium
+
+  * Further updates from heiko/exim-4.94+fixes+taintwarn:
+    + 75_24-Silence-the-compiler.patch
+    + 75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch
+  * Upload to unstable.
+
+ -- Andreas Metzler <ametzler@debian.org>  Mon, 26 Apr 2021 18:35:43 +0200
+
+exim4 (4.94-18) experimental; urgency=medium
+
+  * Pull patches to temporarily add an option to turn taint errors into
+    warnings. (See #987133)
+    + 75_01-Introduce-main-config-option-allow_insecure_tainted_.patch
+    + 75_02-search.patch
+    + 75_03-dbstuff.patch
+    + 75_04-acl.patch
+    + 75_05-parse.patch
+    + 75_06-rda.patch
+    + 75_07-appendfile.patch
+    + 75_08-autoreply.patch
+    + 75_09-pipe.patch
+    + 75_10-deliver.patch
+    + 75_11-directory.patch
+    + 75_12-expand.patch
+    + 75_13-lf_sqlperform.patch
+    + 75_14-rf_get_transport.patch
+    + 75_15-deliver.patch
+    + 75_16-smtp_out.patch
+    + 75_17-smtp.patch
+    + 75_18-update-doc.patch
+    + 75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch
+    + 75_21-tidy-log.c.patch
+    + 75_22-Silence-compiler.patch
+    + 75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch
+  * Update NEWS.Debian to describe the feature.
+
+ -- Andreas Metzler <ametzler@debian.org>  Sun, 25 Apr 2021 07:42:26 +0200
+
 exim4 (4.94-17) unstable; urgency=medium
 
   * Let exim4-config Recommend ca-certificates, needed for certificate
diff -Nru exim4-4.94/debian/NEWS exim4-4.94/debian/NEWS
--- exim4-4.94/debian/NEWS	2021-03-18 13:53:44.000000000 +0100
+++ exim4-4.94/debian/NEWS	2021-04-25 08:08:34.000000000 +0200
@@ -1,19 +1,10 @@
-exim4 (4.94-16) unstable; urgency=medium
+exim4 (4.94-18) experimental; urgency=medium
 
-  The configuration now enforces certificate verification against the
-  system trust store on encrypted connections using the
-  remote_smtp_smarthost transport (smarthost and satellite setups).
-  Delivery will therefore fail if the host certificates are not verifyable
-  and non TLS delivery is not available (e.g. because AUTH PLAIN is used).
-
- -- Andreas Metzler <ametzler@debian.org>  Wed, 17 Mar 2021 13:50:44 +0100
-
-exim4 (4.94~RC0-2) experimental; urgency=low
-
-  Please consider this a *major* exim upgrade. It introduces the concept of
-  tainted data read from untrusted sources, like e.g. message sender or
-  recipient. This tainted data (e.g. $local_part or $domain) cannot be used
-  among other things as a file or directory name or command name.
+  Please consider exim 4.93/4.94 a *major* exim upgrade. It introduces the
+  concept of tainted data read from untrusted sources, like e.g. message
+  sender or recipient. This tainted data (e.g. $local_part or $domain)
+  cannot be used among other things as a file or directory name or command
+  name.
 
   This WILL BREAK configurations which are not updated accordingly.
   Old Debian exim configuration files also will not work unmodified, the new
@@ -32,7 +23,27 @@
   lookup in further processing instead of the original (remote provided)
   value.
 
- -- Andreas Metzler <ametzler@debian.org>  Sun, 10 May 2020 10:27:04 +0200
+  To ease upgrading there is a new main configuration option to temporarily
+  downgrade taint errors to warnings, letting the old configuration work with
+  the newer exim. To make use of this feature add
+  .ifdef _OPT_MAIN_ALLOW_INSECURE_TAINTED_DATA
+   allow_insecure_tainted_data = yes
+  .endif
+  to the exim configuration (e.g. to /etc/exim4/exim4.conf.localmacros)
+  *before* upgrading to exim 4.93/4.94 and check the logfile for taint
+  warnings. This is a temporary workaround which will stop working in 4.95.
+
+ -- Andreas Metzler <ametzler@debian.org>  Sun, 25 Apr 2021 07:42:26 +0200
+
+exim4 (4.94-16) unstable; urgency=medium
+
+  The configuration now enforces certificate verification against the
+  system trust store on encrypted connections using the
+  remote_smtp_smarthost transport (smarthost and satellite setups).
+  Delivery will therefore fail if the host certificates are not verifyable
+  and non TLS delivery is not available (e.g. because AUTH PLAIN is used).
+
+ -- Andreas Metzler <ametzler@debian.org>  Wed, 17 Mar 2021 13:50:44 +0100
 
 exim4 (4.87-3) unstable; urgency=medium
 
diff -Nru exim4-4.94/debian/patches/75_01-Introduce-main-config-option-allow_insecure_tainted_.patch exim4-4.94/debian/patches/75_01-Introduce-main-config-option-allow_insecure_tainted_.patch
--- exim4-4.94/debian/patches/75_01-Introduce-main-config-option-allow_insecure_tainted_.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_01-Introduce-main-config-option-allow_insecure_tainted_.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,230 @@
+From ec06d64532e4952fc36429f73e0222d26997ef7c Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 22:44:31 +0200
+Subject: [PATCH 01/23] Introduce main config option
+ allow_insecure_tainted_data
+
+This option is deprecated already now.
+---
+ src/EDITME            |  7 +++++
+ src/config.h.defaults |  2 ++
+ src/functions.h       | 54 ++++++++++++++++++++++++++++++---------
+ src/globals.c         | 10 ++++++++
+ src/globals.h         |  4 +++
+ src/macros.h          |  3 +++
+ src/readconf.c        |  3 +++
+ 7 files changed, 71 insertions(+), 12 deletions(-)
+
+diff --git a/src/EDITME b/src/EDITME
+index 8da36a353..cebb8e2ec 100644
+--- a/src/EDITME
++++ b/src/EDITME
+@@ -749,6 +749,13 @@ FIXED_NEVER_USERS=root
+ 
+ # WHITELIST_D_MACROS=TLS:SPOOL
+ 
++# The next setting enables a main config option
++# "allow_insecure_tainted_data" to turn taint failures into warnings.
++# Though this option is new, it is deprecated already now, and will be
++# ignored in future releases of Exim. It is meant as mitigation for
++# upgrading old (possibly insecure) configurations to more secure ones.
++ALLOW_INSECURE_TAINTED_DATA=yes
++
+ #------------------------------------------------------------------------------
+ # Exim has support for the AUTH (authentication) extension of the SMTP
+ # protocol, as defined by RFC 2554. If you don't know what SMTP authentication
+diff --git a/src/config.h.defaults b/src/config.h.defaults
+index e17f015f9..4e8b18904 100644
+--- a/src/config.h.defaults
++++ b/src/config.h.defaults
+@@ -17,6 +17,8 @@ Do not put spaces between # and the 'define'.
+ #define ALT_CONFIG_PREFIX
+ #define TRUSTED_CONFIG_LIST
+ 
++#define ALLOW_INSECURE_TAINTED_DATA
++
+ #define APPENDFILE_MODE            0600
+ #define APPENDFILE_DIRECTORY_MODE  0700
+ #define APPENDFILE_LOCKFILE_MODE   0600
+diff --git a/src/functions.h b/src/functions.h
+index 51bb17a09..1e8083673 100644
+--- a/src/functions.h
++++ b/src/functions.h
+@@ -1083,36 +1083,66 @@ if (f.running_in_test_harness && f.testsuite_delays) millisleep(millisec);
+ 
+ /******************************************************************************/
+ /* Taint-checked file opens */
++static inline uschar *
++is_tainted2(const void *p, int lflags, const uschar* fmt, ...)
++{
++va_list ap;
++uschar *msg;
++rmark mark;
++
++if (!is_tainted(p))
++  return NULL;
++
++mark = store_mark();
++va_start(ap, fmt);
++msg = string_from_gstring(string_vformat(NULL, SVFMT_TAINT_NOCHK|SVFMT_EXTEND, fmt, ap));
++va_end(ap);
++
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++if (allow_insecure_tainted_data)
++  {
++  if LOGGING(tainted) log_write(0, LOG_MAIN, "Warning: %s", msg);
++  store_reset(mark);
++  return NULL;
++  }
++#endif
++
++if (lflags) log_write(0, lflags, "%s", msg);
++return msg; /* no store_reset(), as the message might be used afterwards and Exim
++            is expected to exit anyway, so we do not care about the leaked
++            storage */
++}
+ 
+ static inline int
+ exim_open2(const char *pathname, int flags)
+ {
+-if (!is_tainted(pathname)) return open(pathname, flags);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
++if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
++  return open(pathname, flags);
+ errno = EACCES;
+ return -1;
+ }
++
+ static inline int
+ exim_open(const char *pathname, int flags, mode_t mode)
+ {
+-if (!is_tainted(pathname)) return open(pathname, flags, mode);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
++if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
++  return open(pathname, flags, mode);
+ errno = EACCES;
+ return -1;
+ }
+ static inline int
+ exim_openat(int dirfd, const char *pathname, int flags)
+ {
+-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
++if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
++  return openat(dirfd, pathname, flags);
+ errno = EACCES;
+ return -1;
+ }
+ static inline int
+ exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
+ {
+-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
++if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
++  return openat(dirfd, pathname, flags, mode);
+ errno = EACCES;
+ return -1;
+ }
+@@ -1120,8 +1150,8 @@ return -1;
+ static inline FILE *
+ exim_fopen(const char *pathname, const char *mode)
+ {
+-if (!is_tainted(pathname)) return fopen(pathname, mode);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
++if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
++  return fopen(pathname, mode);
+ errno = EACCES;
+ return NULL;
+ }
+@@ -1129,8 +1159,8 @@ return NULL;
+ static inline DIR *
+ exim_opendir(const uschar * name)
+ {
+-if (!is_tainted(name)) return opendir(CCS name);
+-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
++if (!is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name))
++  return opendir(CCS name);
+ errno = EACCES;
+ return NULL;
+ }
+diff --git a/src/globals.c b/src/globals.c
+index c34ac9ddd..ff660c352 100644
+--- a/src/globals.c
++++ b/src/globals.c
+@@ -98,6 +98,10 @@ int     sqlite_lock_timeout    = 5;
+ BOOL    move_frozen_messages   = FALSE;
+ #endif
+ 
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++BOOL    allow_insecure_tainted_data = FALSE;
++#endif
++
+ /* These variables are outside the #ifdef because it keeps the code less
+ cluttered in several places (e.g. during logging) if we can always refer to
+ them. Also, the tls_ variables are now always visible.  Note that these are
+@@ -1033,6 +1037,9 @@ int     log_default[]          = { /* for initializing log_selector */
+   Li_size_reject,
+   Li_skip_delivery,
+   Li_smtp_confirmation,
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++  Li_tainted,
++#endif
+   Li_tls_certificate_verified,
+   Li_tls_cipher,
+   -1
+@@ -1100,6 +1107,9 @@ bit_table log_options[]        = { /* must be in alphabetical order,
+   BIT_TABLE(L, smtp_protocol_error),
+   BIT_TABLE(L, smtp_syntax_error),
+   BIT_TABLE(L, subject),
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++  BIT_TABLE(L, tainted),
++#endif
+   BIT_TABLE(L, tls_certificate_verified),
+   BIT_TABLE(L, tls_cipher),
+   BIT_TABLE(L, tls_peerdn),
+diff --git a/src/globals.h b/src/globals.h
+index a4c1143b7..8d72577e0 100644
+--- a/src/globals.h
++++ b/src/globals.h
+@@ -77,6 +77,10 @@ extern int     sqlite_lock_timeout;    /* Internal lock waiting timeout */
+ extern BOOL    move_frozen_messages;   /* Get them out of the normal directory */
+ #endif
+ 
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++extern BOOL    allow_insecure_tainted_data;
++#endif
++
+ /* These variables are outside the #ifdef because it keeps the code less
+ cluttered in several places (e.g. during logging) if we can always refer to
+ them. Also, the tls_ variables are now always visible. */
+diff --git a/src/macros.h b/src/macros.h
+index f78ae2e3d..322ddbf56 100644
+--- a/src/macros.h
++++ b/src/macros.h
+@@ -498,6 +498,9 @@ enum logbit {
+   Li_smtp_mailauth,
+   Li_smtp_no_mail,
+   Li_subject,
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++  Li_tainted,
++#endif
+   Li_tls_certificate_verified,
+   Li_tls_cipher,
+   Li_tls_peerdn,
+diff --git a/src/readconf.c b/src/readconf.c
+index 948fa2403..133135f8f 100644
+--- a/src/readconf.c
++++ b/src/readconf.c
+@@ -68,6 +68,9 @@ static optionlist optionlist_config[] = {
+   { "add_environment",          opt_stringptr,   {&add_environment} },
+   { "admin_groups",             opt_gidlist,     {&admin_groups} },
+   { "allow_domain_literals",    opt_bool,        {&allow_domain_literals} },
++#ifdef ALLOW_INSECURE_TAINTED_DATA
++  { "allow_insecure_tainted_data", opt_bool,     {&allow_insecure_tainted_data} },
++#endif
+   { "allow_mx_to_ip",           opt_bool,        {&allow_mx_to_ip} },
+   { "allow_utf8_domains",       opt_bool,        {&allow_utf8_domains} },
+   { "auth_advertise_hosts",     opt_stringptr,   {&auth_advertise_hosts} },
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_02-search.patch exim4-4.94/debian/patches/75_02-search.patch
--- exim4-4.94/debian/patches/75_02-search.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_02-search.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,39 @@
+From b71d675f695c2cf17357b190476129535d5f446c Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 22:45:03 +0200
+Subject: [PATCH 02/23] search
+
+---
+ src/search.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/src/search.c b/src/search.c
+index f8aaacb04..f6e4d1f5b 100644
+--- a/src/search.c
++++ b/src/search.c
+@@ -343,12 +343,8 @@ lookup_info *lk = lookup_list[search_type];
+ uschar keybuffer[256];
+ int old_pool = store_pool;
+ 
+-if (filename && is_tainted(filename))
+-  {
+-  log_write(0, LOG_MAIN|LOG_PANIC,
+-    "Tainted filename for search: '%s'", filename);
++if (filename && is_tainted2(filename, LOG_MAIN|LOG_PANIC, "Tainted filename for search '%s'", filename))
+   return NULL;
+-  }
+ 
+ /* Change to the search store pool and remember our reset point */
+ 
+@@ -639,7 +635,7 @@ DEBUG(D_lookup)
+ /* Arrange to put this database at the top of the LRU chain if it is a type
+ that opens real files. */
+ 
+-if (  open_top != (tree_node *)handle 
++if (  open_top != (tree_node *)handle
+    && lookup_list[t->name[0]-'0']->type == lookup_absfile)
+   {
+   search_cache *c = (search_cache *)(t->data.ptr);
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_03-dbstuff.patch exim4-4.94/debian/patches/75_03-dbstuff.patch
--- exim4-4.94/debian/patches/75_03-dbstuff.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_03-dbstuff.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,30 @@
+From 35b11dd0e52b5ac176849f807cca8898bcaf0c3d Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 10:49:49 +0200
+Subject: [PATCH 03/23] dbstuff
+
+---
+ src/dbstuff.h | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/src/dbstuff.h b/src/dbstuff.h
+index c1fb54346..dcee78696 100644
+--- a/src/dbstuff.h
++++ b/src/dbstuff.h
+@@ -643,11 +643,9 @@ after reading data. */
+       : (flags) == O_RDWR ? "O_RDWR"	\
+       : (flags) == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"	\
+       : "??");	\
+-  if (is_tainted(name) || is_tainted(dirname)) \
+-    { \
+-    log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted"); \
++  if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB file not permitted", name) \
++      || is_tainted2(dirname, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB directory not permitted", dirname)) \
+     *dbpp = NULL; \
+-    } \
+   else \
+     { EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); } \
+   DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", *dbpp); \
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_04-acl.patch exim4-4.94/debian/patches/75_04-acl.patch
--- exim4-4.94/debian/patches/75_04-acl.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_04-acl.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,72 @@
+From 44fd80ad8abcd885fc1c8dbb294fc2140e4ef481 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 10:50:14 +0200
+Subject: [PATCH 04/23] acl
+
+---
+ src/acl.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/src/acl.c b/src/acl.c
+index 90e1ce81d..81beab5f3 100644
+--- a/src/acl.c
++++ b/src/acl.c
+@@ -480,7 +480,7 @@ static control_def controls_list[] = {
+   { US"no_delay_flush",          FALSE,
+ 	  ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START
+   },
+-  
++
+ [CONTROL_NO_ENFORCE_SYNC] =
+   { US"no_enforce_sync",         FALSE,
+ 	  ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START
+@@ -3598,20 +3598,22 @@ for (; cb; cb = cb->next)
+     #endif
+ 
+     case ACLC_QUEUE:
+-    if (is_tainted(arg))
+-      {
+-      *log_msgptr = string_sprintf("Tainted name '%s' for queue not permitted",
+-				    arg);
+-      return ERROR;
+-      }
+-    if (Ustrchr(arg, '/'))
+       {
+-      *log_msgptr = string_sprintf(
+-	      "Directory separator not permitted in queue name: '%s'", arg);
+-      return ERROR;
++      uschar *m;
++      if (m = is_tainted2(arg, 0, "Tainted name '%s' for queue not permitted", arg))
++        {
++        *log_msgptr = m;
++        return ERROR;
++        }
++      if (Ustrchr(arg, '/'))
++        {
++        *log_msgptr = string_sprintf(
++                "Directory separator not permitted in queue name: '%s'", arg);
++        return ERROR;
++        }
++      queue_name = string_copy_perm(arg, FALSE);
++      break;
+       }
+-    queue_name = string_copy_perm(arg, FALSE);
+-    break;
+ 
+     case ACLC_RATELIMIT:
+     rc = acl_ratelimit(arg, where, log_msgptr);
+@@ -4007,10 +4009,8 @@ if (Ustrchr(ss, ' ') == NULL)
+   else if (*ss == '/')
+     {
+     struct stat statbuf;
+-    if (is_tainted(ss))
++    if (is_tainted2(ss, LOG_MAIN|LOG_PANIC, "Tainted ACL file name '%s'", ss))
+       {
+-      log_write(0, LOG_MAIN|LOG_PANIC,
+-	"attempt to open tainted ACL file name \"%s\"", ss);
+       /* Avoid leaking info to an attacker */
+       *log_msgptr = US"internal configuration error";
+       return ERROR;
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_05-parse.patch exim4-4.94/debian/patches/75_05-parse.patch
--- exim4-4.94/debian/patches/75_05-parse.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_05-parse.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,30 @@
+From 7eeeb6f26af05322814ecc77c87f09c72ab2216a Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 10:58:46 +0200
+Subject: [PATCH 05/23] parse
+
+---
+ src/parse.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/src/parse.c b/src/parse.c
+index 3ea758ac9..d1bc79039 100644
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -1402,12 +1402,8 @@ for (;;)
+       return FF_ERROR;
+       }
+ 
+-    if (is_tainted(filename))
+-      {
+-      *error = string_sprintf("Tainted name '%s' for included file  not permitted\n",
+-       filename);
++    if (*error = is_tainted2(filename, 0, "Tainted name '%s' for included file not permitted\n", filename))
+       return FF_ERROR;
+-      }
+ 
+     /* Check file name if required */
+ 
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_06-rda.patch exim4-4.94/debian/patches/75_06-rda.patch
--- exim4-4.94/debian/patches/75_06-rda.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_06-rda.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,28 @@
+From a6da9c67acaee699616516be141d600cc178a633 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 10:59:46 +0200
+Subject: [PATCH 06/23] rda
+
+---
+ src/rda.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/rda.c b/src/rda.c
+index aed8abc24..6ad7dd8bd 100644
+--- a/src/rda.c
++++ b/src/rda.c
+@@ -179,10 +179,8 @@ struct stat statbuf;
+ /* Reading a file is a form of expansion; we wish to deny attackers the
+ capability to specify the file name. */
+ 
+-if (is_tainted(filename))
++if (*error = is_tainted2(filename, 0, "Tainted name '%s' for file read not permitted\n", filename))
+   {
+-  *error = string_sprintf("Tainted name '%s' for file read not permitted\n",
+-			filename);
+   *yield = FF_ERROR;
+   return NULL;
+   }
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_07-appendfile.patch exim4-4.94/debian/patches/75_07-appendfile.patch
--- exim4-4.94/debian/patches/75_07-appendfile.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_07-appendfile.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,34 @@
+From c29b50d2fe17cc108d751175ed4f4113c25c1768 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 11:00:06 +0200
+Subject: [PATCH 07/23] appendfile
+
+---
+ src/transports/appendfile.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/transports/appendfile.c b/src/transports/appendfile.c
+index 8ab8b6016..7dbbaa2f9 100644
+--- a/src/transports/appendfile.c
++++ b/src/transports/appendfile.c
+@@ -1286,12 +1286,14 @@ if (!(path = expand_string(fdname)))
+     expand_string_message);
+   goto ret_panic;
+   }
+-if (is_tainted(path))
++{ uschar *m;
++if (m = is_tainted2(path, 0, "Tainted '%s' (file or directory "
++          "name for %s transport) not permitted", path, tblock->name))
+   {
+-  addr->message = string_sprintf("Tainted '%s' (file or directory "
+-    "name for %s transport) not permitted", path, tblock->name);
++  addr->message = m;
+   goto ret_panic;
+   }
++}
+ 
+ if (path[0] != '/')
+   {
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_08-autoreply.patch exim4-4.94/debian/patches/75_08-autoreply.patch
--- exim4-4.94/debian/patches/75_08-autoreply.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_08-autoreply.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,70 @@
+From 26de37d8960da80473866fb59b9dfd10a5761538 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 28 Mar 2021 11:06:27 +0200
+Subject: [PATCH 08/23] autoreply
+
+---
+ src/transports/autoreply.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/src/transports/autoreply.c b/src/transports/autoreply.c
+index 865abbf4f..ed99de4c6 100644
+--- a/src/transports/autoreply.c
++++ b/src/transports/autoreply.c
+@@ -404,14 +404,15 @@ recipient cache. */
+ 
+ if (oncelog && *oncelog && to)
+   {
++  uschar *m;
+   time_t then = 0;
+ 
+-  if (is_tainted(oncelog))
++  if (m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
++      " not permitted", oncelog, tblock->name))
+     {
+     addr->transport_return = DEFER;
+     addr->basic_errno = EACCES;
+-    addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
+-      " not permitted", oncelog, tblock->name);
++    addr->message = m;
+     goto END_OFF;
+     }
+ 
+@@ -515,13 +516,14 @@ if (oncelog && *oncelog && to)
+ 
+   if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec))
+     {
++    uschar *m;
+     int log_fd;
+-    if (is_tainted(logfile))
++    if (m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
++	" not permitted", logfile, tblock->name))
+       {
+       addr->transport_return = DEFER;
+       addr->basic_errno = EACCES;
+-      addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
+-	" not permitted", logfile, tblock->name);
++      addr->message = m;
+       goto END_OFF;
+       }
+ 
+@@ -548,12 +550,13 @@ if (oncelog && *oncelog && to)
+ /* We are going to send a message. Ensure any requested file is available. */
+ if (file)
+   {
+-  if (is_tainted(file))
++  uschar *m;
++  if (m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
++      " not permitted", file, tblock->name))
+     {
+     addr->transport_return = DEFER;
+     addr->basic_errno = EACCES;
+-    addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
+-      " not permitted", file, tblock->name);
++    addr->message = m;
+     return FALSE;
+     }
+   if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_09-pipe.patch exim4-4.94/debian/patches/75_09-pipe.patch
--- exim4-4.94/debian/patches/75_09-pipe.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_09-pipe.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,36 @@
+From f9628406706112be459adb3f121db8e6cf282c2d Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Fri, 2 Apr 2021 17:30:27 +0200
+Subject: [PATCH 09/23] pipe
+
+---
+ src/transports/pipe.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/transports/pipe.c b/src/transports/pipe.c
+index 27422bd42..4c9e68beb 100644
+--- a/src/transports/pipe.c
++++ b/src/transports/pipe.c
+@@ -599,13 +599,16 @@ if (!cmd || !*cmd)
+     tblock->name);
+   return FALSE;
+   }
+-if (is_tainted(cmd))
++
++{ uschar *m;
++if (m = is_tainted2(cmd, 0, "Tainted '%s' (command "
++    "for %s transport) not permitted", cmd, tblock->name))
+   {
+-  addr->message = string_sprintf("Tainted '%s' (command "
+-    "for %s transport) not permitted", cmd, tblock->name);
+   addr->transport_return = PANIC;
++  addr->message = m;
+   return FALSE;
+   }
++}
+ 
+ /* When a pipe is set up by a filter file, there may be values for $thisaddress
+ and numerical the variables in existence. These are passed in
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_10-deliver.patch exim4-4.94/debian/patches/75_10-deliver.patch
--- exim4-4.94/debian/patches/75_10-deliver.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_10-deliver.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,49 @@
+From 2fee91ae42e974c21202e0b5e17185f6a87bf8af Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Wed, 31 Mar 2021 23:12:44 +0200
+Subject: [PATCH 10/23] deliver
+
+---
+ src/deliver.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/src/deliver.c b/src/deliver.c
+index d85edd70e..8b7998f37 100644
+--- a/src/deliver.c
++++ b/src/deliver.c
+@@ -5538,10 +5538,11 @@ FILE * fp = NULL;
+ if (!s || !*s)
+   log_write(0, LOG_MAIN|LOG_PANIC,
+     "Failed to expand %s: '%s'\n", varname, filename);
+-else if (*s != '/' || is_tainted(s))
+-  log_write(0, LOG_MAIN|LOG_PANIC,
+-    "%s is not %s after expansion: '%s'\n",
+-    varname, *s == '/' ? "untainted" : "absolute", s);
++else if (*s != '/')
++  log_write(0, LOG_MAIN|LOG_PANIC, "%s is not absolute after expansion: '%s'\n",
++    varname, s);
++else if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted %s after expansion: '%s'\n", varname, s))
++  ;
+ else if (!(fp = Ufopen(s, "rb")))
+   log_write(0, LOG_MAIN|LOG_PANIC, "Failed to open %s for %s "
+     "message texts: %s", s, reason, strerror(errno));
+@@ -6148,12 +6149,13 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
+           {
+           uschar *tmp = expand_string(tpname);
+           address_file = address_pipe = NULL;
++          uschar *m;
+           if (!tmp)
+             p->message = string_sprintf("failed to expand \"%s\" as a "
+               "system filter transport name", tpname);
+-	  if (is_tainted(tmp))
+-            p->message = string_sprintf("attempt to used tainted value '%s' for"
+-	      "transport '%s' as a system filter", tmp, tpname);
++	  if (is_tainted2(tmp, 0, m = string_sprintf("Tainted values '%s' "
++              "for transport '%s' as a system filter", tmp, tpname)))
++            p->message = m;
+           tpname = tmp;
+           }
+         else
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_11-directory.patch exim4-4.94/debian/patches/75_11-directory.patch
--- exim4-4.94/debian/patches/75_11-directory.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_11-directory.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,26 @@
+From 5f41e800ce9cc7ad154047298914df955e905bf4 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 21:28:59 +0200
+Subject: [PATCH 11/23] directory
+
+---
+ src/directory.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/directory.c b/src/directory.c
+index 2d4d565f4..9f88f4141 100644
+--- a/src/directory.c
++++ b/src/directory.c
+@@ -44,6 +44,9 @@ uschar c = 1;
+ struct stat statbuf;
+ uschar * path;
+ 
++if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted path '%s' for new directory", name))
++  { p = US"create"; path = US name; errno = EACCES; goto bad; }
++
+ if (parent)
+   {
+   path = string_sprintf("%s%s%s", parent, US"/", name);
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_12-expand.patch exim4-4.94/debian/patches/75_12-expand.patch
--- exim4-4.94/debian/patches/75_12-expand.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_12-expand.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,34 @@
+From c02ea85f525ff256d78e084d6f76fe3032fd52e1 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 21:33:50 +0200
+Subject: [PATCH 12/23] expand
+
+---
+ src/expand.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/expand.c b/src/expand.c
+index 05de94c49..21b86ebf5 100644
+--- a/src/expand.c
++++ b/src/expand.c
+@@ -4383,13 +4383,13 @@ DEBUG(D_expand)
+ f.expand_string_forcedfail = FALSE;
+ expand_string_message = US"";
+ 
+-if (is_tainted(string))
++{ uschar *m;
++if (m = is_tainted2(string, LOG_MAIN|LOG_PANIC, "Tainted string '%s' in expansion", s))
+   {
+-  expand_string_message =
+-    string_sprintf("attempt to expand tainted string '%s'", s);
+-  log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
++  expand_string_message = m;
+   goto EXPAND_FAILED;
+   }
++}
+ 
+ while (*s != 0)
+   {
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_13-lf_sqlperform.patch exim4-4.94/debian/patches/75_13-lf_sqlperform.patch
--- exim4-4.94/debian/patches/75_13-lf_sqlperform.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_13-lf_sqlperform.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,49 @@
+From 9810dfc25d8b9687b46e57963a3ac30bf5c9b2c9 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 21:36:12 +0200
+Subject: [PATCH 13/23] lf_sqlperform
+
+---
+ src/lookups/lf_sqlperform.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/lookups/lf_sqlperform.c b/src/lookups/lf_sqlperform.c
+index ad1df29d1..eda3089e2 100644
+--- a/src/lookups/lf_sqlperform.c
++++ b/src/lookups/lf_sqlperform.c
+@@ -102,11 +102,13 @@ if (Ustrncmp(query, "servers", 7) == 0)
+         }
+       }
+ 
+-    if (is_tainted(server))
+-      {
+-      *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server);
++    { uschar *m;
++    if (m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server))
++     {
++      *errmsg = m;
+       return DEFER;
+       }
++    }
+ 
+     rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache, opts);
+     if (rc != DEFER || defer_break) return rc;
+@@ -158,11 +160,13 @@ else
+ 	server = ele;
+ 	}
+ 
+-      if (is_tainted(server))
++      { uschar *m;
++      if (is_tainted2(server, 0, "Tainted %s server '%s'", name, server))
+         {
+-        *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server);
++        *errmsg = m;
+         return DEFER;
+         }
++      }
+ 
+       rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache, opts);
+       if (rc != DEFER || defer_break) return rc;
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_14-rf_get_transport.patch exim4-4.94/debian/patches/75_14-rf_get_transport.patch
--- exim4-4.94/debian/patches/75_14-rf_get_transport.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_14-rf_get_transport.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,28 @@
+From 015fff57c854184f8bce61476c46a2830a97daf8 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Fri, 2 Apr 2021 08:36:24 +0200
+Subject: [PATCH 14/23] rf_get_transport
+
+---
+ src/routers/rf_get_transport.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/routers/rf_get_transport.c b/src/routers/rf_get_transport.c
+index 4a43818ff..32bde9ec3 100644
+--- a/src/routers/rf_get_transport.c
++++ b/src/routers/rf_get_transport.c
+@@ -66,10 +66,8 @@ if (expandable)
+       "\"%s\" in %s router: %s", tpname, router_name, expand_string_message);
+     return FALSE;
+     }
+-  if (is_tainted(ss))
++  if (is_tainted2(ss, LOG_MAIN|LOG_PANIC, "Tainted tainted value '%s' from '%s' for transport", ss, tpname))
+     {
+-    log_write(0, LOG_MAIN|LOG_PANIC,
+-      "attempt to use tainted value '%s' from '%s' for transport", ss, tpname);
+     addr->basic_errno = ERRNO_BADTRANSPORT;
+     /* Avoid leaking info to an attacker */
+     addr->message = US"internal configuration error";
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_15-deliver.patch exim4-4.94/debian/patches/75_15-deliver.patch
--- exim4-4.94/debian/patches/75_15-deliver.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_15-deliver.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,31 @@
+From 2bafe3fc82cf62f0c21f939f5891b8d067f3abc7 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sat, 3 Apr 2021 10:54:22 +0200
+Subject: [PATCH 15/23] deliver
+
+---
+ src/deliver.c  | 5 +++--
+ test/paniclog/0622 | 2 +-
+ test/stderr/0622   | 2 +-
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/src/deliver.c b/src/deliver.c
+index 8b7998f37..87e944b03 100644
+--- a/src/deliver.c
++++ b/src/deliver.c
+@@ -6153,9 +6153,10 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
+           if (!tmp)
+             p->message = string_sprintf("failed to expand \"%s\" as a "
+               "system filter transport name", tpname);
+-	  if (is_tainted2(tmp, 0, m = string_sprintf("Tainted values '%s' "
+-              "for transport '%s' as a system filter", tmp, tpname)))
++          { uschar *m;
++	  if (m = is_tainted2(tmp, 0, "Tainted values '%s' " "for transport '%s' as a system filter", tmp, tpname))
+             p->message = m;
++          }
+           tpname = tmp;
+           }
+         else
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_16-smtp_out.patch exim4-4.94/debian/patches/75_16-smtp_out.patch
--- exim4-4.94/debian/patches/75_16-smtp_out.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_16-smtp_out.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,38 @@
+From b9b967cca71a4da51506f8ba596b9ae40cfcef57 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 21:42:38 +0200
+Subject: [PATCH 16/23] smtp_out
+
+---
+ src/smtp_out.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/src/smtp_out.c b/src/smtp_out.c
+index c4c409677..9c160e697 100644
+--- a/src/smtp_out.c
++++ b/src/smtp_out.c
+@@ -53,11 +53,8 @@ if (!(expint = expand_string(istring)))
+   return FALSE;
+   }
+ 
+-if (is_tainted(expint))
++if (is_tainted2(expint, LOG_MAIN|LOG_PANIC, "Tainted value '%s' from '%s' for interface", expint, istring))
+   {
+-  log_write(0, LOG_MAIN|LOG_PANIC,
+-    "attempt to use tainted value '%s' from '%s' for interface",
+-    expint, istring);
+   addr->transport_return = PANIC;
+   addr->message = string_sprintf("failed to expand \"interface\" "
+       "option for %s: configuration error", msg);
+@@ -425,7 +422,7 @@ if (ob->socks_proxy)
+   {
+   int sock = socks_sock_connect(sc->host, sc->host_af, port, sc->interface,
+ 				sc->tblock, ob->connect_timeout);
+-  
++
+   if (sock >= 0)
+     {
+     if (early_data && early_data->data && early_data->len)
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_17-smtp.patch exim4-4.94/debian/patches/75_17-smtp.patch
--- exim4-4.94/debian/patches/75_17-smtp.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_17-smtp.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,29 @@
+From 8b7d4ba8903ace7e3e3db70343798a5a0b7cea23 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Thu, 1 Apr 2021 22:02:27 +0200
+Subject: [PATCH 17/23] smtp
+
+---
+ src/transports/smtp.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/src/transports/smtp.c b/src/transports/smtp.c
+index 6540e4d2b..8fecf7eef 100644
+--- a/src/transports/smtp.c
++++ b/src/transports/smtp.c
+@@ -4715,11 +4715,8 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
+     else
+       if (ob->hosts_randomize) s = expanded_hosts = string_copy(s);
+ 
+-    if (is_tainted(s))
++    if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted host list '%s' from '%s' in transport %s", s, ob->hosts, tblock->name))
+       {
+-      log_write(0, LOG_MAIN|LOG_PANIC,
+-	"attempt to use tainted host list '%s' from '%s' in transport %s",
+-	s, ob->hosts, tblock->name);
+       /* Avoid leaking info to an attacker */
+       addrlist->message = US"internal configuration error";
+       addrlist->transport_return = PANIC;
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_18-update-doc.patch exim4-4.94/debian/patches/75_18-update-doc.patch
--- exim4-4.94/debian/patches/75_18-update-doc.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_18-update-doc.patch	2021-04-25 07:36:39.000000000 +0200
@@ -0,0 +1,154 @@
+From 77cc1ad3058e4ef7ae82adb914ccff0be9fe2c8b Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sat, 3 Apr 2021 09:29:13 +0200
+Subject: [PATCH 18/23] update doc
+
+---
+ doc/doc-docbook/spec.xfpt | 45 ++++++++++++++++++++++++++++++++++++++-
+ doc/NewStuff      | 45 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 89 insertions(+), 1 deletion(-)
+
+--- a/doc/NewStuff
++++ b/doc/NewStuff
+@@ -4,10 +4,55 @@
+ This file contains descriptions of new features that have been added to Exim.
+ Before a formal release, there may be quite a lot of detail so that people can
+ test from the snapshots or the Git before the documentation is updated. Once
+ the documentation is updated, this file is reduced to a short list.
+ 
++Version 4.95
++------------
++
++ 1. The fast-ramp two phase queue run support, previously experimental, is
++    now supported by default.
++
++ 2. The native SRS support, previously experimental, is now supported. It is
++    not built unless specified in the Local/Makefile.
++
++ 3. TLS resumption support, previously experimental, is now supported and
++    included in default builds.
++
++ 4. Single-key LMDB lookups, previously experimental, are now supported.
++    The support is not built unless specified in the Local/Makefile.
++
++ 5. Option "message_linelength_limit" on the smtp transport to enforce (by
++    default) the RFC 998 character limit.
++
++ 6. An option to ignore the cache on a lookup.
++
++ 7. Quota checking during reception (i.e. at SMTP time) for appendfile-
++    transport-managed quotas.
++
++ 8. Sqlite lookups accept a "file=<path>" option to specify a per-operation
++    db file, replacing the previous prefix to the SQL string (which had
++    issues when the SQL used tainted values).
++
++ 9. Lsearch lookups accept a "ret=full" option, to return both the portion
++    of the line matching the key, and the remainder.
++
++10. A command-line option to have a daemon not create a notifier socket.
++
++11. Faster TLS startup.  When various configuration options contain no
++    expandable elements, the information can be preloaded and cached rather
++    than the provious behaviour of always loading at startup time for every
++    connection.  This helps particularly for the CA bundle.
++
++12. Proxy Protocol Timeout is configurable via "proxy_protocol_timeout"
++    main config option.
++
++13. Option "smtp_accept_msx_per_connection" is now expanded.
++
++13. A main config option "allow_insecure_tainted_data" allows to turn
++    taint errors into warnings.
++
+ Version 4.94
+ ------------
+ 
+  1. EXPERIMENTAL_SRS_NATIVE optional build feature.  See the experimental.spec
+     file.
+--- a/doc/spec.txt
++++ b/doc/spec.txt
+@@ -8650,12 +8650,20 @@
+ Whether a string is expanded depends upon the context. Usually this is solely
+ dependent upon the option for which a value is sought; in this documentation,
+ options for which string expansion is performed are marked with * after the
+ data type. ACL rules always expand strings. A couple of expansion conditions do
+ not expand some of the brace-delimited branches, for security reasons, and
+-expansion of data deriving from the sender ("tainted data") is not permitted.
+-
++expansion of data deriving from the sender ("tainted data") is not permitted
++(including acessing a file using a tainted name).  The main config
++option allow_insecure_tainted_data can be used as mitigation during
++uprades to more secure configurations.
++
++Common ways of obtaining untainted equivalents of variables with tainted
++values come down to using the tainted value as a lookup key in a trusted
++database.  This database could be the filesystem structure, or the
++password file, or accessed via a DBMS.  Specific methods are indexed
++under "de-tainting".
+ 
+ 11.1 Literal text in expanded strings
+ -------------------------------------
+ 
+ An uninterpreted dollar can be included in an expanded string by putting a
+@@ -12946,10 +12954,12 @@
+ 
+ 
+ 14.1 Miscellaneous
+ ------------------
+ 
++add_environment       environment variables
++allow_insecure_tainted_data   turn taint errors into warnings
+ bi_command            to run for -bi command line option
+ debug_store           do extra internal checks
+ disable_ipv6          do no IPv6 processing
+ keep_malformed        for broken files - should not happen
+ localhost_number      for unique message ids in clusters
+@@ -13553,10 +13563,20 @@
+ true, and also to add "@[]" to the list of local domains (defined in the named
+ domain list local_domains in the default configuration). This "magic string"
+ matches the domain literal form of all the local host's IP addresses.
+ 
+ +-----------------------------------------------------+
++|allow_insecure_tainted_data main boolean false       |
+++-----------------------------------------------------+
++
++The handling of tainted data may break older (pre 4.94) configurations.
++Setting this option to "true" turns taint errors (which result in a temporary
++message rejection) into warnings. This option is meant as mitigation only
++and deprecated already today. Future releases of Exim may ignore it.
++The taint log selector can be used to suppress even the warnings.
++
+++-----------------------------------------------------+
+ |allow_mx_to_ip|Use: main|Type: boolean|Default: false|
+ +-----------------------------------------------------+
+ 
+ It appears that more and more DNS zone administrators are breaking the rules
+ and putting domain names that look like IP addresses on the right hand side of
+@@ -35316,10 +35336,11 @@
+  smtp_mailauth                AUTH argument to MAIL commands
+  smtp_no_mail                 session with no MAIL commands
+  smtp_protocol_error          SMTP protocol errors
+  smtp_syntax_error            SMTP syntax errors
+  subject                      contents of Subject: on <= lines
++*taint                        taint errors or warnings
+ *tls_certificate_verified     certificate verification status
+ *tls_cipher                   TLS cipher suite on <= and => lines
+  tls_peerdn                   TLS peer DN on <= and => lines
+  tls_sni                      TLS SNI on <= lines
+  unknown_in_list              DNS lookup failed in list match
+@@ -35604,11 +35625,13 @@
+ 
+   * tls_certificate_verified: An extra item is added to <= and => log lines
+     when TLS is in use. The item is "CV=yes" if the peer's certificate was
+     verified using a CA trust anchor, "CA=dane" if using a DNS trust anchor,
+     and "CV=no" if not.
+-
++  * taint: Log warnings about tainted data. This selector can't be
++    turned of if allow_insecure_tainted_data is false (which is the
++    default).
+   * tls_cipher: When a message is sent or received over an encrypted
+     connection, the cipher suite used is added to the log line, preceded by X=.
+ 
+   * tls_peerdn: When a message is sent or received over an encrypted
+     connection, and a certificate is supplied by the remote host, the peer DN
diff -Nru exim4-4.94/debian/patches/75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch exim4-4.94/debian/patches/75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch
--- exim4-4.94/debian/patches/75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,42 @@
+From 41c494e2465efadc2e82002a07430e8aec85bc9b Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Mon, 12 Apr 2021 08:41:44 +0200
+Subject: [PATCH 20/23] Set mainlog_name and rejectlog_name unconditionally.
+
+(cherry picked from commit 3f06b9b4c7244b169d50bce216c1f54b4dfe7efb)
+---
+ src/log.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/log.c b/src/log.c
+index 99eba5f90..011c4debc 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -402,18 +402,20 @@ it gets statted to see if it has been cycled. With a datestamp, the datestamp
+ will be compared. The static slot for saving it is the same size as buffer,
+ and the text has been checked above to fit, so this use of strcpy() is OK. */
+ 
+-if (type == lt_main && string_datestamp_offset >= 0)
++if (type == lt_main)
+   {
+   Ustrcpy(mainlog_name, buffer);
+-  mainlog_datestamp = mainlog_name + string_datestamp_offset;
++  if (string_datestamp_offset > 0)
++    mainlog_datestamp = mainlog_name + string_datestamp_offset;
+   }
+ 
+ /* Ditto for the reject log */
+ 
+-else if (type == lt_reject && string_datestamp_offset >= 0)
++else if (type == lt_reject)
+   {
+   Ustrcpy(rejectlog_name, buffer);
+-  rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
++  if (string_datestamp_offset > 0)
++    rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
+   }
+ 
+ /* and deal with the debug log (which keeps the datestamp, but does not
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_21-tidy-log.c.patch exim4-4.94/debian/patches/75_21-tidy-log.c.patch
--- exim4-4.94/debian/patches/75_21-tidy-log.c.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_21-tidy-log.c.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,124 @@
+From 8021b95c2e266861aba29c97b4bb90dc6f7637a2 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Mon, 12 Apr 2021 09:19:21 +0200
+Subject: [PATCH 21/23] tidy log.c
+
+(cherry picked from commit 0327b6460eec64da6b0c1543c7e9b3d0f8cb9294)
+---
+ src/log.c | 97 +++++++++++++++++++++++----------------------------
+ 1 file changed, 44 insertions(+), 53 deletions(-)
+
+diff --git a/src/log.c b/src/log.c
+index 011c4debc..7ef7074ec 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -397,62 +397,53 @@ people want, I hope. */
+ 
+ ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);
+ 
+-/* Save the name of the mainlog for rollover processing. Without a datestamp,
+-it gets statted to see if it has been cycled. With a datestamp, the datestamp
+-will be compared. The static slot for saving it is the same size as buffer,
+-and the text has been checked above to fit, so this use of strcpy() is OK. */
+-
+-if (type == lt_main)
++switch (type)
+   {
+-  Ustrcpy(mainlog_name, buffer);
+-  if (string_datestamp_offset > 0)
+-    mainlog_datestamp = mainlog_name + string_datestamp_offset;
+-  }
+-
+-/* Ditto for the reject log */
+-
+-else if (type == lt_reject)
+-  {
+-  Ustrcpy(rejectlog_name, buffer);
+-  if (string_datestamp_offset > 0)
+-    rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
+-  }
+-
+-/* and deal with the debug log (which keeps the datestamp, but does not
+-update it) */
+-
+-else if (type == lt_debug)
+-  {
+-  Ustrcpy(debuglog_name, buffer);
+-  if (tag)
+-    {
+-    /* this won't change the offset of the datestamp */
+-    ok2 = string_format(buffer, sizeof(buffer), "%s%s",
+-      debuglog_name, tag);
+-    if (ok2)
+-      Ustrcpy(debuglog_name, buffer);
+-    }
+-  }
+-
+-/* Remove any datestamp if this is the panic log. This is rare, so there's no
+-need to optimize getting the datestamp length. We remove one non-alphanumeric
+-char afterwards if at the start, otherwise one before. */
+-
+-else if (string_datestamp_offset >= 0)
+-  {
+-  uschar * from = buffer + string_datestamp_offset;
+-  uschar * to = from + string_datestamp_length;
++  case lt_main:
++    /* Save the name of the mainlog for rollover processing. Without a datestamp,
++    it gets statted to see if it has been cycled. With a datestamp, the datestamp
++    will be compared. The static slot for saving it is the same size as buffer,
++    and the text has been checked above to fit, so this use of strcpy() is OK. */
++    Ustrcpy(mainlog_name, buffer);
++    if (string_datestamp_offset > 0)
++      mainlog_datestamp = mainlog_name + string_datestamp_offset;
++  case lt_reject:
++    /* Ditto for the reject log */
++    Ustrcpy(rejectlog_name, buffer);
++    if (string_datestamp_offset > 0)
++      rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
++  case lt_debug:
++    /* and deal with the debug log (which keeps the datestamp, but does not
++    update it) */
++    Ustrcpy(debuglog_name, buffer);
++    if (tag)
++      {
++      /* this won't change the offset of the datestamp */
++      ok2 = string_format(buffer, sizeof(buffer), "%s%s",
++        debuglog_name, tag);
++      if (ok2)
++        Ustrcpy(debuglog_name, buffer);
++      }
++  default:
++    /* Remove any datestamp if this is the panic log. This is rare, so there's no
++  need to optimize getting the datestamp length. We remove one non-alphanumeric
++  char afterwards if at the start, otherwise one before. */
++    if (string_datestamp_offset >= 0)
++      {
++      uschar * from = buffer + string_datestamp_offset;
++      uschar * to = from + string_datestamp_length;
+ 
+-  if (from == buffer || from[-1] == '/')
+-    {
+-    if (!isalnum(*to)) to++;
+-    }
+-  else
+-    if (!isalnum(from[-1])) from--;
++      if (from == buffer || from[-1] == '/')
++        {
++        if (!isalnum(*to)) to++;
++        }
++      else
++        if (!isalnum(from[-1])) from--;
+ 
+-  /* This copy is ok, because we know that to is a substring of from. But
+-  due to overlap we must use memmove() not Ustrcpy(). */
+-  memmove(from, to, Ustrlen(to)+1);
++      /* This copy is ok, because we know that to is a substring of from. But
++      due to overlap we must use memmove() not Ustrcpy(). */
++      memmove(from, to, Ustrlen(to)+1);
++      }
+   }
+ 
+ /* If the file name is too long, it is an unrecoverable disaster */
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_22-Silence-compiler.patch exim4-4.94/debian/patches/75_22-Silence-compiler.patch
--- exim4-4.94/debian/patches/75_22-Silence-compiler.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_22-Silence-compiler.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,222 @@
+From 2c9869d0622cc690b424cc74166d4a8393017ece Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Fri, 23 Apr 2021 17:40:40 +0200
+Subject: [PATCH 22/23] Silence compiler
+
+---
+ src/acl.c                   |  2 +-
+ src/deliver.c               |  3 +--
+ src/expand.c                |  6 +++++-
+ src/functions.h             |  2 +-
+ src/lookups/lf_sqlperform.c |  4 ++--
+ src/parse.c                 |  2 +-
+ src/rda.c                   |  2 +-
+ src/transports/appendfile.c |  4 ++--
+ src/transports/autoreply.c  | 12 ++++++------
+ src/transports/pipe.c       |  4 ++--
+ 10 files changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/src/acl.c b/src/acl.c
+index 81beab5f3..b62af5c65 100644
+--- a/src/acl.c
++++ b/src/acl.c
+@@ -3600,7 +3600,7 @@ for (; cb; cb = cb->next)
+     case ACLC_QUEUE:
+       {
+       uschar *m;
+-      if (m = is_tainted2(arg, 0, "Tainted name '%s' for queue not permitted", arg))
++      if ((m = is_tainted2(arg, 0, "Tainted name '%s' for queue not permitted", arg)))
+         {
+         *log_msgptr = m;
+         return ERROR;
+diff --git a/src/deliver.c b/src/deliver.c
+index 87e944b03..b40eed4f9 100644
+--- a/src/deliver.c
++++ b/src/deliver.c
+@@ -6149,12 +6149,11 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
+           {
+           uschar *tmp = expand_string(tpname);
+           address_file = address_pipe = NULL;
+-          uschar *m;
+           if (!tmp)
+             p->message = string_sprintf("failed to expand \"%s\" as a "
+               "system filter transport name", tpname);
+           { uschar *m;
+-	  if (m = is_tainted2(tmp, 0, "Tainted values '%s' " "for transport '%s' as a system filter", tmp, tpname))
++	  if ((m = is_tainted2(tmp, 0, "Tainted values '%s' " "for transport '%s' as a system filter", tmp, tpname)))
+             p->message = m;
+           }
+           tpname = tmp;
+diff --git a/src/expand.c b/src/expand.c
+index 21b86ebf5..dc4b4e102 100644
+--- a/src/expand.c
++++ b/src/expand.c
+@@ -4384,7 +4384,7 @@ f.expand_string_forcedfail = FALSE;
+ expand_string_message = US"";
+ 
+ { uschar *m;
+-if (m = is_tainted2(string, LOG_MAIN|LOG_PANIC, "Tainted string '%s' in expansion", s))
++if ((m = is_tainted2(string, LOG_MAIN|LOG_PANIC, "Tainted string '%s' in expansion", s)))
+   {
+   expand_string_message = m;
+   goto EXPAND_FAILED;
+@@ -7629,10 +7629,12 @@ while (*s != 0)
+ 	/* Manually track tainting, as we deal in individual chars below */
+ 
+ 	if (is_tainted(sub))
++          {
+ 	  if (yield->s && yield->ptr)
+ 	    gstring_rebuffer(yield);
+ 	  else
+ 	    yield->s = store_get(yield->size = Ustrlen(sub), TRUE);
++          }
+ 
+ 	/* Check the UTF-8, byte-by-byte */
+ 
+@@ -8193,6 +8195,7 @@ that is a bad idea, because expand_string_message is in dynamic store. */
+ EXPAND_FAILED:
+ if (left) *left = s;
+ DEBUG(D_expand)
++  {
+   DEBUG(D_noutf8)
+     {
+     debug_printf_indent("|failed to expand: %s\n", string);
+@@ -8212,6 +8215,7 @@ DEBUG(D_expand)
+     if (f.expand_string_forcedfail)
+       debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
+     }
++  }
+ if (resetok_p && !resetok) *resetok_p = FALSE;
+ expand_level--;
+ return NULL;
+diff --git a/src/functions.h b/src/functions.h
+index 1e8083673..b4d23c4bc 100644
+--- a/src/functions.h
++++ b/src/functions.h
+@@ -1084,7 +1084,7 @@ if (f.running_in_test_harness && f.testsuite_delays) millisleep(millisec);
+ /******************************************************************************/
+ /* Taint-checked file opens */
+ static inline uschar *
+-is_tainted2(const void *p, int lflags, const uschar* fmt, ...)
++is_tainted2(const void *p, int lflags, const char* fmt, ...)
+ {
+ va_list ap;
+ uschar *msg;
+diff --git a/src/lookups/lf_sqlperform.c b/src/lookups/lf_sqlperform.c
+index eda3089e2..38b7c2ad3 100644
+--- a/src/lookups/lf_sqlperform.c
++++ b/src/lookups/lf_sqlperform.c
+@@ -103,7 +103,7 @@ if (Ustrncmp(query, "servers", 7) == 0)
+       }
+ 
+     { uschar *m;
+-    if (m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server))
++    if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
+      {
+       *errmsg = m;
+       return DEFER;
+@@ -161,7 +161,7 @@ else
+ 	}
+ 
+       { uschar *m;
+-      if (is_tainted2(server, 0, "Tainted %s server '%s'", name, server))
++      if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
+         {
+         *errmsg = m;
+         return DEFER;
+diff --git a/src/parse.c b/src/parse.c
+index d1bc79039..0622b3127 100644
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -1402,7 +1402,7 @@ for (;;)
+       return FF_ERROR;
+       }
+ 
+-    if (*error = is_tainted2(filename, 0, "Tainted name '%s' for included file not permitted\n", filename))
++    if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for included file not permitted\n", filename)))
+       return FF_ERROR;
+ 
+     /* Check file name if required */
+diff --git a/src/rda.c b/src/rda.c
+index 6ad7dd8bd..bba0b719b 100644
+--- a/src/rda.c
++++ b/src/rda.c
+@@ -179,7 +179,7 @@ struct stat statbuf;
+ /* Reading a file is a form of expansion; we wish to deny attackers the
+ capability to specify the file name. */
+ 
+-if (*error = is_tainted2(filename, 0, "Tainted name '%s' for file read not permitted\n", filename))
++if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for file read not permitted\n", filename)))
+   {
+   *yield = FF_ERROR;
+   return NULL;
+diff --git a/src/transports/appendfile.c b/src/transports/appendfile.c
+index 7dbbaa2f9..6772b338b 100644
+--- a/src/transports/appendfile.c
++++ b/src/transports/appendfile.c
+@@ -1287,8 +1287,8 @@ if (!(path = expand_string(fdname)))
+   goto ret_panic;
+   }
+ { uschar *m;
+-if (m = is_tainted2(path, 0, "Tainted '%s' (file or directory "
+-          "name for %s transport) not permitted", path, tblock->name))
++if ((m = is_tainted2(path, 0, "Tainted '%s' (file or directory "
++          "name for %s transport) not permitted", path, tblock->name)))
+   {
+   addr->message = m;
+   goto ret_panic;
+diff --git a/src/transports/autoreply.c b/src/transports/autoreply.c
+index ed99de4c6..80c7c0db0 100644
+--- a/src/transports/autoreply.c
++++ b/src/transports/autoreply.c
+@@ -407,8 +407,8 @@ if (oncelog && *oncelog && to)
+   uschar *m;
+   time_t then = 0;
+ 
+-  if (m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
+-      " not permitted", oncelog, tblock->name))
++  if ((m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
++      " not permitted", oncelog, tblock->name)))
+     {
+     addr->transport_return = DEFER;
+     addr->basic_errno = EACCES;
+@@ -518,8 +518,8 @@ if (oncelog && *oncelog && to)
+     {
+     uschar *m;
+     int log_fd;
+-    if (m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
+-	" not permitted", logfile, tblock->name))
++    if ((m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
++	" not permitted", logfile, tblock->name)))
+       {
+       addr->transport_return = DEFER;
+       addr->basic_errno = EACCES;
+@@ -551,8 +551,8 @@ if (oncelog && *oncelog && to)
+ if (file)
+   {
+   uschar *m;
+-  if (m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
+-      " not permitted", file, tblock->name))
++  if ((m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
++      " not permitted", file, tblock->name)))
+     {
+     addr->transport_return = DEFER;
+     addr->basic_errno = EACCES;
+diff --git a/src/transports/pipe.c b/src/transports/pipe.c
+index 4c9e68beb..fc44fa585 100644
+--- a/src/transports/pipe.c
++++ b/src/transports/pipe.c
+@@ -601,8 +601,8 @@ if (!cmd || !*cmd)
+   }
+ 
+ { uschar *m;
+-if (m = is_tainted2(cmd, 0, "Tainted '%s' (command "
+-    "for %s transport) not permitted", cmd, tblock->name))
++if ((m = is_tainted2(cmd, 0, "Tainted '%s' (command "
++    "for %s transport) not permitted", cmd, tblock->name)))
+   {
+   addr->transport_return = PANIC;
+   addr->message = m;
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch exim4-4.94/debian/patches/75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch
--- exim4-4.94/debian/patches/75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch	2021-04-25 07:27:42.000000000 +0200
@@ -0,0 +1,166 @@
+From 235c7030ee9ee1c1aad507786506a470b580bfe2 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Fri, 23 Apr 2021 22:41:57 +0200
+Subject: [PATCH 23/23] Do not close the (main)_log, if we do not see a chance
+ to open it again.
+
+The process doing local deliveries runs as an unprivileged user. If this
+process needs to log failures or warnings (as caused by the
+is_tainting2() function), it can't re-open the main_log and just exits.
+---
+ src/log.c                   | 84 ++++++++++++++++-----------------
+ src/transports/appendfile.c |  6 +++
+ 2 files changed, 47 insertions(+), 43 deletions(-)
+
+diff --git a/src/log.c b/src/log.c
+index 7ef7074ec..c2ef698e7 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -646,18 +646,36 @@ return total_written;
+ }
+ 
+ 
+-
+-static void
+-set_file_path(void)
++void
++set_file_path(BOOL *multiple)
+ {
++uschar *s;
+ int sep = ':';              /* Fixed separator - outside use */
+-uschar *t;
+-const uschar *tt = US LOG_FILE_PATH;
+-while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE)))
++uschar *ss = *log_file_path ? log_file_path : LOG_FILE_PATH;
++
++logging_mode = 0;
++while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+   {
+-  if (Ustrcmp(t, "syslog") == 0 || t[0] == 0) continue;
+-  file_path = string_copy(t);
+-  break;
++  if (Ustrcmp(s, "syslog") == 0)
++    logging_mode |= LOG_MODE_SYSLOG;
++  else if (logging_mode & LOG_MODE_FILE)  /* we know a file already */
++    {
++    if (multiple) *multiple = TRUE;
++    }
++  else
++    {
++    logging_mode |= LOG_MODE_FILE;
++
++    /* If a non-empty path is given, use it */
++
++    if (*s)
++      file_path = string_copy(s);
++
++    /* If the path is empty, we want to use the first non-empty, non-
++    syslog item in LOG_FILE_PATH, if there is one, since the value of
++    log_file_path may have been set at runtime. If there is no such item,
++    use the ultimate default in the spool directory. */
++    }
+   }
+ }
+ 
+@@ -665,7 +683,11 @@ while ((t = string_nextinlist(&tt, &sep, log_buffer, LOG_BUFFER_SIZE)))
+ void
+ mainlog_close(void)
+ {
+-if (mainlogfd < 0) return;
++/* avoid closing it if it is closed already or if we do not see a chance
++to open the file mainlog later again */
++if (mainlogfd < 0 /* already closed */
++   || !(geteuid() == 0 || geteuid() == exim_uid))
++  return;
+ (void)close(mainlogfd);
+ mainlogfd = -1;
+ mainlog_inode = 0;
+@@ -780,38 +802,7 @@ if (!path_inspected)
+   /* If nothing has been set, don't waste effort... the default values for the
+   statics are file_path="" and logging_mode = LOG_MODE_FILE. */
+ 
+-  if (*log_file_path)
+-    {
+-    int sep = ':';              /* Fixed separator - outside use */
+-    uschar *s;
+-    const uschar *ss = log_file_path;
+-
+-    logging_mode = 0;
+-    while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+-      {
+-      if (Ustrcmp(s, "syslog") == 0)
+-        logging_mode |= LOG_MODE_SYSLOG;
+-      else if (logging_mode & LOG_MODE_FILE)
+-	multiple = TRUE;
+-      else
+-        {
+-        logging_mode |= LOG_MODE_FILE;
+-
+-        /* If a non-empty path is given, use it */
+-
+-        if (*s)
+-          file_path = string_copy(s);
+-
+-        /* If the path is empty, we want to use the first non-empty, non-
+-        syslog item in LOG_FILE_PATH, if there is one, since the value of
+-        log_file_path may have been set at runtime. If there is no such item,
+-        use the ultimate default in the spool directory. */
+-
+-        else
+-	  set_file_path();  /* Empty item in log_file_path */
+-        }    /* First non-syslog item in log_file_path */
+-      }      /* Scan of log_file_path */
+-    }
++  if (*log_file_path) set_file_path(&multiple);
+ 
+   /* If no modes have been selected, it is a major disaster */
+ 
+@@ -1431,7 +1422,7 @@ if (opts)
+ resulting in certain setup not having been done.  Hack this for now so we
+ do not segfault; note that nondefault log locations will not work */
+ 
+-if (!*file_path) set_file_path();
++if (!*file_path) set_file_path(NULL);
+ 
+ open_log(&fd, lt_debug, tag_name);
+ 
+@@ -1453,5 +1444,12 @@ debug_file = NULL;
+ unlink_log(lt_debug);
+ }
+ 
++void
++open_logs(const char *m)
++{
++set_file_path(NULL);
++open_log(&mainlogfd, lt_main, 0);
++open_log(&rejectlogfd, lt_reject, 0);
++}
+ 
+ /* End of log.c */
+diff --git a/src/transports/appendfile.c b/src/transports/appendfile.c
+index 6772b338b..706af6dde 100644
+--- a/src/transports/appendfile.c
++++ b/src/transports/appendfile.c
+@@ -217,6 +217,9 @@ Arguments:
+ Returns:     OK, FAIL, or DEFER
+ */
+ 
++void
++openlogs();
++
+ static int
+ appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
+   transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
+@@ -231,6 +234,9 @@ dummy = dummy;
+ uid = uid;
+ gid = gid;
+ 
++/* we can't wait until we're not privileged anymore */
++open_logs("appendfile");
++
+ if (ob->expand_maildir_use_size_file)
+ 	ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file,
+ 		US"`maildir_use_size_file` in transport", tblock->name);
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_24-Silence-the-compiler.patch exim4-4.94/debian/patches/75_24-Silence-the-compiler.patch
--- exim4-4.94/debian/patches/75_24-Silence-the-compiler.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_24-Silence-the-compiler.patch	2021-04-26 18:27:39.000000000 +0200
@@ -0,0 +1,57 @@
+From 33d5b8e8e4c2f23b4e834e3a095e3c9dd9f0686b Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 25 Apr 2021 18:58:35 +0200
+Subject: [PATCH 1/4] Silence the compiler
+
+---
+ src/log.c                   | 4 ++--
+ src/transports/appendfile.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/log.c b/src/log.c
+index c2ef698e7..11d259197 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -651,7 +651,7 @@ set_file_path(BOOL *multiple)
+ {
+ uschar *s;
+ int sep = ':';              /* Fixed separator - outside use */
+-uschar *ss = *log_file_path ? log_file_path : LOG_FILE_PATH;
++const uschar *ss = *log_file_path ? log_file_path : US LOG_FILE_PATH;
+ 
+ logging_mode = 0;
+ while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
+@@ -1445,7 +1445,7 @@ unlink_log(lt_debug);
+ }
+ 
+ void
+-open_logs(const char *m)
++open_logs(void)
+ {
+ set_file_path(NULL);
+ open_log(&mainlogfd, lt_main, 0);
+diff --git a/src/transports/appendfile.c b/src/transports/appendfile.c
+index 706af6dde..c0f4de4c8 100644
+--- a/src/transports/appendfile.c
++++ b/src/transports/appendfile.c
+@@ -218,7 +218,7 @@ Returns:     OK, FAIL, or DEFER
+ */
+ 
+ void
+-openlogs();
++open_logs(void);
+ 
+ static int
+ appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
+@@ -235,7 +235,7 @@ uid = uid;
+ gid = gid;
+ 
+ /* we can't wait until we're not privileged anymore */
+-open_logs("appendfile");
++open_logs();
+ 
+ if (ob->expand_maildir_use_size_file)
+ 	ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file,
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch exim4-4.94/debian/patches/75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch
--- exim4-4.94/debian/patches/75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch	1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.94/debian/patches/75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch	2021-04-26 18:27:39.000000000 +0200
@@ -0,0 +1,27 @@
+From 1416743e923cacf42955392e92995f5fe7e1c680 Mon Sep 17 00:00:00 2001
+From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
+Date: Sun, 25 Apr 2021 10:19:32 +0200
+Subject: [PATCH 3/4] Disable taintchecks for mkdir, this isn't part of 4.94
+
+---
+ src/directory.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/directory.c b/src/directory.c
+index 9f88f4141..ece1ee8f3 100644
+--- a/src/directory.c
++++ b/src/directory.c
+@@ -44,8 +44,10 @@ uschar c = 1;
+ struct stat statbuf;
+ uschar * path;
+ 
++/* does not work with 4.94
+ if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted path '%s' for new directory", name))
+   { p = US"create"; path = US name; errno = EACCES; goto bad; }
++*/
+ 
+ if (parent)
+   {
+-- 
+2.30.2
+
diff -Nru exim4-4.94/debian/patches/series exim4-4.94/debian/patches/series
--- exim4-4.94/debian/patches/series	2021-03-18 13:53:44.000000000 +0100
+++ exim4-4.94/debian/patches/series	2021-04-26 18:29:13.000000000 +0200
@@ -66,4 +66,28 @@
 74_60-Fix-list-expansion-for-various-domainlists-having-in.patch
 74_61-Bulid-fix-DISABLE_PIPE_CONNECT-build.-Bug-2703.patch
 74_62-Docs-fix-description-of-hosts_try_dane.-Bug-2704.patch
+75_01-Introduce-main-config-option-allow_insecure_tainted_.patch
+75_02-search.patch
+75_03-dbstuff.patch
+75_04-acl.patch
+75_05-parse.patch
+75_06-rda.patch
+75_07-appendfile.patch
+75_08-autoreply.patch
+75_09-pipe.patch
+75_10-deliver.patch
+75_11-directory.patch
+75_12-expand.patch
+75_13-lf_sqlperform.patch
+75_14-rf_get_transport.patch
+75_15-deliver.patch
+75_16-smtp_out.patch
+75_17-smtp.patch
+75_18-update-doc.patch
+75_20-Set-mainlog_name-and-rejectlog_name-unconditionally.patch
+75_21-tidy-log.c.patch
+75_22-Silence-compiler.patch
+75_23-Do-not-close-the-main-_log-if-we-do-not-see-a-chance.patch
+75_24-Silence-the-compiler.patch
+75_26-Disable-taintchecks-for-mkdir-this-isn-t-part-of-4.9.patch
 90_localscan_dlopen.dpatch

Attachment: signature.asc
Description: PGP signature


Reply to: