#include <openssl/err.h>
#include <openssl/rand.h>
#ifdef EXPERIMENTAL_OCSP
-#include <openssl/ocsp.h>
+# include <openssl/ocsp.h>
#endif
#ifdef EXPERIMENTAL_OCSP
#endif
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
-#define EXIM_HAVE_OPENSSL_TLSEXT
+# define EXIM_HAVE_OPENSSL_TLSEXT
#endif
/* Structure for collecting random data for seeding. */
uschar *server_cipher_list;
/* only passed down to tls_error: */
host_item *host;
+
+#ifdef EXPERIMENTAL_CERTNAMES
+ uschar * verify_cert_hostnames;
+#endif
} tls_ext_ctx_cb;
/* should figure out a cleanup of API to handle state preserved per
X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx);
static uschar txt[256];
-X509_NAME_oneline(X509_get_subject_name(cert),
- CS txt, sizeof(txt));
+X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt));
if (state == 0)
{
}
else
{
+#ifdef EXPERIMENTAL_CERTNAMES
+ uschar * verify_cert_hostnames;
+#endif
+
tlsp->peerdn = txt;
tlsp->peercert = X509_dup(cert);
+
+#ifdef EXPERIMENTAL_CERTNAMES
+ if ( tlsp == &tls_out
+ && ((verify_cert_hostnames = client_static_cbinfo->verify_cert_hostnames)))
+ /* client, wanting hostname check */
+
+# if OPENSSL_VERSION_NUMBER >= 0x010100000L || OPENSSL_VERSION_NUMBER >= 0x010002000L
+ {
+ int sep = 0;
+ uschar * list = verify_cert_hostnames;
+ uschar * name;
+ while (name = string_nextinlist(&list, &sep, NULL, 0))
+ if (X509_check_host(cert, name, 0, 0))
+ break;
+ if (!name)
+ {
+ log_write(0, LOG_MAIN,
+ "SSL verify error: certificate name mismatch: \"%s\"\n", txt);
+ return 0; /* reject */
+ }
+ }
+# else
+ if (!tls_is_name_for_cert(verify_cert_hostnames, cert))
+ {
+ log_write(0, LOG_MAIN,
+ "SSL verify error: certificate name mismatch: \"%s\"\n", txt);
+ return 0; /* reject */
+ }
+# endif
+#endif
+
DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n",
*calledp ? "" : " authenticated", txt);
if (!*calledp) tlsp->certificate_verified = TRUE;
* Initialize for TLS *
*************************************************/
-/* Called from both server and client code, to do preliminary initialization of
-the library.
+/* Called from both server and client code, to do preliminary initialization
+of the library. We allocate and return a context structure.
Arguments:
host connected host, if client; NULL if server
privatekey private key
ocsp_file file of stapling info (server); flag for require ocsp (client)
addr address if client; NULL if server (for some randomness)
+ cbp place to put allocated context
Returns: OK/DEFER/FAIL
*/
# endif
#endif
+#ifdef EXPERIMENTAL_CERTNAMES
+cbinfo->verify_cert_hostnames = NULL;
+#endif
+
/* Set up the RSA callback */
SSL_CTX_set_tmp_rsa_callback(*ctxp, rsa_callback);
/* stick to the old behaviour for compatibility if tls_verify_certificates is
set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only
the specified host patterns if one of them is defined */
+
if ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) ||
(verify_check_host(&ob->tls_verify_hosts) == OK))
{
ob->tls_crl, host, FALSE, verify_callback_client)) != OK)
return rc;
client_verify_optional = FALSE;
+
+#ifdef EXPERIMENTAL_CERTNAMES
+ if (ob->tls_verify_cert_hostnames)
+ {
+ if (!expand_check(ob->tls_verify_cert_hostnames,
+ US"tls_verify_cert_hostnames",
+ &client_static_cbinfo->verify_cert_hostnames))
+ return FAIL;
+ if (client_static_cbinfo->verify_cert_hostnames)
+ DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
+ client_static_cbinfo->verify_cert_hostnames);
+ }
+#endif
}
else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
{