From 97c5e07c220b55d1c506a1798c9ce3ae3105adea Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Thu, 13 Feb 2020 16:45:38 +0000 Subject: [PATCH] GnuTLS: fix hanging callout connections Broken-by: 925ac8e4f1 (cherry picked from commit bd95ffc2ba87fbd3c752df17bc8fd9c01586d45a) --- doc/doc-txt/ChangeLog | 81 ++++--------------------------------------- src/src/tls-gnu.c | 24 +++++++------ 2 files changed, 20 insertions(+), 85 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index a5b58f781..b78235253 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -5,82 +5,13 @@ affect Exim's operation, with an unchanged configuration file. For new options, and new features, see the NewStuff file next to this ChangeLog. -Since version 4.92 ------------------- +Backported Exim version 4.94 (this list is imcomplete) +------------------------------------------------------ -JH/06 Fix buggy handling of autoreply bounce_return_size_limit, and a possible - buffer overrun for (non-chunking) other transports. - -JH/07 GnuTLS: Our use of late (post-handshake) certificate verification, under - TLS1.3, means that a server rejecting a client certificate is not visible - to the client until the first read of encrypted data (typically the - response to EHLO). Add detection for that case and treat it as a failed - TLS connection attempt, so that the normal retry-in-clear can work (if - suitably configured). - -JB/01 Bug 2375: fix expansions of 822 addresses having comments in local-part - and/or domain. Found and fixed by Jason Betts. - -JH/08 Add hardening against SRV & TLSA lookups the hit CNAMEs (a nonvalid - configuration). If a CNAME target was not a wellformed name pattern, a - 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. - -JH/11 Harden plaintext authenticator against a badly misconfigured client-send - string. Previously it was possible to cause undefined behaviour in a - library routine (usually a crash). Found by "zerons". - -JH/12 Bug 2384: fix "-bP smtp_receive_timeout". Previously it returned no - output. - -JH/13 Bug 2386: Fix builds with Dane under LibreSSL 2.9.0 onward. Some old - API was removed, so update to use the newer ones. - - -JH/16 GnuTLS: rework ciphersuite strings under recent library versions. Thanks - to changes apparently associated with TLS1.3 handling some of the APIs - previously used were either nonfunctional or inappropriate. Strings - like TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM__AEAD:256 - and TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_128_CBC__SHA256:128 replace - the previous TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 . - This affects log line X= elements, the $tls_{in,out}_cipher variables, - and the use of specific cipher names in the encrypted= ACL condition. - -JH/18 GnuTLS: fix $tls_out_ocsp under hosts_request_ocsp. Previously the - verification result was not updated unless hosts_require_ocsp applied. - -JH/19 Bug 2398: fix listing of a named-queue. Previously, even with the option - queue_list_requires_admin set to false, non-admin users were denied the - facility. - -JH/20 Bug 2389: fix server advertising of usable certificates, under GnuTLS in - directory-of-certs mode. Previously they were advertised despite the - documentation. - -JH/27 Bug 2404: Use the main-section configuration option "dsn_from" for - success-DSN messages. Previously the From: header was always the default - one for these; the option was ignored. - -PP/01 Unbreak heimdal_gssapi, broken in 4.92. - -JH/29 Fix DSN Final-Recipient: field. Previously it was the post-routing - delivery address, which leaked information of the results of local - forwarding. Change to the original envelope recipient address, per - standards. - -JH/30 Bug 2411: Fix DSN generation when RFC 3461 failure notification is - requested. Previously not bounce was generated and a log entry of - error ignored was made. - -JH/31 Avoid re-expansion in ${sort } expansion. (CVE-2019-13917, OVE-20190718-0006) +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 diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 867dbbe3d..822ad89c6 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -127,10 +127,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; @@ -163,8 +170,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 = { @@ -2831,9 +2836,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__, @@ -2874,10 +2878,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 -- 2.30.2