diff options
author | Phil Pennock <pdp@exim.org> | 2018-03-28 23:01:34 -0400 |
---|---|---|
committer | Phil Pennock <pdp@exim.org> | 2018-03-28 23:01:34 -0400 |
commit | 5ec37a55162e10377e457fe1deef174093f757a8 (patch) | |
tree | 38a56ce742efe73fb6acd4995965bacc58d2188f /src | |
parent | 405074adb94eb8402e9ffd0abe7da4f7c8c827bc (diff) |
Implement dane_require_tls_ciphers (theoretically)
It compiles with OpenSSL, on Darwin (if restore Darwin OS).
It doesn't crash immediately, but more testing is needed from a place
where port 25 is not just blocked.
Diffstat (limited to 'src')
-rw-r--r-- | src/src/tls-gnu.c | 22 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 21 | ||||
-rw-r--r-- | src/src/transports/smtp.c | 5 | ||||
-rw-r--r-- | src/src/transports/smtp.h | 1 |
4 files changed, 44 insertions, 5 deletions
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index eed8c06dc..0d20fea34 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1681,7 +1681,7 @@ else 1, 0)) || (rc = dane_verify_crt_raw(s, certlist, lsize, gnutls_certificate_type_get(state->session), - r, 0, + r, 0, # ifdef GNUTLS_BROKEN_DANE_VALIDATION usage == (1 << DANESSL_USAGE_DANE_EE) ? DANE_VFLAG_ONLY_CHECK_EE_USAGE : 0, @@ -2260,6 +2260,7 @@ smtp_transport_options_block *ob = (smtp_transport_options_block *)tb->options_block; int rc; exim_gnutls_state_st * state = NULL; +uschar *cipher_list = NULL; #ifndef DISABLE_OCSP BOOL require_ocsp = verify_check_given_host(&ob->hosts_require_ocsp, host) == OK; @@ -2269,9 +2270,26 @@ BOOL request_ocsp = require_ocsp ? TRUE DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd); +#ifdef SUPPORT_DANE +if (ob->dane_require_tls_ciphers) + { + /* not using expand_check_tlsvar because not yet in state */ + if (!expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", + &cipher_list, errstr)) + return DEFER; + if (cipher_list && *cipher_list) + cipher_list = ob->dane_require_tls_ciphers; + else + cipher_list = ob->tls_require_ciphers; + } +#endif + +if (!cipher_list) + cipher_list = ob->tls_require_ciphers; + if ((rc = tls_init(host, ob->tls_certificate, ob->tls_privatekey, ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, - ob->tls_require_ciphers, &state, errstr)) != OK) + cipher_list, &state, errstr)) != OK) return rc; { diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 969a99d99..c142bd059 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -904,7 +904,7 @@ We do not free the stack since it could be needed a second time for SNI handling. Separately we might try to replace using OCSP_basic_verify() - which seems to not -be a public interface into the OpenSSL library (there's no manual entry) - +be a public interface into the OpenSSL library (there's no manual entry) - But what with? We also use OCSP_basic_verify in the client stapling callback. And there we NEED it; we must verify that status... unless the library does it for us anyway? */ @@ -2300,8 +2300,23 @@ if (rc != OK) return rc; tls_out.certificate_verified = FALSE; client_verify_callback_called = FALSE; -if (!expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", - &expciphers, errstr)) +expciphers = NULL; +#ifdef SUPPORT_DANE +if (tlsa_dnsa) + { + /* We fall back to tls_require_ciphers if unset, empty or forced failure, but + other failures should be treated as problems. */ + if (ob->dane_require_tls_ciphers && + !expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", + &expciphers, errstr)) + return FAIL; + if (expciphers && *expciphers == '\0') + expciphers = NULL; + } +#endif +if (!expciphers && + !expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", + &expciphers, errstr)) return FAIL; /* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 23083f5d8..2dfb5b73a 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -38,6 +38,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, connect_timeout) }, { "connection_max_messages", opt_int | opt_public, (void *)offsetof(transport_instance, connection_max_messages) }, +# ifdef SUPPORT_DANE + { "dane_require_tls_ciphers", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, dane_require_tls_ciphers) }, +# endif { "data_timeout", opt_time, (void *)offsetof(smtp_transport_options_block, data_timeout) }, { "delay_after_cutoff", opt_bool, @@ -225,6 +229,7 @@ smtp_transport_options_block smtp_transport_option_defaults = { #ifdef SUPPORT_DANE .hosts_try_dane = NULL, .hosts_require_dane = NULL, + .dane_require_tls_ciphers = NULL, #endif .hosts_try_fastopen = NULL, #ifndef DISABLE_PRDR diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h index 749c6f778..7727c0c6d 100644 --- a/src/src/transports/smtp.h +++ b/src/src/transports/smtp.h @@ -32,6 +32,7 @@ typedef struct { #ifdef SUPPORT_DANE uschar *hosts_try_dane; uschar *hosts_require_dane; + uschar *dane_require_tls_ciphers; #endif uschar *hosts_try_fastopen; #ifndef DISABLE_PRDR |