summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Pennock <pdp@exim.org>2018-03-28 23:01:34 -0400
committerPhil Pennock <pdp@exim.org>2018-03-28 23:01:34 -0400
commit5ec37a55162e10377e457fe1deef174093f757a8 (patch)
tree38a56ce742efe73fb6acd4995965bacc58d2188f
parent405074adb94eb8402e9ffd0abe7da4f7c8c827bc (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.
-rw-r--r--doc/doc-docbook/spec.xfpt18
-rw-r--r--src/src/tls-gnu.c22
-rw-r--r--src/src/tls-openssl.c21
-rw-r--r--src/src/transports/smtp.c5
-rw-r--r--src/src/transports/smtp.h1
5 files changed, 62 insertions, 5 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 9722c0063..16d276ee8 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -23941,6 +23941,24 @@ For testing purposes, this value can be overridden by the &%-oB%& command line
option.
+.new
+.option dane_require_tls_ciphers smtp string&!! unset
+.cindex "TLS" "requiring specific ciphers for DANE"
+.cindex "cipher" "requiring specific"
+.cindex DANE "TLS ciphers"
+This option may be used to override &%tls_require_ciphers%& for connections
+where DANE has been determined to be in effect.
+If not set, then &%tls_require_ciphers%& will be used.
+Normal SMTP delivery is not able to make strong demands of TLS cipher
+configuration, because delivery will fall back to plaintext. Once DANE has
+been determined to be in effect, there is no plaintext fallback and making the
+TLS cipherlist configuration stronger will increase security, rather than
+counter-intuitively decreasing it.
+If the option expands to be empty or is forced to fail, then it will
+be treated as unset and &%tls_require_ciphers%& will be used instead.
+.wen
+
+
.option data_timeout smtp time 5m
This sets a timeout for the transmission of each block in the data portion of
the message. As a result, the overall timeout for a message depends on the size
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