aboutsummaryrefslogtreecommitdiffstats
path: root/dane.c
diff options
context:
space:
mode:
Diffstat (limited to 'dane.c')
-rw-r--r--dane.c287
1 files changed, 240 insertions, 47 deletions
diff --git a/dane.c b/dane.c
index 675dfa8bf335..30dc1f700519 100644
--- a/dane.c
+++ b/dane.c
@@ -327,8 +327,8 @@ ldns_dane_pkix_get_last_self_signed(X509** out_cert,
}
(void) X509_verify_cert(vrfy_ctx);
- if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
- vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
+ if (X509_STORE_CTX_get_error(vrfy_ctx) == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
+ X509_STORE_CTX_get_error(vrfy_ctx) == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
*out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
s = LDNS_STATUS_OK;
@@ -356,7 +356,7 @@ ldns_dane_select_certificate(X509** selected_cert,
assert(selected_cert != NULL);
assert(cert != NULL);
- /* With PKIX validation explicitely turned off (pkix_validation_store
+ /* With PKIX validation explicitly turned off (pkix_validation_store
* == NULL), treat the "CA constraint" and "Service certificate
* constraint" the same as "Trust anchor assertion" and "Domain issued
* certificate" respectively.
@@ -504,6 +504,7 @@ memerror:
}
+#ifdef USE_DANE_VERIFY
/* Return tlsas that actually are TLSA resource records with known values
* for the Certificate usage, Selector and Matching type rdata fields.
*/
@@ -535,6 +536,7 @@ ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
}
+#if !defined(USE_DANE_TA_USAGE)
/* Return whether cert/selector/matching_type matches data.
*/
static ldns_status
@@ -591,34 +593,108 @@ ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
}
return s;
}
+#endif /* !defined(USE_DANE_TA_USAGE) */
+#endif /* USE_DANE_VERIFY */
-
+#ifdef USE_DANE_VERIFY
ldns_status
ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
X509* cert, STACK_OF(X509)* extra_certs,
X509_STORE* pkix_validation_store)
{
- ldns_status s;
-
+#if defined(USE_DANE_TA_USAGE)
+ SSL_CTX *ssl_ctx = NULL;
+ SSL *ssl = NULL;
+ X509_STORE_CTX *store_ctx = NULL;
+#else
STACK_OF(X509)* pkix_validation_chain = NULL;
+#endif
+ ldns_status s = LDNS_STATUS_OK;
- ldns_tlsa_certificate_usage cert_usage;
+ ldns_tlsa_certificate_usage usage;
ldns_tlsa_selector selector;
- ldns_tlsa_matching_type matching_type;
+ ldns_tlsa_matching_type mtype;
ldns_rdf* data;
- if (! tlsa_rr) {
- /* No TLSA, so regular PKIX validation
+ if (! tlsa_rr || ldns_rr_get_type(tlsa_rr) != LDNS_RR_TYPE_TLSA ||
+ ldns_rr_rd_count(tlsa_rr) != 4 ||
+ ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) > 3 ||
+ ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) > 1 ||
+ ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) > 2 ) {
+ /* No (usable) TLSA, so regular PKIX validation
*/
return ldns_dane_pkix_validate(cert, extra_certs,
pkix_validation_store);
}
- cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
- selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
- matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
- data = ldns_rr_rdf(tlsa_rr, 3) ;
+ usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
+ selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
+ mtype = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
+ data = ldns_rr_rdf(tlsa_rr, 3) ;
+
+#if defined(USE_DANE_TA_USAGE)
+ /* Rely on OpenSSL dane functions.
+ *
+ * OpenSSL does not provide offline dane verification. The dane unit
+ * tests within openssl use the undocumented SSL_get0_dane() and
+ * X509_STORE_CTX_set0_dane() to convey dane parameters set on SSL and
+ * SSL_CTX to a X509_STORE_CTX that can be used to do offline
+ * verification. We use these undocumented means with the ldns
+ * dane function prototypes which did only offline dane verification.
+ */
+ if (!(ssl_ctx = SSL_CTX_new(TLS_client_method())))
+ s = LDNS_STATUS_MEM_ERR;
- switch (cert_usage) {
+ else if (SSL_CTX_dane_enable(ssl_ctx) <= 0)
+ s = LDNS_STATUS_SSL_ERR;
+
+ else if (SSL_CTX_dane_set_flags(
+ ssl_ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS),
+ !(ssl = SSL_new(ssl_ctx)))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (SSL_set_connect_state(ssl),
+ (SSL_dane_enable(ssl, NULL) <= 0))
+ s = LDNS_STATUS_SSL_ERR;
+
+ else if (SSL_dane_tlsa_add(ssl, usage, selector, mtype,
+ ldns_rdf_data(data), ldns_rdf_size(data)) <= 0)
+ s = LDNS_STATUS_SSL_ERR;
+
+ else if (!(store_ctx = X509_STORE_CTX_new()))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (!X509_STORE_CTX_init(store_ctx, pkix_validation_store, cert, extra_certs))
+ s = LDNS_STATUS_SSL_ERR;
+
+ else {
+ int ret;
+
+ 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),
+ SSL_get0_param(ssl));
+ X509_STORE_CTX_set0_dane(store_ctx, SSL_get0_dane(ssl));
+ if (SSL_get_verify_callback(ssl))
+ X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
+
+ ret = X509_verify_cert(store_ctx);
+ if (!ret) {
+ if (X509_STORE_CTX_get_error(store_ctx) == X509_V_ERR_DANE_NO_MATCH)
+ s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+ else
+ s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+ }
+ X509_STORE_CTX_cleanup(store_ctx);
+ }
+ if (store_ctx)
+ X509_STORE_CTX_free(store_ctx);
+ if (ssl)
+ SSL_free(ssl);
+ if (ssl_ctx)
+ SSL_CTX_free(ssl_ctx);
+ return s;
+#else
+ switch (usage) {
case LDNS_TLSA_USAGE_CA_CONSTRAINT:
s = ldns_dane_pkix_validate_and_get_chain(
&pkix_validation_chain,
@@ -638,7 +714,7 @@ ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
*/
s = ldns_dane_match_any_cert_with_data(
pkix_validation_chain,
- selector, matching_type, data, true);
+ selector, mtype, data, true);
if (s == LDNS_STATUS_OK) {
/* A TLSA record did match a cert from the
@@ -653,15 +729,16 @@ ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
s = ldns_dane_match_any_cert_with_data(
pkix_validation_chain,
- selector, matching_type, data, true);
+ selector, mtype, data, true);
}
sk_X509_pop_free(pkix_validation_chain, X509_free);
return s;
break;
case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+
s = ldns_dane_match_cert_with_data(cert,
- selector, matching_type, data);
+ selector, mtype, data);
if (s == LDNS_STATUS_OK) {
return ldns_dane_pkix_validate(cert, extra_certs,
@@ -671,78 +748,194 @@ ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
break;
case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+#if 0
s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
cert, extra_certs);
if (s == LDNS_STATUS_OK) {
s = ldns_dane_match_any_cert_with_data(
pkix_validation_chain,
- selector, matching_type, data, false);
+ selector, mtype, data, false);
} else if (! pkix_validation_chain) {
return s;
}
sk_X509_pop_free(pkix_validation_chain, X509_free);
return s;
+#else
+ return LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA;
+#endif
break;
case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
return ldns_dane_match_cert_with_data(cert,
- selector, matching_type, data);
+ selector, mtype, data);
break;
default:
break;
}
+#endif
return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
}
ldns_status
-ldns_dane_verify(ldns_rr_list* tlsas,
+ldns_dane_verify(const ldns_rr_list* tlsas,
X509* cert, STACK_OF(X509)* extra_certs,
X509_STORE* pkix_validation_store)
{
+#if defined(USE_DANE_TA_USAGE)
+ SSL_CTX *ssl_ctx = NULL;
+ ldns_rdf *basename_rdf = NULL;
+ char *basename = NULL;
+ SSL *ssl = NULL;
+ X509_STORE_CTX *store_ctx = NULL;
+#else
+ ldns_status ps;
+#endif
size_t i;
ldns_rr* tlsa_rr;
- ldns_status s = LDNS_STATUS_OK, ps;
+ ldns_rr_list *usable_tlsas;
+ ldns_status s = LDNS_STATUS_OK;
assert(cert != NULL);
- if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
- tlsas = ldns_dane_filter_unusable_records(tlsas);
- if (! tlsas) {
- return LDNS_STATUS_MEM_ERR;
- }
- }
- if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
+ if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0)
/* No TLSA's, so regular PKIX validation
*/
return ldns_dane_pkix_validate(cert, extra_certs,
pkix_validation_store);
- } else {
- for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
- tlsa_rr = ldns_rr_list_rr(tlsas, i);
- ps = s;
- s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
- pkix_validation_store);
- if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
- s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
+/* To enable name checks (which we don't) */
+#if defined(USE_DANE_TA_USAGE) && 0
+ else if (!(basename_rdf = ldns_dname_clone_from(
+ ldns_rr_list_owner(tlsas), 2)))
+ /* Could nog get DANE base name */
+ s = LDNS_STATUS_ERR;
- /* which would be LDNS_STATUS_OK (match)
- * or some fatal error preventing use from
- * trying the next TLSA record.
- */
- break;
- }
- s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
- * over TLSA_DID_NOT_MATCH
- */
+ else if (!(basename = ldns_rdf2str(basename_rdf)))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (strlen(basename) && (basename[strlen(basename)-1] = 0))
+ s = LDNS_STATUS_ERR; /* Intended to be unreachable */
+#endif
+
+ else if (!(usable_tlsas = ldns_dane_filter_unusable_records(tlsas)))
+ return LDNS_STATUS_MEM_ERR;
+
+ else if (ldns_rr_list_rr_count(usable_tlsas) == 0) {
+ /* No TLSA's, so regular PKIX validation
+ */
+ ldns_rr_list_free(usable_tlsas);
+ return ldns_dane_pkix_validate(cert, extra_certs,
+ pkix_validation_store);
+ }
+#if defined(USE_DANE_TA_USAGE)
+ /* Rely on OpenSSL dane functions.
+ *
+ * OpenSSL does not provide offline dane verification. The dane unit
+ * tests within openssl use the undocumented SSL_get0_dane() and
+ * X509_STORE_CTX_set0_dane() to convey dane parameters set on SSL and
+ * SSL_CTX to a X509_STORE_CTX that can be used to do offline
+ * verification. We use these undocumented means with the ldns
+ * dane function prototypes which did only offline dane verification.
+ */
+ if (!(ssl_ctx = SSL_CTX_new(TLS_client_method())))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (SSL_CTX_dane_enable(ssl_ctx) <= 0)
+ s = LDNS_STATUS_SSL_ERR;
+
+ else if (SSL_CTX_dane_set_flags(
+ ssl_ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS),
+ !(ssl = SSL_new(ssl_ctx)))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (SSL_set_connect_state(ssl),
+ (SSL_dane_enable(ssl, basename) <= 0))
+ s = LDNS_STATUS_SSL_ERR;
+
+ else for (i = 0; i < ldns_rr_list_rr_count(usable_tlsas); i++) {
+ ldns_tlsa_certificate_usage usage;
+ ldns_tlsa_selector selector;
+ ldns_tlsa_matching_type mtype;
+ ldns_rdf* data;
+
+ tlsa_rr = ldns_rr_list_rr(usable_tlsas, i);
+ usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,0));
+ selector= ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,1));
+ mtype = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,2));
+ data = ldns_rr_rdf(tlsa_rr,3) ;
+
+ if (SSL_dane_tlsa_add(ssl, usage, selector, mtype,
+ ldns_rdf_data(data),
+ ldns_rdf_size(data)) <= 0) {
+ s = LDNS_STATUS_SSL_ERR;
+ break;
+ }
+ }
+ if (!s && !(store_ctx = X509_STORE_CTX_new()))
+ s = LDNS_STATUS_MEM_ERR;
+
+ else if (!X509_STORE_CTX_init(store_ctx, pkix_validation_store, cert, extra_certs))
+ s = LDNS_STATUS_SSL_ERR;
+
+ else {
+ int ret;
+
+ 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),
+ SSL_get0_param(ssl));
+ X509_STORE_CTX_set0_dane(store_ctx, SSL_get0_dane(ssl));
+ if (SSL_get_verify_callback(ssl))
+ X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
+
+ ret = X509_verify_cert(store_ctx);
+ if (!ret) {
+ if (X509_STORE_CTX_get_error(store_ctx) == X509_V_ERR_DANE_NO_MATCH)
+ s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+ else
+ s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+ }
+ X509_STORE_CTX_cleanup(store_ctx);
+ }
+ if (store_ctx)
+ X509_STORE_CTX_free(store_ctx);
+ if (ssl)
+ SSL_free(ssl);
+ if (ssl_ctx)
+ SSL_CTX_free(ssl_ctx);
+ if (basename)
+ free(basename);
+ ldns_rdf_deep_free(basename_rdf);
+#else
+ for (i = 0; i < ldns_rr_list_rr_count(usable_tlsas); i++) {
+ tlsa_rr = ldns_rr_list_rr(usable_tlsas, i);
+ ps = s;
+ s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
+ pkix_validation_store);
+
+ if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
+ s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE &&
+ s != LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA) {
+
+ /* which would be LDNS_STATUS_OK (match)
+ * or some fatal error preventing use from
+ * trying the next TLSA record.
+ */
+ break;
}
- ldns_rr_list_free(tlsas);
+ s = (s > ps ? s : ps); /* pref NEED_OPENSSL_GE_1_1_FOR_DANE_TA
+ * over PKIX_DID_NOT_VALIDATE
+ * over TLSA_DID_NOT_MATCH
+ */
}
+#endif
+ ldns_rr_list_free(usable_tlsas);
return s;
}
+#endif /* USE_DANE_VERIFY */
#endif /* HAVE_SSL */
#endif /* USE_DANE */