1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
From 332ebeaf8139b2b75f475880fc14b63c7c45c706 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Tue, 19 Mar 2019 15:33:31 +0000
Subject: [PATCH 5/5] OpenSSL: Fix aggregation of messages.
Broken-by: a5ffa9b475
(cherry picked from commit c09dbcfb71f4b9a42cbfd8a20e0be6bfa1b12488)
---
doc/ChangeLog | 5 +++
src/tls-openssl.c | 24 ++++++++++----
test/confs/2152 | 76 +++++++++++++++++++++++++++++++++++++++++++
test/log/2152 | 9 +++++
4 files changed, 108 insertions(+), 6 deletions(-)
create mode 100644 test/confs/2152
create mode 100644 test/log/2152
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 3c0ffbf0..3d63725f 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -26,10 +26,15 @@ JH/08 Add hardening against SRV & TLSA lookups the hit CNAMEs (a nonvalid
crash could result.
JH/09 Logging: Fix initial listening-on line for multiple ports for an IP when
the OS reports them interleaved with other addresses.
+JH/10 OpenSSL: Fix aggregation of messages. Previously, when PIPELINING was
+ used both for input and for a verify callout, both encrypted, SMTP
+ responses being sent by the server could be lost. This resulted in
+ dropped connections and sometimes bounces generated by a peer sending
+ to this system.
Exim version 4.92
-----------------
diff --git a/src/tls-openssl.c b/src/tls-openssl.c
index 8f4cf4d8..cc0ead02 100644
--- a/src/tls-openssl.c
+++ b/src/tls-openssl.c
@@ -272,10 +272,11 @@ Server:
*/
typedef struct {
SSL_CTX * ctx;
SSL * ssl;
+ gstring * corked;
} exim_openssl_client_tls_ctx;
static SSL_CTX *server_ctx = NULL;
static SSL *server_ssl = NULL;
@@ -2471,10 +2472,11 @@ BOOL require_ocsp = FALSE;
#endif
rc = store_pool;
store_pool = POOL_PERM;
exim_client_ctx = store_get(sizeof(exim_openssl_client_tls_ctx));
+exim_client_ctx->corked = NULL;
store_pool = rc;
#ifdef SUPPORT_DANE
tlsp->tlsa_usage = 0;
#endif
@@ -2906,22 +2908,29 @@ Used by both server-side and client-side TLS.
int
tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
{
int outbytes, error, left;
-SSL * ssl = ct_ctx ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
-static gstring * corked = NULL;
+SSL * ssl = ct_ctx
+ ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
+static gstring * server_corked = NULL;
+gstring ** corkedp = ct_ctx
+ ? &((exim_openssl_client_tls_ctx *)ct_ctx)->corked : &server_corked;
+gstring * corked = *corkedp;
DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
buff, (unsigned long)len, more ? ", more" : "");
/* Lacking a CORK or MSG_MORE facility (such as GnuTLS has) we copy data when
"more" is notified. This hack is only ok if small amounts are involved AND only
one stream does it, in one context (i.e. no store reset). Currently it is used
-for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. */
-/*XXX + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's
-a store reset there. */
+for the responses to the received SMTP MAIL , RCPT, DATA sequence, only.
+We support callouts done by the server process by using a separate client
+context for the stashed information. */
+/* + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's
+a store reset there, so use POOL_PERM. */
+/* + if CHUNKING, cmds EHLO,MAIL,RCPT(s),BDAT */
if (!ct_ctx && (more || corked))
{
#ifdef EXPERIMENTAL_PIPE_CONNECT
int save_pool = store_pool;
@@ -2933,14 +2942,17 @@ if (!ct_ctx && (more || corked))
#ifdef EXPERIMENTAL_PIPE_CONNECT
store_pool = save_pool;
#endif
if (more)
+ {
+ *corkedp = corked;
return len;
+ }
buff = CUS corked->s;
len = corked->ptr;
- corked = NULL;
+ *corkedp = NULL;
}
for (left = len; left > 0;)
{
DEBUG(D_tls) debug_printf("SSL_write(%p, %p, %d)\n", ssl, buff, left);
diff --git a/test/confs/2152 b/test/confs/2152
new file mode 100644
index 00000000..f783192b
diff --git a/test/log/2152 b/test/log/2152
new file mode 100644
index 00000000..720200be
--
2.20.1
|