+/* Preload whatever creds are static, onto a transport. The client can then
+just copy the pointer as it starts up. */
+
+/*XXX this is not called for a cmdline send. But one needing to use >1 conn would benefit,
+and there seems little downside. */
+
+static void
+tls_client_creds_init(transport_instance * t, BOOL watch)
+{
+smtp_transport_options_block * ob = t->options_block;
+exim_gnutls_state_st tpt_dummy_state;
+host_item * dummy_host = (host_item *)1;
+uschar * dummy_errstr;
+
+if ( !exim_gnutls_base_init_done
+ && tls_g_init(&dummy_errstr) != OK)
+ return;
+
+ob->tls_preload = null_tls_preload;
+if (gnutls_certificate_allocate_credentials(
+ (struct gnutls_certificate_credentials_st **)&ob->tls_preload.x509_cred))
+ {
+ ob->tls_preload.x509_cred = NULL;
+ return;
+ }
+creds_basic_init(ob->tls_preload.x509_cred, FALSE);
+
+tpt_dummy_state.session = NULL;
+tpt_dummy_state.lib_state = ob->tls_preload;
+
+#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
+if ( opt_set_and_noexpand(ob->tls_certificate)
+ && opt_unset_or_noexpand(ob->tls_privatekey))
+ {
+ if ( !watch
+ || ( tls_set_watch(ob->tls_certificate, FALSE)
+ && tls_set_watch(ob->tls_privatekey, FALSE)
+ ) )
+ {
+ const uschar * pkey = ob->tls_privatekey;
+
+ DEBUG(D_tls)
+ debug_printf("TLS: preloading client certs for transport '%s'\n", t->name);
+
+ /* 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
+ selects a retcode in case of fail, so any value */
+
+ if (creds_load_client_certs(&tpt_dummy_state, dummy_host,
+ ob->tls_certificate, pkey ? pkey : ob->tls_certificate,
+ &dummy_errstr) == OK)
+ ob->tls_preload.conn_certs = TRUE;
+ }
+ }
+else
+ DEBUG(D_tls)
+ debug_printf("TLS: not preloading client certs, for transport '%s'\n", t->name);
+
+/* 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 ( opt_set_and_noexpand(ob->tls_verify_certificates)
+#ifndef SUPPORT_SYSDEFAULT_CABUNDLE
+ && Ustrcmp(ob->tls_verify_certificates, "system") != 0
+#endif
+ )
+ {
+ 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);
+ if (creds_load_cabundle(&tpt_dummy_state, ob->tls_verify_certificates,
+ dummy_host, &dummy_errstr) != OK)
+ return;
+ ob->tls_preload.cabundle = TRUE;
+
+ if (opt_set_and_noexpand(ob->tls_crl))
+ {
+ if (!watch || tls_set_watch(ob->tls_crl, FALSE))
+ {
+ DEBUG(D_tls) debug_printf("TLS: preloading CRL for transport '%s'\n", t->name);
+ 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);
+ }
+ }
+else
+ DEBUG(D_tls)
+ debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", t->name);
+
+/* We do not preload tls_require_ciphers to to the transport as it implicitly
+depends on DANE or plain usage. */
+
+#endif
+}
+
+
+#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
+/* Invalidate the creds cached, by dropping the current ones.
+Call when we notice one of the source files has changed. */
+
+static void
+tls_server_creds_invalidate(void)
+{
+if (state_server.lib_state.pri_cache)
+ gnutls_priority_deinit(state_server.lib_state.pri_cache);
+state_server.lib_state.pri_cache = NULL;
+
+if (state_server.lib_state.x509_cred)
+ gnutls_certificate_free_credentials(state_server.lib_state.x509_cred);
+state_server.lib_state = null_tls_preload;
+}
+
+
+static void
+tls_client_creds_invalidate(transport_instance * t)
+{
+smtp_transport_options_block * ob = t->options_block;
+if (ob->tls_preload.x509_cred)
+ gnutls_certificate_free_credentials(ob->tls_preload.x509_cred);
+ob->tls_preload = null_tls_preload;
+}
+#endif