Testsuite: more robust fix for SHELL vs /bin/sh, take two.
[exim.git] / src / src / tls-openssl.c
index 1938d2fb7a72ad1bc4f8f299621f5b04e9952294..eeab9c1303bbb27d1f88d7e5f2e50d7499e28ceb 100644 (file)
@@ -29,6 +29,10 @@ functions from the OpenSSL library. */
 #define EXIM_OCSP_MAX_AGE (-1L)
 #endif
 
+#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+#define EXIM_HAVE_OPENSSL_TLSEXT
+#endif
+
 /* Structure for collecting random data for seeding. */
 
 typedef struct randstuff {
@@ -77,7 +81,9 @@ static int
 setup_certs(SSL_CTX *sctx, uschar *certs, uschar *crl, host_item *host, BOOL optional);
 
 /* Callbacks */
+#ifdef EXIM_HAVE_OPENSSL_TLSEXT
 static int tls_servername_cb(SSL *s, int *ad ARG_UNUSED, void *arg);
+#endif
 #ifdef EXPERIMENTAL_OCSP
 static int tls_stapling_cb(SSL *s, void *arg);
 #endif
@@ -302,10 +308,19 @@ else
     }
   else
     {
-    SSL_CTX_set_tmp_dh(ctx, dh);
-    DEBUG(D_tls)
-      debug_printf("Diffie-Hellman initialized from %s with %d-bit key\n",
-        dhexpanded, 8*DH_size(dh));
+    if ((8*DH_size(dh)) > tls_dh_max_bits)
+      {
+      DEBUG(D_tls)
+        debug_printf("dhparams file %d bits, is > tls_dh_max_bits limit of %d",
+            8*DH_size(dh), tls_dh_max_bits);
+      }
+    else
+      {
+      SSL_CTX_set_tmp_dh(ctx, dh);
+      DEBUG(D_tls)
+        debug_printf("Diffie-Hellman initialized from %s with %d-bit key\n",
+          dhexpanded, 8*DH_size(dh));
+      }
     DH_free(dh);
     }
   BIO_free(bio);
@@ -540,6 +555,7 @@ Arguments:
 Returns:          SSL_TLSEXT_ERR_{OK,ALERT_WARNING,ALERT_FATAL,NOACK}
 */
 
+#ifdef EXIM_HAVE_OPENSSL_TLSEXT
 static int
 tls_servername_cb(SSL *s, int *ad ARG_UNUSED, void *arg)
 {
@@ -606,6 +622,7 @@ SSL_set_SSL_CTX(s, ctx_sni);
 
 return SSL_TLSEXT_ERR_OK;
 }
+#endif /* EXIM_HAVE_OPENSSL_TLSEXT */
 
 
 
@@ -768,7 +785,7 @@ rc = tls_expand_session_files(ctx, cbinfo);
 if (rc != OK) return rc;
 
 /* If we need to handle SNI, do so */
-#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+#ifdef EXIM_HAVE_OPENSSL_TLSEXT
 if (host == NULL)
   {
 #ifdef EXPERIMENTAL_OCSP
@@ -1489,6 +1506,72 @@ tls_active = -1;
 
 
 
+/*************************************************
+*  Let tls_require_ciphers be checked at startup *
+*************************************************/
+
+/* The tls_require_ciphers option, if set, must be something which the
+library can parse.
+
+Returns:     NULL on success, or error message
+*/
+
+uschar *
+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 */
+
+SSL_load_error_strings();
+OpenSSL_add_ssl_algorithms();
+#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
+
+if (!(tls_require_ciphers && *tls_require_ciphers))
+  return NULL;
+
+if (!expand_check(tls_require_ciphers, US"tls_require_ciphers", &expciphers))
+  return US"failed to expand tls_require_ciphers";
+
+if (!(expciphers && *expciphers))
+  return NULL;
+
+/* normalisation ripped from above */
+s = expciphers;
+while (*s != 0) { if (*s == '_') *s = '-'; s++; }
+
+err = NULL;
+
+ctx = SSL_CTX_new(SSLv23_server_method());
+if (!ctx)
+  {
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  return string_sprintf("SSL_CTX_new() failed: %s", ssl_errstring);
+  }
+
+DEBUG(D_tls)
+  debug_printf("tls_require_ciphers expands to \"%s\"\n", expciphers);
+
+if (!SSL_CTX_set_cipher_list(ctx, CS expciphers))
+  {
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  err = string_sprintf("SSL_CTX_set_cipher_list(%s) failed", expciphers);
+  }
+
+SSL_CTX_free(ctx);
+
+return err;
+}
+
+
+
+
 /*************************************************
 *         Report the library versions.           *
 *************************************************/