build: use pkg-config for i18n
[exim.git] / src / src / tls-gnu.c
index efa6004a38d1b7af1b45530c1d82cd7abfd0ebee..7963e2c97bb5664824c990bd5e1ce3df1508dba3 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* Copyright (c) Phil Pennock 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* Copyright (c) Phil Pennock 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
@@ -1185,6 +1185,8 @@ tls_server_servercerts_cb(gnutls_session_t session, unsigned int htype,
 # ifdef notdef_crashes
                                /*XXX crashes */
 return gnutls_ext_raw_parse(NULL, tls_server_servercerts_ext, msg, 0);
 # ifdef notdef_crashes
                                /*XXX crashes */
 return gnutls_ext_raw_parse(NULL, tls_server_servercerts_ext, msg, 0);
+# else
+return GNUTLS_E_SUCCESS;
 # endif
 }
 #endif /*SUPPORT_GNUTLS_EXT_RAW_PARSE*/
 # endif
 }
 #endif /*SUPPORT_GNUTLS_EXT_RAW_PARSE*/
@@ -1233,7 +1235,7 @@ switch (htype)
     return tls_server_ticket_cb(sess, htype, when, incoming, msg);
 # endif
   default:
     return tls_server_ticket_cb(sess, htype, when, incoming, msg);
 # endif
   default:
-    return 0;
+    return GNUTLS_E_SUCCESS;
   }
 }
 #endif
   }
 }
 #endif
@@ -1628,7 +1630,8 @@ and there seems little downside. */
 static void
 tls_client_creds_init(transport_instance * t, BOOL watch)
 {
 static void
 tls_client_creds_init(transport_instance * t, BOOL watch)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
+const uschar * trname = t->drinst.name;
 exim_gnutls_state_st tpt_dummy_state;
 host_item * dummy_host = (host_item *)1;
 uschar * dummy_errstr;
 exim_gnutls_state_st tpt_dummy_state;
 host_item * dummy_host = (host_item *)1;
 uschar * dummy_errstr;
@@ -1661,7 +1664,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
     const uschar * pkey = ob->tls_privatekey;
 
     DEBUG(D_tls)
     const uschar * pkey = ob->tls_privatekey;
 
     DEBUG(D_tls)
-      debug_printf("TLS: preloading client certs for transport '%s'\n", t->name);
+      debug_printf("TLS: preloading client certs for transport '%s'\n", trname);
 
     /* The state->lib_state.x509_cred is used for the certs load, and is the sole
     structure element used.  So we can set up a dummy.  The hoat arg only
 
     /* The state->lib_state.x509_cred is used for the certs load, and is the sole
     structure element used.  So we can set up a dummy.  The hoat arg only
@@ -1675,7 +1678,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
   }
 else
   DEBUG(D_tls)
   }
 else
   DEBUG(D_tls)
-    debug_printf("TLS: not preloading client certs, for transport '%s'\n", t->name);
+    debug_printf("TLS: not preloading client certs, for transport '%s'\n", trname);
 
 /* If tls_verify_certificates is non-empty and has no $, load CAs.
 If none was configured and we can't handle "system", treat as empty. */
 
 /* If tls_verify_certificates is non-empty and has no $, load CAs.
 If none was configured and we can't handle "system", treat as empty. */
@@ -1689,7 +1692,7 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
   if (!watch || tls_set_watch(ob->tls_verify_certificates, FALSE))
     {
     DEBUG(D_tls)
   if (!watch || tls_set_watch(ob->tls_verify_certificates, FALSE))
     {
     DEBUG(D_tls)
-      debug_printf("TLS: preloading CA bundle for transport '%s'\n", t->name);
+      debug_printf("TLS: preloading CA bundle for transport '%s'\n", trname);
     if (creds_load_cabundle(&tpt_dummy_state, ob->tls_verify_certificates,
                            dummy_host, &dummy_errstr) != OK)
       return;
     if (creds_load_cabundle(&tpt_dummy_state, ob->tls_verify_certificates,
                            dummy_host, &dummy_errstr) != OK)
       return;
@@ -1699,19 +1702,19 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
       {
       if (!watch || tls_set_watch(ob->tls_crl, FALSE))
        {
       {
       if (!watch || tls_set_watch(ob->tls_crl, FALSE))
        {
-       DEBUG(D_tls) debug_printf("TLS: preloading CRL for transport '%s'\n", t->name);
+       DEBUG(D_tls) debug_printf("TLS: preloading CRL for transport '%s'\n", trname);
        if (creds_load_crl(&tpt_dummy_state, ob->tls_crl, &dummy_errstr) != OK)
          return;
        ob->tls_preload.crl = TRUE;
        }
       }
     else
        if (creds_load_crl(&tpt_dummy_state, ob->tls_crl, &dummy_errstr) != OK)
          return;
        ob->tls_preload.crl = TRUE;
        }
       }
     else
-      DEBUG(D_tls) debug_printf("TLS: not preloading CRL, for transport '%s'\n", t->name);
+      DEBUG(D_tls) debug_printf("TLS: not preloading CRL, for transport '%s'\n", trname);
     }
   }
 else
   DEBUG(D_tls)
     }
   }
 else
   DEBUG(D_tls)
