Build: include early-pipelining unless disabled
[exim.git] / src / src / tls-openssl.c
index d165eb2c02908bfd28b92a68683f29c6ddad4823..c5e1abfe9f985ac3ad8d373443ec6cb1f628c39d 100644 (file)
@@ -46,6 +46,7 @@ functions from the OpenSSL library. */
 #endif
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
 # define EXIM_HAVE_OCSP_RESP_COUNT
+# define OPENSSL_AUTO_SHA256
 #else
 # define EXIM_HAVE_EPHEM_RSA_KEX
 # define EXIM_HAVE_RAND_PSEUDO
@@ -1945,6 +1946,23 @@ return i;
 *            Initialize for TLS                  *
 *************************************************/
 
+static void
+tls_openssl_init(void)
+{
+#ifdef EXIM_NEED_OPENSSL_INIT
+SSL_load_error_strings();          /* basic set up */
+OpenSSL_add_ssl_algorithms();
+#endif
+
+#if defined(EXIM_HAVE_SHA256) && !defined(OPENSSL_AUTO_SHA256)
+/* SHA256 is becoming ever more popular. This makes sure it gets added to the
+list of available digests. */
+EVP_add_digest(EVP_sha256());
+#endif
+}
+
+
+
 /* Called from both server and client code, to do preliminary initialization
 of the library.  We allocate and return a context structure.
 
@@ -2000,16 +2018,7 @@ cbinfo->host = host;
 cbinfo->event_action = NULL;
 #endif
 
-#ifdef EXIM_NEED_OPENSSL_INIT
-SSL_load_error_strings();          /* basic set up */
-OpenSSL_add_ssl_algorithms();
-#endif
-
-#ifdef EXIM_HAVE_SHA256
-/* SHA256 is becoming ever more popular. This makes sure it gets added to the
-list of available digests. */
-EVP_add_digest(EVP_sha256());
-#endif
+tls_openssl_init();
 
 /* Create a context.
 The OpenSSL docs in 1.0.1b have not been updated to clarify TLS variant
@@ -2630,8 +2639,41 @@ ALARM_CLR(0);
 
 if (rc <= 0)
   {
-  (void) tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
-  return FAIL;
+  int error = SSL_get_error(server_ssl, rc);
+  switch(error)
+    {
+    case SSL_ERROR_NONE:
+      break;
+
+    case SSL_ERROR_ZERO_RETURN:
+      DEBUG(D_tls) debug_printf("Got SSL_ERROR_ZERO_RETURN\n");
+      (void) tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
+
+      if (SSL_get_shutdown(server_ssl) == SSL_RECEIVED_SHUTDOWN)
+           SSL_shutdown(server_ssl);
+
+      tls_close(NULL, TLS_NO_SHUTDOWN);
+      return FAIL;
+
+    /* Handle genuine errors */
+    case SSL_ERROR_SSL:
+      (void) tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
+      return FAIL;
+
+    default:
+      DEBUG(D_tls) debug_printf("Got SSL error %d\n", error);
+      if (error == SSL_ERROR_SYSCALL)
+       {
+       if (!errno)
+         {
+         *errstr = US"SSL_accept: TCP connection closed by peer";
+         return FAIL;
+         }
+       DEBUG(D_tls) debug_printf(" - syscall %s\n", strerror(errno));
+       }
+      (void) tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL, errstr);
+      return FAIL;
+    }
   }
 
 DEBUG(D_tls) debug_printf("SSL_accept was successful\n");
@@ -3475,14 +3517,14 @@ a store reset there, so use POOL_PERM. */
 
 if ((more || corked))
   {
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
   int save_pool = store_pool;
   store_pool = POOL_PERM;
 #endif
 
   corked = string_catn(corked, buff, len);
 
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
   store_pool = save_pool;
 #endif
 
@@ -3628,18 +3670,7 @@ tls_validate_require_cipher(void)
 SSL_CTX *ctx;
 uschar *s, *expciphers, *err;
 
-/* this duplicates from tls_init(), we need a better "init just global
-state, for no specific purpose" singleton function of our own */
-
-#ifdef EXIM_NEED_OPENSSL_INIT
-SSL_load_error_strings();
-OpenSSL_add_ssl_algorithms();
-#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-/* SHA256 is becoming ever more popular. This makes sure it gets added to the
-list of available digests. */
-EVP_add_digest(EVP_sha256());
-#endif
+tls_openssl_init();
 
 if (!(tls_require_ciphers && *tls_require_ciphers))
   return NULL;