Fix crash after TLS channel shutdown
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 28 Jul 2019 13:47:29 +0000 (14:47 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 28 Jul 2019 14:55:06 +0000 (15:55 +0100)
doc/doc-txt/ChangeLog
src/src/tls-gnu.c
src/src/tls-openssl.c
src/src/verify.c

index 2bfa7762274b97d87a38b498c6e978d6bd0bdcc9..9af9a9759aa9b9c57ade3e8dc8ef21296cedcc12 100644 (file)
@@ -157,6 +157,10 @@ JH/33 Bug 2413: Fix dkim_strict option.  Previously the expansion result
       was unused and the unexpanded text used for the test.  Found and
       fixed by Ruben Jenster.
 
+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.
+
 
 Exim version 4.92
 -----------------
index ca60ddb6abdd509d3e82d3be4bc1d32b18bdaf7d..de44313e80b01d9fa4885da38a501e9bf4165245 100644 (file)
@@ -2836,8 +2836,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)
   {
@@ -2849,12 +2850,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));
 }
@@ -2904,28 +2919,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;
   }
 
index 9542a1ed477681d9f2cf004b5e283b07b080132e..e219f5cc15f19a56f1864d1c6ef44ade8116c36b 100644 (file)
@@ -3189,32 +3189,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 */
@@ -3503,14 +3481,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;
index e98dee669de84f7a15dbaeb303ffb7fa9e031b42..a1276068b0ab3de5279474db34a3006d36c01585 100644 (file)
@@ -1172,7 +1172,7 @@ if (!done)
 /* Come here from within the cache-reading code on fast-track exit. */
 
 END_CALLOUT:
-tls_modify_variables(&tls_in);
+tls_modify_variables(&tls_in); /* return variables to inbound values */
 return yield;
 }
 
@@ -2193,7 +2193,7 @@ the -bv or -bt case). */
 
 out:
 verify_mode = NULL;
-tls_modify_variables(&tls_in);
+tls_modify_variables(&tls_in); /* return variables to inbound values */
 
 return yield;
 }