-      debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", t->name);
+      debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", trname);
 
 /* We do not preload tls_require_ciphers to to the transport as it implicitly
 depends on DANE or plain usage. */
 
 /* We do not preload tls_require_ciphers to to the transport as it implicitly
 depends on DANE or plain usage. */
@@ -1740,7 +1743,7 @@ state_server.lib_state = null_tls_preload;
 static void
 tls_client_creds_invalidate(transport_instance * t)
 {
 static void
 tls_client_creds_invalidate(transport_instance * t)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
 if (ob->tls_preload.x509_cred)
   gnutls_certificate_free_credentials(ob->tls_preload.x509_cred);
 ob->tls_preload = null_tls_preload;
 if (ob->tls_preload.x509_cred)
   gnutls_certificate_free_credentials(ob->tls_preload.x509_cred);
 ob->tls_preload = null_tls_preload;
@@ -2312,8 +2315,9 @@ old_pool = store_pool;
     if (*s) s++;               /* now on _ between groups */
     while ((c = *s))
       {
     if (*s) s++;               /* now on _ between groups */
     while ((c = *s))
       {
-      for (*++s && ++s; (c = *s) && c != ')'; s++)
-       g = string_catn(g, c == '-' ? US"_" : s, 1);
+      if (*++s)
+       for (++s; (c = *s) && c != ')'; s++)
+         g = string_catn(g, c == '-' ? US"_" : s, 1);
       /* now on ) closing group */
       if ((c = *s) && *++s == '-') g = string_catn(g, US"__", 2);
       /* now on _ between groups */
       /* now on ) closing group */
       if ((c = *s) && *++s == '-') g = string_catn(g, US"__", 2);
       /* now on _ between groups */
@@ -2851,7 +2855,7 @@ static int
 tls_server_ticket_cb(gnutls_session_t sess, u_int htype, unsigned when,
   unsigned incoming, const gnutls_datum_t * msg)
 {
 tls_server_ticket_cb(gnutls_session_t sess, u_int htype, unsigned when,
   unsigned incoming, const gnutls_datum_t * msg)
 {
-DEBUG(D_tls) debug_printf("newticket cb\n");
+DEBUG(D_tls) debug_printf("newticket cb (on server)\n");
 tls_in.resumption |= RESUME_CLIENT_REQUESTED;
 return 0;
 }
 tls_in.resumption |= RESUME_CLIENT_REQUESTED;
 return 0;
 }
@@ -2888,9 +2892,12 @@ tls_server_resume_posthandshake(exim_gnutls_state_st * state)
 {
 if (gnutls_session_resumption_requested(state->session))
   {
 {
 if (gnutls_session_resumption_requested(state->session))
   {
-  /* This tells us the client sent a full ticket.  We use a
+  /* This tells us the client sent a full (?) ticket.  We use a
   callback on session-ticket request, elsewhere, to tell
   callback on session-ticket request, elsewhere, to tell
-  if a client asked for a ticket. */
+  if a client asked for a ticket.
+  XXX As of GnuTLS 3.0.1 it seems to be returning true even for
+  a pure ticket-req (a zero-length Session Ticket extension
+  in the Client Hello, for 1.2) which mucks up our logic. */
 
   tls_in.resumption |= RESUME_CLIENT_SUGGESTED;
   DEBUG(D_tls) debug_printf("client requested resumption\n");
 
   tls_in.resumption |= RESUME_CLIENT_SUGGESTED;
   DEBUG(D_tls) debug_printf("client requested resumption\n");
@@ -3000,7 +3007,7 @@ exim_gnutls_state_st * state = NULL;
 if (tls_in.active.sock >= 0)
   {
   tls_error(US"STARTTLS received after TLS started", US "", NULL, errstr);
 if (tls_in.active.sock >= 0)
   {
   tls_error(US"STARTTLS received after TLS started", US "", NULL, errstr);
-  smtp_printf("554 Already in TLS\r\n", FALSE);
+  smtp_printf("554 Already in TLS\r\n", SP_NO_MORE);
   return FAIL;
   }
 
   return FAIL;
   }
 
@@ -3079,7 +3086,7 @@ mode, the fflush() happens when smtp_getc() is called. */
 
 if (!state->tlsp->on_connect)
   {
 
 if (!state->tlsp->on_connect)
   {
-  smtp_printf("220 TLS go ahead\r\n", FALSE);
+  smtp_printf("220 TLS go ahead\r\n", SP_NO_MORE);
   fflush(smtp_out);
   }
 
   fflush(smtp_out);
   }
 
@@ -3319,7 +3326,8 @@ tls_retrieve_session(tls_support * tlsp, gnutls_session_t session,
 tlsp->resumption = RESUME_SUPPORTED;
 
 if (!conn_args->have_lbserver)
 tlsp->resumption = RESUME_SUPPORTED;
 
 if (!conn_args->have_lbserver)
-  { DEBUG(D_tls) debug_printf("resumption not supported on continued-connection\n"); }
+  { DEBUG(D_tls) debug_printf(
+      "resumption not supported: no LB detection done (continued-conn?)\n"); }
 else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host) == OK)
   {
   dbdata_tls_session * dt;
 else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host) == OK)
   {
   dbdata_tls_session * dt;
@@ -3347,6 +3355,7 @@ else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host
     dbfn_close(dbm_file);
     }
   }
     dbfn_close(dbm_file);
     }
   }
+else DEBUG(D_tls) debug_printf("no resumption for this host\n");
 }
 
 
 }
 
 
