Supress TLS/Env warnings in checking and listing mode
[exim.git] / src / src / dane-openssl.c
index ed2b2f5af8e759a397112981aabf96244f24d8c7..674ca380b3c316ca4565ee7445a206af4cdbdc3c 100644 (file)
 # error "OpenSSL 1.0.0 or higher required"
 #else   /* remainder of file */
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-#define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+# define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
 #endif
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+# define EXIM_HAVE_ASN1_MACROS
+# define EXIM_OPAQUE_X509
+#endif
+
 
 #include "danessl.h"
 
@@ -190,6 +195,8 @@ typedef struct ssl_dane
 # define X509_V_ERR_HOSTNAME_MISMATCH X509_V_ERR_APPLICATION_VERIFICATION
 #endif
 
+
+
 static int
 match(dane_selector_list slist, X509 *cert, int depth)
 {
@@ -335,7 +342,11 @@ if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_data(id) == c)
 
 if (  (akid = AUTHORITY_KEYID_new()) != 0
    && (akid->keyid = ASN1_OCTET_STRING_new()) != 0
+#ifdef EXIM_HAVE_ASN1_MACROS
+   && ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1)
+#else
    && M_ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1)
+#endif
    && X509_add1_ext_i2d(cert, nid, akid, 0, X509V3_ADD_APPEND))
   ret = 1;
 if (akid)
@@ -410,7 +421,11 @@ if (cert)
   {
   if (trusted && !X509_add1_trust_object(cert, serverAuth))
     return 0;
+#ifdef EXIM_OPAQUE_X509
+  X509_up_ref(cert);
+#else
   CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
+#endif
   if (!sk_X509_push(*xs, cert))
     {
     X509_free(cert);
@@ -840,6 +855,7 @@ if (gens)
        continue;
       if (!(dane->mhost = OPENSSL_strdup(certid)))
        matched = -1;
+      DEBUG(D_tls) debug_printf("Dane name_check: matched SAN %s\n", certid);
       break;
       }
     }
@@ -850,14 +866,16 @@ if (gens)
  * XXX: Should the subjectName be skipped when *any* altnames are present,
  * or only when DNS altnames are present?
  */
-if (got_altname == 0)
+if (!got_altname)
   {
   char *certid = parse_subject_name(cert);
-  if (certid != 0 && *certid
-    && (matched = match_name(certid, dane)) != 0)
+  if (certid != 0 && *certid && (matched = match_name(certid, dane)) != 0)
+    {
+    DEBUG(D_tls) debug_printf("Dane name_check: matched SN %s\n", certid);
     dane->mhost = OPENSSL_strdup(certid);
-    if (certid)
-      OPENSSL_free(certid);
+    }
+  if (certid)
+    OPENSSL_free(certid);
   }
 return matched;
 }
@@ -875,7 +893,7 @@ X509 *cert = ctx->cert;             /* XXX: accessor? */
 int matched = 0;
 int chain_length = sk_X509_num(ctx->chain);
 
-DEBUG(D_tls) debug_printf("Dane verify-chain\n");
+DEBUG(D_tls) debug_printf("Dane verify_chain\n");
 
 issuer_rrs = dane->selectors[DANESSL_USAGE_PKIX_TA];
 leaf_rrs = dane->selectors[DANESSL_USAGE_PKIX_EE];
@@ -897,29 +915,29 @@ if (!matched)
   }
 matched = 0;
 
-    /*
    * Satisfy at least one usage 0 or 1 constraint, unless we've already
    * matched a usage 2 trust anchor.
    *
    * XXX: internal_verify() doesn't callback with top certs that are not
    * self-issued.  This should be fixed in a future OpenSSL.
    */
-    if (dane->roots && sk_X509_num(dane->roots))
-      {
-      X509 *top = sk_X509_value(ctx->chain, dane->depth);
+/*
+ * Satisfy at least one usage 0 or 1 constraint, unless we've already
+ * matched a usage 2 trust anchor.
+ *
+ * XXX: internal_verify() doesn't callback with top certs that are not
+ * self-issued.  This should be fixed in a future OpenSSL.
+ */
+if (dane->roots && sk_X509_num(dane->roots))
+  {
+  X509 *top = sk_X509_value(ctx->chain, dane->depth);
 
-      dane->mdpth = dane->depth;
-      dane->match = top;
-      X509_up_ref(top);
+  dane->mdpth = dane->depth;
+  dane->match = top;
+  X509_up_ref(top);
 
 #ifndef NO_CALLBACK_WORKAROUND
-      if (X509_check_issued(top, top) != X509_V_OK)
-       {
-        ctx->error_depth = dane->depth;
-        ctx->current_cert = top;
-        if (!cb(1, ctx))
-          return 0;
-        }
+  if (X509_check_issued(top, top) != X509_V_OK)
+    {
+    ctx->error_depth = dane->depth;
+    ctx->current_cert = top;
+    if (!cb(1, ctx))
+      return 0;
+    }
 #endif
   /* Pop synthetic trust-anchor ancestors off the chain! */
   while (--chain_length > dane->depth)
@@ -936,31 +954,33 @@ else
    */
   if (leaf_rrs)
     matched = match(leaf_rrs, xn, 0);
-    if (issuer_rrs)
-      {
-      for (n = chain_length-1; !matched && n >= 0; --n)
-       {
-       xn = sk_X509_value(ctx->chain, n);
-       if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK)
-         matched = match(issuer_rrs, xn, n);
-       }
-      }
+  if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched EE\n");
 
-    if (!matched)
-      {
-      ctx->current_cert = cert;
-      ctx->error_depth = 0;
-      X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_UNTRUSTED);
-      if (!cb(0, ctx))
-       return 0;
-      }
-    else
+  if (!matched && issuer_rrs)
+    for (n = chain_length-1; !matched && n >= 0; --n)
       {
-      dane->mdpth = n;
-      dane->match = xn;
-      X509_up_ref(xn);
+      xn = sk_X509_value(ctx->chain, n);
+      if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK)
+       matched = match(issuer_rrs, xn, n);
       }
+  if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched %s\n",
+    n>0 ? "CA" : "selfisssued EE");
+
+  if (!matched)
+    {
+    ctx->current_cert = cert;
+    ctx->error_depth = 0;
+    X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_UNTRUSTED);
+    if (!cb(0, ctx))
+      return 0;
     }
+  else
+    {
+    dane->mdpth = n;
+    dane->match = xn;
+    X509_up_ref(xn);
+    }
+  }
 
 return ctx->verify(ctx);
 }
@@ -1002,7 +1022,7 @@ int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb;
 int matched;
 X509 *cert = ctx->cert;             /* XXX: accessor? */
 
-DEBUG(D_tls) debug_printf("Dane verify-cert\n");
+DEBUG(D_tls) debug_printf("Dane verify_cert\n");
 
 if (ssl_idx < 0)
   ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
@@ -1016,7 +1036,7 @@ ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx);
 if (!(dane = SSL_get_ex_data(ssl, dane_idx)) || !cert)
   return X509_verify_cert(ctx);
 
-    /* Reset for verification of a new chain, perhaps a renegotiation. */
+/* Reset for verification of a new chain, perhaps a renegotiation. */
 dane_reset(dane);
 
 if (dane->selectors[DANESSL_USAGE_DANE_EE])