Merge branch 'master' of ssh://git.exim.org/home/git/exim
[exim.git] / src / src / tls-openssl.c
index 7d9ab8b4d7426e3685bf081eb7c5cfc46b953615..43ea8a0d2ec31a42b550b538ea8d574fa461a6af 100644 (file)
@@ -167,27 +167,28 @@ Returns:    OK/DEFER/FAIL
 static int
 tls_error(uschar *prefix, host_item *host, uschar *msg)
 {
-if (msg == NULL)
+if (!msg)
   {
   ERR_error_string(ERR_get_error(), ssl_errstring);
   msg = (uschar *)ssl_errstring;
   }
 
-if (host == NULL)
+if (host)
+  {
+  log_write(0, LOG_MAIN, "H=%s [%s] TLS error on connection (%s): %s",
+    host->name, host->address, prefix, msg);
+  return FAIL;
+  }
+else
   {
   uschar *conn_info = smtp_get_connection_info();
   if (Ustrncmp(conn_info, US"SMTP ", 5) == 0)
     conn_info += 5;
+  /* I'd like to get separated H= here, but too hard for now */
   log_write(0, LOG_MAIN, "TLS error on %s (%s): %s",
     conn_info, prefix, msg);
   return DEFER;
   }
-else
-  {
-  log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s): %s",
-    host->name, host->address, prefix, msg);
-  return FAIL;
-  }
 }
 
 
@@ -1377,7 +1378,16 @@ if (expcerts != NULL && *expcerts != '\0')
       return tls_error(US"SSL_CTX_load_verify_locations", host, NULL);
 
     /* Load the list of CAs for which we will accept certs, for sending
-    to the client.  XXX only for file source, not dir? */
+    to the client.  This is only for the one-file tls_verify_certificates
+    variant.
+    If a list isn't loaded into the server, but
+    some verify locations are set, the server end appears to make
+    a wildcard reqest for client certs.
+    Meanwhile, the client library as deafult behaviour *ignores* the list
+    we send over the wire - see man SSL_CTX_set_client_cert_cb.
+    Because of this, and that the dir variant is likely only used for
+    the public-CA bundle (not for a private CA), not worth fixing.
+    */
     if (file != NULL)
       {
       STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file);
@@ -1702,22 +1712,23 @@ for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
   uint8_t usage, selector, mtype;
   const char * mdname;
 
-  found++;
   usage = *p++;
+
+  /* Only DANE-TA(2) and DANE-EE(3) are supported */
+  if (usage != 2 && usage != 3) continue;
+
   selector = *p++;
   mtype = *p++;
 
   switch (mtype)
     {
-    default:
-      log_write(0, LOG_MAIN,
-               "DANE error: TLSA record w/bad mtype 0x%x", mtype);
-      return FAIL;
-    case 0:    mdname = NULL; break;
-    case 1:    mdname = "sha256"; break;
-    case 2:    mdname = "sha512"; break;
+    default: continue; /* Only match-types 0, 1, 2 are supported */
+    case 0:  mdname = NULL; break;
+    case 1:  mdname = "sha256"; break;
+    case 2:  mdname = "sha512"; break;
     }
 
+  found++;
   switch (DANESSL_add_tlsa(ssl, usage, selector, mdname, p, rr->size - 3))
     {
     default:
@@ -1732,7 +1743,7 @@ for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
 if (found)
   return OK;
 
-log_write(0, LOG_MAIN, "DANE error: No TLSA records");
+log_write(0, LOG_MAIN, "DANE error: No usable TLSA records");
 return FAIL;
 }
 #endif /*EXPERIMENTAL_DANE*/
@@ -1784,28 +1795,29 @@ tls_out.tlsa_usage = 0;
 
 #ifndef DISABLE_OCSP
   {
+# ifdef EXPERIMENTAL_DANE
+  if (  tlsa_dnsa
+     && ob->hosts_request_ocsp[0] == '*'
+     && ob->hosts_request_ocsp[1] == '\0'
+     )
+    {
+    /* Unchanged from default.  Use a safer one under DANE */
+    request_ocsp = TRUE;
+    ob->hosts_request_ocsp = US"${if or { {= {0}{$tls_out_tlsa_usage}} "
+                                     "   {= {4}{$tls_out_tlsa_usage}} } "
+                                " {*}{}}";
+    }
+# endif
+
   if ((require_ocsp = verify_check_this_host(&ob->hosts_require_ocsp,
     NULL, host->name, host->address, NULL) == OK))
     request_ocsp = TRUE;
   else
-    {
 # ifdef EXPERIMENTAL_DANE
-    if (  tlsa_dnsa
-       && ob->hosts_request_ocsp[0] == '*'
-       && ob->hosts_request_ocsp[1] == '\0'
-       )
-      {
-      /* Unchanged from default.  Use a safer one under DANE */
-      request_ocsp = TRUE;
-      ob->hosts_request_ocsp = US"${if or { {= {0}{$tls_out_tlsa_usage}} "
-                                       "   {= {4}{$tls_out_tlsa_usage}} } "
-                                  " {*}{}}";
-      }
-    else
+    if (!request_ocsp)
 # endif
       request_ocsp = verify_check_this_host(&ob->hosts_request_ocsp,
          NULL, host->name, host->address, NULL) == OK;
-    }
   }
 #endif