@@ -3374,22 +3383,26 @@ if (gnutls_session_get_flags(session) & GNUTLS_SFLAGS_SESSION_TICKET)
       int dlen = sizeof(dbdata_tls_session) + tkt.size;
       dbdata_tls_session * dt = store_get(dlen, GET_TAINTED);
 
       int dlen = sizeof(dbdata_tls_session) + tkt.size;
       dbdata_tls_session * dt = store_get(dlen, GET_TAINTED);
 
-      DEBUG(D_tls) debug_printf("session data size %u\n", (unsigned)tkt.size);
+      DEBUG(D_tls) debug_printf(" session data size %u\n", (unsigned)tkt.size);
       memcpy(dt->session, tkt.data, tkt.size);
       gnutls_free(tkt.data);
 
       memcpy(dt->session, tkt.data, tkt.size);
       gnutls_free(tkt.data);
 
-      if ((dbm_file = dbfn_open(US"tls", O_RDWR, &dbblock, FALSE, FALSE)))
+      if ((dbm_file = dbfn_open(US"tls", O_RDWR|O_CREAT, &dbblock, FALSE, FALSE)))
        {
        /* key for the db is the IP */
        dbfn_write(dbm_file, tlsp->resume_index, dt, dlen);
        dbfn_close(dbm_file);
 
        DEBUG(D_tls)
        {
        /* key for the db is the IP */
        dbfn_write(dbm_file, tlsp->resume_index, dt, dlen);
        dbfn_close(dbm_file);
 
        DEBUG(D_tls)
-         debug_printf("wrote session db (len %u)\n", (unsigned)dlen);
+         debug_printf(" wrote session db (len %u)\n", (unsigned)dlen);
        }
       }
        }
       }
