DANE: Bitrot: Port to OpenSSL >= 1.1.0
[exim.git] / src / src / dane-openssl.c
index 6c2b1dbdedafff179c7a3f8a4719d5e8fc6b0c51..62778d18f5924c053aa2a1d1ac59e267a00a5945 100644 (file)
@@ -20,7 +20,7 @@
 
 #if OPENSSL_VERSION_NUMBER < 0x1000000fL
 # error "OpenSSL 1.0.0 or higher required"
-#else   /* remainder of file */
+#endif
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
 # define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
 # define X509_STORE_CTX_set0_verified_chain(ctx, sk)   (ctx)->chain = (sk)
 # define X509_STORE_CTX_set_error_depth(ctx, val)      (ctx)->error_depth = (val)
 # define X509_STORE_CTX_set_current_cert(ctx, cert)    (ctx)->current_cert = (cert)
+
+# define ASN1_STRING_get0_data ASN1_STRING_data
+# define X509_getm_notBefore   X509_get_notBefore
+# define X509_getm_notAfter    X509_get_notAfter
+
+# define CRYPTO_ONCE_STATIC_INIT 0
+# define CRYPTO_THREAD_run_once         run_once
+typedef int CRYPTO_ONCE;
 #endif
 
 
@@ -57,6 +65,7 @@
 #define DANESSL_F_SET_TRUST_ANCHOR     110
 #define DANESSL_F_VERIFY_CERT          111
 #define DANESSL_F_WRAP_CERT            112
+#define DANESSL_F_DANESSL_VERIFY_CHAIN 113
 
 #define DANESSL_R_BAD_CERT             100
 #define DANESSL_R_BAD_CERT_PKEY                101
@@ -293,13 +302,14 @@ return matched;
 static int
 push_ext(X509 *cert, X509_EXTENSION *ext)
 {
-    if (ext) {
-       if (X509_add_ext(cert, ext, -1))
-           return 1;
-       X509_EXTENSION_free(ext);
-    }
-    DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE);
-    return 0;
+if (ext)
+  {
+  if (X509_add_ext(cert, ext, -1))
+      return 1;
+  X509_EXTENSION_free(ext);
+  }
+DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE);
+return 0;
 }
 
 static int
@@ -338,7 +348,7 @@ static int
 add_akid(X509 *cert, AUTHORITY_KEYID *akid)
 {
 int nid = NID_authority_key_identifier;
-ASN1_STRING *id;
+ASN1_OCTET_STRING *id;
 unsigned char c = 0;
 int ret = 0;
 
@@ -349,8 +359,8 @@ int ret = 0;
  * exempt from any potential (off by default for now in OpenSSL)
  * self-signature checks!
  */
-id =  (akid && akid->keyid) ? akid->keyid : 0;
-if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_data(id) == c)
+id =  akid && akid->keyid ? akid->keyid : 0;
+if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_get0_data(id) == c)
   c = 1;
 
 if (  (akid = AUTHORITY_KEYID_new()) != 0
@@ -488,10 +498,10 @@ akid = X509_get_ext_d2i(subject, NID_authority_key_identifier, 0, 0);
  */
 if (  !X509_set_version(cert, 2)
    || !set_serial(cert, akid, subject)
-   || !X509_set_subject_name(cert, name)
    || !set_issuer_name(cert, akid)
-   || !X509_gmtime_adj(X509_get_notBefore(cert), -30 * 86400L)
-   || !X509_gmtime_adj(X509_get_notAfter(cert), 30 * 86400L)
+   || !X509_gmtime_adj(X509_getm_notBefore(cert), -30 * 86400L)
+   || !X509_gmtime_adj(X509_getm_notAfter(cert), 30 * 86400L)
+   || !X509_set_subject_name(cert, name)
    || !X509_set_pubkey(cert, newkey)
    || !add_ext(0, cert, NID_basic_constraints, "CA:TRUE")
    || (!top && !add_akid(cert, akid))
@@ -719,11 +729,12 @@ if (matched > 0)
     STACK_OF(X509) * sk = sk_X509_new_null();
     if (sk && sk_X509_push(sk, cert))
       {
-      X509_STORE_CTX_set0_verified_chain(ctx, sk);
       X509_up_ref(cert);
+      X509_STORE_CTX_set0_verified_chain(ctx, sk);
       }
     else
       {
+      if (sk) sk_X509_free(sk);
       DANEerr(DANESSL_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE);
       return -1;
       }
@@ -780,10 +791,10 @@ for (hosts = dane->hosts; hosts; hosts = hosts->next)
 return 0;
 }
 
-static char *
-check_name(char *name, int len)
+static const char *
+check_name(const char *name, int len)
 {
-char *cp = name + len;
+const char *cp = name + len;
 
 while (len > 0 && !*--cp)
   --len;                          /* Ignore trailing NULs */
@@ -804,14 +815,14 @@ if (cp - name != len)               /* Guard against internal NULs */
 return name;
 }
 
-static char *
+static const char *
 parse_dns_name(const GENERAL_NAME *gn)
 {
 if (gn->type != GEN_DNS)
   return 0;
 if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING)
   return 0;
-return check_name((char *) ASN1_STRING_data(gn->d.ia5),
+return check_name((const char *) ASN1_STRING_get0_data(gn->d.ia5),
                  ASN1_STRING_length(gn->d.ia5));
 }
 
@@ -901,7 +912,8 @@ verify_chain(X509_STORE_CTX *ctx)
 {
 int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx);
 X509 *cert = X509_STORE_CTX_get0_cert(ctx);
-int chain_length = sk_X509_num(X509_STORE_CTX_get0_chain(ctx));
+STACK_OF(X509) * chain = X509_STORE_CTX_get0_chain(ctx);
+int chain_length = sk_X509_num(chain);
 int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
 SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx);
 ssl_dane *dane = SSL_get_ex_data(ssl, dane_idx);
