GnuTLS: lose DH-param setup, for recent library versions where no longer needed
[exim.git] / src / src / tls-gnu.c
index 52128b940b922d2126bcfacba7eec949719e676c..13bf905a0153a836f5be183c8986ff43abd0165b 100644 (file)
@@ -76,6 +76,9 @@ require current GnuTLS, then we'll drop support for the ancient libraries).
 #if GNUTLS_VERSION_NUMBER >= 0x030506 && !defined(DISABLE_OCSP)
 # define SUPPORT_SRV_OCSP_STACK
 #endif
+#if GNUTLS_VERSION_NUMBER >= 0x030600
+# define GNUTLS_AUTO_DHPARAMS
+#endif
 #if GNUTLS_VERSION_NUMBER >= 0x030603
 # define EXIM_HAVE_TLS1_3
 # define SUPPORT_GNUTLS_EXT_RAW_PARSE
@@ -217,11 +220,13 @@ XXX But see gnutls_session_get_ptr()
 
 static exim_gnutls_state_st state_server;
 
+#ifndef GNUTLS_AUTO_DHPARAMS
 /* dh_params are initialised once within the lifetime of a process using TLS;
 if we used TLS in a long-lived daemon, we'd have to reconsider this.  But we
 don't want to repeat this. */
 
 static gnutls_dh_params_t dh_server_params = NULL;
+#endif
 
 static int ssl_session_timeout = 7200; /* Two hours */
 
@@ -296,11 +301,6 @@ static void exim_gnutls_logger_cb(int level, const char *message);
 
 static int exim_sni_handling_cb(gnutls_session_t session);
 
-#if !defined(DISABLE_OCSP)
-static int server_ocsp_stapling_cb(gnutls_session_t session, void * ptr,
-  gnutls_datum_t * ocsp_response);
-#endif
-
 #ifdef EXPERIMENTAL_TLS_RESUME
 static int
 tls_server_ticket_cb(gnutls_session_t sess, u_int htype, unsigned when,
@@ -529,6 +529,7 @@ tlsp->sni =    state->received_sni;
 
 
 
+#ifndef GNUTLS_AUTO_DHPARAMS
 /*************************************************
 *            Setup up DH parameters              *
 *************************************************/
@@ -551,7 +552,7 @@ init_server_dh(uschar ** errstr)
 {
 int fd, rc;
 unsigned int dh_bits;
-gnutls_datum_t m;
+gnutls_datum_t m = {.data = NULL, .size = 0};
 uschar filename_buf[PATH_MAX];
 uschar *filename = NULL;
 size_t sz;
@@ -564,9 +565,6 @@ DEBUG(D_tls) debug_printf("Initialising GnuTLS server params.\n");
 if ((rc = gnutls_dh_params_init(&dh_server_params)))
   return tls_error_gnu(US"gnutls_dh_params_init", rc, host, errstr);
 
-m.data = NULL;
-m.size = 0;
-
 if (!expand_check(tls_dhparam, US"tls_dhparam", &exp_tls_dhparam, errstr))
   return DEFER;
 
@@ -716,14 +714,12 @@ if (rc < 0)
     return tls_error_sys(US"Unable to open temp file", errno, NULL, errstr);
   (void)exim_chown(temp_fn, exim_uid, exim_gid);   /* Probably not necessary */
 
-  /* GnuTLS overshoots!
-   * If we ask for 2236, we might get 2237 or more.
-   * But there's no way to ask GnuTLS how many bits there really are.
-   * We can ask how many bits were used in a TLS session, but that's it!
-   * The prime itself is hidden behind too much abstraction.
-   * So we ask for less, and proceed on a wing and a prayer.
-   * First attempt, subtracted 3 for 2233 and got 2240.
-   */
+  /* GnuTLS overshoots!  If we ask for 2236, we might get 2237 or more.  But
+  there's no way to ask GnuTLS how many bits there really are.  We can ask
+  how many bits were used in a TLS session, but that's it!  The prime itself
+  is hidden behind too much abstraction.  So we ask for less, and proceed on
+  a wing and a prayer.  First attempt, subtracted 3 for 2233 and got 2240.  */
+
   if (dh_bits >= EXIM_CLIENT_DH_MIN_BITS + 10)
     {
     dh_bits_gen = dh_bits - 10;
@@ -786,6 +782,7 @@ if (rc < 0)
 DEBUG(D_tls) debug_printf("initialized server D-H parameters\n");
 return OK;
 }
+#endif
 
 
 
@@ -882,6 +879,32 @@ return -rc;
 }
 
 
+#if !defined(DISABLE_OCSP) && !defined(SUPPORT_GNUTLS_EXT_RAW_PARSE)
+/* Load an OCSP proof from file for sending by the server.  Called
+on getting a status-request handshake message, for earlier versions
+of GnuTLS. */
+
+static int
+server_ocsp_stapling_cb(gnutls_session_t session, void * ptr,
+  gnutls_datum_t * ocsp_response)
+{
+int ret;
+DEBUG(D_tls) debug_printf("OCSP stapling callback: %s\n", US ptr);
+
+if ((ret = gnutls_load_file(ptr, ocsp_response)) < 0)
+  {
+  DEBUG(D_tls) debug_printf("Failed to load ocsp stapling file %s\n",
+                             CS ptr);
+  tls_in.ocsp = OCSP_NOT_RESP;
+  return GNUTLS_E_NO_CERTIFICATE_STATUS;
+  }
+
+tls_in.ocsp = OCSP_VFY_NOT_TRIED;
+return 0;
+}
+#endif
+
+
 #ifdef SUPPORT_GNUTLS_EXT_RAW_PARSE
 /* Make a note that we saw a status-request */
 static int
@@ -1209,8 +1232,8 @@ if (state->exp_tls_certificate && *state->exp_tls_certificate)
                  debug_printf("oops; multiple OCSP files not supported\n");
                break;
                }
