+ /* certificate is mandatory in server, optional in client */
+
+ if ( !state->exp_tls_certificate
+ || !*state->exp_tls_certificate
+ )
+ if (!host)
+ return tls_install_selfsign(state, errstr);
+ else
+ DEBUG(D_tls) debug_printf("TLS: no client certificate specified; okay\n");
+
+ if ( state->tls_privatekey && !Expand_check_tlsvar(tls_privatekey, errstr)
+ || f.expand_string_forcedfail
+ )
+ {
+ if (f.expand_string_forcedfail)
+ *errstr = US"expansion of tls_privatekey failed";
+ return DEFER;
+ }
+
+ /* tls_privatekey is optional, defaulting to same file as certificate */
+
+ if (!state->tls_privatekey || !*state->tls_privatekey)
+ {
+ state->tls_privatekey = state->tls_certificate;
+ state->exp_tls_privatekey = state->exp_tls_certificate;
+ }
+
+ if (state->exp_tls_certificate && *state->exp_tls_certificate)
+ {
+ BOOL load = TRUE;
+ DEBUG(D_tls) debug_printf("certificate file = %s\nkey file = %s\n",
+ state->exp_tls_certificate, state->exp_tls_privatekey);
+
+ if (state->received_sni)
+ if ( Ustrcmp(state->exp_tls_certificate, saved_tls_certificate) == 0
+ && Ustrcmp(state->exp_tls_privatekey, saved_tls_privatekey) == 0
+ )
+ {
+ DEBUG(D_tls) debug_printf("TLS SNI: cert and key unchanged\n");
+ load = FALSE; /* avoid re-loading the same certs */
+ }
+ else /* unload the pre-SNI certs before loading new ones */
+ {
+ DEBUG(D_tls) debug_printf("TLS SNI: have a changed cert/key pair\n");
+ gnutls_certificate_free_keys(state->lib_state.x509_cred);
+ }
+
+ if ( load
+ && (rc = host
+ ? creds_load_client_certs(state, host, state->exp_tls_certificate,
+ state->exp_tls_privatekey, errstr)
+ : creds_load_server_certs(state, state->exp_tls_certificate,
+ state->exp_tls_privatekey,
+#ifdef DISABLE_OCSP
+ NULL,
+#else
+ tls_ocsp_file,
+#endif
+ errstr)
+ ) )
+ {
+ DEBUG(D_tls) debug_printf("load-cert: '%s'\n", *errstr);
+ return rc;
+ }
+ }
+ }
+else
+ {
+ DEBUG(D_tls)
+ debug_printf("%s certs were preloaded\n", host ? "client" : "server");
+
+ if (!state->tls_privatekey) state->tls_privatekey = state->tls_certificate;
+ state->exp_tls_certificate = US state->tls_certificate;
+ state->exp_tls_privatekey = US state->tls_privatekey;
+
+#ifdef SUPPORT_GNUTLS_EXT_RAW_PARSE
+ if (state->lib_state.ocsp_hook)
+ gnutls_handshake_set_hook_function(state->session,
+ GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, tls_server_hook_cb);
+#endif
+ }
+
+
+/* Set the trusted CAs file if one is provided, and then add the CRL if one is
+provided. Experiment shows that, if the certificate file is empty, an unhelpful
+error message is provided. However, if we just refrain from setting anything up
+in that case, certificate verification fails, which seems to be the correct
+behaviour.
+If none was configured and we can't handle "system", treat as empty. */
+
+if (!state->lib_state.cabundle)
+ {
+ if (state->tls_verify_certificates && *state->tls_verify_certificates)