@@ -911,6 +923,7 @@ int matched = 0;
 
 DEBUG(D_tls) debug_printf("Dane verify_chain\n");
 
+/* Restore OpenSSL's internal_verify() as the signature check function */
 X509_STORE_CTX_set_verify(ctx, dane->verify);
 
 if ((matched = name_check(dane, cert)) < 0)
@@ -934,17 +947,17 @@ matched = 0;
  * 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.
+ * self-issued.  This is fixed in OpenSSL 1.1.0.
  */
 if (dane->roots && sk_X509_num(dane->roots))
   {
-  X509 *top = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), dane->depth);
+  X509 *top = sk_X509_value(chain, dane->depth);
 
   dane->mdpth = dane->depth;
   dane->match = top;
   X509_up_ref(top);
 
-#ifndef NO_CALLBACK_WORKAROUND
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
   if (X509_check_issued(top, top) != X509_V_OK)
     {
     X509_STORE_CTX_set_error_depth(ctx, dane->depth);
@@ -955,7 +968,7 @@ if (dane->roots && sk_X509_num(dane->roots))
 #endif
   /* Pop synthetic trust-anchor ancestors off the chain! */
   while (--chain_length > dane->depth)
-      X509_free(sk_X509_pop(X509_STORE_CTX_get0_chain(ctx)));
+      X509_free(sk_X509_pop(chain));
   }
 else
   {
@@ -973,7 +986,7 @@ else
   if (!matched && issuer_rrs)
     for (n = chain_length-1; !matched && n >= 0; --n)
       {
-      xn = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), n);
+      xn = sk_X509_value(chain, n);
       if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK)
        matched = match(issuer_rrs, xn, n);
       }
@@ -996,7 +1009,8 @@ else
     }
   }
 
-return (X509_STORE_CTX_get_verify(ctx))(ctx);
+/* Tail recurse into OpenSSL's internal_verify */
+return dane->verify(ctx);
 }
 
 static void
@@ -1083,7 +1097,7 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE])
        */
       X509_STORE_CTX_trusted_stack(ctx, dane->roots);
       X509_STORE_CTX_set_chain(ctx, dane->chain);
-      OPENSSL_assert(X509_STORE_CTX_get0_untrusted(ctx) == dane->chain);
+      OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx));
       }
     }
 
@@ -1153,10 +1167,16 @@ for (head = (dane_list) list; head; head = next)
   }
 }
 
+static void
+ossl_free(void * p)
+{
+OPENSSL_free(p);
+}
+
 static void
 dane_mtype_free(void *p)
 {
-list_free(((dane_mtype) p)->data, CRYPTO_free);
+list_free(((dane_mtype) p)->data, ossl_free);
 OPENSSL_free(p);
 }
 
@@ -1197,7 +1217,7 @@ if (dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx)))
 
 dane_reset(dane);
 if (dane->hosts)
-  list_free(dane->hosts, CRYPTO_free);
+  list_free(dane->hosts, ossl_free);
 for (u = 0; u <= DANESSL_USAGE_LAST; ++u)
   if (dane->selectors[u])
     list_free(dane->selectors[u], dane_selector_free);
@@ -1218,7 +1238,7 @@ while (*src)
   dane_host_list elem = (dane_host_list) OPENSSL_malloc(sizeof(*elem));
   if (elem == 0)
     {
-    list_free(head, CRYPTO_free);
+    list_free(head, ossl_free);
     return 0;
     }
   elem->value = OPENSSL_strdup(*src++);
