GnuTLS: in server, detect TCP RST from client after QUIT under SSL,
[users/heiko/exim.git] / src / src / tls-gnu.c
index a351c34d671502076e2701c02f720b9b3b9addf4..013d9c0e86ffa46df91f41125826afbac027ea49 100644 (file)
@@ -424,11 +424,14 @@ record_io_error(exim_gnutls_state_st *state, int rc, uschar *when, uschar *text)
 const uschar * msg;
 uschar * errstr;
 
-if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
-  msg = string_sprintf("A TLS fatal alert has been received: %s",
-    US gnutls_alert_get_name(gnutls_alert_get(state->session)));
-else
-  msg = US gnutls_strerror(rc);
+msg = rc == GNUTLS_E_FATAL_ALERT_RECEIVED
+  ? string_sprintf("A TLS fatal alert has been received: %s",
+      US gnutls_alert_get_name(gnutls_alert_get(state->session)))
+#ifdef GNUTLS_E_PREMATURE_TERMINATION
+  : rc == GNUTLS_E_PREMATURE_TERMINATION && errno
+  ? string_sprintf("%s: syscall: %s", US gnutls_strerror(rc), strerror(errno))
+#endif
+  : US gnutls_strerror(rc);
 
 (void) tls_error(when, msg, state->host, &errstr);
 
@@ -723,7 +726,7 @@ else if (errno == ENOENT)
     debug_printf("D-H parameter cache file \"%s\" does not exist\n", filename);
   }
 else
-  return tls_error(string_open_failed(errno, "\"%s\" for reading", filename),
+  return tls_error(string_open_failed("\"%s\" for reading", filename),
       NULL, NULL, errstr);
 
 /* If ret < 0, either the cache file does not exist, or the data it contains
@@ -2603,9 +2606,9 @@ if (verify_check_given_host(CUSS &ob->tls_verify_cert_hostnames, host) == OK)
   {
   state->exp_tls_verify_cert_hostnames =
 #ifdef SUPPORT_I18N
-    string_domain_utf8_to_alabel(host->name, NULL);
+    string_domain_utf8_to_alabel(host->certname, NULL);
 #else
-    host->name;
+    host->certname;
 #endif
   DEBUG(D_tls)
     debug_printf("TLS: server cert verification includes hostname: \"%s\".\n",
@@ -3391,8 +3394,24 @@ while (left > 0)
 
   if (outbytes < 0)
     {
-    DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
-    record_io_error(state, outbytes, US"send", NULL);
+#ifdef GNUTLS_E_PREMATURE_TERMINATION
+    if (  outbytes == GNUTLS_E_PREMATURE_TERMINATION && errno == ECONNRESET
+       && !ct_ctx && f.smtp_in_quit
+       )
+      {                                        /* Outlook, dammit */
+      if (LOGGING(protocol_detail))
+       log_write(0, LOG_MAIN, "[%s] after QUIT, client reset TCP before"
+         " SMTP response and TLS close\n", sender_host_address);
+      else
+       DEBUG(D_tls) debug_printf("[%s] SSL_write: after QUIT,"
+         " client reset TCP before TLS close\n", sender_host_address);
+      }
+    else
+#endif
+      {
+      DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
+      record_io_error(state, outbytes, US"send", NULL);
+      }
     return -1;
     }
   if (outbytes == 0)