exim/patch-exim-fixes-ee83de04d3087efaf808d1f2235a988275c2ee94
Peter Wullinger c7d2171b05 Accepting request 802873 from home:pwcau:branches:server:mail
- 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
2020-05-12 08:36:31 +00:00

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