summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2019-03-19 15:33:31 +0000
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2019-07-19 08:55:06 +0200
commit1bd4207a399775cf842607930e76c14ac54327df (patch)
treee68595dd06f9cc8856f12f2b982d8247284110fc
parent8b81ffe198b36c7d3dcaa1697ab71eefa78946ed (diff)
downloadexim4-1bd4207a399775cf842607930e76c14ac54327df.tar.gz
OpenSSL: Fix aggregation of messages.
Broken-by: a5ffa9b475 (cherry picked from commit c09dbcfb71f4b9a42cbfd8a20e0be6bfa1b12488) (cherry picked from commit 332ebeaf8139b2b75f475880fc14b63c7c45c706)
-rw-r--r--doc/doc-txt/ChangeLog5
-rw-r--r--src/src/tls-openssl.c24
-rw-r--r--test/confs/215276
-rw-r--r--test/log/21529
4 files changed, 108 insertions, 6 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 2bc608a0f..6492d2d10 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -34,6 +34,11 @@ JH/08 Add hardening against SRV & TLSA lookups the hit CNAMEs (a nonvalid
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/src/tls-openssl.c b/src/src/tls-openssl.c
index 8f4cf4d82..cc0ead02a 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -274,6 +274,7 @@ Server:
typedef struct {
SSL_CTX * ctx;
SSL * ssl;
+ gstring * corked;
} exim_openssl_client_tls_ctx;
static SSL_CTX *server_ctx = NULL;
@@ -2473,6 +2474,7 @@ BOOL require_ocsp = FALSE;
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
@@ -2908,8 +2910,12 @@ 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" : "");
@@ -2917,9 +2923,12 @@ DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
/* 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))
{
@@ -2935,10 +2944,13 @@ if (!ct_ctx && (more || corked))
#endif
if (more)
+ {
+ *corkedp = corked;
return len;
+ }
buff = CUS corked->s;
len = corked->ptr;
- corked = NULL;
+ *corkedp = NULL;
}
for (left = len; left > 0;)
diff --git a/test/confs/2152 b/test/confs/2152
new file mode 100644
index 000000000..f783192bd
--- /dev/null
+++ b/test/confs/2152
@@ -0,0 +1,76 @@
+# Exim test configuration 2152
+
+SERVER=
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = chk_r
+
+#log_selector = +tls_peerdn
+
+queue_only
+queue_run_in_order
+
+tls_advertise_hosts = *
+
+tls_certificate = DIR/aux-fixed/cert1
+tls_privatekey = DIR/aux-fixed/cert1
+
+
+# ----- ACL -----
+
+begin acl
+
+chk_r:
+ accept condition = ${if = {$received_port}{PORT_D2}}
+ accept verify = recipient/callout
+
+# ----- Routers -----
+
+begin routers
+
+client:
+ driver = accept
+ condition = ${if !eq {SERVER}{server}}
+ transport = send_to_server
+
+srvr_v:
+ driver = accept
+ verify_only
+ transport = send_to_server_v
+
+
+# ----- Transports -----
+
+begin transports
+
+send_to_server:
+ driver = smtp
+ allow_localhost
+ hosts = 127.0.0.1
+ port = PORT_D
+ tls_verify_certificates = DIR/aux-fixed/cert1
+ tls_verify_cert_hostnames = :
+
+send_to_server_v:
+ driver = smtp
+ allow_localhost
+ hosts = 127.0.0.1
+ port = PORT_D2
+ tls_verify_certificates = DIR/aux-fixed/cert1
+ tls_verify_cert_hostnames = :
+
+
+# ----- Retry -----
+
+
+begin retry
+
+* * F,5d,10s
+
+
+# End
diff --git a/test/log/2152 b/test/log/2152
new file mode 100644
index 000000000..720200be2
--- /dev/null
+++ b/test/log/2152
@@ -0,0 +1,9 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 port 1226
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@myhost.test.ex