From 513adf9d59bd8d9515a3c6b9c092a2c376cc6102 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 28 Jul 2019 14:47:29 +0100 Subject: [PATCH] Fix crash after TLS channel shutdown (cherry picked from commit bd231acd0f24e4c27c6d6885f48c24360700ec7f) --- doc/doc-txt/ChangeLog | 8 ++++++-- src/src/tls-gnu.c | 44 +++++++++++++++++++------------------------ src/src/tls-openssl.c | 39 ++++++++++++++------------------------ 3 files changed, 39 insertions(+), 52 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index e92ca2403..f863b9a16 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -5,11 +5,15 @@ affect Exim's operation, with an unchanged configuration file. For new options, and new features, see the NewStuff file next to this ChangeLog. -Exim version 4.92.1 -------------------- +Since version 4.92.1 +-------------------- JH/31 Avoid re-expansion in ${sort } expansion. (CVE-2019-13917, OVE-20190718-0006) +JH/34 Fix crash after TLS shutdown. When the TCP/SMTP channel was left open, + an attempt to use a TLS library read routine dereffed a nul pointer, + causing a segfault. + Since version 4.92 ------------------ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 867dbbe3d..8d911d572 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -2569,8 +2569,9 @@ void tls_close(void * ct_ctx, int shutdown) { exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server; +tls_support * tlsp = state->tlsp; -if (!state->tlsp || state->tlsp->active.sock < 0) return; /* TLS was not active */ +if (!tlsp || tlsp->active.sock < 0) return; /* TLS was not active */ if (shutdown) { @@ -2582,12 +2583,26 @@ if (shutdown) ALARM_CLR(0); } +if (!ct_ctx) /* server */ + { + receive_getc = smtp_getc; + receive_getbuf = smtp_getbuf; + receive_get_cache = smtp_get_cache; + receive_ungetc = smtp_ungetc; + receive_feof = smtp_feof; + receive_ferror = smtp_ferror; + receive_smtp_buffered = smtp_buffered; + } + gnutls_deinit(state->session); gnutls_certificate_free_credentials(state->x509_cred); +tlsp->active.sock = -1; +tlsp->active.tls_ctx = NULL; +/* Leave bits, peercert, cipher, peerdn, certificate_verified set, for logging */ +tls_channelbinding_b64 = NULL; + -state->tlsp->active.sock = -1; -state->tlsp->active.tls_ctx = NULL; if (state->xfer_buffer) store_free(state->xfer_buffer); memcpy(state, &exim_gnutls_state_init, sizeof(exim_gnutls_state_init)); } @@ -2637,28 +2652,7 @@ if (sigalrm_seen) else if (inbytes == 0) { DEBUG(D_tls) debug_printf("Got TLS_EOF\n"); - - receive_getc = smtp_getc; - receive_getbuf = smtp_getbuf; - receive_get_cache = smtp_get_cache; - receive_ungetc = smtp_ungetc; - receive_feof = smtp_feof; - receive_ferror = smtp_ferror; - receive_smtp_buffered = smtp_buffered; - - gnutls_deinit(state->session); - gnutls_certificate_free_credentials(state->x509_cred); - - state->session = NULL; - state->tlsp->active.sock = -1; - state->tlsp->active.tls_ctx = NULL; - state->tlsp->bits = 0; - state->tlsp->certificate_verified = FALSE; - tls_channelbinding_b64 = NULL; - state->tlsp->cipher = NULL; - state->tlsp->peercert = NULL; - state->tlsp->peerdn = NULL; - + tls_close(NULL, TLS_NO_SHUTDOWN); return FALSE; } diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index cc0ead02a..e751edd9a 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2727,32 +2727,10 @@ switch(error) case SSL_ERROR_ZERO_RETURN: DEBUG(D_tls) debug_printf("Got SSL_ERROR_ZERO_RETURN\n"); - receive_getc = smtp_getc; - receive_getbuf = smtp_getbuf; - receive_get_cache = smtp_get_cache; - receive_ungetc = smtp_ungetc; - receive_feof = smtp_feof; - receive_ferror = smtp_ferror; - receive_smtp_buffered = smtp_buffered; - if (SSL_get_shutdown(server_ssl) == SSL_RECEIVED_SHUTDOWN) SSL_shutdown(server_ssl); -#ifndef DISABLE_OCSP - sk_X509_pop_free(server_static_cbinfo->verify_stack, X509_free); - server_static_cbinfo->verify_stack = NULL; -#endif - SSL_free(server_ssl); - SSL_CTX_free(server_ctx); - server_ctx = NULL; - server_ssl = NULL; - tls_in.active.sock = -1; - tls_in.active.tls_ctx = NULL; - tls_in.bits = 0; - tls_in.cipher = NULL; - tls_in.peerdn = NULL; - tls_in.sni = NULL; - + tls_close(NULL, TLS_NO_SHUTDOWN); return FALSE; /* Handle genuine errors */ @@ -3040,14 +3018,25 @@ if (shutdown) } } -#ifndef DISABLE_OCSP if (!o_ctx) /* server side */ { +#ifndef DISABLE_OCSP sk_X509_pop_free(server_static_cbinfo->verify_stack, X509_free); server_static_cbinfo->verify_stack = NULL; - } #endif + receive_getc = smtp_getc; + receive_getbuf = smtp_getbuf; + receive_get_cache = smtp_get_cache; + receive_ungetc = smtp_ungetc; + receive_feof = smtp_feof; + receive_ferror = smtp_ferror; + receive_smtp_buffered = smtp_buffered; + tls_in.active.tls_ctx = NULL; + tls_in.sni = NULL; + /* Leave bits, peercert, cipher, peerdn, certificate_verified set, for logging */ + } + SSL_CTX_free(*ctxp); SSL_free(*sslp); *ctxp = NULL; -- 2.30.2