Commit | Line | Data |
---|---|---|
0c0c20aa AM |
1 | From 97c5e07c220b55d1c506a1798c9ce3ae3105adea Mon Sep 17 00:00:00 2001 |
2 | From: Jeremy Harris <jgh146exb@wizmail.org> | |
3 | Date: Thu, 13 Feb 2020 16:45:38 +0000 | |
4 | Subject: [PATCH 4/6] GnuTLS: fix hanging callout connections | |
5 | ||
6 | Broken-by: 925ac8e4f1 | |
7 | (cherry picked from commit bd95ffc2ba87fbd3c752df17bc8fd9c01586d45a) | |
8 | --- | |
9 | doc/ChangeLog | 81 ++++--------------------------------------- | |
10 | src/tls-gnu.c | 24 +++++++------ | |
11 | 2 files changed, 20 insertions(+), 85 deletions(-) | |
12 | ||
13 | --- a/doc/ChangeLog | |
14 | +++ b/doc/ChangeLog | |
15 | @@ -67,6 +67,11 @@ JH/41 Bug 2571: Fix SPA authenticator. | |
16 | being used. A malicious client could thus cause an out-of-bounds read and | |
17 | possibly gain authentication. Fix by adding the check. | |
18 | ||
19 | +JH/25 Fix use of concurrent TLS connections under GnuTLS. When a callout was | |
20 | + done during a receiving connection, and both used TLS, global info was | |
21 | + used rather than per-connection info for tracking the state of data | |
22 | + queued for transmission. This could result in a connection hang. | |
23 | + | |
24 | ||
25 | Exim version 4.92 | |
26 | ----------------- | |
27 | --- a/src/tls-gnu.c | |
28 | +++ b/src/tls-gnu.c | |
29 | @@ -124,10 +124,17 @@ typedef struct exim_gnutls_state { | |
30 | enum peer_verify_requirement verify_requirement; | |
31 | int fd_in; | |
32 | int fd_out; | |
33 | - BOOL peer_cert_verified; | |
34 | - BOOL peer_dane_verified; | |
35 | - BOOL trigger_sni_changes; | |
36 | - BOOL have_set_peerdn; | |
37 | + | |
38 | + BOOL peer_cert_verified:1; | |
39 | + BOOL peer_dane_verified:1; | |
40 | + BOOL trigger_sni_changes:1; | |
41 | + BOOL have_set_peerdn:1; | |
42 | + BOOL xfer_eof:1; /*XXX never gets set! */ | |
43 | + BOOL xfer_error:1; | |
44 | +#ifdef SUPPORT_CORK | |
45 | + BOOL corked:1; | |
46 | +#endif | |
47 | + | |
48 | const struct host_item *host; /* NULL if server */ | |
49 | gnutls_x509_crt_t peercert; | |
50 | uschar *peerdn; | |
51 | @@ -160,8 +167,6 @@ typedef struct exim_gnutls_state { | |
52 | uschar *xfer_buffer; | |
53 | int xfer_buffer_lwm; | |
54 | int xfer_buffer_hwm; | |
55 | - BOOL xfer_eof; /*XXX never gets set! */ | |
56 | - BOOL xfer_error; | |
57 | } exim_gnutls_state_st; | |
58 | ||
59 | static const exim_gnutls_state_st exim_gnutls_state_init = { | |
60 | @@ -2790,9 +2795,8 @@ ssize_t outbytes; | |
61 | size_t left = len; | |
62 | exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server; | |
63 | #ifdef SUPPORT_CORK | |
64 | -static BOOL corked = FALSE; | |
65 | ||
66 | -if (more && !corked) gnutls_record_cork(state->session); | |
67 | +if (more && !state->corked) gnutls_record_cork(state->session); | |
68 | #endif | |
69 | ||
70 | DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__, | |
71 | @@ -2833,10 +2837,10 @@ if (len > INT_MAX) | |
72 | } | |
73 | ||
74 | #ifdef SUPPORT_CORK | |
75 | -if (more != corked) | |
76 | +if (more != state->corked) | |
77 | { | |
78 | if (!more) (void) gnutls_record_uncork(state->session, 0); | |
79 | - corked = more; | |
80 | + state->corked = more; | |
81 | } | |
82 | #endif | |
83 |