#if OPENSSL_VERSION_NUMBER >= 0x10100000L
# define EXIM_HAVE_OCSP_RESP_COUNT
# define OPENSSL_AUTO_SHA256
+# define OPENSSL_MIN_PROTO_VERSION
#else
# define EXIM_HAVE_EPHEM_RSA_KEX
# define EXIM_HAVE_RAND_PSEUDO
/* Callbacks */
#ifndef DISABLE_OCSP
static int tls_server_stapling_cb(SSL *s, void *arg);
+static void x509_stack_dump_cert_s_names(const STACK_OF(X509) * sk);
+static void x509_store_dump_cert_s_names(X509_STORE * store);
#endif
*/
static void
-info_callback(SSL *s, int where, int ret)
+info_callback(SSL * s, int where, int ret)
{
DEBUG(D_tls)
{
- const uschar * str;
-
- if (where & SSL_ST_CONNECT)
- str = US"SSL_connect";
- else if (where & SSL_ST_ACCEPT)
- str = US"SSL_accept";
- else
- str = US"SSL info (undefined)";
+ gstring * g = NULL;
+
+ if (where & SSL_ST_CONNECT) g = string_append_listele(g, ',', US"SSL_connect");
+ if (where & SSL_ST_ACCEPT) g = string_append_listele(g, ',', US"SSL_accept");
+ if (where & SSL_CB_LOOP) g = string_append_listele(g, ',', US"state_chg");
+ if (where & SSL_CB_EXIT) g = string_append_listele(g, ',', US"hshake_exit");
+ if (where & SSL_CB_READ) g = string_append_listele(g, ',', US"read");
+ if (where & SSL_CB_WRITE) g = string_append_listele(g, ',', US"write");
+ if (where & SSL_CB_ALERT) g = string_append_listele(g, ',', US"alert");
+ if (where & SSL_CB_HANDSHAKE_START) g = string_append_listele(g, ',', US"hshake_start");
+ if (where & SSL_CB_HANDSHAKE_DONE) g = string_append_listele(g, ',', US"hshake_done");
if (where & SSL_CB_LOOP)
- debug_printf("%s: %s\n", str, SSL_state_string_long(s));
+ debug_printf("SSL %s: %s\n", g->s, SSL_state_string_long(s));
else if (where & SSL_CB_ALERT)
- debug_printf("SSL3 alert %s:%s:%s\n",
- str = where & SSL_CB_READ ? US"read" : US"write",
+ debug_printf("SSL %s %s:%s\n", g->s,
SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
else if (where & SSL_CB_EXIT)
{
- if (ret == 0)
- debug_printf("%s: failed in %s\n", str, SSL_state_string_long(s));
- else if (ret < 0)
- debug_printf("%s: error in %s\n", str, SSL_state_string_long(s));
+ if (ret <= 0)
+ debug_printf("SSL %s: %s in %s\n", g->s,
+ ret == 0 ? "failed" : "error", SSL_state_string_long(s));
}
- else if (where & SSL_CB_HANDSHAKE_START)
- debug_printf("%s: hshake start: %s\n", str, SSL_state_string_long(s));
- else if (where & SSL_CB_HANDSHAKE_DONE)
- debug_printf("%s: hshake done: %s\n", str, SSL_state_string_long(s));
+ else if (where & (SSL_CB_HANDSHAKE_START | SSL_CB_HANDSHAKE_DONE))
+ debug_printf("SSL %s: %s\n", g->s, SSL_state_string_long(s));
}
}
OCSP_SINGLERESP * single_response;
ASN1_GENERALIZEDTIME * rev, * thisupd, * nextupd;
STACK_OF(X509) * sk;
-unsigned long verify_flags;
int status, reason, i;
DEBUG(D_tls)
goto bad;
}
-sk = state->verify_stack;
-verify_flags = OCSP_NOVERIFY; /* check sigs, but not purpose */
+sk = state->verify_stack; /* set by setup_certs() / chain_from_pem_file() */
/* May need to expose ability to adjust those flags?
OCSP_NOSIGS OCSP_NOVERIFY OCSP_NOCHAIN OCSP_NOCHECKS OCSP_NOEXPLICIT
OCSP_TRUSTOTHER OCSP_NOINTERN */
-/* This does a full verify on the OCSP proof before we load it for serving
-up; possibly overkill - just date-checks might be nice enough.
+/* This does a partial verify (only the signer link, not the whole chain-to-CA)
+on the OCSP proof before we load it for serving up; possibly overkill -
+just date-checks might be nice enough.
OCSP_basic_verify takes a "store" arg, but does not
-use it for the chain verification, which is all we do
-when OCSP_NOVERIFY is set. The content from the wire
-"basic_response" and a cert-stack "sk" are all that is used.
+use it for the chain verification, when OCSP_NOVERIFY is set.
+The content from the wire "basic_response" and a cert-stack "sk" are all
+that is used.
We have a stack, loaded in setup_certs() if tls_verify_certificates
was a file (not a directory, or "system"). It is unfortunate we
And there we NEED it; we must verify that status... unless the
library does it for us anyway? */
-if ((i = OCSP_basic_verify(basic_response, sk, NULL, verify_flags)) < 0)
+if ((i = OCSP_basic_verify(basic_response, sk, NULL, OCSP_NOVERIFY)) < 0)
{
DEBUG(D_tls)
{
DEBUG(D_tls) debug_printf("TLS: not preloading ECDH curve for server\n");
#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
-/* If we can, preload the server-side cert, key and ocsp */
-
-if ( opt_set_and_noexpand(tls_certificate)
-# ifndef DISABLE_OCSP
- && opt_unset_or_noexpand(tls_ocsp_file)
-#endif
- && opt_unset_or_noexpand(tls_privatekey))
- {
- /* Set watches on the filenames. The implementation does de-duplication
- so we can just blindly do them all. */
-
- if ( tls_set_watch(tls_certificate, TRUE)
-# ifndef DISABLE_OCSP
- && tls_set_watch(tls_ocsp_file, TRUE)
-#endif
- && tls_set_watch(tls_privatekey, TRUE))
- {
- state_server.certificate = tls_certificate;
- state_server.privatekey = tls_privatekey;
-#ifndef DISABLE_OCSP
- state_server.u_ocsp.server.file = tls_ocsp_file;
-#endif
-
- DEBUG(D_tls) debug_printf("TLS: preloading server certs\n");
- if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
- state_server.lib_state.conn_certs = TRUE;
- }
- }
-else if ( !tls_certificate && !tls_privatekey
-# ifndef DISABLE_OCSP
- && !tls_ocsp_file
-#endif
- )
- { /* Generate & preload a selfsigned cert. No files to watch. */
- if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
- {
- state_server.lib_state.conn_certs = TRUE;
- lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
- }
- }
-else
- DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
-
-
/* If we can, preload the Authorities for checking client certs against.
Actual choice to do verify is made (tls_{,try_}verify_hosts)
-at TLS conn startup */
+at TLS conn startup.
+Do this before the server ocsp so that its info can verify the ocsp. */
if ( opt_set_and_noexpand(tls_verify_certificates)
&& opt_unset_or_noexpand(tls_crl))
if (setup_certs(ctx, tls_verify_certificates, tls_crl, NULL, &dummy_errstr)
== OK)
state_server.lib_state.cabundle = TRUE;
- }
+
+ /* If we can, preload the server-side cert, key and ocsp */
+
+ if ( opt_set_and_noexpand(tls_certificate)
+# ifndef DISABLE_OCSP
+ && opt_unset_or_noexpand(tls_ocsp_file)
+# endif
+ && opt_unset_or_noexpand(tls_privatekey))
+ {
+ /* Set watches on the filenames. The implementation does de-duplication
+ so we can just blindly do them all. */
+
+ if ( tls_set_watch(tls_certificate, TRUE)
+# ifndef DISABLE_OCSP
+ && tls_set_watch(tls_ocsp_file, TRUE)
+# endif
+ && tls_set_watch(tls_privatekey, TRUE))
+ {
+ state_server.certificate = tls_certificate;
+ state_server.privatekey = tls_privatekey;
+#ifndef DISABLE_OCSP
+ state_server.u_ocsp.server.file = tls_ocsp_file;
+# endif
+
+ DEBUG(D_tls) debug_printf("TLS: preloading server certs\n");
+ if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
+ state_server.lib_state.conn_certs = TRUE;
+ }
+ }
+ else if ( !tls_certificate && !tls_privatekey
+# ifndef DISABLE_OCSP
+ && !tls_ocsp_file
+# endif
+ )
+ { /* Generate & preload a selfsigned cert. No files to watch. */
+ if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
+ {
+ state_server.lib_state.conn_certs = TRUE;
+ lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
+ }
+ }
+ else
+ DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
+ }
}
else
DEBUG(D_tls) debug_printf("TLS: not preloading CA bundle for server\n");
+
+
#endif /* EXIM_HAVE_INOTIFY */
{
SSL_CTX_free(state_server.lib_state.lib_ctx);
state_server.lib_state = null_tls_preload;
+#ifndef DISABLE_OCSP
state_server.u_ocsp.server.file_expanded = NULL;
+#endif
}
SSL_CTX * ctx = state_server.lib_state.lib_ctx;
SSL_CTX_set_info_callback(server_sni, SSL_CTX_get_info_callback(ctx));
SSL_CTX_set_mode(server_sni, SSL_CTX_get_mode(ctx));
+#ifdef OPENSSL_MIN_PROTO_VERSION
+ SSL_CTX_set_min_proto_version(server_sni, SSL3_VERSION);
+#endif
SSL_CTX_set_options(server_sni, SSL_CTX_get_options(ctx));
+ SSL_CTX_clear_options(server_sni, ~SSL_CTX_get_options(ctx));
SSL_CTX_set_timeout(server_sni, SSL_CTX_get_timeout(ctx));
SSL_CTX_set_tlsext_servername_callback(server_sni, tls_servername_cb);
SSL_CTX_set_tlsext_servername_arg(server_sni, state);
}
#endif
- DEBUG(D_tls) debug_printf("setting SSL CTX options: %#lx\n", init_options);
- if (!(SSL_CTX_set_options(ctx, init_options)))
- return tls_error(string_sprintf(
+#ifdef OPENSSL_MIN_PROTO_VERSION
+ SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
+#endif
+ DEBUG(D_tls) debug_printf("setting SSL CTX options: %016lx\n", init_options);
+ SSL_CTX_set_options(ctx, init_options);
+ {
+ uint64_t readback = SSL_CTX_clear_options(ctx, ~init_options);
+ if (readback != init_options)
+ return tls_error(string_sprintf(
"SSL_CTX_set_option(%#lx)", init_options), host, NULL, errstr);
+ }
}
else
DEBUG(D_tls) debug_printf("no SSL CTX options to set\n");