summaryrefslogtreecommitdiffstats
path: root/debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch')
-rw-r--r--debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch83
1 files changed, 83 insertions, 0 deletions
diff --git a/debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch b/debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch
new file mode 100644
index 0000000..0f36d73
--- /dev/null
+++ b/debian/patches/80_01-GnuTLS-fix-hanging-callout-connections.patch
@@ -0,0 +1,83 @@
+From 97c5e07c220b55d1c506a1798c9ce3ae3105adea Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Thu, 13 Feb 2020 16:45:38 +0000
+Subject: [PATCH 4/6] GnuTLS: fix hanging callout connections
+
+Broken-by: 925ac8e4f1
+(cherry picked from commit bd95ffc2ba87fbd3c752df17bc8fd9c01586d45a)
+---
+ doc/ChangeLog | 81 ++++---------------------------------------
+ src/tls-gnu.c | 24 +++++++------
+ 2 files changed, 20 insertions(+), 85 deletions(-)
+
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -67,6 +67,11 @@ JH/41 Bug 2571: Fix SPA authenticator.
+ being used. A malicious client could thus cause an out-of-bounds read and
+ possibly gain authentication. Fix by adding the check.
+
++JH/25 Fix use of concurrent TLS connections under GnuTLS. When a callout was
++ done during a receiving connection, and both used TLS, global info was
++ used rather than per-connection info for tracking the state of data
++ queued for transmission. This could result in a connection hang.
++
+
+ Exim version 4.92
+ -----------------
+--- a/src/tls-gnu.c
++++ b/src/tls-gnu.c
+@@ -124,10 +124,17 @@ typedef struct exim_gnutls_state {
+ enum peer_verify_requirement verify_requirement;
+ int fd_in;
+ int fd_out;
+- BOOL peer_cert_verified;
+- BOOL peer_dane_verified;
+- BOOL trigger_sni_changes;
+- BOOL have_set_peerdn;
++
++ BOOL peer_cert_verified:1;
++ BOOL peer_dane_verified:1;
++ BOOL trigger_sni_changes:1;
++ BOOL have_set_peerdn:1;
++ BOOL xfer_eof:1; /*XXX never gets set! */
++ BOOL xfer_error:1;
++#ifdef SUPPORT_CORK
++ BOOL corked:1;
++#endif
++
+ const struct host_item *host; /* NULL if server */
+ gnutls_x509_crt_t peercert;
+ uschar *peerdn;
+@@ -160,8 +167,6 @@ typedef struct exim_gnutls_state {
+ uschar *xfer_buffer;
+ int xfer_buffer_lwm;
+ int xfer_buffer_hwm;
+- BOOL xfer_eof; /*XXX never gets set! */
+- BOOL xfer_error;
+ } exim_gnutls_state_st;
+
+ static const exim_gnutls_state_st exim_gnutls_state_init = {
+@@ -2790,9 +2795,8 @@ ssize_t outbytes;
+ 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__,
+@@ -2833,10 +2837,10 @@ if (len > INT_MAX)
+ }
+
+ #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
+