mirror of
https://git.FreeBSD.org/ports.git
synced 2024-10-18 19:49:40 +00:00
mail/exim: fix update to 4.96 by adding missing patches
PR: 265098 Reported by: David Siebuerger <drs-freebsd@sieborger.nom.za>
This commit is contained in:
parent
fe2317c01a
commit
0034826752
@ -0,0 +1,57 @@
|
||||
From e7ec503729970a03d4509921342bc81313976126 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Tue, 12 Jul 2022 22:14:04 +0100
|
||||
Subject: [PATCH] Fix exit on attempt to rewrite a malformed address. Bug 2903
|
||||
|
||||
---
|
||||
doc/ChangeLog | 5 +
|
||||
src/rewrite.c | 9 +-
|
||||
test/confs/0471 | 7 +
|
||||
test/log/0471 | 5 +
|
||||
test/scripts/0000-Basic/0471 | 4 +-
|
||||
test/stderr/0471 | 245 ++++++++++++++++++++++++++++++++++-
|
||||
6 files changed, 267 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -1,9 +1,14 @@
|
||||
This document describes *changes* to previous versions, that might
|
||||
affect Exim's operation, with an unchanged configuration file. For new
|
||||
options, and new features, see the NewStuff file next to this ChangeLog.
|
||||
|
||||
+JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
|
||||
+ Make the rewrite never match and keep the logging. Trust the
|
||||
+ admin to be using verify=header-syntax (to actually reject the message).
|
||||
+
|
||||
+
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
JH/01 Move the wait-for-next-tick (needed for unique messmage IDs) from
|
||||
after reception to before a subsequent reception. This should
|
||||
--- a/src/rewrite.c
|
||||
+++ b/src/rewrite.c
|
||||
@@ -493,19 +493,18 @@
|
||||
empty address, overlong addres. Sometimes the result matters, sometimes not.
|
||||
It seems this function is called for *any* header we see. */
|
||||
|
||||
if (!recipient)
|
||||
{
|
||||
- /* Handle unparesable addresses in the header. Slightly ugly because a
|
||||
+ /* Log unparesable addresses in the header. Slightly ugly because a
|
||||
null output from the extract can also result from a header without an
|
||||
- address, "To: undisclosed recpients:;" being the classic case. */
|
||||
+ address, "To: undisclosed recpients:;" being the classic case. Ignore
|
||||
+ this one and carry on. */
|
||||
|
||||
if ((rewrite_rules || routed_old) && Ustrcmp(errmess, "empty address") != 0)
|
||||
- {
|
||||
log_write(0, LOG_MAIN, "rewrite: %s", errmess);
|
||||
- exim_exit(EXIT_FAILURE);
|
||||
- }
|
||||
+
|
||||
loop_reset_point = store_reset(loop_reset_point);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If routed_old is not NULL, this is a rewrite caused by a router,
|
@ -0,0 +1,25 @@
|
||||
From 93c722ce0549360af68269f088f4e59ed8fc130e Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Sun, 7 Aug 2022 17:00:27 +0100
|
||||
Subject: [PATCH] SPF: fix memory accounting for error case
|
||||
|
||||
---
|
||||
src/spf.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/spf.c b/src/spf.c
|
||||
index db6eea3a8..a8c0f75c4 100644
|
||||
--- a/src/spf.c
|
||||
+++ b/src/spf.c
|
||||
@@ -204,7 +204,7 @@ spf_nxdomain = SPF_dns_rr_new_init(spf_dns_server,
|
||||
"", ns_t_any, 24 * 60 * 60, HOST_NOT_FOUND);
|
||||
if (!spf_nxdomain)
|
||||
{
|
||||
- free(spf_dns_server);
|
||||
+ store_free(spf_dns_server);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,193 @@
|
||||
From 4e9ed49f8f12eb331b29bd5b6dc3693c520fddc2 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Wed, 31 Aug 2022 15:37:40 +0100
|
||||
Subject: [PATCH] Fix $regex<n> use-after-free. Bug 2915
|
||||
|
||||
---
|
||||
doc/ChangeLog | 8 +++++++-
|
||||
src/exim.c | 4 +---
|
||||
src/expand.c | 2 +-
|
||||
src/functions.h | 1 +
|
||||
src/globals.c | 2 +-
|
||||
src/regex.c | 29 ++++++++++++++++++-----------
|
||||
src/smtp_in.c | 2 ++
|
||||
7 files changed, 55 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -4,15 +4,21 @@
|
||||
|
||||
JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
|
||||
Make the rewrite never match and keep the logging. Trust the
|
||||
admin to be using verify=header-syntax (to actually reject the message).
|
||||
|
||||
+JH/08 Bug 2915: Fix use-after-free for $regex<n> variables. Previously when
|
||||
+ more than one message arrived in a single connection a reference from
|
||||
+ the earlier message could be re-used. Often a sigsegv resulted.
|
||||
+ These variables were introduced in Exim 4.87.
|
||||
+ Debug help from Graeme Fowler.
|
||||
+
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
-JH/01 Move the wait-for-next-tick (needed for unique messmage IDs) from
|
||||
+JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
|
||||
after reception to before a subsequent reception. This should
|
||||
mean slightly faster delivery, and also confirmation of reception
|
||||
to senders.
|
||||
|
||||
JH/02 Move from using the pcre library to pcre2. The former is no longer
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -1999,12 +1999,10 @@
|
||||
|
||||
regex_whitelisted_macro =
|
||||
regex_must_compile(US"^[A-Za-z0-9_/.-]*$", FALSE, TRUE);
|
||||
#endif
|
||||
|
||||
-for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
-
|
||||
/* If the program is called as "mailq" treat it as equivalent to "exim -bp";
|
||||
this seems to be a generally accepted convention, since one finds symbolic
|
||||
links called "mailq" in standard OS configurations. */
|
||||
|
||||
if ((namelen == 5 && Ustrcmp(argv[0], "mailq") == 0) ||
|
||||
@@ -6082,11 +6080,11 @@
|
||||
callout_address = NULL;
|
||||
sending_ip_address = NULL;
|
||||
deliver_localpart_data = deliver_domain_data =
|
||||
recipient_data = sender_data = NULL;
|
||||
acl_var_m = NULL;
|
||||
- for(int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
+ regex_vars_clear();
|
||||
|
||||
store_reset(reset_point);
|
||||
}
|
||||
|
||||
exim_exit(EXIT_SUCCESS); /* Never returns */
|
||||
--- a/src/expand.c
|
||||
+++ b/src/expand.c
|
||||
@@ -1871,11 +1871,11 @@
|
||||
{
|
||||
tree_node * node = tree_search(router_var, name + 2);
|
||||
return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
|
||||
}
|
||||
|
||||
-/* Handle $auth<n> variables. */
|
||||
+/* Handle $auth<n>, $regex<n> variables. */
|
||||
|
||||
if (Ustrncmp(name, "auth", 4) == 0)
|
||||
{
|
||||
uschar *endptr;
|
||||
int n = Ustrtoul(name + 4, &endptr, 10);
|
||||
--- a/src/functions.h
|
||||
+++ b/src/functions.h
|
||||
@@ -436,10 +436,11 @@
|
||||
extern int regex(const uschar **);
|
||||
#endif
|
||||
extern BOOL regex_match(const pcre2_code *, const uschar *, int, uschar **);
|
||||
extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, int);
|
||||
extern const pcre2_code *regex_must_compile(const uschar *, BOOL, BOOL);
|
||||
+extern void regex_vars_clear(void);
|
||||
extern void retry_add_item(address_item *, uschar *, int);
|
||||
extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL,
|
||||
uschar **, uschar **);
|
||||
extern retry_config *retry_find_config(const uschar *, const uschar *, int, int);
|
||||
extern BOOL retry_ultimate_address_timeout(uschar *, const uschar *,
|
||||
--- a/src/globals.c
|
||||
+++ b/src/globals.c
|
||||
@@ -1313,11 +1313,11 @@
|
||||
#ifndef DISABLE_PIPE_CONNECT
|
||||
const pcre2_code *regex_EARLY_PIPE = NULL;
|
||||
#endif
|
||||
const pcre2_code *regex_ismsgid = NULL;
|
||||
const pcre2_code *regex_smtp_code = NULL;
|
||||
-const uschar *regex_vars[REGEX_VARS];
|
||||
+const uschar *regex_vars[REGEX_VARS] = { 0 };;
|
||||
#ifdef WHITELIST_D_MACROS
|
||||
const pcre2_code *regex_whitelisted_macro = NULL;
|
||||
#endif
|
||||
#ifdef WITH_CONTENT_SCAN
|
||||
uschar *regex_match_string = NULL;
|
||||
--- a/src/regex.c
|
||||
+++ b/src/regex.c
|
||||
@@ -94,22 +94,32 @@
|
||||
}
|
||||
pcre2_match_data_free(md);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
+
|
||||
+/* reset expansion variables */
|
||||
+void
|
||||
+regex_vars_clear(void)
|
||||
+{
|
||||
+regex_match_string = NULL;
|
||||
+for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
int
|
||||
-regex(const uschar **listptr)
|
||||
+regex(const uschar ** listptr)
|
||||
{
|
||||
unsigned long mbox_size;
|
||||
-FILE *mbox_file;
|
||||
-pcre_list *re_list_head;
|
||||
-uschar *linebuffer;
|
||||
+FILE * mbox_file;
|
||||
+pcre_list * re_list_head;
|
||||
+uschar * linebuffer;
|
||||
long f_pos = 0;
|
||||
int ret = FAIL;
|
||||
|
||||
-/* reset expansion variable */
|
||||
-regex_match_string = NULL;
|
||||
+regex_vars_clear();
|
||||
|
||||
if (!mime_stream) /* We are in the DATA ACL */
|
||||
{
|
||||
if (!(mbox_file = spool_mbox(&mbox_size, NULL, NULL)))
|
||||
{ /* error while spooling */
|
||||
@@ -167,18 +177,17 @@
|
||||
|
||||
|
||||
int
|
||||
mime_regex(const uschar **listptr)
|
||||
{
|
||||
-pcre_list *re_list_head = NULL;
|
||||
-FILE *f;
|
||||
-uschar *mime_subject = NULL;
|
||||
+pcre_list * re_list_head = NULL;
|
||||
+FILE * f;
|
||||
+uschar * mime_subject = NULL;
|
||||
int mime_subject_len = 0;
|
||||
int ret;
|
||||
|
||||
-/* reset expansion variable */
|
||||
-regex_match_string = NULL;
|
||||
+regex_vars_clear();
|
||||
|
||||
/* precompile our regexes */
|
||||
if (!(re_list_head = compile(*listptr)))
|
||||
return FAIL; /* no regexes -> nothing to do */
|
||||
|
||||
--- a/src/smtp_in.c
|
||||
+++ b/src/smtp_in.c
|
||||
@@ -2155,12 +2155,14 @@
|
||||
prdr_requested = FALSE;
|
||||
#endif
|
||||
#ifdef SUPPORT_I18N
|
||||
message_smtputf8 = FALSE;
|
||||
#endif
|
||||
+regex_vars_clear();
|
||||
body_linecount = body_zerocount = 0;
|
||||
|
||||
+lookup_value = NULL; /* Can be set by ACL */
|
||||
sender_rate = sender_rate_limit = sender_rate_period = NULL;
|
||||
ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */
|
||||
/* Note that ratelimiters_conn persists across resets. */
|
||||
|
||||
/* Reset message ACL variables */
|
@ -0,0 +1,58 @@
|
||||
From d8ecc7bf97934a1e2244788c610c958cacd740bd Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Wed, 31 Aug 2022 17:03:37 +0100
|
||||
Subject: [PATCH 1/3] Fix non-WITH_CONTENT_SCAN build.
|
||||
|
||||
Broken-by: 4e9ed49f8f
|
||||
---
|
||||
src/exim.c | 11 +++++++++++
|
||||
src/regex.c | 10 ----------
|
||||
2 files changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -1677,10 +1677,21 @@
|
||||
if ((s = expand_string(big_buffer))) printf("%s\n", CS s);
|
||||
else printf("Failed: %s\n", expand_string_message);
|
||||
}
|
||||
|
||||
|
||||
+/* reset regex expansion variables */
|
||||
+void
|
||||
+regex_vars_clear(void)
|
||||
+{
|
||||
+regex_match_string = NULL;
|
||||
+for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
|
||||
/*************************************************
|
||||
* Entry point and high-level code *
|
||||
*************************************************/
|
||||
|
||||
--- a/src/regex.c
|
||||
+++ b/src/regex.c
|
||||
@@ -95,20 +95,10 @@
|
||||
pcre2_match_data_free(md);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
|
||||
-/* reset expansion variables */
|
||||
-void
|
||||
-regex_vars_clear(void)
|
||||
-{
|
||||
-regex_match_string = NULL;
|
||||
-for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-
|
||||
int
|
||||
regex(const uschar ** listptr)
|
||||
{
|
||||
unsigned long mbox_size;
|
||||
FILE * mbox_file;
|
@ -0,0 +1,135 @@
|
||||
From 158dff9936e36a2d31d037d3988b9353458d6471 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Wed, 31 Aug 2022 17:17:59 +0100
|
||||
Subject: [PATCH 2/3] Fix non-WITH_CONTENT_SCAN build (2)
|
||||
|
||||
Broken-by: d8ecc7bf97
|
||||
---
|
||||
src/exim.c | 13 +------------
|
||||
src/functions.h | 2 +-
|
||||
src/globals.h | 2 +-
|
||||
src/regex.c | 10 ++++++++++
|
||||
src/smtp_in.c | 2 ++
|
||||
5 files changed, 15 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -1677,21 +1677,10 @@
|
||||
if ((s = expand_string(big_buffer))) printf("%s\n", CS s);
|
||||
else printf("Failed: %s\n", expand_string_message);
|
||||
}
|
||||
|
||||
|
||||
-/* reset regex expansion variables */
|
||||
-void
|
||||
-regex_vars_clear(void)
|
||||
-{
|
||||
-regex_match_string = NULL;
|
||||
-for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
/*************************************************
|
||||
* Entry point and high-level code *
|
||||
*************************************************/
|
||||
|
||||
@@ -6085,17 +6074,17 @@
|
||||
deliver_domain_orig = NULL;
|
||||
deliver_host = deliver_host_address = NULL;
|
||||
dnslist_domain = dnslist_matched = NULL;
|
||||
#ifdef WITH_CONTENT_SCAN
|
||||
malware_name = NULL;
|
||||
+ regex_vars_clear();
|
||||
#endif
|
||||
callout_address = NULL;
|
||||
sending_ip_address = NULL;
|
||||
deliver_localpart_data = deliver_domain_data =
|
||||
recipient_data = sender_data = NULL;
|
||||
acl_var_m = NULL;
|
||||
- regex_vars_clear();
|
||||
|
||||
store_reset(reset_point);
|
||||
}
|
||||
|
||||
exim_exit(EXIT_SUCCESS); /* Never returns */
|
||||
--- a/src/functions.h
|
||||
+++ b/src/functions.h
|
||||
@@ -432,15 +432,15 @@
|
||||
extern BOOL receive_msg(BOOL);
|
||||
extern int_eximarith_t receive_statvfs(BOOL, int *);
|
||||
extern void receive_swallow_smtp(void);
|
||||
#ifdef WITH_CONTENT_SCAN
|
||||
extern int regex(const uschar **);
|
||||
+extern void regex_vars_clear(void);
|
||||
#endif
|
||||
extern BOOL regex_match(const pcre2_code *, const uschar *, int, uschar **);
|
||||
extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, int);
|
||||
extern const pcre2_code *regex_must_compile(const uschar *, BOOL, BOOL);
|
||||
-extern void regex_vars_clear(void);
|
||||
extern void retry_add_item(address_item *, uschar *, int);
|
||||
extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL,
|
||||
uschar **, uschar **);
|
||||
extern retry_config *retry_find_config(const uschar *, const uschar *, int, int);
|
||||
extern BOOL retry_ultimate_address_timeout(uschar *, const uschar *,
|
||||
--- a/src/globals.h
|
||||
+++ b/src/globals.h
|
||||
@@ -895,16 +895,16 @@
|
||||
#ifndef DISABLE_PIPE_CONNECT
|
||||
extern const pcre2_code *regex_EARLY_PIPE; /* For recognizing PIPE_CONNCT */
|
||||
#endif
|
||||
extern const pcre2_code *regex_ismsgid; /* Compiled r.e. for message ID */
|
||||
extern const pcre2_code *regex_smtp_code; /* For recognizing SMTP codes */
|
||||
-extern const uschar *regex_vars[]; /* $regexN variables */
|
||||
#ifdef WHITELIST_D_MACROS
|
||||
extern const pcre2_code *regex_whitelisted_macro; /* For -D macro values */
|
||||
#endif
|
||||
#ifdef WITH_CONTENT_SCAN
|
||||
extern uschar *regex_match_string; /* regex that matched a line (regex ACL condition) */
|
||||
+extern const uschar *regex_vars[];
|
||||
#endif
|
||||
extern int remote_delivery_count; /* Number of remote addresses */
|
||||
extern int remote_max_parallel; /* Maximum parallel delivery */
|
||||
extern uschar *remote_sort_domains; /* Remote domain sorting order */
|
||||
extern retry_config *retries; /* Chain of retry config information */
|
||||
--- a/src/regex.c
|
||||
+++ b/src/regex.c
|
||||
@@ -95,10 +95,20 @@
|
||||
pcre2_match_data_free(md);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
|
||||
+/* reset expansion variables */
|
||||
+void
|
||||
+regex_vars_clear(void)
|
||||
+{
|
||||
+regex_match_string = NULL;
|
||||
+for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
int
|
||||
regex(const uschar ** listptr)
|
||||
{
|
||||
unsigned long mbox_size;
|
||||
FILE * mbox_file;
|
||||
--- a/src/smtp_in.c
|
||||
+++ b/src/smtp_in.c
|
||||
@@ -2155,11 +2155,13 @@
|
||||
prdr_requested = FALSE;
|
||||
#endif
|
||||
#ifdef SUPPORT_I18N
|
||||
message_smtputf8 = FALSE;
|
||||
#endif
|
||||
+#ifdef WITH_CONTENT_SCAN
|
||||
regex_vars_clear();
|
||||
+#endif
|
||||
body_linecount = body_zerocount = 0;
|
||||
|
||||
lookup_value = NULL; /* Can be set by ACL */
|
||||
sender_rate = sender_rate_limit = sender_rate_period = NULL;
|
||||
ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */
|
@ -0,0 +1,45 @@
|
||||
From 32da6327e434e986a18b75a84f2d8c687ba14619 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Thu, 1 Sep 2022 15:54:35 +0100
|
||||
Subject: [PATCH 3/3] Fix non-WITH_CONTENT_SCAN build (3)
|
||||
|
||||
Broken-by: d8ecc7bf97
|
||||
---
|
||||
src/expand.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/expand.c b/src/expand.c
|
||||
index 89de56255..831ca2b75 100644
|
||||
--- a/src/expand.c
|
||||
+++ b/src/expand.c
|
||||
@@ -1869,6 +1869,7 @@ if (Ustrncmp(name, "auth", 4) == 0)
|
||||
if (!*endptr && n != 0 && n <= AUTH_VARS)
|
||||
return auth_vars[n-1] ? auth_vars[n-1] : US"";
|
||||
}
|
||||
+#ifdef WITH_CONTENT_SCAN
|
||||
else if (Ustrncmp(name, "regex", 5) == 0)
|
||||
{
|
||||
uschar *endptr;
|
||||
@@ -1876,6 +1877,7 @@ else if (Ustrncmp(name, "regex", 5) == 0)
|
||||
if (!*endptr && n != 0 && n <= REGEX_VARS)
|
||||
return regex_vars[n-1] ? regex_vars[n-1] : US"";
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* For all other variables, search the table */
|
||||
|
||||
@@ -8715,9 +8717,11 @@ assert_variable_notin() treats as const, so deconst is safe. */
|
||||
for (int i = 0; i < AUTH_VARS; i++) if (auth_vars[i])
|
||||
assert_variable_notin(US"auth<n>", US auth_vars[i], &e);
|
||||
|
||||
+#ifdef WITH_CONTENT_SCAN
|
||||
/* check regex<n> variables. assert_variable_notin() treats as const. */
|
||||
for (int i = 0; i < REGEX_VARS; i++) if (regex_vars[i])
|
||||
assert_variable_notin(US"regex<n>", US regex_vars[i], &e);
|
||||
+#endif
|
||||
|
||||
/* check known-name variables */
|
||||
for (var_entry * v = var_table; v < var_table + var_table_size; v++)
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,114 @@
|
||||
From ece23f05d6a430a461a75639197271c23f6858ec Mon Sep 17 00:00:00 2001
|
||||
From: Jasen Betts <jasen@xnet.co.nz>
|
||||
Date: Fri, 30 Sep 2022 13:49:41 +0100
|
||||
Subject: [PATCH] GnuTLS: fix for clients offering no TLS extensions
|
||||
|
||||
---
|
||||
doc/ChangeLog | 3 +++
|
||||
src/tls-gnu.c | 3 ++-
|
||||
src/tls-openssl.c | 39 +++++++++++++++---------------
|
||||
test/confs/2091 | 1 +
|
||||
test/log/2091 | 3 +++
|
||||
test/scripts/2090-GnuTLS-ALPN/2091 | 19 +++++++++++++++
|
||||
test/stdout/2091 | 21 ++++++++++++++++
|
||||
7 files changed, 68 insertions(+), 21 deletions(-)
|
||||
create mode 120000 test/confs/2091
|
||||
create mode 100644 test/log/2091
|
||||
create mode 100644 test/scripts/2090-GnuTLS-ALPN/2091
|
||||
create mode 100644 test/stdout/2091
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -10,10 +10,14 @@
|
||||
more than one message arrived in a single connection a reference from
|
||||
the earlier message could be re-used. Often a sigsegv resulted.
|
||||
These variables were introduced in Exim 4.87.
|
||||
Debug help from Graeme Fowler.
|
||||
|
||||
+JH/10 GnuTLS: fix for (IOT?) clients offering no TLS extensions at all.
|
||||
+ Find and fix by Jasen Betts.
|
||||
+
|
||||
+
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
|
||||
--- a/src/tls-gnu.c
|
||||
+++ b/src/tls-gnu.c
|
||||
@@ -1130,12 +1130,13 @@
|
||||
static int
|
||||
tls_server_clienthello_cb(gnutls_session_t session, unsigned int htype,
|
||||
unsigned when, unsigned int incoming, const gnutls_datum_t * msg)
|
||||
{
|
||||
/* Call fn for each extension seen. 3.6.3 onwards */
|
||||
-return gnutls_ext_raw_parse(NULL, tls_server_clienthello_ext, msg,
|
||||
+int rc = gnutls_ext_raw_parse(NULL, tls_server_clienthello_ext, msg,
|
||||
GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
|
||||
+return rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE ? 0 : rc;
|
||||
}
|
||||
|
||||
|
||||
# ifdef notdef_crashes
|
||||
/* Make a note that we saw a status-response */
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -940,40 +940,39 @@
|
||||
|
||||
Returns: nothing
|
||||
*/
|
||||
|
||||
static void
|
||||
-info_callback(SSL *s, int where, int ret)
|
||||
+info_callback(SSL * s, int where, int ret)
|
||||
{
|
||||
DEBUG(D_tls)
|
||||
{
|
||||
- const uschar * str;
|
||||
+ gstring * g = NULL;
|
||||
|
||||
- if (where & SSL_ST_CONNECT)
|
||||
- str = US"SSL_connect";
|
||||
- else if (where & SSL_ST_ACCEPT)
|
||||
- str = US"SSL_accept";
|
||||
- else
|
||||
- str = US"SSL info (undefined)";
|
||||
+ if (where & SSL_ST_CONNECT) g = string_append_listele(g, ',', US"SSL_connect");
|
||||
+ if (where & SSL_ST_ACCEPT) g = string_append_listele(g, ',', US"SSL_accept");
|
||||
+ if (where & SSL_CB_LOOP) g = string_append_listele(g, ',', US"state_chg");
|
||||
+ if (where & SSL_CB_EXIT) g = string_append_listele(g, ',', US"hshake_exit");
|
||||
+ if (where & SSL_CB_READ) g = string_append_listele(g, ',', US"read");
|
||||
+ if (where & SSL_CB_WRITE) g = string_append_listele(g, ',', US"write");
|
||||
+ if (where & SSL_CB_ALERT) g = string_append_listele(g, ',', US"alert");
|
||||
+ if (where & SSL_CB_HANDSHAKE_START) g = string_append_listele(g, ',', US"hshake_start");
|
||||
+ if (where & SSL_CB_HANDSHAKE_DONE) g = string_append_listele(g, ',', US"hshake_done");
|
||||
|
||||
if (where & SSL_CB_LOOP)
|
||||
- debug_printf("%s: %s\n", str, SSL_state_string_long(s));
|
||||
+ debug_printf("SSL %s: %s\n", g->s, SSL_state_string_long(s));
|
||||
else if (where & SSL_CB_ALERT)
|
||||
- debug_printf("SSL3 alert %s:%s:%s\n",
|
||||
- str = where & SSL_CB_READ ? US"read" : US"write",
|
||||
+ debug_printf("SSL %s %s:%s\n", g->s,
|
||||
SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
|
||||
else if (where & SSL_CB_EXIT)
|
||||
{
|
||||
- if (ret == 0)
|
||||
- debug_printf("%s: failed in %s\n", str, SSL_state_string_long(s));
|
||||
- else if (ret < 0)
|
||||
- debug_printf("%s: error in %s\n", str, SSL_state_string_long(s));
|
||||
+ if (ret <= 0)
|
||||
+ debug_printf("SSL %s: %s in %s\n", g->s,
|
||||
+ ret == 0 ? "failed" : "error", SSL_state_string_long(s));
|
||||
}
|
||||
- else if (where & SSL_CB_HANDSHAKE_START)
|
||||
- debug_printf("%s: hshake start: %s\n", str, SSL_state_string_long(s));
|
||||
- else if (where & SSL_CB_HANDSHAKE_DONE)
|
||||
- debug_printf("%s: hshake done: %s\n", str, SSL_state_string_long(s));
|
||||
+ else if (where & (SSL_CB_HANDSHAKE_START | SSL_CB_HANDSHAKE_DONE))
|
||||
+ debug_printf("SSL %s: %s\n", g->s, SSL_state_string_long(s));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_HAVE_KEYLOG_CB
|
||||
static void
|
@ -0,0 +1,88 @@
|
||||
From 1561c5d88b3a23a4348d8e3c1ce28554fcbcfe46 Mon Sep 17 00:00:00 2001
|
||||
From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de>
|
||||
Date: Sat, 15 Oct 2022 19:30:58 +0200
|
||||
Subject: [PATCH 1/2] Fix: Build with libopendmarc 1.4.x (fixes 2728)
|
||||
|
||||
---
|
||||
doc/ChangeLog | 3 +++
|
||||
src/EDITME | 7 +++++--
|
||||
src/config.h.defaults | 1 +
|
||||
src/dmarc.c | 7 ++++++-
|
||||
4 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -13,10 +13,13 @@
|
||||
Debug help from Graeme Fowler.
|
||||
|
||||
JH/10 GnuTLS: fix for (IOT?) clients offering no TLS extensions at all.
|
||||
Find and fix by Jasen Betts.
|
||||
|
||||
+HS/01 Bug 2728: Introduce EDITME option "DMARC_API" to work around incompatible
|
||||
+ API changes in libopendmarc.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/EDITME
|
||||
+++ b/src/EDITME
|
||||
@@ -600,18 +600,21 @@
|
||||
|
||||
# EXPERIMENTAL_DCC=yes
|
||||
|
||||
# Uncomment the following line to add DMARC checking capability, implemented
|
||||
# using libopendmarc libraries. You must have SPF and DKIM support enabled also.
|
||||
-# Library version libopendmarc-1.4.1-1.fc33.x86_64 (on Fedora 33) is known broken;
|
||||
-# 1.3.2-3 works. I seems that the OpenDMARC project broke their API.
|
||||
# SUPPORT_DMARC=yes
|
||||
# CFLAGS += -I/usr/local/include
|
||||
# LDFLAGS += -lopendmarc
|
||||
# Uncomment the following if you need to change the default. You can
|
||||
# override it at runtime (main config option dmarc_tld_file)
|
||||
# DMARC_TLD_FILE=/etc/exim/opendmarc.tlds
|
||||
+#
|
||||
+# Library version libopendmarc-1.4.1-1.fc33.x86_64 (on Fedora 33) is known broken;
|
||||
+# 1.3.2-3 works. It seems that the OpenDMARC project broke their API.
|
||||
+# Use this option if you need to build with an old library (1.3.x)
|
||||
+# DMARC_API=100300
|
||||
|
||||
# Uncomment the following line to add ARC (Authenticated Received Chain)
|
||||
# support. You must have SPF and DKIM support enabled also.
|
||||
# EXPERIMENTAL_ARC=yes
|
||||
|
||||
--- a/src/config.h.defaults
|
||||
+++ b/src/config.h.defaults
|
||||
@@ -148,10 +148,11 @@
|
||||
#define STRING_SPRINTF_BUFFER_SIZE (8192 * 4)
|
||||
|
||||
#define SUPPORT_CRYPTEQ
|
||||
#define SUPPORT_DANE
|
||||
#define SUPPORT_DMARC
|
||||
+#define DMARC_API 100400
|
||||
#define DMARC_TLD_FILE "/etc/exim/opendmarc.tlds"
|
||||
#define SUPPORT_I18N
|
||||
#define SUPPORT_I18N_2008
|
||||
#define SUPPORT_MAILDIR
|
||||
#define SUPPORT_MAILSTORE
|
||||
--- a/src/dmarc.c
|
||||
+++ b/src/dmarc.c
|
||||
@@ -457,11 +457,16 @@
|
||||
dkim_result = vs == PDKIM_VERIFY_PASS ? DMARC_POLICY_DKIM_OUTCOME_PASS :
|
||||
vs == PDKIM_VERIFY_FAIL ? DMARC_POLICY_DKIM_OUTCOME_FAIL :
|
||||
vs == PDKIM_VERIFY_INVALID ? DMARC_POLICY_DKIM_OUTCOME_TMPFAIL :
|
||||
DMARC_POLICY_DKIM_OUTCOME_NONE;
|
||||
libdm_status = opendmarc_policy_store_dkim(dmarc_pctx, US sig->domain,
|
||||
- dkim_result, US"");
|
||||
+/* The opendmarc project broke its API in a way we can't detect * easily.
|
||||
+ * The EDITME provides a DMARC_API variable */
|
||||
+#if DMARC_API >= 100400
|
||||
+ sig->selector,
|
||||
+#endif
|
||||
+ dkim_result, US"");
|
||||
DEBUG(D_receive)
|
||||
debug_printf("DMARC adding DKIM sender domain = %s\n", sig->domain);
|
||||
if (libdm_status != DMARC_PARSE_OKAY)
|
||||
log_write(0, LOG_MAIN|LOG_PANIC,
|
||||
"failure to store dkim (%s) for DMARC: %s",
|
@ -0,0 +1,39 @@
|
||||
From 12fb3842f81bcbd4a4519d5728f2d7e0e3ca1445 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenz Brun <lorenz@brun.one>
|
||||
Date: Fri, 14 Oct 2022 21:02:51 +0200
|
||||
Subject: [PATCH 2/2] DMARC: fix use-after-free in dmarc_dns_lookup
|
||||
|
||||
This fixes a use-after-free in dmarc_dns_lookup where the result
|
||||
of dns_lookup in dnsa is freed before the required data is copied out.
|
||||
|
||||
Fixes: 9258363 ("DNS: explicit alloc/free of workspace")
|
||||
---
|
||||
src/dmarc.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/dmarc.c b/src/dmarc.c
|
||||
index ad0c26c91..53c2752ac 100644
|
||||
--- a/src/dmarc.c
|
||||
+++ b/src/dmarc.c
|
||||
@@ -226,16 +226,17 @@ dns_scan dnss;
|
||||
int rc = dns_lookup(dnsa, string_sprintf("_dmarc.%s", dom), T_TXT, NULL);
|
||||
|
||||
if (rc == DNS_SUCCEED)
|
||||
for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
|
||||
rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
|
||||
if (rr->type == T_TXT && rr->size > 3)
|
||||
{
|
||||
+ uschar *record = string_copyn_taint(US rr->data, rr->size, GET_TAINTED);
|
||||
store_free_dns_answer(dnsa);
|
||||
- return string_copyn_taint(US rr->data, rr->size, GET_TAINTED);
|
||||
+ return record;
|
||||
}
|
||||
store_free_dns_answer(dnsa);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 221321d2c51b83d1feced80ecd6c2fe33ec5456c Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Thu, 3 Nov 2022 20:08:25 +0000
|
||||
Subject: [PATCH 1/2] Fix daemon startup. Bug 2930
|
||||
|
||||
Broken-by: 7d5055276a
|
||||
---
|
||||
doc/ChangeLog | 4 ++++
|
||||
src/daemon.c | 8 ++++++--
|
||||
2 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -16,10 +16,14 @@
|
||||
Find and fix by Jasen Betts.
|
||||
|
||||
HS/01 Bug 2728: Introduce EDITME option "DMARC_API" to work around incompatible
|
||||
API changes in libopendmarc.
|
||||
|
||||
+JH/12 Bug 2930: Fix daemon startup. When started from any process apart from
|
||||
+ pid 1, in the normal "background daemon" mode, having to drop process-
|
||||
+ group leadership also lost track of needing to create listener sockets.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/daemon.c
|
||||
+++ b/src/daemon.c
|
||||
@@ -1744,19 +1744,23 @@
|
||||
{
|
||||
/* If the parent process of this one has pid == 1, we are re-initializing the
|
||||
daemon as the result of a SIGHUP. In this case, there is no need to do
|
||||
anything, because the controlling terminal has long gone. Otherwise, fork, in
|
||||
case current process is a process group leader (see 'man setsid' for an
|
||||
- explanation) before calling setsid(). */
|
||||
+ explanation) before calling setsid().
|
||||
+ All other forks want daemon_listen cleared. Rather than blow a register, jsut
|
||||
+ restore it here. */
|
||||
|
||||
if (getppid() != 1)
|
||||
{
|
||||
+ BOOL daemon_listen = f.daemon_listen;
|
||||
pid_t pid = exim_fork(US"daemon");
|
||||
if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
|
||||
"fork() failed when starting daemon: %s", strerror(errno));
|
||||
if (pid > 0) exit(EXIT_SUCCESS); /* in parent process, just exit */
|
||||
(void)setsid(); /* release controlling terminal */
|
||||
+ f.daemon_listen = daemon_listen;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are now in the disconnected, daemon process (unless debugging). Set up
|
||||
the listening sockets if required. */
|
||||
@@ -2090,11 +2094,11 @@
|
||||
{ /* found; append port to list */
|
||||
for (p = i2->log; *p; ) p++; /* end of existing string */
|
||||
if (*--p == '}') *p = '\0'; /* drop EOL */
|
||||
while (isdigit(*--p)) ; /* char before port */
|
||||
|
||||
- i2->log = *p == ':' /* no list yet? */
|
||||
+ i2->log = *p == ':' /* no list yet? { */
|
||||
? string_sprintf("%.*s{%s,%d}",
|
||||
(int)(p - i2->log + 1), i2->log, p+1, ipa->port)
|
||||
: string_sprintf("%s,%d}", i2->log, ipa->port);
|
||||
ipa->log = NULL;
|
||||
break;
|
@ -0,0 +1,45 @@
|
||||
From 6b331d5834d12bdda21857cd6fffac17038ce3c7 Mon Sep 17 00:00:00 2001
|
||||
From: Ruben Jenster <r.jenster@drachenfels.de>
|
||||
Date: Thu, 3 Nov 2022 21:38:15 +0000
|
||||
Subject: [PATCH 2/2] Fix $reccipients after ${run...}. Bug 2929
|
||||
|
||||
Broken-by: cfe6acff2d
|
||||
---
|
||||
doc/ChangeLog | 3 +++
|
||||
src/transport.c | 3 ++-
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -20,10 +20,13 @@
|
||||
|
||||
JH/12 Bug 2930: Fix daemon startup. When started from any process apart from
|
||||
pid 1, in the normal "background daemon" mode, having to drop process-
|
||||
group leadership also lost track of needing to create listener sockets.
|
||||
|
||||
+JH/13 Bug 2929: Fix using $recipients after ${run...}. A change made for 4.96
|
||||
+ resulted in the variable appearing empty. Find and fix by Ruben Jenster.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/transport.c
|
||||
+++ b/src/transport.c
|
||||
@@ -2342,13 +2342,14 @@
|
||||
/* Handle normal expansion string */
|
||||
|
||||
else
|
||||
{
|
||||
const uschar *expanded_arg;
|
||||
+ BOOL enable_dollar_recipients_g = f.enable_dollar_recipients;
|
||||
f.enable_dollar_recipients = allow_dollar_recipients;
|
||||
expanded_arg = expand_cstring(argv[i]);
|
||||
- f.enable_dollar_recipients = FALSE;
|
||||
+ f.enable_dollar_recipients = enable_dollar_recipients_g;
|
||||
|
||||
if (!expanded_arg)
|
||||
{
|
||||
uschar *msg = string_sprintf("Expansion of \"%s\" "
|
||||
"from command \"%s\" in %s failed: %s",
|
@ -0,0 +1,79 @@
|
||||
From e63825824cc406c160ccbf2b154c5d81b168604a Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Fri, 11 Nov 2022 00:05:59 +0000
|
||||
Subject: [PATCH 1/2] Fix regext substring capture variables for null matches.
|
||||
Bug 2933
|
||||
|
||||
broken-by: 59d66fdc13f0
|
||||
---
|
||||
doc/ChangeLog | 5 +++++
|
||||
src/exim.c | 2 ++
|
||||
src/malware.c | 3 +++
|
||||
src/regex.c | 2 +-
|
||||
4 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -22,10 +22,15 @@
|
||||
pid 1, in the normal "background daemon" mode, having to drop process-
|
||||
group leadership also lost track of needing to create listener sockets.
|
||||
|
||||
JH/13 Bug 2929: Fix using $recipients after ${run...}. A change made for 4.96
|
||||
resulted in the variable appearing empty. Find and fix by Ruben Jenster.
|
||||
+
|
||||
+JH/14 Bug 2933: Fix regex substring match variables for null matches. Since 4.96
|
||||
+ a capture group which obtained no text (eg. "(abc)*" matching zero
|
||||
+ occurrences) could cause a segfault if the corresponding $<n> was
|
||||
+ expanded.
|
||||
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -167,10 +167,12 @@
|
||||
for (int matchnum = setup < 0 ? 0 : 1; matchnum < res; matchnum++)
|
||||
{
|
||||
PCRE2_SIZE len;
|
||||
pcre2_substring_get_bynumber(md, matchnum,
|
||||
(PCRE2_UCHAR **)&expand_nstring[expand_nmax], &len);
|
||||
+ if (!expand_nstring[expand_nmax])
|
||||
+ { expand_nstring[expand_nmax] = US""; len = 0; }
|
||||
expand_nlength[expand_nmax++] = (int)len;
|
||||
}
|
||||
expand_nmax--;
|
||||
}
|
||||
else if (res != PCRE2_ERROR_NOMATCH) DEBUG(D_any)
|
||||
--- a/src/malware.c
|
||||
+++ b/src/malware.c
|
||||
@@ -323,11 +323,14 @@
|
||||
int i = pcre2_match(cre, text, PCRE2_ZERO_TERMINATED, 0, 0, md, pcre_mtc_ctx);
|
||||
PCRE2_UCHAR * substr = NULL;
|
||||
PCRE2_SIZE slen;
|
||||
|
||||
if (i >= 2) /* Got it */
|
||||
+ {
|
||||
pcre2_substring_get_bynumber(md, 1, &substr, &slen);
|
||||
+ if (!substr) substr = US"";
|
||||
+ }
|
||||
return US substr;
|
||||
}
|
||||
|
||||
static const pcre2_code *
|
||||
m_pcre_nextinlist(const uschar ** list, int * sep,
|
||||
--- a/src/regex.c
|
||||
+++ b/src/regex.c
|
||||
@@ -84,11 +84,11 @@
|
||||
for (int nn = 1; nn < n; nn++)
|
||||
{
|
||||
PCRE2_UCHAR * cstr;
|
||||
PCRE2_SIZE cslen;
|
||||
pcre2_substring_get_bynumber(md, nn, &cstr, &cslen);
|
||||
- regex_vars[nn-1] = CUS cstr;
|
||||
+ regex_vars[nn-1] = cstr ? CUS cstr : CUS"";
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
From 7ad1a2b2cc57b5f4bcb59186a9a8abcbed9f4f76 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Fri, 11 Nov 2022 18:22:00 +0000
|
||||
Subject: [PATCH 2/2] Fix regex substring capture variables for null matches
|
||||
(again). Bug 2933
|
||||
|
||||
Broken-by: 59d66fdc13f0
|
||||
---
|
||||
src/exim.c | 11 +++++------
|
||||
src/malware.c | 10 +++++-----
|
||||
src/regex.c | 8 ++++----
|
||||
test/aux-var-src/0383.F | 4 ++--
|
||||
test/log/0383 | 4 ++--
|
||||
test/mail/0383.CALLER | 8 ++++----
|
||||
test/scripts/0000-Basic/0002 | 2 ++
|
||||
test/stdout/0002 | 2 ++
|
||||
8 files changed, 26 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -160,20 +160,19 @@
|
||||
PCRE_EOPT | options, md, pcre_mtc_ctx);
|
||||
BOOL yield;
|
||||
|
||||
if ((yield = (res >= 0)))
|
||||
{
|
||||
+ PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
|
||||
res = pcre2_get_ovector_count(md);
|
||||
expand_nmax = setup < 0 ? 0 : setup + 1;
|
||||
for (int matchnum = setup < 0 ? 0 : 1; matchnum < res; matchnum++)
|
||||
{
|
||||
- PCRE2_SIZE len;
|
||||
- pcre2_substring_get_bynumber(md, matchnum,
|
||||
- (PCRE2_UCHAR **)&expand_nstring[expand_nmax], &len);
|
||||
- if (!expand_nstring[expand_nmax])
|
||||
- { expand_nstring[expand_nmax] = US""; len = 0; }
|
||||
- expand_nlength[expand_nmax++] = (int)len;
|
||||
+ int off = matchnum * 2;
|
||||
+ int len = ovec[off + 1] - ovec[off];
|
||||
+ expand_nstring[expand_nmax] = string_copyn(subject + ovec[off], len);
|
||||
+ expand_nlength[expand_nmax++] = len;
|
||||
}
|
||||
expand_nmax--;
|
||||
}
|
||||
else if (res != PCRE2_ERROR_NOMATCH) DEBUG(D_any)
|
||||
{
|
||||
--- a/src/malware.c
|
||||
+++ b/src/malware.c
|
||||
@@ -319,19 +319,19 @@
|
||||
uschar *
|
||||
m_pcre_exec(const pcre2_code * cre, uschar * text)
|
||||
{
|
||||
pcre2_match_data * md = pcre2_match_data_create(2, pcre_gen_ctx);
|
||||
int i = pcre2_match(cre, text, PCRE2_ZERO_TERMINATED, 0, 0, md, pcre_mtc_ctx);
|
||||
-PCRE2_UCHAR * substr = NULL;
|
||||
-PCRE2_SIZE slen;
|
||||
+uschar * substr = NULL;
|
||||
|
||||
if (i >= 2) /* Got it */
|
||||
{
|
||||
- pcre2_substring_get_bynumber(md, 1, &substr, &slen);
|
||||
- if (!substr) substr = US"";
|
||||
+ PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
|
||||
+ int len = ovec[3] - ovec[2];
|
||||
+ substr = string_copyn(text + ovec[2], len);
|
||||
}
|
||||
-return US substr;
|
||||
+return substr;
|
||||
}
|
||||
|
||||
static const pcre2_code *
|
||||
m_pcre_nextinlist(const uschar ** list, int * sep,
|
||||
char * listerr, uschar ** errstr)
|
||||
--- a/src/regex.c
|
||||
+++ b/src/regex.c
|
||||
@@ -81,14 +81,14 @@
|
||||
sizeof(regex_match_string_buffer)-1);
|
||||
regex_match_string = regex_match_string_buffer;
|
||||
|
||||
for (int nn = 1; nn < n; nn++)
|
||||
{
|
||||
- PCRE2_UCHAR * cstr;
|
||||
- PCRE2_SIZE cslen;
|
||||
- pcre2_substring_get_bynumber(md, nn, &cstr, &cslen);
|
||||
- regex_vars[nn-1] = cstr ? CUS cstr : CUS"";
|
||||
+ PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
|
||||
+ int off = nn * 2;
|
||||
+ int len = ovec[off + 1] - ovec[off];
|
||||
+ regex_vars[nn-1] = string_copyn(linebuffer + ovec[off], len);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
From 9ba47886c71d40edc99b026a99edee269d9c9c6f Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Sat, 12 Nov 2022 12:38:22 +0000
|
||||
Subject: [PATCH] Fix regex substring capture - commentary. Bug 2933
|
||||
|
||||
Broken-by (corrected): 22ed7a5295f1
|
||||
---
|
||||
src/exim.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/exim.c b/src/exim.c
|
||||
index 16c0184e0..625494ce4 100644
|
||||
--- a/src/exim.c
|
||||
+++ b/src/exim.c
|
||||
@@ -102,11 +102,13 @@ pcre_gen_mtc_ctx = pcre2_match_context_create(pcre_gen_ctx);
|
||||
* Execute regular expression and set strings *
|
||||
*************************************************/
|
||||
|
||||
/* This function runs a regular expression match, and sets up the pointers to
|
||||
the matched substrings. The matched strings are copied so the lifetime of
|
||||
-the subject is not a problem.
|
||||
+the subject is not a problem. Matched strings will have the same taint status
|
||||
+as the subject string (this is not a de-taint method, and must not be made so
|
||||
+given the support for wildcards in REs).
|
||||
|
||||
Arguments:
|
||||
re the compiled expression
|
||||
subject the subject string
|
||||
options additional PCRE options
|
||||
@@ -130,10 +132,15 @@ if ((yield = (res >= 0)))
|
||||
PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
|
||||
res = pcre2_get_ovector_count(md);
|
||||
expand_nmax = setup < 0 ? 0 : setup + 1;
|
||||
for (int matchnum = setup < 0 ? 0 : 1; matchnum < res; matchnum++)
|
||||
{
|
||||
+ /* Although PCRE2 has a pcre2_substring_get_bynumber() conveneience, it
|
||||
+ seems to return a bad pointer when a capture group had no data, eg. (.*)
|
||||
+ matching zero letters. So use the underlying ovec and hope (!) that the
|
||||
+ offsets are sane (including that case). Should we go further and range-
|
||||
+ check each one vs. the subject string length? */
|
||||
int off = matchnum * 2;
|
||||
int len = ovec[off + 1] - ovec[off];
|
||||
expand_nstring[expand_nmax] = string_copyn(subject + ovec[off], len);
|
||||
expand_nlength[expand_nmax++] = len;
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,232 @@
|
||||
From 7f65a63b60c6ea86db683ac00e221939f3bb1d47 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Tue, 25 Oct 2022 21:26:30 +0100
|
||||
Subject: [PATCH 1/2] OpenSSL: when preloading creds do the server certs before
|
||||
the OCSP proofs so that the latter can ve verified before loading
|
||||
|
||||
---
|
||||
src/tls-openssl.c | 113 ++++++++++++++++++++++--------------------
|
||||
1 file changed, 58 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/src/tls-openssl.c b/src/tls-openssl.c
|
||||
index 68ad6f15b..fdf0d92b2 100644
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -441,14 +441,16 @@ exim_openssl_state_st state_server = {.is_server = TRUE};
|
||||
static int
|
||||
setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host,
|
||||
uschar ** errstr );
|
||||
|
||||
/* Callbacks */
|
||||
#ifndef DISABLE_OCSP
|
||||
static int tls_server_stapling_cb(SSL *s, void *arg);
|
||||
+static void x509_stack_dump_cert_s_names(const STACK_OF(X509) * sk);
|
||||
+static void x509_store_dump_cert_s_names(X509_STORE * store);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Daemon-called, before every connection, key create/rotate */
|
||||
#ifndef DISABLE_TLS_RESUME
|
||||
static void tk_init(void);
|
||||
@@ -1307,15 +1309,14 @@ ocsp_load_response(exim_openssl_state_st * state, const uschar * filename,
|
||||
{
|
||||
BIO * bio;
|
||||
OCSP_RESPONSE * resp;
|
||||
OCSP_BASICRESP * basic_response;
|
||||
OCSP_SINGLERESP * single_response;
|
||||
ASN1_GENERALIZEDTIME * rev, * thisupd, * nextupd;
|
||||
STACK_OF(X509) * sk;
|
||||
-unsigned long verify_flags;
|
||||
int status, reason, i;
|
||||
|
||||
DEBUG(D_tls)
|
||||
debug_printf("tls_ocsp_file (%s) '%s'\n", is_pem ? "PEM" : "DER", filename);
|
||||
|
||||
if (!filename || !*filename) return;
|
||||
|
||||
@@ -1372,28 +1373,28 @@ if ((status = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL)
|
||||
if (!(basic_response = OCSP_response_get1_basic(resp)))
|
||||
{
|
||||
DEBUG(D_tls)
|
||||
debug_printf("OCSP response parse error: unable to extract basic response.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
-sk = state->verify_stack;
|
||||
-verify_flags = OCSP_NOVERIFY; /* check sigs, but not purpose */
|
||||
+sk = state->verify_stack; /* set by setup_certs() / chain_from_pem_file() */
|
||||
|
||||
/* May need to expose ability to adjust those flags?
|
||||
OCSP_NOSIGS OCSP_NOVERIFY OCSP_NOCHAIN OCSP_NOCHECKS OCSP_NOEXPLICIT
|
||||
OCSP_TRUSTOTHER OCSP_NOINTERN */
|
||||
|
||||
-/* This does a full verify on the OCSP proof before we load it for serving
|
||||
-up; possibly overkill - just date-checks might be nice enough.
|
||||
+/* This does a partial verify (only the signer link, not the whole chain-to-CA)
|
||||
+on the OCSP proof before we load it for serving up; possibly overkill -
|
||||
+just date-checks might be nice enough.
|
||||
|
||||
OCSP_basic_verify takes a "store" arg, but does not
|
||||
-use it for the chain verification, which is all we do
|
||||
-when OCSP_NOVERIFY is set. The content from the wire
|
||||
-"basic_response" and a cert-stack "sk" are all that is used.
|
||||
+use it for the chain verification, when OCSP_NOVERIFY is set.
|
||||
+The content from the wire "basic_response" and a cert-stack "sk" are all
|
||||
+that is used.
|
||||
|
||||
We have a stack, loaded in setup_certs() if tls_verify_certificates
|
||||
was a file (not a directory, or "system"). It is unfortunate we
|
||||
cannot used the connection context store, as that would neatly
|
||||
handle the "system" case too, but there seems to be no library
|
||||
function for getting a stack from a store.
|
||||
[ In OpenSSL 1.1 - ? X509_STORE_CTX_get0_chain(ctx) ? ]
|
||||
@@ -1402,15 +1403,15 @@ SNI handling.
|
||||
|
||||
Separately we might try to replace using OCSP_basic_verify() - which seems to not
|
||||
be a public interface into the OpenSSL library (there's no manual entry) -
|
||||
But what with? We also use OCSP_basic_verify in the client stapling callback.
|
||||
And there we NEED it; we must verify that status... unless the
|
||||
library does it for us anyway? */
|
||||
|
||||
-if ((i = OCSP_basic_verify(basic_response, sk, NULL, verify_flags)) < 0)
|
||||
+if ((i = OCSP_basic_verify(basic_response, sk, NULL, OCSP_NOVERIFY)) < 0)
|
||||
{
|
||||
DEBUG(D_tls)
|
||||
{
|
||||
ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
|
||||
debug_printf("OCSP response verify failure: %s\n", US ssl_errstring);
|
||||
}
|
||||
goto bad;
|
||||
@@ -1747,61 +1748,18 @@ if (opt_unset_or_noexpand(tls_eccurve))
|
||||
if (init_ecdh(ctx, &dummy_errstr))
|
||||
state_server.lib_state.ecdh = TRUE;
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls) debug_printf("TLS: not preloading ECDH curve for server\n");
|
||||
|
||||
#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
|
||||
-/* If we can, preload the server-side cert, key and ocsp */
|
||||
-
|
||||
-if ( opt_set_and_noexpand(tls_certificate)
|
||||
-# ifndef DISABLE_OCSP
|
||||
- && opt_unset_or_noexpand(tls_ocsp_file)
|
||||
-#endif
|
||||
- && opt_unset_or_noexpand(tls_privatekey))
|
||||
- {
|
||||
- /* Set watches on the filenames. The implementation does de-duplication
|
||||
- so we can just blindly do them all. */
|
||||
-
|
||||
- if ( tls_set_watch(tls_certificate, TRUE)
|
||||
-# ifndef DISABLE_OCSP
|
||||
- && tls_set_watch(tls_ocsp_file, TRUE)
|
||||
-#endif
|
||||
- && tls_set_watch(tls_privatekey, TRUE))
|
||||
- {
|
||||
- state_server.certificate = tls_certificate;
|
||||
- state_server.privatekey = tls_privatekey;
|
||||
-#ifndef DISABLE_OCSP
|
||||
- state_server.u_ocsp.server.file = tls_ocsp_file;
|
||||
-#endif
|
||||
-
|
||||
- DEBUG(D_tls) debug_printf("TLS: preloading server certs\n");
|
||||
- if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
|
||||
- state_server.lib_state.conn_certs = TRUE;
|
||||
- }
|
||||
- }
|
||||
-else if ( !tls_certificate && !tls_privatekey
|
||||
-# ifndef DISABLE_OCSP
|
||||
- && !tls_ocsp_file
|
||||
-#endif
|
||||
- )
|
||||
- { /* Generate & preload a selfsigned cert. No files to watch. */
|
||||
- if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
|
||||
- {
|
||||
- state_server.lib_state.conn_certs = TRUE;
|
||||
- lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
|
||||
- }
|
||||
- }
|
||||
-else
|
||||
- DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
|
||||
-
|
||||
-
|
||||
/* If we can, preload the Authorities for checking client certs against.
|
||||
Actual choice to do verify is made (tls_{,try_}verify_hosts)
|
||||
-at TLS conn startup */
|
||||
+at TLS conn startup.
|
||||
+Do this before the server ocsp so that its info can verify the ocsp. */
|
||||
|
||||
if ( opt_set_and_noexpand(tls_verify_certificates)
|
||||
&& opt_unset_or_noexpand(tls_crl))
|
||||
{
|
||||
/* Watch the default dir also as they are always included */
|
||||
|
||||
if ( tls_set_watch(CUS X509_get_default_cert_file(), FALSE)
|
||||
@@ -1809,18 +1767,63 @@ if ( opt_set_and_noexpand(tls_verify_certificates)
|
||||
&& tls_set_watch(tls_crl, FALSE))
|
||||
{
|
||||
DEBUG(D_tls) debug_printf("TLS: preloading CA bundle for server\n");
|
||||
|
||||
if (setup_certs(ctx, tls_verify_certificates, tls_crl, NULL, &dummy_errstr)
|
||||
== OK)
|
||||
state_server.lib_state.cabundle = TRUE;
|
||||
- }
|
||||
+
|
||||
+ /* If we can, preload the server-side cert, key and ocsp */
|
||||
+
|
||||
+ if ( opt_set_and_noexpand(tls_certificate)
|
||||
+# ifndef DISABLE_OCSP
|
||||
+ && opt_unset_or_noexpand(tls_ocsp_file)
|
||||
+# endif
|
||||
+ && opt_unset_or_noexpand(tls_privatekey))
|
||||
+ {
|
||||
+ /* Set watches on the filenames. The implementation does de-duplication
|
||||
+ so we can just blindly do them all. */
|
||||
+
|
||||
+ if ( tls_set_watch(tls_certificate, TRUE)
|
||||
+# ifndef DISABLE_OCSP
|
||||
+ && tls_set_watch(tls_ocsp_file, TRUE)
|
||||
+# endif
|
||||
+ && tls_set_watch(tls_privatekey, TRUE))
|
||||
+ {
|
||||
+ state_server.certificate = tls_certificate;
|
||||
+ state_server.privatekey = tls_privatekey;
|
||||
+#ifndef DISABLE_OCSP
|
||||
+ state_server.u_ocsp.server.file = tls_ocsp_file;
|
||||
+# endif
|
||||
+
|
||||
+ DEBUG(D_tls) debug_printf("TLS: preloading server certs\n");
|
||||
+ if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
|
||||
+ state_server.lib_state.conn_certs = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ( !tls_certificate && !tls_privatekey
|
||||
+# ifndef DISABLE_OCSP
|
||||
+ && !tls_ocsp_file
|
||||
+# endif
|
||||
+ )
|
||||
+ { /* Generate & preload a selfsigned cert. No files to watch. */
|
||||
+ if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
|
||||
+ {
|
||||
+ state_server.lib_state.conn_certs = TRUE;
|
||||
+ lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
|
||||
+ }
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls) debug_printf("TLS: not preloading CA bundle for server\n");
|
||||
+
|
||||
+
|
||||
#endif /* EXIM_HAVE_INOTIFY */
|
||||
|
||||
|
||||
/* If we can, preload the ciphers control string */
|
||||
|
||||
if (opt_set_and_noexpand(tls_require_ciphers))
|
||||
{
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,217 @@
|
||||
From 62b97c2ecf148ee86053d82e5509e4c3a5a20054 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Sat, 29 Oct 2022 22:33:43 +0100
|
||||
Subject: [PATCH 2/2] OpenSSL: fix double-expansion of tls_verify_certificates
|
||||
|
||||
---
|
||||
src/tls-openssl.c | 66 +++++++++++++++++++++----------------------
|
||||
1 file changed, 33 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/src/tls-openssl.c b/src/tls-openssl.c
|
||||
index fdf0d92b2..2e09882d2 100644
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -435,15 +435,15 @@ typedef struct exim_openssl_state {
|
||||
/* should figure out a cleanup of API to handle state preserved per
|
||||
implementation, for various reasons, which can be void * in the APIs.
|
||||
For now, we hack around it. */
|
||||
exim_openssl_state_st *client_static_state = NULL; /*XXX should not use static; multiple concurrent clients! */
|
||||
exim_openssl_state_st state_server = {.is_server = TRUE};
|
||||
|
||||
static int
|
||||
-setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host,
|
||||
+setup_certs(SSL_CTX * sctx, uschar ** certs, uschar * crl, host_item * host,
|
||||
uschar ** errstr );
|
||||
|
||||
/* Callbacks */
|
||||
#ifndef DISABLE_OCSP
|
||||
static int tls_server_stapling_cb(SSL *s, void *arg);
|
||||
static void x509_stack_dump_cert_s_names(const STACK_OF(X509) * sk);
|
||||
static void x509_store_dump_cert_s_names(X509_STORE * store);
|
||||
@@ -1762,18 +1762,18 @@ if ( opt_set_and_noexpand(tls_verify_certificates)
|
||||
{
|
||||
/* Watch the default dir also as they are always included */
|
||||
|
||||
if ( tls_set_watch(CUS X509_get_default_cert_file(), FALSE)
|
||||
&& tls_set_watch(tls_verify_certificates, FALSE)
|
||||
&& tls_set_watch(tls_crl, FALSE))
|
||||
{
|
||||
+ uschar * v_certs = tls_verify_certificates;
|
||||
DEBUG(D_tls) debug_printf("TLS: preloading CA bundle for server\n");
|
||||
|
||||
- if (setup_certs(ctx, tls_verify_certificates, tls_crl, NULL, &dummy_errstr)
|
||||
- == OK)
|
||||
+ if (setup_certs(ctx, &v_certs, tls_crl, NULL, &dummy_errstr) == OK)
|
||||
state_server.lib_state.cabundle = TRUE;
|
||||
|
||||
/* If we can, preload the server-side cert, key and ocsp */
|
||||
|
||||
if ( opt_set_and_noexpand(tls_certificate)
|
||||
# ifndef DISABLE_OCSP
|
||||
&& opt_unset_or_noexpand(tls_ocsp_file)
|
||||
@@ -1897,18 +1897,19 @@ if ( opt_set_and_noexpand(ob->tls_verify_certificates)
|
||||
{
|
||||
if ( !watch
|
||||
|| tls_set_watch(CUS X509_get_default_cert_file(), FALSE)
|
||||
&& tls_set_watch(ob->tls_verify_certificates, FALSE)
|
||||
&& tls_set_watch(ob->tls_crl, FALSE)
|
||||
)
|
||||
{
|
||||
+ uschar * v_certs = ob->tls_verify_certificates;
|
||||
DEBUG(D_tls)
|
||||
debug_printf("TLS: preloading CA bundle for transport '%s'\n", t->name);
|
||||
|
||||
- if (setup_certs(ctx, ob->tls_verify_certificates,
|
||||
+ if (setup_certs(ctx, &v_certs,
|
||||
ob->tls_crl, dummy_host, &dummy_errstr) == OK)
|
||||
ob->tls_preload.cabundle = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls)
|
||||
debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", t->name);
|
||||
@@ -2238,22 +2239,20 @@ if (state->u_ocsp.server.file)
|
||||
{
|
||||
SSL_CTX_set_tlsext_status_cb(server_sni, tls_server_stapling_cb);
|
||||
SSL_CTX_set_tlsext_status_arg(server_sni, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
- uschar * expcerts;
|
||||
- if ( !expand_check(tls_verify_certificates, US"tls_verify_certificates",
|
||||
- &expcerts, &dummy_errstr)
|
||||
- || (rc = setup_certs(server_sni, expcerts, tls_crl, NULL,
|
||||
+ uschar * v_certs = tls_verify_certificates;
|
||||
+ if ((rc = setup_certs(server_sni, &v_certs, tls_crl, NULL,
|
||||
&dummy_errstr)) != OK)
|
||||
goto bad;
|
||||
|
||||
- if (expcerts && *expcerts)
|
||||
+ if (v_certs && *v_certs)
|
||||
setup_cert_verify(server_sni, FALSE, verify_callback_server);
|
||||
}
|
||||
|
||||
/* do this after setup_certs, because this can require the certs for verifying
|
||||
OCSP information. */
|
||||
if ((rc = tls_expand_session_files(server_sni, state, &dummy_errstr)) != OK)
|
||||
goto bad;
|
||||
@@ -3017,32 +3016,33 @@ return TRUE;
|
||||
|
||||
|
||||
/* Called by both client and server startup; on the server possibly
|
||||
repeated after a Server Name Indication.
|
||||
|
||||
Arguments:
|
||||
sctx SSL_CTX* to initialise
|
||||
- certs certs file, expanded
|
||||
+ certs certs file, returned expanded
|
||||
crl CRL file or NULL
|
||||
host NULL in a server; the remote host in a client
|
||||
errstr error string pointer
|
||||
|
||||
Returns: OK/DEFER/FAIL
|
||||
*/
|
||||
|
||||
static int
|
||||
-setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host,
|
||||
+setup_certs(SSL_CTX * sctx, uschar ** certsp, uschar * crl, host_item * host,
|
||||
uschar ** errstr)
|
||||
{
|
||||
-uschar *expcerts, *expcrl;
|
||||
+uschar * expcerts, * expcrl;
|
||||
|
||||
-if (!expand_check(certs, US"tls_verify_certificates", &expcerts, errstr))
|
||||
+if (!expand_check(*certsp, US"tls_verify_certificates", &expcerts, errstr))
|
||||
return DEFER;
|
||||
DEBUG(D_tls) debug_printf("tls_verify_certificates: %s\n", expcerts);
|
||||
|
||||
+*certsp = expcerts;
|
||||
if (expcerts && *expcerts)
|
||||
{
|
||||
/* Tell the library to use its compiled-in location for the system default
|
||||
CA bundle. Then add the ones specified in the config, if any. */
|
||||
|
||||
if (!SSL_CTX_set_default_verify_paths(sctx))
|
||||
return tls_error(US"SSL_CTX_set_default_verify_paths", host, NULL, errstr);
|
||||
@@ -3330,28 +3330,28 @@ if (verify_check_host(&tls_verify_hosts) == OK)
|
||||
server_verify_optional = FALSE;
|
||||
else if (verify_check_host(&tls_try_verify_hosts) == OK)
|
||||
server_verify_optional = TRUE;
|
||||
else
|
||||
goto skip_certs;
|
||||
|
||||
{
|
||||
- uschar * expcerts;
|
||||
- if (!expand_check(tls_verify_certificates, US"tls_verify_certificates",
|
||||
- &expcerts, errstr))
|
||||
- return DEFER;
|
||||
- DEBUG(D_tls) debug_printf("tls_verify_certificates: %s\n", expcerts);
|
||||
+ uschar * v_certs = tls_verify_certificates;
|
||||
|
||||
if (state_server.lib_state.cabundle)
|
||||
- { DEBUG(D_tls) debug_printf("TLS: CA bundle for server was preloaded\n"); }
|
||||
+ {
|
||||
+ DEBUG(D_tls) debug_printf("TLS: CA bundle for server was preloaded\n");
|
||||
+ setup_cert_verify(ctx, server_verify_optional, verify_callback_server);
|
||||
+ }
|
||||
else
|
||||
- if ((rc = setup_certs(ctx, expcerts, tls_crl, NULL, errstr)) != OK)
|
||||
+ {
|
||||
+ if ((rc = setup_certs(ctx, &v_certs, tls_crl, NULL, errstr)) != OK)
|
||||
return rc;
|
||||
-
|
||||
- if (expcerts && *expcerts)
|
||||
- setup_cert_verify(ctx, server_verify_optional, verify_callback_server);
|
||||
+ if (v_certs && *v_certs)
|
||||
+ setup_cert_verify(ctx, server_verify_optional, verify_callback_server);
|
||||
+ }
|
||||
}
|
||||
skip_certs: ;
|
||||
|
||||
#ifndef DISABLE_TLS_RESUME
|
||||
# if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
SSL_CTX_set_tlsext_ticket_key_cb(ctx, ticket_key_callback);
|
||||
/* despite working, appears to always return failure, so ignoring */
|
||||
@@ -3606,28 +3606,28 @@ if ( ( ( !ob->tls_verify_hosts || !ob->tls_verify_hosts
|
||||
client_verify_optional = FALSE;
|
||||
else if (verify_check_given_host(CUSS &ob->tls_try_verify_hosts, host) == OK)
|
||||
client_verify_optional = TRUE;
|
||||
else
|
||||
return OK;
|
||||
|
||||
{
|
||||
- uschar * expcerts;
|
||||
- if (!expand_check(ob->tls_verify_certificates, US"tls_verify_certificates",
|
||||
- &expcerts, errstr))
|
||||
- return DEFER;
|
||||
- DEBUG(D_tls) debug_printf("tls_verify_certificates: %s\n", expcerts);
|
||||
+ uschar * v_certs = ob->tls_verify_certificates;
|
||||
|
||||
if (state->lib_state.cabundle)
|
||||
- { DEBUG(D_tls) debug_printf("TLS: CA bundle was preloaded\n"); }
|
||||
+ {
|
||||
+ DEBUG(D_tls) debug_printf("TLS: CA bundle for tpt was preloaded\n");
|
||||
+ setup_cert_verify(ctx, client_verify_optional, verify_callback_client);
|
||||
+ }
|
||||
else
|
||||
- if ((rc = setup_certs(ctx, expcerts, ob->tls_crl, host, errstr)) != OK)
|
||||
+ {
|
||||
+ if ((rc = setup_certs(ctx, &v_certs, ob->tls_crl, host, errstr)) != OK)
|
||||
return rc;
|
||||
-
|
||||
- if (expcerts && *expcerts)
|
||||
- setup_cert_verify(ctx, client_verify_optional, verify_callback_client);
|
||||
+ if (v_certs && *v_certs)
|
||||
+ setup_cert_verify(ctx, client_verify_optional, verify_callback_client);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (verify_check_given_host(CUSS &ob->tls_verify_cert_hostnames, host) == OK)
|
||||
{
|
||||
state->verify_cert_hostnames =
|
||||
#ifdef SUPPORT_I18N
|
||||
string_domain_utf8_to_alabel(host->certname, NULL);
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,82 @@
|
||||
From 1ed24e36e279c922d3366f6c3144570cc5f54d7a Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Mon, 19 Dec 2022 21:09:17 +0000
|
||||
Subject: [PATCH] Fix logging of max-size log line
|
||||
|
||||
Broken-by: d12746bc15d8
|
||||
---
|
||||
doc/ChangeLog | 5 +++++
|
||||
src/log.c | 7 ++++---
|
||||
test/confs/0633 | 21 ++++++++++++++++++++
|
||||
test/scripts/0000-Basic/0633 | 9 +++++++++
|
||||
test/stderr/0633 | 38 ++++++++++++++++++++++++++++++++++++
|
||||
test/stdout/0633 | 15 ++++++++++++++
|
||||
6 files changed, 92 insertions(+), 3 deletions(-)
|
||||
create mode 100644 test/confs/0633
|
||||
create mode 100644 test/scripts/0000-Basic/0633
|
||||
create mode 100644 test/stderr/0633
|
||||
create mode 100644 test/stdout/0633
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -28,10 +28,15 @@ JH/13 Bug 2929: Fix using $recipients af
|
||||
JH/14 Bug 2933: Fix regex substring match variables for null matches. Since 4.96
|
||||
a capture group which obtained no text (eg. "(abc)*" matching zero
|
||||
occurrences) could cause a segfault if the corresponding $<n> was
|
||||
expanded.
|
||||
|
||||
+JH/18 Fix a fencepost error in logging. Previously (since 4.92) when a log line
|
||||
+ was exactly sized compared to the log buffer, a crash occurred with the
|
||||
+ misleading message "bad memory reference; pool not found".
|
||||
+ Found and traced by Jasen Betts.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/log.c
|
||||
+++ b/src/log.c
|
||||
@@ -803,11 +803,11 @@ Returns: nothing
|
||||
void
|
||||
log_write(unsigned int selector, int flags, const char *format, ...)
|
||||
{
|
||||
int paniclogfd;
|
||||
ssize_t written_len;
|
||||
-gstring gs = { .size = LOG_BUFFER_SIZE-1, .ptr = 0, .s = log_buffer };
|
||||
+gstring gs = { .size = LOG_BUFFER_SIZE-2, .ptr = 0, .s = log_buffer };
|
||||
gstring * g;
|
||||
va_list ap;
|
||||
|
||||
/* If panic_recurseflag is set, we have failed to open the panic log. This is
|
||||
the ultimate disaster. First try to write the message to a debug file and/or
|
||||
@@ -949,15 +949,14 @@ DEBUG(D_any|D_v)
|
||||
g->ptr = i;
|
||||
g = string_cat(g, US"**** log string overflowed log buffer ****");
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
- g->size = LOG_BUFFER_SIZE;
|
||||
g = string_catn(g, US"\n", 1);
|
||||
debug_printf("%s", string_from_gstring(g));
|
||||
|
||||
- gs.size = LOG_BUFFER_SIZE-1; /* Having used the buffer for debug output, */
|
||||
+ gs.size = LOG_BUFFER_SIZE-2; /* Having used the buffer for debug output, */
|
||||
gs.ptr = 0; /* reset it for the real use. */
|
||||
gs.s = log_buffer;
|
||||
}
|
||||
/* If no log file is specified, we are in a mess. */
|
||||
|
||||
@@ -1035,10 +1034,12 @@ if ( flags & LOG_RECIPIENTS
|
||||
if (LOG_BUFFER_SIZE - g->ptr < Ustrlen(s) + 3) break;
|
||||
g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, " %s", s);
|
||||
}
|
||||
}
|
||||
|
||||
+/* actual size, now we are placing the newline (and space for NUL) */
|
||||
+gs.size = LOG_BUFFER_SIZE;
|
||||
g = string_catn(g, US"\n", 1);
|
||||
string_from_gstring(g);
|
||||
|
||||
/* Handle loggable errors when running a utility, or when address testing.
|
||||
Write to log_stderr unless debugging (when it will already have been written),
|
@ -0,0 +1,76 @@
|
||||
From 1d38781da934809e6ce0b8c3718c4b3bccdfe1d2 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Wed, 28 Dec 2022 19:39:06 +0000
|
||||
Subject: [PATCH] Fix recursion on dns_again_means_nonexist. Bug 2911
|
||||
|
||||
---
|
||||
doc/ChangeLog | 8 +++++
|
||||
src/dns.c | 12 ++++++++
|
||||
test/confs/2202 | 18 +++++++++--
|
||||
test/scripts/2200-dnsdb/2202 | 8 +++++
|
||||
test/stderr/2202 | 58 +++++++++++++++++++++++++++++++++++-
|
||||
test/stdout/2202 | 8 +++++
|
||||
6 files changed, 108 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -33,10 +33,18 @@ JH/14 Bug 2933: Fix regex substring matc
|
||||
JH/18 Fix a fencepost error in logging. Previously (since 4.92) when a log line
|
||||
was exactly sized compared to the log buffer, a crash occurred with the
|
||||
misleading message "bad memory reference; pool not found".
|
||||
Found and traced by Jasen Betts.
|
||||
|
||||
+JH/19 Bug 2911: Fix a recursion in DNS lookups. Previously, if the main option
|
||||
+ dns_again_means_nonexist included an element causing a DNS lookup which
|
||||
+ iteslf returned DNS_AGAIN, unbounded recursion occurred. Possible results
|
||||
+ included (though probably not limited to) a process crash from stack
|
||||
+ memory limit, or from excessive open files. Replace this with a paniclog
|
||||
+ whine (as this is likely a configuration error), and returning
|
||||
+ DNS_NOMATCH.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/dns.c
|
||||
+++ b/src/dns.c
|
||||
@@ -799,10 +799,11 @@ int
|
||||
dns_basic_lookup(dns_answer * dnsa, const uschar * name, int type)
|
||||
{
|
||||
int rc;
|
||||
#ifndef STAND_ALONE
|
||||
const uschar * save_domain;
|
||||
+static BOOL try_again_recursion = FALSE;
|
||||
#endif
|
||||
|
||||
/* DNS lookup failures of any kind are cached in a tree. This is mainly so that
|
||||
a timeout on one domain doesn't happen time and time again for messages that
|
||||
have many addresses in the same domain. We rely on the resolver and name server
|
||||
@@ -903,15 +904,26 @@ if (dnsa->answerlen < 0) switch (h_errno
|
||||
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
|
||||
name, dns_text_type(type));
|
||||
|
||||
/* Cut this out for various test programs */
|
||||
#ifndef STAND_ALONE
|
||||
+ if (try_again_recursion)
|
||||
+ {
|
||||
+ log_write(0, LOG_MAIN|LOG_PANIC,
|
||||
+ "dns_again_means_nonexist recursion seen for %s (assuming nonexist)",
|
||||
+ name);
|
||||
+ return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
|
||||
+ }
|
||||
+
|
||||
+ try_again_recursion = TRUE;
|
||||
save_domain = deliver_domain;
|
||||
deliver_domain = string_copy(name); /* set $domain */
|
||||
rc = match_isinlist(name, CUSS &dns_again_means_nonexist, 0,
|
||||
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
|
||||
deliver_domain = save_domain;
|
||||
+ try_again_recursion = FALSE;
|
||||
+
|
||||
if (rc != OK)
|
||||
{
|
||||
DEBUG(D_dns) debug_printf("returning DNS_AGAIN\n");
|
||||
return dns_fail_return(name, type, 0, DNS_AGAIN);
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
From 57d70161718e02927a22d6a3481803b72035ac46 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Sat, 31 Dec 2022 13:37:17 +0000
|
||||
Subject: [PATCH] Close server smtp socket explicitly on connect ACL "drop"
|
||||
|
||||
---
|
||||
src/smtp_in.c | 13 ++++++++
|
||||
test/confs/0022 | 2 ++
|
||||
test/log/0022 | 2 ++
|
||||
test/rejectlog/0022 | 3 ++
|
||||
test/scripts/0000-Basic/0022 | 13 ++++++++
|
||||
test/stderr/0022 | 60 ++++++++++++++++++------------------
|
||||
test/stdout/0022 | 6 ++++
|
||||
7 files changed, 69 insertions(+), 30 deletions(-)
|
||||
create mode 100644 test/rejectlog/0022
|
||||
|
||||
diff --git a/src/smtp_in.c b/src/smtp_in.c
|
||||
index 1cfcc0404..6880e3c09 100644
|
||||
--- a/src/smtp_in.c
|
||||
+++ b/src/smtp_in.c
|
||||
@@ -3563,10 +3563,23 @@ log_write(L_smtp_connection, LOG_MAIN, "%s closed by DROP in ACL",
|
||||
/* Run the not-quit ACL, but without any custom messages. This should not be a
|
||||
problem, because we get here only if some other ACL has issued "drop", and
|
||||
in that case, *its* custom messages will have been used above. */
|
||||
|
||||
smtp_notquit_exit(US"acl-drop", NULL, NULL);
|
||||
+
|
||||
+/* An overenthusiastic fail2ban/iptables implimentation has been seen to result
|
||||
+in the TCP conn staying open, and retrying, despite this process exiting. A
|
||||
+malicious client could possibly do the same, tying up server netowrking
|
||||
+resources. Close the socket explicitly to try to avoid that (there's a note in
|
||||
+the Linux socket(7) manpage, SO_LINGER para, to the effect that exim() without
|
||||
+close() results in the socket always lingering). */
|
||||
+
|
||||
+(void) poll_one_fd(fileno(smtp_in), POLLIN, 200);
|
||||
+DEBUG(D_any) debug_printf_indent("SMTP(close)>>\n");
|
||||
+(void) fclose(smtp_in);
|
||||
+(void) fclose(smtp_out);
|
||||
+
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
diff --git a/test/rejectlog/0022 b/test/rejectlog/0022
|
||||
new file mode 100644
|
||||
index 000000000..68e21fff3
|
||||
--
|
||||
2.39.0
|
||||
|
@ -0,0 +1,184 @@
|
||||
From ca4014de81e6aa367aa0a54c49b4c3d4b137814c Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Sun, 1 Jan 2023 12:18:38 +0000
|
||||
Subject: [PATCH] OpenSSL: fix tls_eccurve setting explicit curve/group. Bug
|
||||
2954
|
||||
|
||||
---
|
||||
doc/ChangeLog | 4 +++
|
||||
src/tls-openssl.c | 39 ++++++++++++++----------
|
||||
test/confs/2148 | 54 ++++++++++++++++++++++++++++++++++
|
||||
test/confs/2149 | 39 +++++++++++++-----------
|
||||
test/log/2148 | 48 ++++++++++++++++++++++++++++++
|
||||
test/log/2149 | 39 ++++++++++++------------
|
||||
test/paniclog/{2149 => 2148} | 0
|
||||
test/scripts/2100-OpenSSL/2148 | 50 +++++++++++++++++++++++++++++++
|
||||
test/scripts/2100-OpenSSL/2149 | 50 ++++++++++++++++---------------
|
||||
test/stderr/2148 | 5 ++++
|
||||
test/stderr/2149 | 3 --
|
||||
11 files changed, 250 insertions(+), 81 deletions(-)
|
||||
create mode 100644 test/confs/2148
|
||||
create mode 100644 test/log/2148
|
||||
rename test/paniclog/{2149 => 2148} (100%)
|
||||
create mode 100644 test/scripts/2100-OpenSSL/2148
|
||||
create mode 100644 test/stderr/2148
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -41,10 +41,14 @@ JH/19 Bug 2911: Fix a recursion in DNS l
|
||||
included (though probably not limited to) a process crash from stack
|
||||
memory limit, or from excessive open files. Replace this with a paniclog
|
||||
whine (as this is likely a configuration error), and returning
|
||||
DNS_NOMATCH.
|
||||
|
||||
+JH/20 Bug 2954: (OpenSSL) Fix setting of explicit EC curve/group. Previously
|
||||
+ this always failed, probably leading to the usual downgrade to in-clear
|
||||
+ connections.
|
||||
+
|
||||
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -657,16 +657,16 @@ if (dh_bitsize <= tls_dh_max_bits)
|
||||
/* EVP_PKEY_free(pkey); crashes */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls)
|
||||
- debug_printf("Diffie-Hellman initialized from %s with %d-bit prime\n",
|
||||
+ debug_printf(" Diffie-Hellman initialized from %s with %d-bit prime\n",
|
||||
dhexpanded ? dhexpanded : US"default", dh_bitsize);
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls)
|
||||
- debug_printf("dhparams '%s' %d bits, is > tls_dh_max_bits limit of %d\n",
|
||||
+ debug_printf(" dhparams '%s' %d bits, is > tls_dh_max_bits limit of %d\n",
|
||||
dhexpanded ? dhexpanded : US"default", dh_bitsize, tls_dh_max_bits);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
DH_free(dh);
|
||||
#endif
|
||||
@@ -712,23 +712,31 @@ init_ecdh(SSL_CTX * sctx, uschar ** errs
|
||||
#ifdef OPENSSL_NO_ECDH
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
uschar * exp_curve;
|
||||
-int nid;
|
||||
-BOOL rv;
|
||||
+int nid, rc;
|
||||
|
||||
# ifndef EXIM_HAVE_ECDH
|
||||
DEBUG(D_tls)
|
||||
- debug_printf("No OpenSSL API to define ECDH parameters, skipping\n");
|
||||
+ debug_printf(" No OpenSSL API to define ECDH parameters, skipping\n");
|
||||
return TRUE;
|
||||
# else
|
||||
|
||||
if (!expand_check(tls_eccurve, US"tls_eccurve", &exp_curve, errstr))
|
||||
return FALSE;
|
||||
+
|
||||
+/* Is the option deliberately empty? */
|
||||
+
|
||||
if (!exp_curve || !*exp_curve)
|
||||
+ {
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
+ DEBUG(D_tls) debug_printf( " ECDH OpenSSL 1.0.2+: clearing curves list\n");
|
||||
+ (void) SSL_CTX_set1_curves(sctx, &nid, 0);
|
||||
+#endif
|
||||
return TRUE;
|
||||
+ }
|
||||
|
||||
/* "auto" needs to be handled carefully.
|
||||
* OpenSSL < 1.0.2: we do not select anything, but fallback to prime256v1
|
||||
* OpenSSL < 1.1.0: we have to call SSL_CTX_set_ecdh_auto
|
||||
* (openssl/ssl.h defines SSL_CTRL_SET_ECDH_AUTO)
|
||||
@@ -737,27 +745,26 @@ if (!exp_curve || !*exp_curve)
|
||||
*/
|
||||
if (Ustrcmp(exp_curve, "auto") == 0)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
||||
DEBUG(D_tls) debug_printf(
|
||||
- "ECDH OpenSSL < 1.0.2: temp key parameter settings: overriding \"auto\" with \"prime256v1\"\n");
|
||||
+ " ECDH OpenSSL < 1.0.2: temp key parameter settings: overriding \"auto\" with \"prime256v1\"\n");
|
||||
exp_curve = US"prime256v1";
|
||||
#else
|
||||
# if defined SSL_CTRL_SET_ECDH_AUTO
|
||||
DEBUG(D_tls) debug_printf(
|
||||
- "ECDH OpenSSL 1.0.2+: temp key parameter settings: autoselection\n");
|
||||
+ " ECDH OpenSSL 1.0.2+: temp key parameter settings: autoselection\n");
|
||||
SSL_CTX_set_ecdh_auto(sctx, 1);
|
||||
return TRUE;
|
||||
# else
|
||||
DEBUG(D_tls) debug_printf(
|
||||
- "ECDH OpenSSL 1.1.0+: temp key parameter settings: default selection\n");
|
||||
+ " ECDH OpenSSL 1.1.0+: temp key parameter settings: library default selection\n");
|
||||
return TRUE;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
-DEBUG(D_tls) debug_printf("ECDH: curve '%s'\n", exp_curve);
|
||||
if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef
|
||||
# ifdef EXIM_HAVE_OPENSSL_EC_NIST2NID
|
||||
&& (nid = EC_curve_nist2nid(CCS exp_curve)) == NID_undef
|
||||
# endif
|
||||
)
|
||||
@@ -777,27 +784,27 @@ if ( (nid = OBJ_sn2nid (CCS exp_c
|
||||
}
|
||||
|
||||
/* The "tmp" in the name here refers to setting a temporary key
|
||||
not to the stability of the interface. */
|
||||
|
||||
- if ((rv = SSL_CTX_set_tmp_ecdh(sctx, ecdh) == 0))
|
||||
+ if ((rc = SSL_CTX_set_tmp_ecdh(sctx, ecdh) == 0))
|
||||
tls_error(string_sprintf("Error enabling '%s' curve", exp_curve), NULL, NULL, errstr);
|
||||
else
|
||||
- DEBUG(D_tls) debug_printf("ECDH: enabled '%s' curve\n", exp_curve);
|
||||
+ DEBUG(D_tls) debug_printf(" ECDH: enabled '%s' curve\n", exp_curve);
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
|
||||
#else /* v 3.0.0 + */
|
||||
|
||||
-if ((rv = SSL_CTX_set1_groups(sctx, &nid, 1)) == 0)
|
||||
+if ((rc = SSL_CTX_set1_groups(sctx, &nid, 1)) == 0)
|
||||
tls_error(string_sprintf("Error enabling '%s' group", exp_curve), NULL, NULL, errstr);
|
||||
else
|
||||
- DEBUG(D_tls) debug_printf("ECDH: enabled '%s' group\n", exp_curve);
|
||||
+ DEBUG(D_tls) debug_printf(" ECDH: enabled '%s' group\n", exp_curve);
|
||||
|
||||
#endif
|
||||
|
||||
-return !rv;
|
||||
+return !!rc;
|
||||
|
||||
# endif /*EXIM_HAVE_ECDH*/
|
||||
#endif /*OPENSSL_NO_ECDH*/
|
||||
}
|
||||
|
||||
@@ -1719,19 +1726,19 @@ state_server.lib_state.lib_ctx = ctx;
|
||||
|
||||
/* Preload DH params and EC curve */
|
||||
|
||||
if (opt_unset_or_noexpand(tls_dhparam))
|
||||
{
|
||||
- DEBUG(D_tls) debug_printf("TLS: preloading DH params for server\n");
|
||||
+ DEBUG(D_tls) debug_printf("TLS: preloading DH params '%s' for server\n", tls_dhparam);
|
||||
if (init_dh(ctx, tls_dhparam, &dummy_errstr))
|
||||
state_server.lib_state.dh = TRUE;
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls) debug_printf("TLS: not preloading DH params for server\n");
|
||||
if (opt_unset_or_noexpand(tls_eccurve))
|
||||
{
|
||||
- DEBUG(D_tls) debug_printf("TLS: preloading ECDH curve for server\n");
|
||||
+ DEBUG(D_tls) debug_printf("TLS: preloading ECDH curve '%s' for server\n", tls_eccurve);
|
||||
if (init_ecdh(ctx, &dummy_errstr))
|
||||
state_server.lib_state.ecdh = TRUE;
|
||||
}
|
||||
else
|
||||
DEBUG(D_tls) debug_printf("TLS: not preloading ECDH curve for server\n");
|
@ -0,0 +1,42 @@
|
||||
From 7fa5764c203f2f4a900898a79ed02d674075313f Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Mon, 2 Jan 2023 15:04:14 +0000
|
||||
Subject: [PATCH 1/3] OpenSSL: Fix tls_eccurve on earlier versions than 3.0.0.
|
||||
Bug 2954
|
||||
|
||||
Broken-by: ca4014de81e6
|
||||
---
|
||||
src/tls-openssl.c | 7 ++++---
|
||||
test/log/2149 | 28 ++++++++++++++--------------
|
||||
test/runtest | 3 +++
|
||||
test/scripts/2100-OpenSSL/2149 | 22 ++++++++++++----------
|
||||
4 files changed, 33 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/tls-openssl.c b/src/tls-openssl.c
|
||||
index 4d0f99ea9..e063d29bd 100644
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -786,8 +786,9 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef
|
||||
# endif
|
||||
)
|
||||
{
|
||||
- tls_error(string_sprintf("Unknown curve name tls_eccurve '%s'", exp_curve),
|
||||
- NULL, NULL, errstr);
|
||||
+ uschar * s = string_sprintf("Unknown curve name tls_eccurve '%s'", exp_curve);
|
||||
+ DEBUG(D_tls) debug_printf("TLS error '%s'\n", s);
|
||||
+ if (errstr) *errstr = s;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -803,7 +804,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef
|
||||
/* The "tmp" in the name here refers to setting a temporary key
|
||||
not to the stability of the interface. */
|
||||
|
||||
- if ((rc = SSL_CTX_set_tmp_ecdh(sctx, ecdh) == 0))
|
||||
+ if ((rc = SSL_CTX_set_tmp_ecdh(sctx, ecdh)) == 0)
|
||||
tls_error(string_sprintf("Error enabling '%s' curve", exp_curve), NULL, NULL, errstr);
|
||||
else
|
||||
DEBUG(D_tls) debug_printf(" ECDH: enabled '%s' curve\n", exp_curve);
|
||||
--
|
||||
2.39.0
|
||||
|
@ -0,0 +1,99 @@
|
||||
From e1aca33756f73c22b00a98d40ce2be8ed94464b1 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Thu, 5 Jan 2023 13:03:37 +0000
|
||||
Subject: [PATCH 2/3] OpenSSL: log conns rejected for bad ALPN, with the
|
||||
offered value
|
||||
|
||||
Unfortunately, no way to do this under GnuTLS
|
||||
---
|
||||
src/match.c | 1 +
|
||||
src/tls-gnu.c | 9 ++++++++-
|
||||
src/tls-openssl.c | 13 +++++++++++--
|
||||
test/log/1190 | 2 ++
|
||||
test/runtest | 3 +++
|
||||
5 files changed, 25 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/match.c b/src/match.c
|
||||
index 91a49c0f0..07070362d 100644
|
||||
--- a/src/match.c
|
||||
+++ b/src/match.c
|
||||
@@ -968,6 +968,7 @@ Arguments:
|
||||
s string to search for
|
||||
listptr ptr to ptr to colon separated list of patterns, or NULL
|
||||
sep a separator value for the list (see string_nextinlist())
|
||||
+ or zero for auto
|
||||
anchorptr ptr to tree for named items, or NULL if no named items
|
||||
cache_bits ptr to cache_bits for ditto, or NULL if not caching
|
||||
type MCL_DOMAIN when matching a domain list
|
||||
diff --git a/src/tls-gnu.c b/src/tls-gnu.c
|
||||
index 729fb5879..b47fabf1d 100644
|
||||
--- a/src/tls-gnu.c
|
||||
+++ b/src/tls-gnu.c
|
||||
@@ -1119,21 +1119,28 @@ switch (tls_id)
|
||||
/* The format of "data" here doesn't seem to be documented, but appears
|
||||
to be a 2-byte field with a (redundant, given the "size" arg) total length
|
||||
then a sequence of one-byte size then string (not nul-term) names. The
|
||||
- latter is as described in OpenSSL documentation. */
|
||||
+ latter is as described in OpenSSL documentation.
|
||||
+ Note that we do not get called for a match_fail, making it hard to log
|
||||
+ a single bad ALPN being offered (the common case). */
|
||||
+ {
|
||||
+ gstring * g = NULL;
|
||||
|
||||
DEBUG(D_tls) debug_printf("Seen ALPN extension from client (s=%u):", size);
|
||||
for (const uschar * s = data+2; s-data < size-1; s += *s + 1)
|
||||
{
|
||||
server_seen_alpn++;
|
||||
+ g = string_append_listele_n(g, ':', s+1, *s);
|
||||
DEBUG(D_tls) debug_printf(" '%.*s'", (int)*s, s+1);
|
||||
}
|
||||
DEBUG(D_tls) debug_printf("\n");
|
||||
if (server_seen_alpn > 1)
|
||||
{
|
||||
+ log_write(0, LOG_MAIN, "TLS ALPN (%s) rejected", string_from_gstring(g));
|
||||
DEBUG(D_tls) debug_printf("TLS: too many ALPNs presented in handshake\n");
|
||||
return GNUTLS_E_NO_APPLICATION_PROTOCOL;
|
||||
}
|
||||
break;
|
||||
+ }
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
diff --git a/src/tls-openssl.c b/src/tls-openssl.c
|
||||
index e063d29bd..513ba0d3a 100644
|
||||
--- a/src/tls-openssl.c
|
||||
+++ b/src/tls-openssl.c
|
||||
@@ -2324,6 +2324,8 @@ static int
|
||||
tls_server_alpn_cb(SSL *ssl, const uschar ** out, uschar * outlen,
|
||||
const uschar * in, unsigned int inlen, void * arg)
|
||||
{
|
||||
+gstring * g = NULL;
|
||||
+
|
||||
server_seen_alpn = TRUE;
|
||||
DEBUG(D_tls)
|
||||
{
|
||||
@@ -2354,12 +2356,19 @@ if ( inlen > 1 /* at least one name */
|
||||
}
|
||||
}
|
||||
|
||||
-/* More than one name from clilent, or name did not match our list. */
|
||||
+/* More than one name from client, or name did not match our list. */
|
||||
|
||||
/* This will be fatal to the TLS conn; would be nice to kill TCP also.
|
||||
Maybe as an option in future; for now leave control to the config (must-tls). */
|
||||
|
||||
-DEBUG(D_tls) debug_printf("TLS ALPN rejected\n");
|
||||
+for (int pos = 0, siz; pos < inlen; pos += siz+1)
|
||||
+ {
|
||||
+ siz = in[pos];
|
||||
+ if (pos + 1 + siz > inlen) siz = inlen - pos - 1;
|
||||
+ g = string_append_listele_n(g, ':', in + pos + 1, siz);
|
||||
+ }
|
||||
+log_write(0, LOG_MAIN, "TLS ALPN (%s) rejected", string_from_gstring(g));
|
||||
+gstring_release_unused(g);
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
#endif /* EXIM_HAVE_ALPN */
|
||||
--
|
||||
2.39.0
|
||||
|
@ -0,0 +1,96 @@
|
||||
From 30520c8f87fcf660ed99a2344cae7f9787f7bc89 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Thu, 5 Jan 2023 18:39:51 +0000
|
||||
Subject: [PATCH 3/3] DANE: do not check dns_again_means_nonexist for TLSA
|
||||
results of TRY_AGAIN
|
||||
|
||||
---
|
||||
doc/doc-docbook/spec.xfpt | 7 ++++++-
|
||||
doc/ChangeLog | 4 ++++
|
||||
src/dns.c | 35 ++++++++++++++++++++++-------------
|
||||
3 files changed, 32 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -46,10 +46,14 @@ JH/19 Bug 2911: Fix a recursion in DNS l
|
||||
JH/20 Bug 2954: (OpenSSL) Fix setting of explicit EC curve/group. Previously
|
||||
this always failed, probably leading to the usual downgrade to in-clear
|
||||
connections.
|
||||
|
||||
|
||||
+JH/20 Fix TLSA lookups. Previously dns_again_means_nonexist would affect
|
||||
+ SERVFAIL results, which breaks the downgrade resistance of DANE. Change
|
||||
+ to not checking that list for these looks.
|
||||
+
|
||||
|
||||
Exim version 4.96
|
||||
-----------------
|
||||
|
||||
JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
|
||||
--- a/src/dns.c
|
||||
+++ b/src/dns.c
|
||||
@@ -904,25 +904,34 @@ if (dnsa->answerlen < 0) switch (h_errno
|
||||
DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
|
||||
name, dns_text_type(type));
|
||||
|
||||
/* Cut this out for various test programs */
|
||||
#ifndef STAND_ALONE
|
||||
- if (try_again_recursion)
|
||||
+ /* Permitting dns_again_means nonexist for TLSA lookups breaks the
|
||||
+ doewngrade resistance of dane, so avoid for those. */
|
||||
+
|
||||
+ if (type == T_TLSA)
|
||||
+ rc = FAIL;
|
||||
+ else
|
||||
{
|
||||
- log_write(0, LOG_MAIN|LOG_PANIC,
|
||||
- "dns_again_means_nonexist recursion seen for %s (assuming nonexist)",
|
||||
- name);
|
||||
- return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type), DNS_NOMATCH);
|
||||
- }
|
||||
+ if (try_again_recursion)
|
||||
+ {
|
||||
+ log_write(0, LOG_MAIN|LOG_PANIC,
|
||||
+ "dns_again_means_nonexist recursion seen for %s"
|
||||
+ " (assuming nonexist)", name);
|
||||
+ return dns_fail_return(name, type, dns_expire_from_soa(dnsa, type),
|
||||
+ DNS_NOMATCH);
|
||||
+ }
|
||||
|
||||
- try_again_recursion = TRUE;
|
||||
- save_domain = deliver_domain;
|
||||
- deliver_domain = string_copy(name); /* set $domain */
|
||||
- rc = match_isinlist(name, CUSS &dns_again_means_nonexist, 0,
|
||||
- &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
|
||||
- deliver_domain = save_domain;
|
||||
- try_again_recursion = FALSE;
|
||||
+ try_again_recursion = TRUE;
|
||||
+ save_domain = deliver_domain;
|
||||
+ deliver_domain = string_copy(name); /* set $domain */
|
||||
+ rc = match_isinlist(name, CUSS &dns_again_means_nonexist, 0,
|
||||
+ &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
|
||||
+ deliver_domain = save_domain;
|
||||
+ try_again_recursion = FALSE;
|
||||
+ }
|
||||
|
||||
if (rc != OK)
|
||||
{
|
||||
DEBUG(D_dns) debug_printf("returning DNS_AGAIN\n");
|
||||
return dns_fail_return(name, type, 0, DNS_AGAIN);
|
||||
--- a/doc/spec.txt
|
||||
+++ b/doc/spec.txt
|
||||
@@ -14246,11 +14246,13 @@ dns_again_means_nonexist, it is treated
|
||||
should be used with care. You can make it apply to reverse lookups by a setting
|
||||
such as this:
|
||||
|
||||
dns_again_means_nonexist = *.in-addr.arpa
|
||||
|
||||
-This option applies to all DNS lookups that Exim does. It also applies when the
|
||||
+This option applies to all DNS lookups that Exim does, except for TLSA lookups
|
||||
+(where knowing about such failures +is security-relevant). It also applies
|
||||
+when the
|
||||
gethostbyname() or getipnodebyname() functions give temporary errors, since
|
||||
these are most likely to be caused by DNS lookup problems. The dnslookup router
|
||||
has some options of its own for controlling what happens when lookups for MX or
|
||||
SRV records give temporary errors. These more specific options are applied
|
||||
after this global option.
|
84
mail/exim/files/debian/75_66-Fix-crash-in-expansions.patch
Normal file
84
mail/exim/files/debian/75_66-Fix-crash-in-expansions.patch
Normal file
@ -0,0 +1,84 @@
|
||||
From 70069b65a39a7ba73a36fbd95371ff03cde1eb23 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Harris <jgh146exb@wizmail.org>
|
||||
Date: Thu, 2 Feb 2023 20:00:35 +0000
|
||||
Subject: [PATCH] Fix crash in expansions
|
||||
|
||||
Broken-by: 1058096b8c53
|
||||
---
|
||||
doc/ChangeLog | 4 ++++
|
||||
src/expand.c | 9 +++++----
|
||||
test/stderr/0630 | 1 +
|
||||
3 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/doc/ChangeLog
|
||||
+++ b/doc/ChangeLog
|
||||
@@ -50,10 +50,14 @@ JH/20 Bug 2954: (OpenSSL) Fix setting of
|
||||
|
||||
JH/20 Fix TLSA lookups. Previously dns_again_means_nonexist would affect
|
||||
SERVFAIL results, which breaks the downgrade resistance of DANE. Change
|
||||
to not checking that list for these looks.
|
||||
|
||||
+JH/23 Fix crash in string expansions. Previously, if an empty variable was
|
||||
+ immediately followed by an expansion operator, a null-indirection read
|
||||
+ was done, killing the process.
|
||||
+
|
||||
|
||||
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
|
||||
@@ -4652,11 +4652,11 @@ while (*s)
|
||||
yield = string_catn(yield, value, len);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (isdigit(*s))
|
||||
+ if (isdigit(*s)) /* A $<n> variable */
|
||||
{
|
||||
int n;
|
||||
s = read_cnumber(&n, s);
|
||||
if (n >= 0 && n <= expand_nmax)
|
||||
yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
|
||||
@@ -7060,10 +7060,11 @@ NOT_ITEM: ;
|
||||
if (arg) *arg++ = '_'; /* Put back for error messages */
|
||||
}
|
||||
|
||||
/* Deal specially with operators that might take a certificate variable
|
||||
as we do not want to do the usual expansion. For most, expand the string.*/
|
||||
+
|
||||
switch(c)
|
||||
{
|
||||
#ifndef DISABLE_TLS
|
||||
case EOP_MD5:
|
||||
case EOP_SHA1:
|
||||
@@ -7107,11 +7108,11 @@ NOT_ITEM: ;
|
||||
|
||||
/* Otherwise, switch on the operator type. After handling go back
|
||||
to the main loop top. */
|
||||
|
||||
{
|
||||
- int start = yield->ptr;
|
||||
+ unsigned expansion_start = gstring_length(yield);
|
||||
switch(c)
|
||||
{
|
||||
case EOP_BASE32:
|
||||
{
|
||||
uschar *t;
|
||||
@@ -8168,12 +8169,12 @@ NOT_ITEM: ;
|
||||
goto EXPAND_FAILED;
|
||||
} /* EOP_* switch */
|
||||
|
||||
DEBUG(D_expand)
|
||||
{
|
||||
- const uschar * s = yield->s + start;
|
||||
- int i = yield->ptr - start;
|
||||
+ const uschar * s = yield->s + expansion_start;
|
||||
+ int i = gstring_length(yield) - expansion_start;
|
||||
BOOL tainted = is_tainted(s);
|
||||
|
||||
DEBUG(D_noutf8)
|
||||
{
|
||||
debug_printf_indent("|-----op-res: %.*s\n", i, s);
|
Loading…
Reference in New Issue
Block a user