tidying
[exim.git] / src / src / tls-gnu.c
index 30c8d40c0f10cdb4e93d7bfa87a8c66fccce49c7..69387a3a7eb7ba383de5461f97297b890d8d0101 100644 (file)
@@ -6,6 +6,7 @@
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* Copyright (c) Phil Pennock 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* This file provides TLS/SSL support for Exim using the GnuTLS library,
 one of the available supported implementations.  This file is #included into
@@ -121,6 +122,10 @@ require current GnuTLS, then we'll drop support for the ancient libraries).
 # endif
 #endif
 
+#if GNUTLS_VERSION_NUMBER >= 0x030702
+# define HAVE_GNUTLS_EXPORTER
+#endif
+
 #ifndef DISABLE_OCSP
 # include <gnutls/ocsp.h>
 #endif
@@ -646,14 +651,20 @@ tlsp->channelbinding = NULL;
 #ifdef HAVE_GNUTLS_SESSION_CHANNEL_BINDING
   {
   gnutls_datum_t channel = {.data = NULL, .size = 0};
-  uschar * buf;
   int rc;
 
-# ifdef HAVE_GNUTLS_PRF_RFC5705
+# ifdef HAVE_GNUTLS_EXPORTER
+  if (gnutls_protocol_get_version(state->session) >= GNUTLS_TLS1_3)
+    {
+    rc = gnutls_session_channel_binding(state->session, GNUTLS_CB_TLS_EXPORTER, &channel);
+    tlsp->channelbind_exporter = TRUE;
+    }
+  else
+# elif defined(HAVE_GNUTLS_PRF_RFC5705)
   /* Older libraries may not have GNUTLS_TLS1_3 defined! */
   if (gnutls_protocol_get_version(state->session) > GNUTLS_TLS1_2)
     {
-    buf = store_get(32, state->host ? GET_TAINTED : GET_UNTAINTED);
+    uschar * buf = store_get(32, state->host ? GET_TAINTED : GET_UNTAINTED);
     rc = gnutls_prf_rfc5705(state->session,
                                (size_t)24,  "EXPORTER-Channel-Binding", (size_t)0, "",
                                32, CS buf);
@@ -670,11 +681,11 @@ tlsp->channelbinding = NULL;
     {
     int old_pool = store_pool;
     /* Declare the taintedness of the binding info.  On server, untainted; on
-    client, tainted - being the Finish msg from the server. */
+    client, tainted if we used the Finish msg from the server. */
 
     store_pool = POOL_PERM;
     tlsp->channelbinding = b64encode_taint(CUS channel.data, (int)channel.size,
-                                           state->host ? GET_TAINTED : GET_UNTAINTED);
+               !tlsp->channelbind_exporter && state->host ? GET_TAINTED : GET_UNTAINTED);
     store_pool = old_pool;
     DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
     }
@@ -1132,8 +1143,9 @@ tls_server_clienthello_cb(gnutls_session_t session, unsigned int htype,
   unsigned when, unsigned int incoming, const gnutls_datum_t * msg)
 {
 /* Call fn for each extension seen.  3.6.3 onwards */
-return gnutls_ext_raw_parse(NULL, tls_server_clienthello_ext, msg,
+int rc = gnutls_ext_raw_parse(NULL, tls_server_clienthello_ext, msg,
                           GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
+return rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE ? 0 : rc;
 }
 
 
@@ -2731,25 +2743,25 @@ exim_gnutls_state_st * state = gnutls_session_get_ptr(session);
 
 if ((cert_list = gnutls_certificate_get_peers(session, &cert_list_size)))
   while (cert_list_size--)
-  {
-  if ((rc = import_cert(&cert_list[cert_list_size], &crt)) != GNUTLS_E_SUCCESS)
     {
-    DEBUG(D_tls) debug_printf("TLS: peer cert problem: depth %d: %s\n",
-      cert_list_size, gnutls_strerror(rc));
-    break;
-    }
+    if ((rc = import_cert(&cert_list[cert_list_size], &crt)) != GNUTLS_E_SUCCESS)
+      {
+      DEBUG(D_tls) debug_printf("TLS: peer cert problem: depth %d: %s\n",
+       cert_list_size, gnutls_strerror(rc));
+      break;
+      }
 
-  state->tlsp->peercert = crt;
-  if ((yield = event_raise(state->event_action,
-             US"tls:cert", string_sprintf("%d", cert_list_size), &errno)))
-    {
-    log_write(0, LOG_MAIN,
-             "SSL verify denied by event-action: depth=%d: %s",
-             cert_list_size, yield);
-    return 1;                     /* reject */
+    state->tlsp->peercert = crt;
+    if ((yield = event_raise(state->event_action,
+               US"tls:cert", string_sprintf("%d", cert_list_size), &errno)))
+      {
+      log_write(0, LOG_MAIN,
+               "SSL verify denied by event-action: depth=%d: %s",
+               cert_list_size, yield);
+      return 1;                     /* reject */
+      }
+    state->tlsp->peercert = NULL;
     }
-  state->tlsp->peercert = NULL;
-  }
 
 return 0;
 }
@@ -3277,7 +3289,10 @@ tls_retrieve_session(tls_support * tlsp, gnutls_session_t session,
   smtp_connect_args * conn_args, smtp_transport_options_block * ob)
 {
 tlsp->resumption = RESUME_SUPPORTED;
-if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host) == OK)
+
+if (!conn_args->have_lbserver)
+  { DEBUG(D_tls) debug_printf("resumption not supported on continued-connection\n"); }
+else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host) == OK)
   {
   dbdata_tls_session * dt;
   int len, rc;