/*
* Author: Viktor Dukhovni
* License: THIS CODE IS IN THE PUBLIC DOMAIN.
+ *
+ * Copyright (c) The Exim Maintainers 2014 - 2016
*/
#include <stdio.h>
#include <string.h>
# 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"
#define DANESSL_F_ADD_SKID 100
# define X509_V_ERR_HOSTNAME_MISMATCH X509_V_ERR_APPLICATION_VERIFICATION
#endif
+
+
static int
match(dane_selector_list slist, X509 *cert, int depth)
{
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)
{
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);
continue;
if (!(dane->mhost = OPENSSL_strdup(certid)))
matched = -1;
+ DEBUG(D_tls) debug_printf("Dane name_check: matched SAN %s\n", certid);
break;
}
}
* 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;
}
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];
}
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)
*/
if (leaf_rrs)
matched = match(leaf_rrs, xn, 0);
+ if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched EE\n");
if (!matched && issuer_rrs)
for (n = chain_length-1; !matched && n >= 0; --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)
{
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();
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])