#ifdef HAVE_SSL
#include <openssl/ssl.h>
#include <openssl/err.h>
+#include <openssl/x509v3.h>
#endif
#ifndef max
/* Return whether any certificate from the chain with selector/matching_type
* matches data.
+ * ca should be true if the certificate has to be a CA certificate too.
*/
static ldns_status
ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
ldns_tlsa_selector selector,
- ldns_tlsa_matching_type matching_type, ldns_rdf* data)
+ ldns_tlsa_matching_type matching_type,
+ ldns_rdf* data, bool ca)
{
ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
size_t n, i;
}
s = ldns_dane_match_cert_with_data(cert,
selector, matching_type, data);
+ if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
+ s = LDNS_STATUS_DANE_TLSA_MATCHED_NON_CA_CERTIFICATE;
+ }
X509_free(cert);
if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
break;
}
+ /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+ * try to match the next certificate
+ */
}
return s;
}
*/
s = ldns_dane_match_any_cert_with_data(
pkix_validation_chain,
- selector, matching_type, data);
+ selector, matching_type, data, true);
if (s == LDNS_STATUS_OK) {
/* A TLSA record did match a cert from the
} else if (s == LDNS_STATUS_OK) {
/* PKIX validated, does the TLSA match too? */
- /* Pop the last cert from the validation chain */
- cert = sk_X509_pop(pkix_validation_chain);
- if (! cert) {
- s = LDNS_STATUS_SSL_ERR;
- } else {
- s = ldns_dane_match_cert_with_data(cert,
- selector, matching_type, data);
- X509_free(cert);
- /*
- * TODO: What to do when we had no match?
- *
- * Does OpenSSL create the longest possible
- * validation_chain?
- *
- * In that case we have to test whether
- * intermediate certificates are in the
- * pkix_validation_store.
- *
- * Otherwise, we have to remove the signing
- * CA from the pkix_validation_store, and see
- * if that removed cert might itself be
- * validated by a CA that *does* match.
- */
- }
+ s = ldns_dane_match_any_cert_with_data(
+ pkix_validation_chain,
+ selector, matching_type, data, true);
}
sk_X509_pop_free(pkix_validation_chain, X509_free);
return s;
if (s == LDNS_STATUS_OK) {
s = ldns_dane_match_any_cert_with_data(
pkix_validation_chain,
- selector, matching_type, data);
+ selector, matching_type, data, false);
} else if (! pkix_validation_chain) {
return s;
"extra certificates" },
{ LDNS_STATUS_DANE_INSECURE, /* Unused by library */
"The queried resource records were insecure" },
+ { LDNS_STATUS_DANE_BOGUS, /* Unused by library */
+ "The queried resource records were bogus" },
{ LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
"The TLSA record(s) "
"did not match with the server certificate (chain)" },
+ { LDNS_STATUS_DANE_TLSA_MATCHED_NON_CA_CERTIFICATE,
+ "A TLSA record matched, but was not a CA certificate" },
{ LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
- "DANE PKIX Could not validate" },
+ "Could not PKIX validate" },
{ LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR, /* Trust anchor assertion */
"The validation chain must end in a self-signed certificate " },
{ 0, NULL }
LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED,
LDNS_STATUS_DANE_INDEX_OUT_OF_RANGE,
LDNS_STATUS_DANE_INSECURE,
+ LDNS_STATUS_DANE_BOGUS,
LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+ LDNS_STATUS_DANE_TLSA_MATCHED_NON_CA_CERTIFICATE,
LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR
};