X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/c562fd30c03126dd72d76ec43842d9d00fcd8bf3..09c17790eec23907b93df1ec7cee746b28dfc836:/src/src/tls-openssl.c diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 43ea8a0d2..63bf83b1d 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -38,6 +38,13 @@ functions from the OpenSSL library. */ #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) # define EXIM_HAVE_OPENSSL_TLSEXT #endif +#if OPENSSL_VERSION_NUMBER >= 0x010100000L +# define EXIM_HAVE_OPENSSL_CHECKHOST +#endif +#if OPENSSL_VERSION_NUMBER >= 0x010000000L \ + && (OPENSSL_VERSION_NUMBER & 0x0000ff000L) >= 0x000002000L +# define EXIM_HAVE_OPENSSL_CHECKHOST +#endif #if !defined(EXIM_HAVE_OPENSSL_TLSEXT) && !defined(DISABLE_OCSP) # warning "OpenSSL library version too old; define DISABLE_OCSP in Makefile" @@ -120,7 +127,7 @@ typedef struct tls_ext_ctx_cb { #ifdef EXPERIMENTAL_CERTNAMES uschar * verify_cert_hostnames; #endif -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT uschar * event_action; #endif } tls_ext_ctx_cb; @@ -288,6 +295,10 @@ verify_callback(int state, X509_STORE_CTX *x509ctx, X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx); int depth = X509_STORE_CTX_get_error_depth(x509ctx); static uschar txt[256]; +#ifdef EXPERIMENTAL_EVENT +uschar * ev; +uschar * yield; +#endif X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt)); @@ -297,7 +308,6 @@ if (state == 0) depth, X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509ctx)), txt); - tlsp->certificate_verified = FALSE; *calledp = TRUE; if (!*optionalp) { @@ -322,18 +332,20 @@ else if (depth != 0) ERR_clear_error(); } #endif -#ifdef EXPERIMENTAL_TPDA - if (tlsp == &tls_out && client_static_cbinfo->event_action) +#ifdef EXPERIMENTAL_EVENT + ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action; + if (ev) { tlsp->peercert = X509_dup(cert); - if (tpda_raise_event(client_static_cbinfo->event_action, - US"tls:cert", string_sprintf("%d", depth)) == DEFER) + if ((yield = event_raise(ev, US"tls:cert", string_sprintf("%d", depth)))) { log_write(0, LOG_MAIN, "SSL verify denied by event-action: " - "depth=%d cert=%s", depth, txt); - tlsp->certificate_verified = FALSE; + "depth=%d cert=%s: %s", depth, txt, yield); *calledp = TRUE; - return 0; /* reject */ + if (!*optionalp) + return 0; /* reject */ + DEBUG(D_tls) debug_printf("Event-action verify failure overridden " + "(host in tls_try_verify_hosts)\n"); } X509_free(tlsp->peercert); tlsp->peercert = NULL; @@ -354,9 +366,12 @@ else && ((verify_cert_hostnames = client_static_cbinfo->verify_cert_hostnames))) /* client, wanting hostname check */ -# if OPENSSL_VERSION_NUMBER >= 0x010100000L || OPENSSL_VERSION_NUMBER >= 0x010002000L +# if EXIM_HAVE_OPENSSL_CHECKHOST # ifndef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS # define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0 +# endif +# ifndef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS +# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0 # endif { int sep = 0; @@ -365,7 +380,8 @@ else int rc; while ((name = string_nextinlist(&list, &sep, NULL, 0))) if ((rc = X509_check_host(cert, name, 0, - X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS))) + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + | X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS))) { if (rc < 0) { @@ -378,7 +394,11 @@ else { log_write(0, LOG_MAIN, "SSL verify error: certificate name mismatch: \"%s\"\n", txt); - return 0; /* reject */ + *calledp = TRUE; + if (!*optionalp) + return 0; /* reject */ + DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in " + "tls_try_verify_hosts)\n"); } } # else @@ -386,24 +406,28 @@ else { log_write(0, LOG_MAIN, "SSL verify error: certificate name mismatch: \"%s\"\n", txt); - return 0; /* reject */ + *calledp = TRUE; + if (!*optionalp) + return 0; /* reject */ + DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in " + "tls_try_verify_hosts)\n"); } # endif #endif /*EXPERIMENTAL_CERTNAMES*/ -#ifdef EXPERIMENTAL_TPDA - if (tlsp == &tls_out) - { - if (tpda_raise_event(client_static_cbinfo->event_action, - US"tls:cert", US"0") == DEFER) +#ifdef EXPERIMENTAL_EVENT + ev = tlsp == &tls_out ? client_static_cbinfo->event_action : event_action; + if (ev) + if ((yield = event_raise(ev, US"tls:cert", US"0"))) { log_write(0, LOG_MAIN, "SSL verify denied by event-action: " - "depth=0 cert=%s", txt); - tlsp->certificate_verified = FALSE; + "depth=0 cert=%s: %s", txt, yield); *calledp = TRUE; - return 0; /* reject */ + if (!*optionalp) + return 0; /* reject */ + DEBUG(D_tls) debug_printf("Event-action verify failure overridden " + "(host in tls_try_verify_hosts)\n"); } - } #endif DEBUG(D_tls) debug_printf("SSL%s verify ok: depth=0 SN=%s\n", @@ -438,8 +462,9 @@ verify_callback_client_dane(int state, X509_STORE_CTX * x509ctx) { X509 * cert = X509_STORE_CTX_get_current_cert(x509ctx); static uschar txt[256]; -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT int depth = X509_STORE_CTX_get_error_depth(x509ctx); +uschar * yield; #endif X509_NAME_oneline(X509_get_subject_name(cert), CS txt, sizeof(txt)); @@ -448,14 +473,14 @@ DEBUG(D_tls) debug_printf("verify_callback_client_dane: %s\n", txt); tls_out.peerdn = txt; tls_out.peercert = X509_dup(cert); -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT if (client_static_cbinfo->event_action) { - if (tpda_raise_event(client_static_cbinfo->event_action, - US"tls:cert", string_sprintf("%d", depth)) == DEFER) + if ((yield = event_raise(client_static_cbinfo->event_action, + US"tls:cert", string_sprintf("%d", depth)))) { log_write(0, LOG_MAIN, "DANE verify denied by event-action: " - "depth=%d cert=%s", depth, txt); + "depth=%d cert=%s: %s", depth, txt, yield); tls_out.certificate_verified = FALSE; return 0; /* reject */ } @@ -1140,7 +1165,7 @@ else cbinfo->dhparam = dhparam; cbinfo->server_cipher_list = NULL; cbinfo->host = host; -#ifdef EXPERIMENTAL_TPDA +#ifdef EXPERIMENTAL_EVENT cbinfo->event_action = NULL; #endif @@ -1935,8 +1960,8 @@ if (request_ocsp) } #endif -#ifdef EXPERIMENTAL_TPDA -client_static_cbinfo->event_action = tb->tpda_event_action; +#ifdef EXPERIMENTAL_EVENT +client_static_cbinfo->event_action = tb->event_action; #endif /* There doesn't seem to be a built-in timeout on connection. */