@@ -1259,28 +1279,36 @@ DANESSL_verify_chain(SSL *ssl, STACK_OF(X509) *chain)
 {
 int ret;
 X509 *cert;
-X509_STORE_CTX store_ctx;
+X509_STORE_CTX store_ctx;
 SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl);
 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
 int store_ctx_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
 
 cert = sk_X509_value(chain, 0);
-if (!X509_STORE_CTX_init(&store_ctx, store, cert, chain))
+if (!(store_ctx = X509_STORE_CTX_new()))
+  {
+  DANEerr(DANESSL_F_DANESSL_VERIFY_CHAIN, ERR_R_MALLOC_FAILURE);
+  return 0;
+  }
+if (!X509_STORE_CTX_init(store_ctx, store, cert, chain))
+  {
+  X509_STORE_CTX_free(store_ctx);
   return 0;
-X509_STORE_CTX_set_ex_data(&store_ctx, store_ctx_idx, ssl);
+  }
+X509_STORE_CTX_set_ex_data(store_ctx, store_ctx_idx, ssl);
 
-X509_STORE_CTX_set_default(&store_ctx,
+X509_STORE_CTX_set_default(store_ctx,
             SSL_is_server(ssl) ? "ssl_client" : "ssl_server");
-X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&store_ctx),
+X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx),
             SSL_get0_param(ssl));
 
 if (SSL_get_verify_callback(ssl))
-  X509_STORE_CTX_set_verify_cb(&store_ctx, SSL_get_verify_callback(ssl));
+  X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
 
-ret = verify_cert(&store_ctx, NULL);
+ret = verify_cert(store_ctx, NULL);
 
-SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(&store_ctx));
-X509_STORE_CTX_cleanup(&store_ctx);
+SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(store_ctx));
+X509_STORE_CTX_cleanup(store_ctx);
 
 return (ret);
 }
@@ -1449,7 +1477,7 @@ if (!m)
   {
   if ((m = (dane_mtype_list) list_alloc(sizeof(*m->value))) == 0)
     {
-    list_free(d, CRYPTO_free);
+    list_free(d, ossl_free);
     xkfreeret(0);
     }
   m->value->data = 0;
@@ -1590,31 +1618,6 @@ DANEerr(DANESSL_F_CTX_INIT, DANESSL_R_LIBRARY_INIT);
 return -1;
 }
 
-static int
-init_once(volatile int *value, int (*init)(void), void (*postinit)(void))
-{
-int wlock = 0;
-
-CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
-if (*value < 0)
-  {
-  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
-  CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
-  wlock = 1;
-  if (*value < 0)
-    {
-    *value = init();
-    if (postinit)
-      postinit();
-    }
-  }
-if (wlock)
-    CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
-else
-    CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
-return *value;
-}
-
 static void
 dane_init(void)
 {
@@ -1622,10 +1625,15 @@ dane_init(void)
  * Store library id in zeroth function slot, used to locate the library
  * name.  This must be done before we load the error strings.
  */
+err_lib_dane = ERR_get_next_error_library();
+
 #ifndef OPENSSL_NO_ERR
-dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0);
-ERR_load_strings(err_lib_dane, dane_str_functs);
-ERR_load_strings(err_lib_dane, dane_str_reasons);
+if (err_lib_dane > 0)
+  {
+  dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0);
+  ERR_load_strings(err_lib_dane, dane_str_functs);
+  ERR_load_strings(err_lib_dane, dane_str_reasons);
+  }
 #endif
 
 /*
@@ -1650,6 +1658,32 @@ dane_idx = SSL_get_ex_new_index(0, 0, 0, 0, 0);
 }
 
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+static void
+run_once(volatile int * once, void (*init)(void))
+{
+int wlock = 0;
+
+CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+if (!*once)
+  {
+  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+  CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+  wlock = 1;
+  if (!*once)
+    {
+    *once = 1;
+    init();
+    }
+  }
+if (wlock)
+  CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+else
+  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+}
+#endif
+
+
 
 /*
 
@@ -1666,9 +1700,10 @@ Return
 int
 DANESSL_library_init(void)
 {
+static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT;
+
 DEBUG(D_tls) debug_printf("Dane lib-init\n");
-if (err_lib_dane < 0)
-  init_once(&err_lib_dane, ERR_get_next_error_library, dane_init);
+(void) CRYPTO_THREAD_run_once(&once, dane_init);
 
 #if defined(LN_sha256)
 /* No DANE without SHA256 support */
@@ -1680,6 +1715,5 @@ return 0;
 }
 
 
-#endif /* OPENSSL_VERSION_NUMBER */
 /* vi: aw ai sw=2
 */