Add observability variables and provision for avoiding OCSP conflicts
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 16 Aug 2014 23:41:17 +0000 (00:41 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 16 Aug 2014 23:41:17 +0000 (00:41 +0100)
doc/doc-txt/experimental-spec.txt
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/tls-openssl.c
test/confs/5840

index b1b89e0070bc0f1f8cafb8a7798d1d515edfebb2..c060a6c5a99856e2b7c77b9ccbbc767eaaced660 100644 (file)
@@ -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
index e5af63d898903ec94454bcbbd1823629c3f6794d..ba2c6f7cdc61fdb6de6de9b43ff1db5878f1438b 100644 (file)
@@ -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)
index d09903d650c95e8b1f5732160f3fb6b8ac6485d0..409c324e95beb1ecd8561ecf8cb79d4a8dfd7644 100644 (file)
@@ -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 */
index 654114848beee29d63dda61e95d168d097b376b4..1adda6411abd7e7f8bd9dad1804463fb3a58d940 100644 (file)
@@ -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 */
index 144be6f63e151cbe6e98b2f6c8b73bdcdb6d1d13..57b0808fb6d399e98c0aebba66dc2d7c58ce6007 100644 (file)
@@ -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,9 +1857,31 @@ 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);
@@ -1866,12 +1890,6 @@ if (request_ocsp)
   }
 #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. */
 
index c381ef616709884384b85cc0e748ac27be13a960..4359b9a59c2fd5ce4760bea3e02c06a2d72ba156 100644 (file)
@@ -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 -----