Bug#1049899: bookworm-pu: package exim4/4.96-15+deb12u2
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian.org@packages.debian.org
Usertags: pu
Control: affects -1 + src:exim4
Hello,
I would like to push another round of cherry-picked upstream fixes to
bookworm. They have been part of the uploads to sid up to and including
4.96-19.
This was mainly triggered by
+ 75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch: Fix on-demand
TLS cert expiry date. Closes: #1043233
which borders on RC and
+ 75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch
(Upstream bug 3013)
which is similar to #1025420.
cu Andreas
--
`What a good friend you are to him, Dr. Maturin. His other friends are
so grateful to you.'
`I sew his ears on from time to time, sure'
diff -Nru exim4-4.96/debian/changelog exim4-4.96/debian/changelog
--- exim4-4.96/debian/changelog 2023-07-02 14:56:17.000000000 +0200
+++ exim4-4.96/debian/changelog 2023-08-16 15:12:39.000000000 +0200
@@ -1,3 +1,19 @@
+exim4 (4.96-15+deb12u2) bookworm; urgency=medium
+
+ * Multiple bugfixes from upstream GIT master:
+ + 75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch
+ + 75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch
+ (Upstream bug 2998)
+ + 75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch
+ + 75_78-Fix-free-of-value-after-run.patch
+ + 75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch
+ (Upstream bug 3013)
+ + 75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch: Fix on-demand
+ TLS cert expiry date. Closes: #1043233
+ (Upstream bug 3014)
+
+ -- Andreas Metzler <ametzler@debian.org> Wed, 16 Aug 2023 15:12:39 +0200
+
exim4 (4.96-15+deb12u1) bookworm; urgency=medium
* 75_42-Fix-run-arg-parsing.patch (From upstream GIT master, backported by
diff -Nru exim4-4.96/debian/patches/75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch exim4-4.96/debian/patches/75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch
--- exim4-4.96/debian/patches/75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch 2023-08-16 14:59:06.000000000 +0200
@@ -0,0 +1,35 @@
+From 4d108e7777e9b8e5fb212c31812fef61529cd414 Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Mon, 12 Jun 2023 22:13:46 +0100
+Subject: [PATCH] Cancel early-pipe on an observed advertising change
+
+---
+ src/transports/smtp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/transports/smtp.c b/src/transports/smtp.c
+index c72028ce9..24ee577a2 100644
+--- a/src/transports/smtp.c
++++ b/src/transports/smtp.c
+@@ -1111,15 +1111,18 @@ if (pending_EHLO)
+ *(tls_out.active.sock < 0
+ ? &sx->ehlo_resp.cleartext_features : &sx->ehlo_resp.crypted_features) =
+ peer_offered;
+ *ap = authbits;
+ write_ehlo_cache_entry(sx);
+ }
+ else
++ {
+ invalidate_ehlo_cache_entry(sx);
++ sx->early_pipe_active = FALSE; /* cancel further early-pipe on this conn */
++ }
+
+ return OK; /* just carry on */
+ }
+ # ifdef EXPERIMENTAL_ESMTP_LIMITS
+ /* If we are handling LIMITS, compare the actual EHLO LIMITS values with the
+ cached values and invalidate cache if different. OK to carry on with
+ connect since values are advisory. */
+--
+2.40.1
+
diff -Nru exim4-4.96/debian/patches/75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch exim4-4.96/debian/patches/75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch
--- exim4-4.96/debian/patches/75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch 2023-08-16 15:11:54.000000000 +0200
@@ -0,0 +1,99 @@
+From 1209e3e19e292cee517e43a2ccfe9b44b33bb1dc Mon Sep 17 00:00:00 2001
+From: Jasen Betts <jasen@xnet.co.nz>
+Date: Sun, 23 Jul 2023 13:43:59 +0100
+Subject: [PATCH] Expansions: disallow UTF-16 surrogates from ${utf8clean:...}.
+ Bug 2998
+
+---
+ doc/ChangeLog | 4 ++++
+ src/expand.c | 27 +++++++++++++++++----------
+ 2 files changed, 21 insertions(+), 10 deletions(-)
+
+--- a/src/expand.c
++++ b/src/expand.c
+@@ -7731,11 +7731,11 @@ NOT_ITEM: ;
+
+ case EOP_UTF8CLEAN:
+ {
+ int seq_len = 0, index = 0;
+ int bytes_left = 0;
+- long codepoint = -1;
++ ulong codepoint = (ulong)-1;
+ int complete;
+ uschar seq_buff[4]; /* accumulate utf-8 here */
+
+ /* Manually track tainting, as we deal in individual chars below */
+
+@@ -7761,40 +7761,47 @@ NOT_ITEM: ;
+ codepoint = (codepoint << 6) | (c & 0x3f);
+ seq_buff[index++] = c;
+ if (--bytes_left == 0) /* codepoint complete */
+ if(codepoint > 0x10FFFF) /* is it too large? */
+ complete = -1; /* error (RFC3629 limit) */
++ else if ( (codepoint & 0x1FF800 ) == 0xD800 ) /* surrogate */
++ /* A UTF-16 surrogate (which should be one of a pair that
++ encode a Unicode codepoint that is outside the Basic
++ Multilingual Plane). Error, not UTF8.
++ RFC2279.2 is slightly unclear on this, but
++ https://unicodebook.readthedocs.io/issues.html#strict-utf8-decoder
++ says "Surrogates characters are also invalid in UTF-8:
++ characters in U+D800—U+DFFF have to be rejected." */
++ complete = -1;
+ else
+ { /* finished; output utf-8 sequence */
+ yield = string_catn(yield, seq_buff, seq_len);
+ index = 0;
+ }
+ }
+ }
+ else /* no bytes left: new sequence */
+ {
+- if(!(c & 0x80)) /* 1-byte sequence, US-ASCII, keep it */
++ if (!(c & 0x80)) /* 1-byte sequence, US-ASCII, keep it */
+ {
+ yield = string_catn(yield, &c, 1);
+ continue;
+ }
+- if((c & 0xe0) == 0xc0) /* 2-byte sequence */
+- {
+- if(c == 0xc0 || c == 0xc1) /* 0xc0 and 0xc1 are illegal */
++ if ((c & 0xe0) == 0xc0) /* 2-byte sequence */
++ if (c == 0xc0 || c == 0xc1) /* 0xc0 and 0xc1 are illegal */
+ complete = -1;
+ else
+ {
+- bytes_left = 1;
+- codepoint = c & 0x1f;
++ bytes_left = 1;
++ codepoint = c & 0x1f;
+ }
+- }
+- else if((c & 0xf0) == 0xe0) /* 3-byte sequence */
++ else if ((c & 0xf0) == 0xe0) /* 3-byte sequence */
+ {
+ bytes_left = 2;
+ codepoint = c & 0x0f;
+ }
+- else if((c & 0xf8) == 0xf0) /* 4-byte sequence */
++ else if ((c & 0xf8) == 0xf0) /* 4-byte sequence */
+ {
+ bytes_left = 3;
+ codepoint = c & 0x07;
+ }
+ else /* invalid or too long (RFC3629 allows only 4 bytes) */
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -69,10 +69,13 @@ JH/28 Bug 2996: Fix a crash in the smtp
+ to close it tried to use an uninitialized variable. This would afftect
+ high-volume sites more, especially when running mailing-list-style loads.
+ Pollution of logs was the major effect, as the other process delivered
+ the message. Found and partly investigated by Graeme Fowler.
+
++JH/31 Bug 2998: Fix ${utf8clean:...} to disallow UTF-16 surrogate codepoints.
++ Found and fixed by Jasen Betts. No testcase for this as my usual text
++ editor insists on emitting only valid UTF-8.
+
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
diff -Nru exim4-4.96/debian/patches/75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch exim4-4.96/debian/patches/75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch
--- exim4-4.96/debian/patches/75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch 2023-08-16 15:12:39.000000000 +0200
@@ -0,0 +1,92 @@
+From 8e9770348dc4173ab83657ee023c22f479ebb712 Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Mon, 24 Jul 2023 13:30:40 +0100
+Subject: [PATCH] GnuTLS: fix crash with "tls_dhparam = none"
+
+---
+ doc/ChangeLog | 4 ++++
+ src/tls-gnu.c | 16 +++++++++-------
+ test/log/2049 | 7 +++++++
+ test/scripts/2000-GnuTLS/2049 | 8 ++++++++
+ 4 files changed, 28 insertions(+), 7 deletions(-)
+
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -73,10 +73,14 @@ JH/28 Bug 2996: Fix a crash in the smtp
+
+ JH/31 Bug 2998: Fix ${utf8clean:...} to disallow UTF-16 surrogate codepoints.
+ Found and fixed by Jasen Betts. No testcase for this as my usual text
+ editor insists on emitting only valid UTF-8.
+
++JH/32 Fix "tls_dhparam = none" under GnuTLS. At least with 3.7.9 this gave
++ a null-indireciton SIGSEGV for the receive process.
++
++
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
+ after reception to before a subsequent reception. This should
+--- a/src/tls-gnu.c
++++ b/src/tls-gnu.c
+@@ -712,11 +712,11 @@ exist, we generate them. This means that
+ The new file is written as a temporary file and renamed, so that an incomplete
+ file is never present. If two processes both compute some new parameters, you
+ waste a bit of effort, but it doesn't seem worth messing around with locking to
+ prevent this.
+
+-Returns: OK/DEFER/FAIL
++Returns: OK/DEFER (expansion issue)/FAIL (requested none)
+ */
+
+ static int
+ init_server_dh(uschar ** errstr)
+ {
+@@ -750,11 +750,11 @@ if (!exp_tls_dhparam)
+ else if (Ustrcmp(exp_tls_dhparam, "historic") == 0)
+ use_file_in_spool = TRUE;
+ else if (Ustrcmp(exp_tls_dhparam, "none") == 0)
+ {
+ DEBUG(D_tls) debug_printf("Requested no DH parameters\n");
+- return OK;
++ return FAIL;
+ }
+ else if (exp_tls_dhparam[0] != '/')
+ {
+ if (!(m.data = US std_dh_prime_named(exp_tls_dhparam)))
+ return tls_error(US"No standard prime named", exp_tls_dhparam, NULL, errstr);
+@@ -1971,27 +1971,29 @@ Arguments:
+
+ Returns: OK/DEFER/FAIL
+ */
+
+ static int
+-tls_set_remaining_x509(exim_gnutls_state_st *state, uschar ** errstr)
++tls_set_remaining_x509(exim_gnutls_state_st * state, uschar ** errstr)
+ {
+-int rc;
+-const host_item *host = state->host; /* macro should be reconsidered? */
++int rc = OK;
++const host_item * host = state->host; /* macro should be reconsidered? */
+
+ /* Create D-H parameters, or read them from the cache file. This function does
+ its own SMTP error messaging. This only happens for the server, TLS D-H ignores
+ client-side params. */
+
+ if (!state->host)
+ {
+ if (!dh_server_params)
+- if ((rc = init_server_dh(errstr)) != OK) return rc;
++ if ((rc = init_server_dh(errstr)) == DEFER) return rc;
+
+ /* Unnecessary & discouraged with 3.6.0 or later, according to docs. But without it,
+ no DHE- ciphers are advertised. */
+- gnutls_certificate_set_dh_params(state->lib_state.x509_cred, dh_server_params);
++
++ if (rc == OK)
++ gnutls_certificate_set_dh_params(state->lib_state.x509_cred, dh_server_params);
+ }
+
+ /* Link the credentials to the session. */
+
+ if ((rc = gnutls_credentials_set(state->session,
diff -Nru exim4-4.96/debian/patches/75_78-Fix-free-of-value-after-run.patch exim4-4.96/debian/patches/75_78-Fix-free-of-value-after-run.patch
--- exim4-4.96/debian/patches/75_78-Fix-free-of-value-after-run.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_78-Fix-free-of-value-after-run.patch 2023-08-16 14:59:06.000000000 +0200
@@ -0,0 +1,75 @@
+From cf3fecb9e873df38a9245775a3887e73a8716083 Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Thu, 3 Aug 2023 18:34:06 +0100
+Subject: [PATCH 1/2] Fix free of $value after ${run...}
+
+---
+ doc/ChangeLog | 3 +++
+ src/expand.c | 10 ++++++++--
+ test/log/0635 | 7 +++++++
+ test/mail/0635.CALLER | 13 +++++++++++++
+ 4 files changed, 31 insertions(+), 2 deletions(-)
+ create mode 100644 test/log/0635
+ create mode 100644 test/mail/0635.CALLER
+
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -81,10 +81,12 @@ JH/31 Bug 2998: Fix ${utf8clean:...} to
+ editor insists on emitting only valid UTF-8.
+
+ JH/32 Fix "tls_dhparam = none" under GnuTLS. At least with 3.7.9 this gave
+ a null-indireciton SIGSEGV for the receive process.
+
++JH/33 Fix free for live variable $value created by a ${run ...} expansion.
++ Although not seen, this could have resulted in a SIGSEGV.
+
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
+--- a/src/expand.c
++++ b/src/expand.c
+@@ -5535,10 +5535,12 @@ while (*s)
+ case EITEM_RUN:
+ {
+ FILE * f;
+ const uschar * arg, ** argv;
+ BOOL late_expand = TRUE;
++ uschar * save_value = lookup_value;
++ int yesno;
+
+ if (expand_forbid & RDO_RUN)
+ {
+ expand_string_message = US"running a command is not permitted";
+ goto EXPAND_FAILED;
+@@ -5658,24 +5660,28 @@ while (*s)
+
+ else
+ expand_string_message = string_sprintf("command killed by signal %d",
+ -runrc);
+
++ lookup_value = save_value;
+ goto EXPAND_FAILED;
+ }
+ }
+
+ /* Process the yes/no strings; $value may be useful in both cases */
+
+- switch(process_yesno(
++ yesno = process_yesno(
+ skipping, /* were previously skipping */
+ runrc == 0, /* success/failure indicator */
+ lookup_value, /* value to reset for string2 */
+ &s, /* input pointer */
+ &yield, /* output pointer */
+ US"run", /* condition type */
+- &resetok))
++ &resetok);
++ lookup_value = save_value;
++
++ switch(yesno)
+ {
+ case 1: goto EXPAND_FAILED; /* when all is well, the */
+ case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */
+ }
+
diff -Nru exim4-4.96/debian/patches/75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch exim4-4.96/debian/patches/75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch
--- exim4-4.96/debian/patches/75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch 2023-08-16 14:59:06.000000000 +0200
@@ -0,0 +1,295 @@
+From 6707bfa9fb78858de938a1abca2846c820c5ded7 Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Thu, 3 Aug 2023 18:40:42 +0100
+Subject: [PATCH 2/2] Fix $recipients expansion when used within ${run...}.
+ Bug 3013
+
+Broken-by: cfe6acff2ddc
+---
+ doc/ChangeLog | 3 +++
+ src/deliver.c | 2 +-
+ src/expand.c | 5 ++---
+ src/functions.h | 2 +-
+ src/macros.h | 5 +++++
+ src/routers/queryprogram.c | 3 +--
+ src/smtp_in.c | 4 ++--
+ src/transport.c | 18 +++++++++---------
+ src/transports/lmtp.c | 4 ++--
+ src/transports/pipe.c | 11 ++++++-----
+ src/transports/smtp.c | 2 +-
+ test/log/0635 | 2 +-
+ 12 files changed, 34 insertions(+), 27 deletions(-)
+
+--- a/src/deliver.c
++++ b/src/deliver.c
+@@ -2382,11 +2382,11 @@ if ((pid = exim_fork(US"delivery-local")
+
+ if (tp->filter_command)
+ {
+ ok = transport_set_up_command(&transport_filter_argv,
+ tp->filter_command,
+- TRUE, PANIC, addr, FALSE, US"transport filter", NULL);
++ TSUC_EXPAND_ARGS, PANIC, addr, US"transport filter", NULL);
+ transport_filter_timeout = tp->filter_timeout;
+ }
+ else transport_filter_argv = NULL;
+
+ if (ok)
+--- a/src/expand.c
++++ b/src/expand.c
+@@ -5534,11 +5534,11 @@ while (*s)
+
+ case EITEM_RUN:
+ {
+ FILE * f;
+ const uschar * arg, ** argv;
+- BOOL late_expand = TRUE;
++ unsigned late_expand = TSUC_EXPAND_ARGS | TSUC_ALLOW_TAINTED_ARGS | TSUC_ALLOW_RECIPIENTS;
+ uschar * save_value = lookup_value;
+ int yesno;
+
+ if (expand_forbid & RDO_RUN)
+ {
+@@ -5549,11 +5549,11 @@ while (*s)
+ /* Handle options to the "run" */
+
+ while (*s == ',')
+ {
+ if (Ustrncmp(++s, "preexpand", 9) == 0)
+- { late_expand = FALSE; s += 9; }
++ { late_expand = 0; s += 9; }
+ else
+ {
+ const uschar * t = s;
+ while (isalpha(*++t)) ;
+ expand_string_message = string_sprintf("bad option '%.*s' for run",
+@@ -5608,11 +5608,10 @@ while (*s)
+ if (!transport_set_up_command(&argv, /* anchor for arg list */
+ arg, /* raw command */
+ late_expand, /* expand args if not already done */
+ 0, /* not relevant when... */
+ NULL, /* no transporting address */
+- late_expand, /* allow tainted args, when expand-after-split */
+ US"${run} expansion", /* for error messages */
+ &expand_string_message)) /* where to put error message */
+ goto EXPAND_FAILED;
+
+ /* Create the child process, making it a group leader. */
+--- a/src/functions.h
++++ b/src/functions.h
+@@ -616,11 +616,11 @@ extern BOOL transport_pass_socket(con
+ , unsigned, unsigned, unsigned
+ #endif
+ );
+ extern uschar *transport_rcpt_address(address_item *, BOOL);
+ extern BOOL transport_set_up_command(const uschar ***, const uschar *,
+- BOOL, int, address_item *, BOOL, const uschar *, uschar **);
++ unsigned, int, address_item *, const uschar *, uschar **);
+ extern void transport_update_waiting(host_item *, uschar *);
+ extern BOOL transport_write_block(transport_ctx *, uschar *, int, BOOL);
+ extern void transport_write_reset(int);
+ extern BOOL transport_write_string(int, const char *, ...);
+ extern BOOL transport_headers_send(transport_ctx *,
+--- a/src/macros.h
++++ b/src/macros.h
+@@ -1112,6 +1112,11 @@ should not be one active. */
+
+ #define NOTIFIER_SOCKET_NAME "exim_daemon_notify"
+ #define NOTIFY_MSG_QRUN 1 /* Notify message types */
+ #define NOTIFY_QUEUE_SIZE_REQ 2
+
++/* Flags for transport_set_up_command() */
++#define TSUC_EXPAND_ARGS BIT(0)
++#define TSUC_ALLOW_TAINTED_ARGS BIT(1)
++#define TSUC_ALLOW_RECIPIENTS BIT(2)
++
+ /* End of macros.h */
+--- a/src/routers/queryprogram.c
++++ b/src/routers/queryprogram.c
+@@ -286,14 +286,13 @@ if (curr_uid != root_uid && (uid != curr
+
+ /* Set up the command to run */
+
+ if (!transport_set_up_command(&argvptr, /* anchor for arg list */
+ ob->command, /* raw command */
+- TRUE, /* expand the arguments */
++ TSUC_EXPAND_ARGS, /* arguments expanded but must not be tainted */
+ 0, /* not relevant when... */
+ NULL, /* no transporting address */
+- FALSE, /* args must be untainted */
+ US"queryprogram router", /* for error messages */
+ &addr->message)) /* where to put error message */
+ return DEFER;
+
+ /* Create the child process, making it a group leader. */
+--- a/src/smtp_in.c
++++ b/src/smtp_in.c
+@@ -5840,12 +5840,12 @@ while (done <= 0)
+ {
+ uschar *error;
+ BOOL rc;
+ etrn_command = smtp_etrn_command;
+ deliver_domain = smtp_cmd_data;
+- rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL,
+- FALSE, US"ETRN processing", &error);
++ rc = transport_set_up_command(&argv, smtp_etrn_command, TSUC_EXPAND_ARGS, 0, NULL,
++ US"ETRN processing", &error);
+ deliver_domain = NULL;
+ if (!rc)
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC, "failed to set up ETRN command: %s",
+ error);
+--- a/src/transport.c
++++ b/src/transport.c
+@@ -2082,34 +2082,34 @@ return FALSE;
+ * Set up direct (non-shell) command *
+ *************************************************/
+
+ /* This function is called when a command line is to be parsed and executed
+ directly, without the use of /bin/sh. It is called by the pipe transport,
+-the queryprogram router, and also from the main delivery code when setting up a
++the queryprogram router, for any ${run } expansion,
++and also from the main delivery code when setting up a
+ transport filter process. The code for ETRN also makes use of this; in that
+ case, no addresses are passed.
+
+ Arguments:
+ argvptr pointer to anchor for argv vector
+ cmd points to the command string (modified IN PLACE)
+- expand_arguments true if expansion is to occur
++ flags bits for expand-args, allow taint, allow $recipients
+ expand_failed error value to set if expansion fails; not relevant if
+ addr == NULL
+ addr chain of addresses, or NULL
+- allow_tainted_args as it says; used for ${run}
+ etext text for use in error messages
+ errptr where to put error message if addr is NULL;
+ otherwise it is put in the first address
+
+ Returns: TRUE if all went well; otherwise an error will be
+ set in the first address and FALSE returned
+ */
+
+ BOOL
+ transport_set_up_command(const uschar *** argvptr, const uschar * cmd,
+- BOOL expand_arguments, int expand_failed, address_item * addr,
+- BOOL allow_tainted_args, const uschar * etext, uschar ** errptr)
++ unsigned flags, int expand_failed, address_item * addr,
++ const uschar * etext, uschar ** errptr)
+ {
+ const uschar ** argv, * s;
+ int address_count = 0, argcount = 0, max_args;
+
+ /* Get store in which to build an argument list. Count the number of addresses
+@@ -2180,14 +2180,14 @@ DEBUG(D_transport)
+ debug_printf("direct command:\n");
+ for (int i = 0; argv[i]; i++)
+ debug_printf(" argv[%d] = '%s'\n", i, string_printing(argv[i]));
+ }
+
+-if (expand_arguments)
++if (flags & TSUC_EXPAND_ARGS)
+ {
+- BOOL allow_dollar_recipients = addr && addr->parent
+- && Ustrcmp(addr->parent->address, "system-filter") == 0;
++ BOOL allow_dollar_recipients = (flags & TSUC_ALLOW_RECIPIENTS)
++ || (addr && addr->parent && Ustrcmp(addr->parent->address, "system-filter") == 0); /*XXX could we check this at caller? */
+
+ for (int i = 0; argv[i]; i++)
+ {
+ DEBUG(D_expand) debug_printf_indent("arg %d\n", i);
+
+@@ -2370,11 +2370,11 @@ if (expand_arguments)
+ { /* hack, would be good to not need it */
+ DEBUG(D_transport)
+ debug_printf("SPECIFIC TESTSUITE EXEMPTION: tainted arg '%s'\n",
+ expanded_arg);
+ }
+- else if ( !allow_tainted_args
++ else if ( !(flags & TSUC_ALLOW_TAINTED_ARGS)
+ && arg_is_tainted(expanded_arg, i, addr, etext, errptr))
+ return FALSE;
+ argv[i] = expanded_arg;
+ }
+ }
+--- a/src/transports/lmtp.c
++++ b/src/transports/lmtp.c
+@@ -487,12 +487,12 @@ argument list and expanding the items. *
+
+ if (ob->cmd)
+ {
+ DEBUG(D_transport) debug_printf("using command %s\n", ob->cmd);
+ sprintf(CS buffer, "%.50s transport", tblock->name);
+- if (!transport_set_up_command(&argv, ob->cmd, TRUE, PANIC, addrlist, FALSE,
+- buffer, NULL))
++ if (!transport_set_up_command(&argv, ob->cmd, TSUC_EXPAND_ARGS, PANIC,
++ addrlist, buffer, NULL))
+ return FALSE;
+
+ /* If the -N option is set, can't do any more. Presume all has gone well. */
+ if (f.dont_deliver)
+ goto MINUS_N;
+--- a/src/transports/pipe.c
++++ b/src/transports/pipe.c
+@@ -289,24 +289,25 @@ Arguments:
+ Returns: TRUE if all went well; otherwise an error will be
+ set in the first address and FALSE returned
+ */
+
+ static BOOL
+-set_up_direct_command(const uschar ***argvptr, uschar *cmd,
+- BOOL expand_arguments, int expand_fail, address_item *addr, uschar *tname,
+- pipe_transport_options_block *ob)
++set_up_direct_command(const uschar *** argvptr, uschar * cmd,
++ BOOL expand_arguments, int expand_fail, address_item * addr, uschar * tname,
++ pipe_transport_options_block * ob)
+ {
+ BOOL permitted = FALSE;
+ const uschar **argv;
+
+ /* Set up "transport <name>" to be put in any error messages, and then
+ call the common function for creating an argument list and expanding
+ the items if necessary. If it fails, this function fails (error information
+ is in the addresses). */
+
+-if (!transport_set_up_command(argvptr, cmd, expand_arguments, expand_fail,
+- addr, FALSE, string_sprintf("%.50s transport", tname), NULL))
++if (!transport_set_up_command(argvptr, cmd,
++ expand_arguments ? TSUC_EXPAND_ARGS : 0,
++ expand_fail, addr, string_sprintf("%.50s transport", tname), NULL))
+ return FALSE;
+
+ /* Point to the set-up arguments. */
+
+ argv = *argvptr;
+--- a/src/transports/smtp.c
++++ b/src/transports/smtp.c
+@@ -3803,11 +3803,11 @@ if (tblock->filter_command)
+
+ /* On failure, copy the error to all addresses, abandon the SMTP call, and
+ yield ERROR. */
+
+ if (!transport_set_up_command(&transport_filter_argv,
+- tblock->filter_command, TRUE, DEFER, addrlist, FALSE,
++ tblock->filter_command, TSUC_EXPAND_ARGS, DEFER, addrlist,
+ string_sprintf("%.50s transport filter", tblock->name), NULL))
+ {
+ set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
+ FALSE, &sx->delivery_start);
+ yield = ERROR;
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -84,10 +84,13 @@ JH/32 Fix "tls_dhparam = none" under Gnu
+ a null-indireciton SIGSEGV for the receive process.
+
+ JH/33 Fix free for live variable $value created by a ${run ...} expansion.
+ Although not seen, this could have resulted in a SIGSEGV.
+
++JH/34 Bug 3013: Fix use of $recipients within arguments for ${run...}.
++ In 4.96 this would expand to empty.
++
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
+ after reception to before a subsequent reception. This should
diff -Nru exim4-4.96/debian/patches/75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch exim4-4.96/debian/patches/75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch
--- exim4-4.96/debian/patches/75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch 1970-01-01 01:00:00.000000000 +0100
+++ exim4-4.96/debian/patches/75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch 2023-08-16 14:59:06.000000000 +0200
@@ -0,0 +1,42 @@
+From 36bc854c86908ee921225c1d30e35c4d59eed822 Mon Sep 17 00:00:00 2001
+From: Andreas Metzler <ametzler@bebt.de>
+Date: Mon, 14 Aug 2023 17:27:16 +0100
+Subject: [PATCH] GnuTLS: fix autogen cert expiry date. Bug 3014
+
+Broken-by: 48e9099006
+---
+ doc/ChangeLog | 3 +++
+ src/tls-gnu.c | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -87,10 +87,13 @@ JH/33 Fix free for live variable $value
+ Although not seen, this could have resulted in a SIGSEGV.
+
+ JH/34 Bug 3013: Fix use of $recipients within arguments for ${run...}.
+ In 4.96 this would expand to empty.
+
++JH/35 Bug 3014: GnuTLS: fix expiry date for an auto-generated server
++ certificate. Find and fix by Andreas Metzler.
++
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
+ after reception to before a subsequent reception. This should
+--- a/src/tls-gnu.c
++++ b/src/tls-gnu.c
+@@ -1001,11 +1001,11 @@ if ((rc = gnutls_x509_privkey_generate(p
+ where = US"configuring cert";
+ now = 1;
+ if ( (rc = gnutls_x509_crt_set_version(cert, 3))
+ || (rc = gnutls_x509_crt_set_serial(cert, &now, sizeof(now)))
+ || (rc = gnutls_x509_crt_set_activation_time(cert, now = time(NULL)))
+- || (rc = gnutls_x509_crt_set_expiration_time(cert, (long)2 * 60 * 60)) /* 2 hour */
++ || (rc = gnutls_x509_crt_set_expiration_time(cert, now + (long)2 * 60 * 60)) /* 2 hour */
+ || (rc = gnutls_x509_crt_set_key(cert, pkey))
+
+ || (rc = gnutls_x509_crt_set_dn_by_oid(cert,
+ GNUTLS_OID_X520_COUNTRY_NAME, 0, "UK", 2))
+ || (rc = gnutls_x509_crt_set_dn_by_oid(cert,
diff -Nru exim4-4.96/debian/patches/series exim4-4.96/debian/patches/series
--- exim4-4.96/debian/patches/series 2023-07-02 14:54:58.000000000 +0200
+++ exim4-4.96/debian/patches/series 2023-08-16 15:10:05.000000000 +0200
@@ -33,4 +33,10 @@
75_66-Fix-crash-in-expansions.patch
75_68-Fix-srs_encode-.-for-mod-1024-day-zero.patch
75_70-Fix-variable-initialisation-in-smtp-transport.-Bug-2.patch
+75_74-Cancel-early-pipe-on-an-observed-advertising-change.patch
+75_76-Expansions-disallow-UTF-16-surrogates-from-utf8clean.patch
+75_77-GnuTLS-fix-crash-with-tls_dhparam-none.patch
+75_78-Fix-free-of-value-after-run.patch
+75_79-Fix-recipients-expansion-when-used-within-run.-.-Bug.patch
+75_82-GnuTLS-fix-autogen-cert-expiry-date.-Bug-3014.patch
90_localscan_dlopen.dpatch
Reply to: