From a5ffa9b475a426bc73366db01f7cc92a3811bc3a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 19 May 2017 22:55:25 +0100 Subject: [PATCH] TLS: PIPELINING under OpenSSL --- doc/doc-txt/ChangeLog | 12 ++++++------ src/src/tls-openssl.c | 30 +++++++++++++++++++++++------- src/src/transport.c | 8 +++++--- test/confs/2107 | 1 + 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 12c1ff35b..6ba9a3e5e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -76,7 +76,7 @@ JH/11 Bug 2104: Fix continued use of a transport connection with TLS. In the JH/12 Fix check on SMTP command input synchronisation. Previously there were false-negatives in the check that the sender had not preempted a response or prompt from Exim (running as a server), due to that code's lack of - awareness of the SMTP input buferring. + awareness of the SMTP input buffering. PP/04 Add commandline_checks_require_admin option. Exim drops privileges sanely, various checks such as -be aren't a @@ -86,11 +86,11 @@ PP/04 Add commandline_checks_require_admin option. AND make fixes to the calling application, such as using `--` to stop processing options. -JH/13 Do pipelining under TLS, with GnuTLS. Previously, although safe, no - advantage was taken. Now take care to pack both (client) MAIL,RCPT,DATA, - and (server) responses to those, into a single TLS record each way (this - usually means a single packet). As a side issue, we can now detect - over-eager senders in non-pipelined mode. +JH/13 Do pipelining under TLS. Previously, although safe, no advantage was + taken. Now take care to pack both (client) MAIL,RCPT,DATA, and (server) + responses to those, into a single TLS record each way (this usually means + a single packet). As a side issue, smtp_enforce_sync now works on TLS + connections. Exim version 4.89 diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 7f41c106e..c09d9bdf6 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2483,8 +2483,7 @@ if (n > 0) BOOL tls_could_read(void) { -/* XXX no actual inquiry into library; only our buffer */ -return ssl_xfer_buffer_lwm < ssl_xfer_buffer_hwm; +return ssl_xfer_buffer_lwm < ssl_xfer_buffer_hwm || SSL_pending(server_ssl) > 0; } @@ -2551,13 +2550,30 @@ Used by both server-side and client-side TLS. int tls_write(BOOL is_server, const uschar *buff, size_t len, BOOL more) { -int outbytes; -int error; -int left = len; +int outbytes, error, left; SSL *ssl = is_server ? server_ssl : client_ssl; +static uschar * corked = NULL; +static int c_size = 0, c_len = 0; + +DEBUG(D_tls) debug_printf("%s(%p, %d%s)\n", __FUNCTION__, + buff, left, 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. */ + +if (is_server && (more || corked)) + { + corked = string_catn(corked, &c_size, &c_len, buff, len); + if (more) + return len; + buff = CUS corked; + len = c_len; + corked = NULL; c_size = c_len = 0; + } -DEBUG(D_tls) debug_printf("%s(%p, %d)\n", __FUNCTION__, buff, left); -while (left > 0) +for (left = len; left > 0;) { DEBUG(D_tls) debug_printf("SSL_write(SSL, %p, %d)\n", buff, left); outbytes = SSL_write(ssl, CS buff, left); diff --git a/src/src/transport.c b/src/src/transport.c index 04b67f9e9..20d0b8a52 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -969,9 +969,11 @@ if (!(tctx->options & topt_no_headers)) if (tctx->options & topt_add_delivery_date) { - uschar buffer[100]; - int n = sprintf(CS buffer, "Delivery-date: %s\n", tod_stamp(tod_full)); - if (!write_chunk(tctx, buffer, n)) goto bad; + uschar * s = tod_stamp(tod_full); + + if ( !write_chunk(tctx, US"Delivery-date: ", 15) + || !write_chunk(tctx, s, Ustrlen(s)) + || !write_chunk(tctx, US"\n", 1)) goto bad; } /* Then the message's headers. Don't write any that are flagged as "old"; diff --git a/test/confs/2107 b/test/confs/2107 index 9487445cc..679367315 100644 --- a/test/confs/2107 +++ b/test/confs/2107 @@ -16,6 +16,7 @@ queue_only queue_run_in_order tls_advertise_hosts = * +tls_require_ciphers = AES256-SHA # Set certificate only if server -- 2.30.2