-    else DEBUG(D_tls)
-      debug_printf("extract session data: %s\n", US gnutls_strerror(rc));
+    else
+      { DEBUG(D_tls)
+      debug_printf(" extract session data: %s\n", US gnutls_strerror(rc));
+      }
+  else DEBUG(D_tls)
+      debug_printf(" host not resmable; not saving ticket\n");
   }
 }
 
   }
 }
 
@@ -3406,7 +3419,7 @@ tls_client_ticket_cb(gnutls_session_t sess, u_int htype, unsigned when,
 exim_gnutls_state_st * state = gnutls_session_get_ptr(sess);
 tls_support * tlsp = state->tlsp;
 
 exim_gnutls_state_st * state = gnutls_session_get_ptr(sess);
 tls_support * tlsp = state->tlsp;
 
-DEBUG(D_tls) debug_printf("newticket cb\n");
+DEBUG(D_tls) debug_printf("newticket cb (on client)\n");
 
 if (!tlsp->ticket_received)
   tls_save_session(tlsp, sess, state->host);
 
 if (!tlsp->ticket_received)
   tls_save_session(tlsp, sess, state->host);
@@ -3466,7 +3479,7 @@ tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args,
 host_item * host = conn_args->host;          /* for msgs and option-tests */
 transport_instance * tb = conn_args->tblock; /* always smtp or NULL */
 smtp_transport_options_block * ob = tb
 host_item * host = conn_args->host;          /* for msgs and option-tests */
 transport_instance * tb = conn_args->tblock; /* always smtp or NULL */
 smtp_transport_options_block * ob = tb
-  ? (smtp_transport_options_block *)tb->options_block
+  ? tb->drinst.options_block
   : &smtp_transport_option_defaults;
 int rc;
 exim_gnutls_state_st * state = NULL;
   : &smtp_transport_option_defaults;
 int rc;
 exim_gnutls_state_st * state = NULL;
@@ -3891,7 +3904,7 @@ else if (inbytes < 0)
   return FALSE;
   }
 #ifndef DISABLE_DKIM
   return FALSE;
   }
 #ifndef DISABLE_DKIM
-dkim_exim_verify_feed(state->xfer_buffer, inbytes);
+smtp_verify_feed(state->xfer_buffer, inbytes);
 #endif
 state->xfer_buffer_hwm = (int) inbytes;
 state->xfer_buffer_lwm = 0;
 #endif
 state->xfer_buffer_hwm = (int) inbytes;
 state->xfer_buffer_lwm = 0;
@@ -3967,7 +3980,7 @@ int n = state->xfer_buffer_hwm - state->xfer_buffer_lwm;
 if (n > lim)
   n = lim;
 if (n > 0)
 if (n > lim)
   n = lim;
 if (n > 0)
-  dkim_exim_verify_feed(state->xfer_buffer+state->xfer_buffer_lwm, n);
+  smtp_verify_feed(state->xfer_buffer+state->xfer_buffer_lwm, n);
 #endif
 }
 
 #endif
 }