From ad7fc6eb6895ff40cc9998d157d1401bbf43c35e Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 23 Oct 2016 14:09:55 +0100 Subject: [PATCH] Fix bug with aborted server TLS connection, under GnuTLS Longstanding, but exposed by 60d10ce --- doc/doc-txt/ChangeLog | 6 ++++++ src/src/daemon.c | 22 +++++++++++++--------- src/src/tls-gnu.c | 6 +++++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 1267d75dc..1fdfc126e 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -120,6 +120,12 @@ PP/01 Changed default Diffie-Hellman parameters to be Exim-specific, created PP/02 Unbreak build via pkg-config with new hash support when crypto headers are not in the system include path. +JH/31 Fix longstanding bug with aborted TLS server connection handling. Under + GnuTLS, when a sennsion startup failed (eg because the client disconnected) + Exim did stdio operations after fclose. This was exposed by a recent + change which nulled out the file handle after the fclose. + + Exim version 4.87 ----------------- diff --git a/src/src/daemon.c b/src/src/daemon.c index 60275c02d..dc49eeb85 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -385,10 +385,10 @@ if (pid == 0) likely what it depends on.) */ smtp_active_hostname = primary_hostname; - if (raw_active_hostname != NULL) + if (raw_active_hostname) { - uschar *nah = expand_string(raw_active_hostname); - if (nah == NULL) + uschar * nah = expand_string(raw_active_hostname); + if (!nah) { if (!expand_string_forcedfail) { @@ -402,7 +402,7 @@ if (pid == 0) _exit(EXIT_FAILURE); } } - else if (nah[0] != 0) smtp_active_hostname = nah; + else if (*nah) smtp_active_hostname = nah; } /* Initialize the queueing flags */ @@ -518,11 +518,15 @@ if (pid == 0) } else { - int i; - uschar * buf[128]; - mac_smtp_fflush(); - /* drain socket, for clean TCP FINs */ - for(i = 16; read(fileno(smtp_in), buf, sizeof(buf)) > 0 && i > 0; ) i--; + if (smtp_out) + { + int i; + uschar buf[128]; + + mac_smtp_fflush(); + /* drain socket, for clean TCP FINs */ + for(i = 16; read(fileno(smtp_in), buf, sizeof(buf)) > 0 && i > 0; ) i--; + } search_tidyup(); smtp_log_no_mail(); /* Log no mail if configured */ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 7ddd7a724..9afaa8fea 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1827,13 +1827,17 @@ if (rc != GNUTLS_E_SUCCESS) until the server times out. */ if (sigalrm_seen) + { tls_error(US"gnutls_handshake", "timed out", NULL); + gnutls_db_remove_session(state->session); + } else { tls_error(US"gnutls_handshake", gnutls_strerror(rc), NULL); (void) gnutls_alert_send_appropriate(state->session, rc); + gnutls_deinit(state->session); millisleep(500); - shutdown(state->fd_in, SHUT_WR); + shutdown(state->fd_out, SHUT_WR); for (rc = 1024; fgetc(smtp_in) != EOF && rc > 0; ) rc--; /* drain skt */ (void)fclose(smtp_out); (void)fclose(smtp_in); -- 2.30.2