- bring changes from current in +fixes branch (patch-exim-fixes-ee83de04d3087efaf808d1f2235a988275c2ee94) * fixes CVE-2020-12783 (bsc#1171490) * Regard command-line recipients as tainted. * Bug 2489: Fix crash in the "pam" expansion condition. * Use tainted buffers for the transport smtp context. * Bug 2493: Harden ARC verify against Outlook, which has been seen to mix the ordering of its ARC headers. This caused a crash. * Bug 2492: Use tainted memory for retry record when needed. Previously when a new record was being constructed with information from the peer, a trap was taken. * Bug 2494: Unset the default for dmarc_tld_file. * Fix an uninitialised flag in early-pipelining. Previously connections could, depending on the platform, hang at the STARTTLS response. * Bug 2498: Reset a counter used for ARC verify before handling another message on a connection. Previously if one message had ARC headers and the following one did not, a crash could result when adding an Authentication-Results: header. * Bug 2500: Rewind some of the common-coding in string handling between the Exim main code and Exim-related utities. * Fix the variables set by the gsasl authenticator. * Bug 2507: Modules: on handling a dynamic-module (lookups) open failure, only retrieve the errormessage once. * Bug 2501: Fix init call in the heimdal authenticator. Previously it adjusted the size of a major service buffer; this failed because the buffer was in use at the time. Change to a compile-time increase in the buffer size, when this authenticator is compiled into exim. OBS-URL: https://build.opensuse.org/request/show/802873 OBS-URL: https://build.opensuse.org/package/show/server:mail/exim?expand=0&rev=234
1185 lines
41 KiB
Plaintext
1185 lines
41 KiB
Plaintext
Only in a: Local
|
|
diff -ru a/OS/Makefile-Base b/OS/Makefile-Base
|
|
--- a/OS/Makefile-Base 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/OS/Makefile-Base 2020-05-12 10:13:22.020198000 +0200
|
|
@@ -659,10 +659,13 @@
|
|
.c.o:; @echo "$(CC) $*.c"
|
|
$(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $(IPV6_INCLUDE) $(TLS_INCLUDE) $*.c
|
|
|
|
-# Update Exim's version information and build the version object.
|
|
+# Update Exim's version information and build the version object. The dependency
|
|
+# chain here avoids problems under parallel-make.
|
|
|
|
-version.h version.sh::
|
|
+version.sh:
|
|
@../scripts/reversion
|
|
+
|
|
+version.h: version.sh
|
|
|
|
cnumber.h: version.h
|
|
|
|
Only in a: doc
|
|
diff -ru a/exim_monitor/em_version.c b/exim_monitor/em_version.c
|
|
--- a/exim_monitor/em_version.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/exim_monitor/em_version.c 2020-05-12 10:13:22.022512000 +0200
|
|
@@ -5,6 +5,8 @@
|
|
/* Copyright (c) University of Cambridge 1995 - 2018 */
|
|
/* See the file NOTICE for conditions of use and distribution. */
|
|
|
|
+#define EM_VERSION_C
|
|
+
|
|
#include "mytypes.h"
|
|
#include "store.h"
|
|
#include "macros.h"
|
|
diff -ru a/src/acl.c b/src/acl.c
|
|
--- a/src/acl.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/acl.c 2020-05-12 10:13:22.024864000 +0200
|
|
@@ -2259,7 +2259,7 @@
|
|
|
|
/* Parse the other options. */
|
|
|
|
-while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)))
|
|
+while ((ss = string_nextinlist(&arg, &sep, NULL, 0)))
|
|
{
|
|
if (strcmpic(ss, US"leaky") == 0) leaky = TRUE;
|
|
else if (strcmpic(ss, US"strict") == 0) strict = TRUE;
|
|
diff -ru a/src/arc.c b/src/arc.c
|
|
--- a/src/arc.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/arc.c 2020-05-12 10:13:22.025287000 +0200
|
|
@@ -735,7 +735,7 @@
|
|
|
|
/* Setup the interface to the signing library */
|
|
|
|
-if ((errstr = exim_dkim_verify_init(&p->key, KEYFMT_DER, &vctx)))
|
|
+if ((errstr = exim_dkim_verify_init(&p->key, KEYFMT_DER, &vctx, NULL)))
|
|
{
|
|
DEBUG(D_acl) debug_printf("ARC verify init: %s\n", errstr);
|
|
as->ams_verify_done = arc_state_reason = US"internal sigverify init error";
|
|
@@ -964,7 +964,7 @@
|
|
/* We know the b-tag blob is of a nul-term string, so safe as a string */
|
|
pdkim_decode_base64(hdr_as->b.data, &sighash);
|
|
|
|
-if ((errstr = exim_dkim_verify_init(&p->key, KEYFMT_DER, &vctx)))
|
|
+if ((errstr = exim_dkim_verify_init(&p->key, KEYFMT_DER, &vctx, NULL)))
|
|
{
|
|
DEBUG(D_acl) debug_printf("ARC verify init: %s\n", errstr);
|
|
return US"fail";
|
|
diff -ru a/src/auths/README b/src/auths/README
|
|
--- a/src/auths/README 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/auths/README 2020-04-01 15:04:02.374233000 +0200
|
|
@@ -34,7 +34,7 @@
|
|
the server and/or client functions are available for this authenticator.
|
|
Typically this depends on whether server or client configuration options have
|
|
been set, but it is also possible to have an authenticator that has only one of
|
|
-the server or client functions.
|
|
+the server or client functions. The function may not touch big_buffer.
|
|
|
|
SERVER AUTHENTICATION
|
|
|
|
diff -ru a/src/auths/call_radius.c b/src/auths/call_radius.c
|
|
--- a/src/auths/call_radius.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/auths/call_radius.c 2020-05-12 10:13:22.026117000 +0200
|
|
@@ -2,6 +2,7 @@
|
|
* Exim - an Internet mail transport agent *
|
|
*************************************************/
|
|
|
|
+/* Copyright (c) The Exim Maintainers 2020 */
|
|
/* Copyright (c) University of Cambridge 1995 - 2016 */
|
|
/* See the file NOTICE for conditions of use and distribution. */
|
|
|
|
@@ -115,34 +116,34 @@
|
|
*errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
|
|
|
|
else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
|
|
- *errptr = string_sprintf("RADIUS: can't read dictionary");
|
|
+ *errptr = US"RADIUS: can't read dictionary";
|
|
|
|
-else if (rc_avpair_add(&send, PW_USER_NAME, user, 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add user name failed\n");
|
|
+else if (!rc_avpair_add(&send, PW_USER_NAME, user, 0))
|
|
+ *errptr = US"RADIUS: add user name failed";
|
|
|
|
-else if (rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add password failed\n");
|
|
+else if (!rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0))
|
|
+ *errptr = US"RADIUS: add password failed");
|
|
|
|
-else if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add service type failed\n");
|
|
+else if (!rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0))
|
|
+ *errptr = US"RADIUS: add service type failed";
|
|
|
|
#else /* RADIUS_LIB_RADIUSCLIENT unset => RADIUS_LIB_RADIUSCLIENT2 */
|
|
|
|
-if ((h = rc_read_config(RADIUS_CONFIG_FILE)) == NULL)
|
|
+if (!(h = rc_read_config(RADIUS_CONFIG_FILE)))
|
|
*errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
|
|
|
|
else if (rc_read_dictionary(h, rc_conf_str(h, "dictionary")) != 0)
|
|
- *errptr = string_sprintf("RADIUS: can't read dictionary");
|
|
+ *errptr = US"RADIUS: can't read dictionary";
|
|
|
|
-else if (rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add user name failed\n");
|
|
+else if (!rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0))
|
|
+ *errptr = US"RADIUS: add user name failed";
|
|
|
|
-else if (rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
|
|
- Ustrlen(radius_args), 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add password failed\n");
|
|
+else if (!rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
|
|
+ Ustrlen(radius_args), 0))
|
|
+ *errptr = US"RADIUS: add password failed";
|
|
|
|
-else if (rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0) == NULL)
|
|
- *errptr = string_sprintf("RADIUS: add service type failed\n");
|
|
+else if (!rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0))
|
|
+ *errptr = US"RADIUS: add service type failed";
|
|
|
|
#endif /* RADIUS_LIB_RADIUSCLIENT */
|
|
|
|
diff -ru a/src/auths/cyrus_sasl.c b/src/auths/cyrus_sasl.c
|
|
--- a/src/auths/cyrus_sasl.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/auths/cyrus_sasl.c 2020-05-12 10:13:22.026558000 +0200
|
|
@@ -347,10 +347,10 @@
|
|
}
|
|
else
|
|
{
|
|
- /* make sure that we have a null-terminated string */
|
|
- out2 = string_copyn(output, outlen);
|
|
+ /* auth_get_data() takes a length-specfied block of binary
|
|
+ which can include zeroes; no terminating NUL is needed */
|
|
|
|
- if ((rc = auth_get_data(&input, out2, outlen)) != OK)
|
|
+ if ((rc = auth_get_data(&input, output, outlen)) != OK)
|
|
{
|
|
/* we couldn't get the data, so free up the library before
|
|
* returning whatever error we get */
|
|
diff -ru a/src/auths/heimdal_gssapi.c b/src/auths/heimdal_gssapi.c
|
|
--- a/src/auths/heimdal_gssapi.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/auths/heimdal_gssapi.c 2020-05-12 10:13:22.028703000 +0200
|
|
@@ -200,16 +200,6 @@
|
|
|
|
krb5_free_context(context);
|
|
|
|
-/* RFC 4121 section 5.2, SHOULD support 64K input buffers */
|
|
-if (big_buffer_size < (64 * 1024))
|
|
- {
|
|
- uschar *newbuf;
|
|
- big_buffer_size = 64 * 1024;
|
|
- newbuf = store_malloc(big_buffer_size);
|
|
- store_free(big_buffer);
|
|
- big_buffer = newbuf;
|
|
- }
|
|
-
|
|
ablock->server = TRUE;
|
|
}
|
|
|
|
diff -ru a/src/auths/spa.c b/src/auths/spa.c
|
|
--- a/src/auths/spa.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/auths/spa.c 2020-05-12 10:13:22.029070000 +0200
|
|
@@ -139,7 +139,8 @@
|
|
SPAAuthResponse response;
|
|
SPAAuthResponse *responseptr = &response;
|
|
uschar msgbuf[2048];
|
|
-uschar *clearpass;
|
|
+uschar *clearpass, *s;
|
|
+unsigned off;
|
|
|
|
/* send a 334, MS Exchange style, and grab the client's request,
|
|
unless we already have it via an initial response. */
|
|
@@ -194,9 +195,19 @@
|
|
|
|
{
|
|
int i;
|
|
- char *p = ((char*)responseptr) + IVAL(&responseptr->uUser.offset,0);
|
|
+ char * p;
|
|
int len = SVAL(&responseptr->uUser.len,0)/2;
|
|
|
|
+ if ( (off = IVAL(&responseptr->uUser.offset,0)) >= sizeof(SPAAuthResponse)
|
|
+ || len >= sizeof(responseptr->buffer)/2
|
|
+ || (p = (CS responseptr) + off) + len*2 >= CS (responseptr+1)
|
|
+ )
|
|
+ {
|
|
+ DEBUG(D_auth)
|
|
+ debug_printf("auth_spa_server(): bad uUser spec in response\n");
|
|
+ return FAIL;
|
|
+ }
|
|
+
|
|
if (len + 1 >= sizeof(msgbuf)) return FAIL;
|
|
for (i = 0; i < len; ++i)
|
|
{
|
|
@@ -245,13 +256,17 @@
|
|
|
|
/* compare NT hash (LM may not be available) */
|
|
|
|
-if (memcmp(ntRespData,
|
|
- ((unsigned char*)responseptr)+IVAL(&responseptr->ntResponse.offset,0),
|
|
- 24) == 0)
|
|
- /* success. we have a winner. */
|
|
+off = IVAL(&responseptr->ntResponse.offset,0);
|
|
+if (off >= sizeof(SPAAuthResponse) - 24)
|
|
{
|
|
- return auth_check_serv_cond(ablock);
|
|
+ DEBUG(D_auth)
|
|
+ debug_printf("auth_spa_server(): bad ntRespData spec in response\n");
|
|
+ return FAIL;
|
|
}
|
|
+s = (US responseptr) + off;
|
|
+
|
|
+if (memcmp(ntRespData, s, 24) == 0)
|
|
+ return auth_check_serv_cond(ablock); /* success. we have a winner. */
|
|
|
|
/* Expand server_condition as an authorization check (PH) */
|
|
|
|
Only in a/src: cnumber.h
|
|
diff -ru a/src/dkim.c b/src/dkim.c
|
|
--- a/src/dkim.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/dkim.c 2020-05-12 10:13:22.056772000 +0200
|
|
@@ -401,7 +401,7 @@
|
|
dkim_cur_sig = sig;
|
|
dkim_signing_domain = US sig->domain;
|
|
dkim_signing_selector = US sig->selector;
|
|
- dkim_key_length = sig->sighash.len * 8;
|
|
+ dkim_key_length = sig->keybits;
|
|
|
|
/* These two return static strings, so we can compare the addr
|
|
later to see if the ACL overwrote them. Check that when logging */
|
|
diff -ru a/src/drtables.c b/src/drtables.c
|
|
--- a/src/drtables.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/drtables.c 2020-05-12 10:13:22.057565000 +0200
|
|
@@ -740,10 +740,11 @@
|
|
|
|
dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
|
|
if (dl == NULL) {
|
|
- fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
|
|
- moduleerrors++;
|
|
- log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
|
|
- continue;
|
|
+ errormessage = dlerror();
|
|
+ fprintf(stderr, "Error loading %s: %s\n", name, errormessage);
|
|
+ log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormessage);
|
|
+ moduleerrors++;
|
|
+ continue;
|
|
}
|
|
|
|
/* FreeBSD nsdispatch() can trigger dlerror() errors about
|
|
@@ -756,16 +757,16 @@
|
|
info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
|
|
if ((errormsg = dlerror()) != NULL) {
|
|
fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
|
|
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
|
|
dlclose(dl);
|
|
moduleerrors++;
|
|
- log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
|
|
continue;
|
|
}
|
|
if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
|
|
fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
|
|
+ log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
|
|
dlclose(dl);
|
|
moduleerrors++;
|
|
- log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
|
|
continue;
|
|
}
|
|
|
|
diff -ru a/src/exim.c b/src/exim.c
|
|
--- a/src/exim.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/exim.c 2020-05-12 10:13:22.059213000 +0200
|
|
@@ -2554,8 +2554,10 @@
|
|
#ifdef SUPPORT_I18N
|
|
allow_utf8_domains = TRUE;
|
|
#endif
|
|
- sender_address = parse_extract_address(argrest, &errmess,
|
|
- &dummy_start, &dummy_end, &sender_address_domain, TRUE);
|
|
+ if (!(sender_address = parse_extract_address(argrest, &errmess,
|
|
+ &dummy_start, &dummy_end, &sender_address_domain, TRUE)))
|
|
+ exim_fail("exim: bad -f address \"%s\": %s\n", argrest, errmess);
|
|
+
|
|
sender_address = string_copy_taint(sender_address, TRUE);
|
|
#ifdef SUPPORT_I18N
|
|
message_smtputf8 = string_is_utf8(sender_address);
|
|
@@ -2563,8 +2565,6 @@
|
|
#endif
|
|
allow_domain_literals = FALSE;
|
|
strip_trailing_dot = FALSE;
|
|
- if (!sender_address)
|
|
- exim_fail("exim: bad -f address \"%s\": %s\n", argrest, errmess);
|
|
}
|
|
f.sender_address_forced = TRUE;
|
|
}
|
|
@@ -5021,6 +5021,8 @@
|
|
deliver_localpart_orig = NULL;
|
|
deliver_domain_orig = NULL;
|
|
callout_address = sending_ip_address = NULL;
|
|
+ deliver_localpart_data = deliver_domain_data =
|
|
+ recipient_data = sender_data = NULL;
|
|
sender_rate = sender_rate_limit = sender_rate_period = NULL;
|
|
}
|
|
smtp_log_no_mail();
|
|
@@ -5681,6 +5683,8 @@
|
|
#endif
|
|
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;
|
|
|
|
diff -ru a/src/expand.c b/src/expand.c
|
|
--- a/src/expand.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/expand.c 2020-05-12 10:13:22.095677000 +0200
|
|
@@ -5029,7 +5029,7 @@
|
|
{
|
|
client_conn_ctx cctx;
|
|
int timeout = 5;
|
|
- int save_ptr = yield->ptr;
|
|
+ int save_ptr = yield ? yield->ptr : 0;
|
|
FILE * fp = NULL;
|
|
uschar * arg;
|
|
uschar * sub_arg[4];
|
|
@@ -5070,8 +5070,9 @@
|
|
uschar * item;
|
|
int sep = 0;
|
|
|
|
- item = string_nextinlist(&list, &sep, NULL, 0);
|
|
- if ((timeout = readconf_readtime(item, 0, FALSE)) < 0)
|
|
+ if ( !(item = string_nextinlist(&list, &sep, NULL, 0))
|
|
+ || !*item
|
|
+ || (timeout = readconf_readtime(item, 0, FALSE)) < 0)
|
|
{
|
|
expand_string_message = string_sprintf("bad time value %s", item);
|
|
goto EXPAND_FAILED;
|
|
@@ -5262,7 +5263,7 @@
|
|
|
|
if (sigalrm_seen)
|
|
{
|
|
- yield->ptr = save_ptr;
|
|
+ if (yield) yield->ptr = save_ptr;
|
|
expand_string_message = US "socket read timed out";
|
|
goto SOCK_FAIL;
|
|
}
|
|
@@ -5429,7 +5430,7 @@
|
|
|
|
case EITEM_TR:
|
|
{
|
|
- int oldptr = yield->ptr;
|
|
+ int oldptr = yield ? yield->ptr : 0;
|
|
int o2m;
|
|
uschar *sub[3];
|
|
|
|
@@ -6170,7 +6171,7 @@
|
|
case EITEM_REDUCE:
|
|
{
|
|
int sep = 0;
|
|
- int save_ptr = yield->ptr;
|
|
+ int save_ptr = yield ? yield->ptr : 0;
|
|
uschar outsep[2] = { '\0', '\0' };
|
|
const uschar *list, *expr, *temp;
|
|
uschar *save_iterate_item = iterate_item;
|
|
@@ -6317,7 +6318,8 @@
|
|
item of the output list, add in a space if the new item begins with the
|
|
separator character, or is an empty string. */
|
|
|
|
- if (yield->ptr != save_ptr && (temp[0] == *outsep || temp[0] == 0))
|
|
+ if ( yield && yield->ptr != save_ptr
|
|
+ && (temp[0] == *outsep || temp[0] == 0))
|
|
yield = string_catn(yield, US" ", 1);
|
|
|
|
/* Add the string in "temp" to the output list that we are building,
|
|
@@ -6357,7 +6359,7 @@
|
|
the redundant final separator. Even though an empty item at the end of a
|
|
list does not count, this is tidier. */
|
|
|
|
- else if (yield->ptr != save_ptr) yield->ptr--;
|
|
+ else if (yield && yield->ptr != save_ptr) yield->ptr--;
|
|
|
|
/* Restore preserved $item */
|
|
|
|
@@ -7222,7 +7224,7 @@
|
|
{
|
|
uschar outsep[2] = { ':', '\0' };
|
|
uschar *address, *error;
|
|
- int save_ptr = yield->ptr;
|
|
+ int save_ptr = yield ? yield->ptr : 0;
|
|
int start, end, domain; /* Not really used */
|
|
|
|
while (isspace(*sub)) sub++;
|
|
@@ -7253,7 +7255,7 @@
|
|
|
|
if (address)
|
|
{
|
|
- if (yield->ptr != save_ptr && address[0] == *outsep)
|
|
+ if (yield && yield->ptr != save_ptr && address[0] == *outsep)
|
|
yield = string_catn(yield, US" ", 1);
|
|
|
|
for (;;)
|
|
@@ -7282,7 +7284,7 @@
|
|
/* If we have generated anything, remove the redundant final
|
|
separator. */
|
|
|
|
- if (yield->ptr != save_ptr) yield->ptr--;
|
|
+ if (yield && yield->ptr != save_ptr) yield->ptr--;
|
|
f.parse_allow_group = FALSE;
|
|
continue;
|
|
}
|
|
@@ -7421,10 +7423,10 @@
|
|
|
|
case EOP_FROM_UTF8:
|
|
{
|
|
- while (*sub != 0)
|
|
+ uschar * buff = store_get(4, is_tainted(sub));
|
|
+ while (*sub)
|
|
{
|
|
int c;
|
|
- uschar buff[4];
|
|
GETUTF8INC(c, sub);
|
|
if (c > 255) c = '_';
|
|
buff[0] = c;
|
|
@@ -7445,7 +7447,17 @@
|
|
int complete;
|
|
uschar seq_buff[4]; /* accumulate utf-8 here */
|
|
|
|
- while (*sub != 0)
|
|
+ /* Manually track tainting, as we deal in individual chars below */
|
|
+
|
|
+ if (is_tainted(sub))
|
|
+ if (yield->s && yield->ptr)
|
|
+ gstring_rebuffer(yield);
|
|
+ else
|
|
+ yield->s = store_get(yield->size = Ustrlen(sub), TRUE);
|
|
+
|
|
+ /* Check the UTF-8, byte-by-byte */
|
|
+
|
|
+ while (*sub)
|
|
{
|
|
complete = 0;
|
|
uschar c = *sub++;
|
|
diff -ru a/src/functions.h b/src/functions.h
|
|
--- a/src/functions.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/functions.h 2020-05-12 10:13:22.097024000 +0200
|
|
@@ -187,6 +187,7 @@
|
|
extern uschar *deliver_get_sender_address (uschar *id);
|
|
extern void delivery_re_exec(int);
|
|
|
|
+extern void die_tainted(const uschar *, const uschar *, int);
|
|
extern BOOL directory_make(const uschar *, const uschar *, int, BOOL);
|
|
#ifndef DISABLE_DKIM
|
|
extern uschar *dkim_exim_query_dns_txt(const uschar *);
|
|
@@ -602,6 +603,58 @@
|
|
extern ssize_t write_to_fd_buf(int, const uschar *, size_t);
|
|
|
|
|
|
+/******************************************************************************/
|
|
+/* Predicate: if an address is in a tainted pool.
|
|
+By extension, a variable pointing to this address is tainted.
|
|
+*/
|
|
+
|
|
+static inline BOOL
|
|
+is_tainted(const void * p)
|
|
+{
|
|
+#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) || defined(EM_VERSION_C)
|
|
+return FALSE;
|
|
+
|
|
+#else
|
|
+extern BOOL is_tainted_fn(const void *);
|
|
+return is_tainted_fn(p);
|
|
+#endif
|
|
+}
|
|
+
|
|
+/******************************************************************************/
|
|
+/* String functions */
|
|
+static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line)
|
|
+{
|
|
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
|
|
+#endif
|
|
+return US strcat(CS dst, CCS src);
|
|
+}
|
|
+static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
|
|
+{
|
|
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
|
|
+#endif
|
|
+return US strcpy(CS dst, CCS src);
|
|
+}
|
|
+static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
|
|
+{
|
|
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
|
|
+#endif
|
|
+return US strncat(CS dst, CCS src, n);
|
|
+}
|
|
+static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
|
|
+{
|
|
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
|
|
+#endif
|
|
+return US strncpy(CS dst, CCS src, n);
|
|
+}
|
|
+/*XXX will likely need unchecked copy also */
|
|
+
|
|
+
|
|
+/******************************************************************************/
|
|
+
|
|
#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
|
|
/* exim_chown - in some NFSv4 setups *seemes* to be an issue with
|
|
chown(<exim-uid>, <exim-gid>).
|
|
@@ -634,8 +687,8 @@
|
|
return chown(CCS name, owner, group)
|
|
? exim_chown_failure(-1, name, owner, group) : 0;
|
|
}
|
|
-
|
|
#endif /* !MACRO_PREDEF && !COMPILE_UTILITY */
|
|
+
|
|
/******************************************************************************/
|
|
/* String functions */
|
|
|
|
@@ -848,6 +901,18 @@
|
|
va_end(ap);
|
|
return g;
|
|
}
|
|
+
|
|
+
|
|
+/* Copy the content of a string to tainted memory */
|
|
+
|
|
+static inline void
|
|
+gstring_rebuffer(gstring * g)
|
|
+{
|
|
+uschar * s = store_get(g->size, TRUE);
|
|
+memcpy(s, g->s, g->ptr);
|
|
+g->s = s;
|
|
+}
|
|
+
|
|
|
|
/******************************************************************************/
|
|
|
|
diff -ru a/src/globals.c b/src/globals.c
|
|
--- a/src/globals.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/globals.c 2020-05-12 10:13:22.097761000 +0200
|
|
@@ -311,6 +311,7 @@
|
|
.synchronous_delivery = FALSE,
|
|
.system_filtering = FALSE,
|
|
|
|
+ .taint_check_slow = FALSE,
|
|
.tcp_fastopen_ok = FALSE,
|
|
.tcp_in_fastopen = FALSE,
|
|
.tcp_in_fastopen_data = FALSE,
|
|
diff -ru a/src/globals.h b/src/globals.h
|
|
--- a/src/globals.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/globals.h 2020-05-12 10:13:22.098294000 +0200
|
|
@@ -272,6 +272,7 @@
|
|
BOOL synchronous_delivery :1; /* TRUE if -odi is set */
|
|
BOOL system_filtering :1; /* TRUE when running system filter */
|
|
|
|
+ BOOL taint_check_slow :1; /* malloc/mmap are not returning distinct ranges */
|
|
BOOL tcp_fastopen_ok :1; /* appears to be supported by kernel */
|
|
BOOL tcp_in_fastopen :1; /* conn usefully used fastopen */
|
|
BOOL tcp_in_fastopen_data :1; /* fastopen carried data */
|
|
@@ -339,7 +340,7 @@
|
|
extern BOOL allow_domain_literals; /* As it says */
|
|
extern BOOL allow_mx_to_ip; /* Allow MX records to -> ip address */
|
|
#ifdef EXPERIMENTAL_ARC
|
|
-struct arc_set *arc_received; /* highest ARC instance evaluation struct */
|
|
+extern struct arc_set *arc_received; /* highest ARC instance evaluation struct */
|
|
extern int arc_received_instance; /* highest ARC instance number in headers */
|
|
extern int arc_oldest_pass; /* lowest passing instance number in headers */
|
|
extern const uschar *arc_state; /* verification state */
|
|
diff -ru a/src/ip.c b/src/ip.c
|
|
--- a/src/ip.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/ip.c 2020-05-12 10:13:22.099852000 +0200
|
|
@@ -269,28 +269,34 @@
|
|
/*XXX also seen on successful TFO, sigh */
|
|
tcp_out_fastopen = fastopen_blob->len > 0 ? TFO_ATTEMPTED_DATA : TFO_ATTEMPTED_NODATA;
|
|
}
|
|
- else if (errno == EINPROGRESS) /* expected if we had no cookie for peer */
|
|
+ else switch (errno)
|
|
+ {
|
|
+ case EINPROGRESS: /* expected if we had no cookie for peer */
|
|
/* seen for no-data, proper TFO option, both cookie-request and with-cookie cases */
|
|
/* apparently no visibility of the diffference at this point */
|
|
/* seen for with-data, proper TFO opt, cookie-req */
|
|
/* with netwk delay, post-conn tcp_info sees unacked 1 for R, 2 for C; code in smtp_out.c */
|
|
/* ? older Experimental TFO option behaviour ? */
|
|
- { /* queue unsent data */
|
|
- DEBUG(D_transport|D_v) debug_printf(" TFO mode sendto, %s data: EINPROGRESS\n",
|
|
- fastopen_blob->len > 0 ? "with" : "no");
|
|
- if (!fastopen_blob->data)
|
|
- {
|
|
- tcp_out_fastopen = TFO_ATTEMPTED_NODATA; /* we tried; unknown if useful yet */
|
|
- rc = 0;
|
|
- }
|
|
- else
|
|
- rc = send(sock, fastopen_blob->data, fastopen_blob->len, 0);
|
|
- }
|
|
- else if(errno == EOPNOTSUPP)
|
|
- {
|
|
- DEBUG(D_transport)
|
|
- debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
|
|
- goto legacy_connect;
|
|
+ DEBUG(D_transport|D_v) debug_printf(" TFO mode sendto, %s data: EINPROGRESS\n",
|
|
+ fastopen_blob->len > 0 ? "with" : "no");
|
|
+ if (!fastopen_blob->data)
|
|
+ {
|
|
+ tcp_out_fastopen = TFO_ATTEMPTED_NODATA; /* we tried; unknown if useful yet */
|
|
+ rc = 0;
|
|
+ }
|
|
+ else /* queue unsent data */
|
|
+ rc = send(sock, fastopen_blob->data, fastopen_blob->len, 0);
|
|
+ break;
|
|
+
|
|
+ case EOPNOTSUPP:
|
|
+ DEBUG(D_transport)
|
|
+ debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
|
|
+ goto legacy_connect;
|
|
+
|
|
+ case EPIPE:
|
|
+ DEBUG(D_transport)
|
|
+ debug_printf("Tried TCP Fast Open but kernel too old to support it\n");
|
|
+ goto legacy_connect;
|
|
}
|
|
# endif
|
|
# ifdef EXIM_TFO_CONNECTX
|
|
diff -ru a/src/lookups/dsearch.c b/src/lookups/dsearch.c
|
|
--- a/src/lookups/dsearch.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/lookups/dsearch.c 2020-05-12 10:13:22.117328000 +0200
|
|
@@ -28,7 +28,7 @@
|
|
dsearch_open(uschar *dirname, uschar **errmsg)
|
|
{
|
|
DIR *dp = opendir(CS dirname);
|
|
-if (dp == NULL)
|
|
+if (!dp)
|
|
{
|
|
int save_errno = errno;
|
|
*errmsg = string_open_failed(errno, "%s for directory search", dirname);
|
|
@@ -47,8 +47,8 @@
|
|
/* The handle will always be (void *)(-1), but don't try casting it to an
|
|
integer as this gives warnings on 64-bit systems. */
|
|
|
|
-BOOL
|
|
-static dsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners,
|
|
+static BOOL
|
|
+dsearch_check(void *handle, uschar *filename, int modemask, uid_t *owners,
|
|
gid_t *owngroups, uschar **errmsg)
|
|
{
|
|
handle = handle;
|
|
@@ -87,7 +87,9 @@
|
|
filename = string_sprintf("%s/%s", dirname, keystring);
|
|
if (Ulstat(filename, &statbuf) >= 0)
|
|
{
|
|
- *result = string_copy(keystring);
|
|
+ /* Since the filename exists in the filesystem, we can return a
|
|
+ non-tainted result. */
|
|
+ *result = string_copy_taint(keystring, FALSE);
|
|
return OK;
|
|
}
|
|
|
|
diff -ru a/src/macros.h b/src/macros.h
|
|
--- a/src/macros.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/macros.h 2020-05-12 10:13:22.122799000 +0200
|
|
@@ -152,12 +152,19 @@
|
|
into big_buffer_size and in some circumstances increased. It should be at least
|
|
as long as the maximum path length. */
|
|
|
|
-#if defined PATH_MAX && PATH_MAX > 16384
|
|
+#ifdef AUTH_HEIMDAL_GSSAPI
|
|
+ /* RFC 4121 section 5.2, SHOULD support 64K input buffers */
|
|
+# define __BIG_BUFFER_SIZE 65536
|
|
+#else
|
|
+# define __BIG_BUFFER_SIZE 16384
|
|
+#endif
|
|
+
|
|
+#if defined PATH_MAX && PATH_MAX > __BIG_BUFFER_SIZE
|
|
# define BIG_BUFFER_SIZE PATH_MAX
|
|
-#elif defined MAXPATHLEN && MAXPATHLEN > 16384
|
|
+#elif defined MAXPATHLEN && MAXPATHLEN > __BIG_BUFFER_SIZE
|
|
# define BIG_BUFFER_SIZE MAXPATHLEN
|
|
#else
|
|
-# define BIG_BUFFER_SIZE 16384
|
|
+# define BIG_BUFFER_SIZE __BIG_BUFFER_SIZE
|
|
#endif
|
|
|
|
/* header size of pipe content
|
|
diff -ru a/src/mytypes.h b/src/mytypes.h
|
|
--- a/src/mytypes.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/mytypes.h 2020-05-12 10:13:22.125222000 +0200
|
|
@@ -100,19 +100,15 @@
|
|
#define Uread(f,b,l) read(f,CS(b),l)
|
|
#define Urename(s,t) rename(CCS(s),CCS(t))
|
|
#define Ustat(s,t) stat(CCS(s),t)
|
|
-#define Ustrcat(s,t) __Ustrcat(s, CUS(t), __FUNCTION__, __LINE__)
|
|
#define Ustrchr(s,n) US strchr(CCS(s),n)
|
|
#define CUstrchr(s,n) CUS strchr(CCS(s),n)
|
|
#define CUstrerror(n) CUS strerror(n)
|
|
#define Ustrcmp(s,t) strcmp(CCS(s),CCS(t))
|
|
-#define Ustrcpy(s,t) __Ustrcpy(s, CUS(t), __FUNCTION__, __LINE__)
|
|
#define Ustrcpy_nt(s,t) strcpy(CS s, CCS t) /* no taint check */
|
|
#define Ustrcspn(s,t) strcspn(CCS(s),CCS(t))
|
|
#define Ustrftime(s,m,f,t) strftime(CS(s),m,f,t)
|
|
#define Ustrlen(s) (int)strlen(CCS(s))
|
|
-#define Ustrncat(s,t,n) __Ustrncat(s, CUS(t),n, __FUNCTION__, __LINE__)
|
|
#define Ustrncmp(s,t,n) strncmp(CCS(s),CCS(t),n)
|
|
-#define Ustrncpy(s,t,n) __Ustrncpy(s, CUS(t),n, __FUNCTION__, __LINE__)
|
|
#define Ustrncpy_nt(s,t,n) strncpy(CS s, CCS t, n) /* no taint check */
|
|
#define Ustrpbrk(s,t) strpbrk(CCS(s),CCS(t))
|
|
#define Ustrrchr(s,n) US strrchr(CCS(s),n)
|
|
@@ -125,57 +121,17 @@
|
|
#define Ustrtoul(s,t,b) strtoul(CCS(s),CSS(t),b)
|
|
#define Uunlink(s) unlink(CCS(s))
|
|
|
|
-extern void die_tainted(const uschar *, const uschar *, int);
|
|
-
|
|
-/* Predicate: if an address is in a tainted pool.
|
|
-By extension, a variable pointing to this address is tainted.
|
|
-*/
|
|
-
|
|
-static inline BOOL
|
|
-is_tainted(const void * p)
|
|
-{
|
|
-#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
|
|
-return FALSE;
|
|
-
|
|
-#elif defined(TAINT_CHECK_SLOW)
|
|
-extern BOOL is_tainted_fn(const void *);
|
|
-return is_tainted_fn(p);
|
|
-
|
|
+#ifdef EM_VERSION_C
|
|
+# define Ustrcat(s,t) strcat(CS(s), CCS(t))
|
|
+# define Ustrcpy(s,t) strcpy(CS(s), CCS(t))
|
|
+# define Ustrncat(s,t,n) strncat(CS(s), CCS(t), n)
|
|
+# define Ustrncpy(s,t,n) strncpy(CS(s), CCS(t), n)
|
|
#else
|
|
-extern void * tainted_base, * tainted_top;
|
|
-return p >= tainted_base && p < tainted_top;
|
|
+# define Ustrcat(s,t) __Ustrcat(s, CUS(t), __FUNCTION__, __LINE__)
|
|
+# define Ustrcpy(s,t) __Ustrcpy(s, CUS(t), __FUNCTION__, __LINE__)
|
|
+# define Ustrncat(s,t,n) __Ustrncat(s, CUS(t), n, __FUNCTION__, __LINE__)
|
|
+# define Ustrncpy(s,t,n) __Ustrncpy(s, CUS(t), n, __FUNCTION__, __LINE__)
|
|
#endif
|
|
-}
|
|
-
|
|
-static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line)
|
|
-{
|
|
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
|
|
-#endif
|
|
-return US strcat(CS dst, CCS src);
|
|
-}
|
|
-static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
|
|
-{
|
|
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
|
|
-#endif
|
|
-return US strcpy(CS dst, CCS src);
|
|
-}
|
|
-static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
|
|
-{
|
|
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
|
|
-#endif
|
|
-return US strncat(CS dst, CCS src, n);
|
|
-}
|
|
-static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
|
|
-{
|
|
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
|
|
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
|
|
-#endif
|
|
-return US strncpy(CS dst, CCS src, n);
|
|
-}
|
|
-/*XXX will likely need unchecked copy also */
|
|
|
|
#endif
|
|
/* End of mytypes.h */
|
|
diff -ru a/src/pdkim/pdkim.c b/src/pdkim/pdkim.c
|
|
--- a/src/pdkim/pdkim.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/pdkim/pdkim.c 2020-05-12 10:13:22.126558000 +0200
|
|
@@ -1430,7 +1430,7 @@
|
|
|
|
if ((*errstr = exim_dkim_verify_init(&p->key,
|
|
sig->keytype == KEYTYPE_ED25519 ? KEYFMT_ED25519_BARE : KEYFMT_DER,
|
|
- vctx)))
|
|
+ vctx, &sig->keybits)))
|
|
{
|
|
DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
|
|
sig->verify_status = PDKIM_VERIFY_INVALID;
|
|
diff -ru a/src/pdkim/pdkim.h b/src/pdkim/pdkim.h
|
|
--- a/src/pdkim/pdkim.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/pdkim/pdkim.h 2020-05-12 10:13:22.126756000 +0200
|
|
@@ -140,8 +140,9 @@
|
|
int version;
|
|
|
|
/* (a=) The signature algorithm. */
|
|
- int keytype; /* pdkim_keytypes index */
|
|
- int hashtype; /* pdkim_hashes index */
|
|
+ int keytype; /* pdkim_keytypes index */
|
|
+ unsigned keybits; /* size of the key */
|
|
+ int hashtype; /* pdkim_hashes index */
|
|
|
|
/* (c=x/) Header canonicalization method. Either PDKIM_CANON_SIMPLE
|
|
or PDKIM_CANON_RELAXED */
|
|
diff -ru a/src/pdkim/signing.c b/src/pdkim/signing.c
|
|
--- a/src/pdkim/signing.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/pdkim/signing.c 2020-05-12 10:13:22.127061000 +0200
|
|
@@ -155,7 +155,8 @@
|
|
Return: NULL for success, or an error string */
|
|
|
|
const uschar *
|
|
-exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx)
|
|
+exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx,
|
|
+ unsigned * bits)
|
|
{
|
|
gnutls_datum_t k;
|
|
int rc;
|
|
@@ -182,6 +183,7 @@
|
|
ret = US"pubkey format not handled";
|
|
break;
|
|
}
|
|
+if (!ret && bits) gnutls_pubkey_get_pk_algorithm(verify_ctx->key, bits);
|
|
return ret;
|
|
}
|
|
|
|
@@ -552,7 +554,8 @@
|
|
Return: NULL for success, or an error string */
|
|
|
|
const uschar *
|
|
-exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx)
|
|
+exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx,
|
|
+ unsigned * bits)
|
|
{
|
|
/*
|
|
in code sequence per b81207d2bfa92 rsa_parse_public_key() and asn1_get_mpi()
|
|
@@ -560,6 +563,7 @@
|
|
uschar tag_class;
|
|
int taglen;
|
|
long alen;
|
|
+unsigned nbits;
|
|
int rc;
|
|
uschar * errstr;
|
|
gcry_error_t gerr;
|
|
@@ -608,10 +612,10 @@
|
|
|
|
/* read two integers */
|
|
DEBUG(D_acl) stage = US"MPI";
|
|
-if ( (errstr = as_mpi(pubkey, &verify_ctx->n))
|
|
- || (errstr = as_mpi(pubkey, &verify_ctx->e))
|
|
- )
|
|
- return errstr;
|
|
+nbits = pubkey->len;
|
|
+if ((errstr = as_mpi(pubkey, &verify_ctx->n))) return errstr;
|
|
+nbits = (nbits - pubkey->len) * 8;
|
|
+if ((errstr = as_mpi(pubkey, &verify_ctx->e))) return errstr;
|
|
|
|
#ifdef extreme_debug
|
|
DEBUG(D_acl) debug_printf_indent("rsa_verify_init:\n");
|
|
@@ -624,6 +628,7 @@
|
|
}
|
|
|
|
#endif
|
|
+if (bits) *bits = nbits;
|
|
return NULL;
|
|
|
|
asn_err:
|
|
@@ -794,7 +799,8 @@
|
|
Return: NULL for success, or an error string */
|
|
|
|
const uschar *
|
|
-exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx)
|
|
+exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx,
|
|
+ unsigned * bits)
|
|
{
|
|
const uschar * s = pubkey->data;
|
|
uschar * ret = NULL;
|
|
@@ -818,6 +824,7 @@
|
|
break;
|
|
}
|
|
|
|
+if (!ret && bits) *bits = EVP_PKEY_bits(verify_ctx->key);
|
|
return ret;
|
|
}
|
|
|
|
diff -ru a/src/pdkim/signing.h b/src/pdkim/signing.h
|
|
--- a/src/pdkim/signing.h 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/pdkim/signing.h 2020-05-12 10:13:22.127197000 +0200
|
|
@@ -90,7 +90,7 @@
|
|
|
|
extern const uschar * exim_dkim_signing_init(const uschar *, es_ctx *);
|
|
extern const uschar * exim_dkim_sign(es_ctx *, hashmethod, blob *, blob *);
|
|
-extern const uschar * exim_dkim_verify_init(blob *, keyformat, ev_ctx *);
|
|
+extern const uschar * exim_dkim_verify_init(blob *, keyformat, ev_ctx *, unsigned *);
|
|
extern const uschar * exim_dkim_verify(ev_ctx *, hashmethod, blob *, blob *);
|
|
|
|
#endif /*DISABLE_DKIM*/
|
|
diff -ru a/src/readconf.c b/src/readconf.c
|
|
--- a/src/readconf.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/readconf.c 2020-05-12 10:13:22.129420000 +0200
|
|
@@ -3788,6 +3788,7 @@
|
|
if (!d->driver_name)
|
|
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
|
|
"no driver defined for %s \"%s\"", class, d->name);
|
|
+ /* s is using big_buffer, so this call had better not */
|
|
(d->info->init)(d);
|
|
d = NULL;
|
|
}
|
|
diff -ru a/src/receive.c b/src/receive.c
|
|
--- a/src/receive.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/receive.c 2020-05-12 10:13:22.130574000 +0200
|
|
@@ -270,8 +270,8 @@
|
|
"check_space = " PR_EXIM_ARITH "K inodes = %d msg_size = %d\n",
|
|
space, inodes, check_spool_space, check_spool_inodes, msg_size);
|
|
|
|
- if ((space >= 0 && space < check_spool_space) ||
|
|
- (inodes >= 0 && inodes < check_spool_inodes))
|
|
+ if ( space >= 0 && space + msg_size / 1024 < check_spool_space
|
|
+ || inodes >= 0 && inodes < check_spool_inodes)
|
|
{
|
|
log_write(0, LOG_MAIN, "spool directory space check failed: space="
|
|
PR_EXIM_ARITH " inodes=%d", space, inodes);
|
|
@@ -1755,6 +1755,13 @@
|
|
|
|
message_linecount = body_linecount = body_zerocount =
|
|
max_received_linelength = 0;
|
|
+
|
|
+#ifdef WITH_CONTENT_SCAN
|
|
+/* reset non-per-part mime variables */
|
|
+mime_is_coverletter = 0;
|
|
+mime_is_rfc822 = 0;
|
|
+mime_part_count = -1;
|
|
+#endif
|
|
|
|
#ifndef DISABLE_DKIM
|
|
/* Call into DKIM to set up the context. In CHUNKING mode
|
|
diff -ru a/src/smtp_in.c b/src/smtp_in.c
|
|
--- a/src/smtp_in.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/smtp_in.c 2020-05-12 10:13:22.137165000 +0200
|
|
@@ -2050,7 +2050,8 @@
|
|
f.active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
|
|
sending_ip_address = NULL;
|
|
return_path = sender_address = NULL;
|
|
-sender_data = NULL; /* Can be set by ACL */
|
|
+deliver_localpart_data = deliver_domain_data =
|
|
+recipient_data = sender_data = NULL; /* Can be set by ACL */
|
|
deliver_localpart_parent = deliver_localpart_orig = NULL;
|
|
deliver_domain_parent = deliver_domain_orig = NULL;
|
|
callout_address = NULL;
|
|
diff -ru a/src/spf.c b/src/spf.c
|
|
--- a/src/spf.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/spf.c 2020-05-12 10:13:22.138197000 +0200
|
|
@@ -139,7 +139,12 @@
|
|
srr.rr[found++] = (void *) s;
|
|
}
|
|
|
|
-srr.num_rr = found;
|
|
+/* Did we filter out all TXT RRs? Return NO_DATA instead of SUCCESS with
|
|
+empty ANSWER section. */
|
|
+
|
|
+if (!(srr.num_rr = found))
|
|
+ srr.herrno = NO_DATA;
|
|
+
|
|
/* spfrr->rr must have been malloc()d for this */
|
|
SPF_dns_rr_dup(&spfrr, &srr);
|
|
return spfrr;
|
|
diff -ru a/src/store.c b/src/store.c
|
|
--- a/src/store.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/store.c 2020-05-12 10:13:22.139605000 +0200
|
|
@@ -102,13 +102,6 @@
|
|
static void *next_yield[NPOOLS];
|
|
static int yield_length[NPOOLS] = { -1, -1, -1, -1, -1, -1 };
|
|
|
|
-/* The limits of the tainted pools. Tracking these on new allocations enables
|
|
-a fast is_tainted implementation. We assume the kernel only allocates mmaps using
|
|
-one side or the other of data+heap, not both. */
|
|
-
|
|
-void * tainted_base = (void *)-1;
|
|
-void * tainted_top = (void *)0;
|
|
-
|
|
/* pool_malloc holds the amount of memory used by the store pools; this goes up
|
|
and down as store is reset or released. nonpool_malloc is the total got by
|
|
malloc from other calls; this doesn't go down because it is just freed by
|
|
@@ -162,32 +155,34 @@
|
|
|
|
/******************************************************************************/
|
|
|
|
-/* Slower version check, for use when platform intermixes malloc and mmap area
|
|
-addresses. */
|
|
+/* Test if a pointer refers to tainted memory.
|
|
|
|
+Slower version check, for use when platform intermixes malloc and mmap area
|
|
+addresses. Test against the current-block of all tainted pools first, then all
|
|
+blocks of all tainted pools.
|
|
+
|
|
+Return: TRUE iff tainted
|
|
+*/
|
|
+
|
|
BOOL
|
|
is_tainted_fn(const void * p)
|
|
{
|
|
storeblock * b;
|
|
-int pool;
|
|
|
|
-for (pool = 0; pool < nelem(chainbase); pool++)
|
|
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
|
|
if ((b = current_block[pool]))
|
|
{
|
|
- char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
|
|
- if (CS p >= bc && CS p <= bc + b->length) goto hit;
|
|
+ uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
|
|
+ if (US p >= bc && US p <= bc + b->length) return TRUE;
|
|
}
|
|
|
|
-for (pool = 0; pool < nelem(chainbase); pool++)
|
|
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
|
|
for (b = chainbase[pool]; b; b = b->next)
|
|
{
|
|
- char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
|
|
- if (CS p >= bc && CS p <= bc + b->length) goto hit;
|
|
+ uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
|
|
+ if (US p >= bc && US p <= bc + b->length) return TRUE;
|
|
}
|
|
return FALSE;
|
|
-
|
|
-hit:
|
|
-return pool >= POOL_TAINT_BASE;
|
|
}
|
|
|
|
|
|
@@ -199,6 +194,7 @@
|
|
}
|
|
|
|
|
|
+
|
|
/*************************************************
|
|
* Get a block from the current pool *
|
|
*************************************************/
|
|
@@ -730,7 +726,7 @@
|
|
BOOL release_ok = !tainted && store_last_get[pool] == block;
|
|
uschar * newtext;
|
|
|
|
-#ifndef MACRO_PREDEF
|
|
+#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
|
|
if (is_tainted(block) != tainted)
|
|
die_tainted(US"store_newblock", CUS func, linenumber);
|
|
#endif
|
|
@@ -786,9 +782,6 @@
|
|
PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)))
|
|
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to mmap %d bytes of memory: "
|
|
"called from line %d of %s", size, line, func);
|
|
-
|
|
-if (yield < tainted_base) tainted_base = yield;
|
|
-if ((top = US yield + size) > tainted_top) tainted_top = top;
|
|
|
|
return store_alloc_tail(yield, size, func, line, US"Mmap");
|
|
}
|
|
diff -ru a/src/string.c b/src/string.c
|
|
--- a/src/string.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/string.c 2020-05-12 10:13:22.146645000 +0200
|
|
@@ -12,7 +12,6 @@
|
|
#include "exim.h"
|
|
#include <assert.h>
|
|
|
|
-static void gstring_rebuffer(gstring * g);
|
|
|
|
#ifndef COMPILE_UTILITY
|
|
/*************************************************
|
|
@@ -1241,16 +1240,6 @@
|
|
return !!gp;
|
|
}
|
|
|
|
-
|
|
-
|
|
-/* Copy the content of a string to tainted memory */
|
|
-static void
|
|
-gstring_rebuffer(gstring * g)
|
|
-{
|
|
-uschar * s = store_get(g->size, TRUE);
|
|
-memcpy(s, g->s, g->ptr);
|
|
-g->s = s;
|
|
-}
|
|
|
|
|
|
|
|
diff -ru a/src/tls-gnu.c b/src/tls-gnu.c
|
|
--- a/src/tls-gnu.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/tls-gnu.c 2020-05-12 10:13:22.148137000 +0200
|
|
@@ -181,6 +181,10 @@
|
|
BOOL peer_dane_verified;
|
|
BOOL trigger_sni_changes;
|
|
BOOL have_set_peerdn;
|
|
+#ifdef SUPPORT_CORK
|
|
+ BOOL corked:1;
|
|
+#endif
|
|
+
|
|
const struct host_item *host; /* NULL if server */
|
|
gnutls_x509_crt_t peercert;
|
|
uschar *peerdn;
|
|
@@ -3309,9 +3313,8 @@
|
|
size_t left = len;
|
|
exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server;
|
|
#ifdef SUPPORT_CORK
|
|
-static BOOL corked = FALSE;
|
|
|
|
-if (more && !corked) gnutls_record_cork(state->session);
|
|
+if (more && !state->corked) gnutls_record_cork(state->session);
|
|
#endif
|
|
|
|
DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
|
|
@@ -3352,10 +3355,10 @@
|
|
}
|
|
|
|
#ifdef SUPPORT_CORK
|
|
-if (more != corked)
|
|
+if (more != state->corked)
|
|
{
|
|
if (!more) (void) gnutls_record_uncork(state->session, 0);
|
|
- corked = more;
|
|
+ state->corked = more;
|
|
}
|
|
#endif
|
|
|
|
diff -ru a/src/tls-openssl.c b/src/tls-openssl.c
|
|
--- a/src/tls-openssl.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/tls-openssl.c 2020-05-12 10:13:22.149180000 +0200
|
|
@@ -2480,7 +2480,7 @@
|
|
#endif
|
|
}
|
|
|
|
- /* If a certificate file is empty, the next function fails with an
|
|
+ /* If a certificate file is empty, the load function fails with an
|
|
unhelpful error message. If we skip it, we get the correct behaviour (no
|
|
certificates are recognized, but the error message is still misleading (it
|
|
says no certificate was supplied). But this is better. */
|
|
@@ -2489,9 +2489,9 @@
|
|
&& !SSL_CTX_load_verify_locations(sctx, CS file, CS dir))
|
|
return tls_error(US"SSL_CTX_load_verify_locations", host, NULL, errstr);
|
|
|
|
- /* Load the list of CAs for which we will accept certs, for sending
|
|
- to the client. This is only for the one-file tls_verify_certificates
|
|
- variant.
|
|
+ /* On the server load the list of CAs for which we will accept certs, for
|
|
+ sending to the client. This is only for the one-file
|
|
+ tls_verify_certificates variant.
|
|
If a list isn't loaded into the server, but some verify locations are set,
|
|
the server end appears to make a wildcard request for client certs.
|
|
Meanwhile, the client library as default behaviour *ignores* the list
|
|
@@ -2503,7 +2503,7 @@
|
|
{
|
|
STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file);
|
|
|
|
- SSL_CTX_set_client_CA_list(sctx, names);
|
|
+ if (!host) SSL_CTX_set_client_CA_list(sctx, names);
|
|
DEBUG(D_tls) debug_printf("Added %d certificate authorities.\n",
|
|
sk_X509_NAME_num(names));
|
|
}
|
|
diff -ru a/src/transport.c b/src/transport.c
|
|
--- a/src/transport.c 2020-01-03 13:08:52.000000000 +0100
|
|
+++ b/src/transport.c 2020-05-12 10:13:22.150276000 +0200
|
|
@@ -253,6 +253,7 @@
|
|
|
|
else
|
|
{
|
|
+ sigalrm_seen = FALSE;
|
|
ALARM(local_timeout);
|
|
|
|
rc =
|
|
Only in a/src: version.h
|
|
Only in a/src: version.sh
|