Gitweb:
http://git.exim.org/exim.git/commitdiff/594706ea2e56fe8c972eab772bd3e58c7a0c89ab
Commit: 594706ea2e56fe8c972eab772bd3e58c7a0c89ab
Parent: fde080a4f34a8eb0f92af6dfc7e4e6ae01fd61f8
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Aug 17 00:41:17 2014 +0100
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sun Aug 17 00:41:17 2014 +0100
Add observability variables and provision for avoiding OCSP conflicts
---
doc/doc-txt/experimental-spec.txt | 25 ++++++++++++++++++++++++-
src/src/expand.c | 6 ++++++
src/src/globals.c | 2 ++
src/src/globals.h | 1 +
src/src/tls-openssl.c | 32 +++++++++++++++++++++++++-------
test/confs/5840 | 3 +++
6 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index b1b89e0..c060a6c 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -1235,7 +1235,25 @@ must have a correct name (SubjectName or SubjectAltName).
The use of OCSP-stapling should be considered, allowing
for fast revocation of certificates (which would otherwise
be limited by the DNS TTL on the TLSA records). However,
-this is likely to only be usable with DANE_TA.
+this is likely to only be usable with DANE_TA. NOTE: the
+default is to request OCSP for all hosts; the certificate
+chain in DANE_EE usage will be insufficient to validate
+the OCSP proof and verification will fail. Either disable
+OCSP completely or use the (new) variable $tls_out_tlsa_usage
+like so:
+
+ hosts_request_ocsp = ${if or { {= {4}{$tls_out_tlsa_usage}} \
+ {= {0}{$tls_out_tlsa_usage}} } \
+ {*}{}}
+The variable is a bitfield with numbered bits set for TLSA
+record usage codes. The zero above means DANE was not in use,
+the four means that only DANE_TA usage TLSA records were
+found. If the definition of hosts_require_ocsp or
+hosts_request_ocsp includes the string "tls_out_tlsa_usage",
+they are re-expanded in time to control the OCSP request.
+
+[ All a bit complicated. Should we make that definition
+the default? Should we override the user's definition? ]
For client-side DANE there are two new smtp transport options,
@@ -1260,6 +1278,11 @@ and dnssec_require_domains is ignored.
If verification was successful using DANE then the "CV" item
in the delivery log line will show as "CV=dane".
+There is a new variable $tls_out_dane which will have "yes" if
+verification succeeded using DANE and "no" otherwise (only useful
+in combination with EXPERIMENTAL_TPDA), and a new variable
+$tls_out_tlsa_usage (detailed above).
+
--------------------------------------------------------------
End of file
diff --git a/src/src/expand.c b/src/src/expand.c
index e5af63d..ba2c6f7 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -684,6 +684,9 @@ static var_entry var_table[] = {
{ "tls_out_bits", vtype_int, &tls_out.bits },
{ "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
{ "tls_out_cipher", vtype_stringptr, &tls_out.cipher },
+#ifdef EXPERIMENTAL_DANE
+ { "tls_out_dane", vtype_bool, &tls_out.dane_verified },
+#endif
{ "tls_out_ocsp", vtype_int, &tls_out.ocsp },
{ "tls_out_ourcert", vtype_cert, &tls_out.ourcert },
{ "tls_out_peercert", vtype_cert, &tls_out.peercert },
@@ -691,6 +694,9 @@ static var_entry var_table[] = {
#if defined(SUPPORT_TLS)
{ "tls_out_sni", vtype_stringptr, &tls_out.sni },
#endif
+#ifdef EXPERIMENTAL_DANE
+ { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage },
+#endif
{ "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */
#if defined(SUPPORT_TLS)
diff --git a/src/src/globals.c b/src/src/globals.c
index d09903d..409c324 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -105,6 +105,7 @@ tls_support tls_in = {
FALSE,/* tls_certificate_verified */
#ifdef EXPERIMENTAL_DANE
FALSE,/* dane_verified */
+ 0, /* tlsa_usage */
#endif
NULL, /* tls_cipher */
FALSE,/* tls_on_connect */
@@ -121,6 +122,7 @@ tls_support tls_out = {
FALSE,/* tls_certificate_verified */
#ifdef EXPERIMENTAL_DANE
FALSE,/* dane_verified */
+ 0, /* tlsa_usage */
#endif
NULL, /* tls_cipher */
FALSE,/* tls_on_connect */
diff --git a/src/src/globals.h b/src/src/globals.h
index 6541148..1adda64 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -84,6 +84,7 @@ typedef struct {
BOOL certificate_verified; /* Client certificate verified */
#ifdef EXPERIMENTAL_DANE
BOOL dane_verified; /* ... via DANE */
+ int tlsa_usage; /* TLSA record(s) usage */
#endif
uschar *cipher; /* Cipher used */
BOOL on_connect; /* For older MTAs that don't STARTTLS */
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 144be6f..57b0808 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1693,6 +1693,8 @@ for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
return tls_error(US"tlsa load", host, NULL);
case 1: break;
}
+
+ tls_out.tlsa_usage |= 1<<usage;
}
if (found)
@@ -1745,6 +1747,7 @@ BOOL dane_required;
#ifdef EXPERIMENTAL_DANE
tls_out.dane_verified = FALSE;
+tls_out.tlsa_usage = 0;
dane_required = verify_check_this_host(&ob->hosts_require_dane, NULL,
host->name, host->address, NULL) == OK;
@@ -1764,7 +1767,6 @@ else if (dane_required)
log_write(0, LOG_MAIN, "DANE error: previous lookup not DNSSEC");
return FAIL;
}
-
#endif
#ifndef DISABLE_OCSP
@@ -1855,23 +1857,39 @@ if (ob->tls_sni)
}
}
+#ifdef EXPERIMENTAL_DANE
+if (dane)
+ if ((rc = dane_tlsa_load(client_ssl, host, &tlsa_dnsa)) != OK)
+ return rc;
+#endif
+
#ifndef DISABLE_OCSP
/* Request certificate status at connection-time. If the server
does OCSP stapling we will get the callback (set in tls_init()) */
if (request_ocsp)
{
+ const uschar * s;
+ if ( (s = ob->hosts_require_ocsp) && Ustrstr(s, US"tls_out_tlsa_usage")
+ || (s = ob->hosts_request_ocsp) && Ustrstr(s, US"tls_out_tlsa_usage")
+ )
+ { /* Re-eval now $tls_out_tlsa_usage is populated. If
+ this means we avoid the OCSP request, we wasted the setup
+ cost in tls_init(). */
+ require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
+ NULL, host->name, host->address, NULL) == OK;
+ request_ocsp = require_ocsp ? TRUE
+ : verify_check_this_host(&ob->hosts_request_ocsp,
+ NULL, host->name, host->address, NULL) == OK;
+ }
+ }
+if (request_ocsp)
+ {
SSL_set_tlsext_status_type(client_ssl, TLSEXT_STATUSTYPE_ocsp);
client_static_cbinfo->u_ocsp.client.verify_required = require_ocsp;
tls_out.ocsp = OCSP_NOT_RESP;
}
#endif
-#ifdef EXPERIMENTAL_DANE
-if (dane)
- if ((rc = dane_tlsa_load(client_ssl, host, &tlsa_dnsa)) != OK)
- return rc;
-#endif
-
/* There doesn't seem to be a built-in timeout on connection. */
diff --git a/test/confs/5840 b/test/confs/5840
index c381ef6..4359b9a 100644
--- a/test/confs/5840
+++ b/test/confs/5840
@@ -67,6 +67,9 @@ send_to_server:
# hosts_try_dane = *
hosts_require_dane = *
+ hosts_request_ocsp = ${if or { {= {4}{$tls_out_tlsa_usage}} \
+ {= {0}{$tls_out_tlsa_usage}} } \
+ {*}{}}
# ----- Retry -----