-               gnutls_certificate_set_ocsp_status_request_function(
-                 state->x509_cred, server_ocsp_stapling_cb, ofile);
+             gnutls_certificate_set_ocsp_status_request_function(
+               state->x509_cred, server_ocsp_stapling_cb, ofile);
              }
 # endif        /* SUPPORT_GNUTLS_EXT_RAW_PARSE */
            }
@@ -1273,7 +1296,7 @@ else
   {
   if (Ustat(state->exp_tls_verify_certificates, &statbuf) < 0)
     {
-    log_write(0, LOG_MAIN|LOG_PANIC, "could not stat %s "
+    log_write(0, LOG_MAIN|LOG_PANIC, "could not stat '%s' "
        "(tls_verify_certificates): %s", state->exp_tls_verify_certificates,
        strerror(errno));
     return DEFER;
@@ -1374,6 +1397,7 @@ tls_set_remaining_x509(exim_gnutls_state_st *state, uschar ** errstr)
 int rc;
 const host_item *host = state->host;  /* macro should be reconsidered? */
 
+#ifndef GNUTLS_AUTO_DHPARAMS
 /* Create D-H parameters, or read them from the cache file. This function does
 its own SMTP error messaging. This only happens for the server, TLS D-H ignores
 client-side params. */
@@ -1382,8 +1406,11 @@ if (!state->host)
   {
   if (!dh_server_params)
     if ((rc = init_server_dh(errstr)) != OK) return rc;
+
+  /* Unnecessary & discouraged with 3.6.0 or later */
   gnutls_certificate_set_dh_params(state->x509_cred, dh_server_params);
   }
+#endif
 
 /* Link the credentials to the session. */
 
@@ -2158,30 +2185,6 @@ return 0;
 
 
 
-#if !defined(DISABLE_OCSP)
-
-static int
-server_ocsp_stapling_cb(gnutls_session_t session, void * ptr,
-  gnutls_datum_t * ocsp_response)
-{
-int ret;
-DEBUG(D_tls) debug_printf("OCSP stapling callback: %s\n", US ptr);
-
-if ((ret = gnutls_load_file(ptr, ocsp_response)) < 0)
-  {
-  DEBUG(D_tls) debug_printf("Failed to load ocsp stapling file %s\n",
-                             CS ptr);
-  tls_in.ocsp = OCSP_NOT_RESP;
-  return GNUTLS_E_NO_CERTIFICATE_STATUS;
-  }
-
-tls_in.ocsp = OCSP_VFY_NOT_TRIED;
-return 0;
-}
-
-#endif
-
-
 #ifndef DISABLE_EVENT
 /*
 We use this callback to get observability and detail-level control