]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Some more documentation for the dane functions.
authorWillem Toorop <willem@NLnetLabs.nl>
Wed, 12 Sep 2012 14:49:51 +0000 (14:49 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Wed, 12 Sep 2012 14:49:51 +0000 (14:49 +0000)
dane.c
doc/function_manpages
examples/ldns-dane.c
ldns/dane.h
ldns/dname.h
libdns.doxygen

diff --git a/dane.c b/dane.c
index 54561e01c93c3e679d5adddfc5f4bba00f226d2f..1d8cdc7a2bd3546e6267ee3909296a4ead7fa7b9 100644 (file)
--- a/dane.c
+++ b/dane.c
 #include <openssl/err.h>
 #endif
 
+#ifndef max
+#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
+#endif
+
 ldns_status
 ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
                uint16_t port, ldns_dane_transport transport)
@@ -68,6 +72,7 @@ ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
        return LDNS_STATUS_OK;
 }
 
+
 #ifdef HAVE_SSL
 ldns_status
 ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
@@ -155,6 +160,9 @@ ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
 }
 
 
+/* Ordinary PKIX validation of cert (with extra_certs to help)
+ * against the CA's in store
+ */
 static ldns_status
 ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
                X509_STORE* store)
@@ -186,6 +194,9 @@ ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
 }
 
 
+/* Orinary PKIX validation of cert (with extra_certs to help)
+ * against the CA's in store, but also return the validation chain.
+ */
 static ldns_status
 ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
                STACK_OF(X509)* extra_certs, X509_STORE* store)
@@ -232,6 +243,8 @@ exit_free_empty_store:
 }
 
 
+/* Return the validation chain that can be build out of cert, with extra_certs.
+ */
 static ldns_status
 ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
                X509* cert, STACK_OF(X509)* extra_certs)
@@ -269,6 +282,8 @@ exit_free_empty_store:
 }
 
 
+/* Pop n+1 certs and return the last popped.
+ */
 static ldns_status
 ldns_dane_get_nth_cert_from_validation_chain(
                X509** cert, STACK_OF(X509)* chain, int n)
@@ -287,6 +302,9 @@ ldns_dane_get_nth_cert_from_validation_chain(
 }
 
 
+/* Create validation chain with cert and extra_certs and returns the last
+ * self-signed (if present).
+ */
 static ldns_status
 ldns_dane_pkix_get_last_self_signed(X509** out_cert,
                X509* cert, STACK_OF(X509)* extra_certs)
@@ -484,6 +502,9 @@ memerror:
 }
 
 
+/* Return tlsas that actually are TLSA resource records with known values
+ * for the Certificate usage, Selector and Matching type rdata fields.
+ */
 static ldns_rr_list*
 ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
 {
@@ -512,6 +533,8 @@ ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
 }
 
 
+/* Return whether cert/selector/matching_type matches data.
+ */
 static ldns_status
 ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
                ldns_tlsa_matching_type matching_type, ldns_rdf* data)
@@ -530,6 +553,9 @@ ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
 }
 
 
+/* Return whether any certificate from the chain with selector/matching_type
+ * matches data.
+ */
 static ldns_status
 ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
                ldns_tlsa_selector      selector,
@@ -683,11 +709,11 @@ ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
 ldns_status
 ldns_dane_verify(ldns_rr_list* tlsas,
                X509* cert, STACK_OF(X509)* extra_certs,
-               X509_STORE* validate_store)
+               X509_STORE* pkix_validation_store)
 {
        size_t i;
        ldns_rr* tlsa_rr;
-       ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+       ldns_status s = LDNS_STATUS_OK, ps;
 
        assert(cert != NULL);
 
@@ -698,17 +724,19 @@ ldns_dane_verify(ldns_rr_list* tlsas,
                }
        }
        if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
-
-               return ldns_dane_verify_rr(NULL,
-                               cert, extra_certs, validate_store);
+               /* 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);
-                       s = ldns_dane_verify_rr(tlsa_rr,
-                                       cert, extra_certs, validate_store);
+                       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_PKIX_DID_NOT_VALIDATE) {
 
                                /* which would be LDNS_STATUS_OK (match)
                                 * or some fatal error preventing use from
@@ -716,6 +744,9 @@ ldns_dane_verify(ldns_rr_list* tlsas,
                                 */
                                break;
                        }
+                       s = max(s, ps); /* prefer PKIX_DID_NOT_VALIDATE
+                                        * over   TLSA_DID_NOT_MATCH
+                                        */
                }
                ldns_rr_list_free(tlsas);
        }
index 15706fada57907d9ff7cba8a2d21af946270b104..ce05899b7cf14d187cbdd608432d3c28d4d1f459 100644 (file)
@@ -39,6 +39,11 @@ ldns_dname_compare, ldns_dname_interval | ldns_dname_is_subdomain | ldns_dname
 ldns_dname | ldns_dname_left_chop, ldns_dname_label_count, ldns_dname2canonical, ldns_dname_cat, ldns_dname_cat_clone, ldns_dname_new, ldns_dname_new_frm_str, ldns_dname_new_frm_data, ldns_dname_is_subdomain, ldns_dname_str_absolute, ldns_dname_label, ldns_dname_compare, ldns_dname_interval
 ### /dname.h
 
+### dane.h
+ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr | ldns_dane_verify, ldns_dane_verify_rr
+ldns_dane_verify, ldns_dane_verify_rr | ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr
+### /dane.h
+
 ### rdata.h
 ldns_rdf, ldns_rdf_type | ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data, ldns_rdf_size, ldns_rdf_get_type, ldns_rdf_data, ldns_rdf_compare, ldns_rdf_new, ldns_rdf_clone, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_free, ldns_rdf_deep_free, ldns_rdf_print, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t
 ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data | ldns_rdf
index 334df86167f902f0ae1830afb2db2e8540f89066..e20f19e0e90bc24f7c173952be1b1bd428f5feb7 100644 (file)
@@ -544,7 +544,7 @@ dane_query(ldns_rr_list** rrs, ldns_resolver* r,
 
 ldns_rr_list*
 dane_lookup_addresses(ldns_resolver* res, ldns_rdf* dname,
-               ldns_dane_protocol protocol)
+               int ai_family)
 {
        ldns_status s;
        ldns_rr_list *as = NULL;
@@ -554,8 +554,7 @@ dane_lookup_addresses(ldns_resolver* res, ldns_rdf* dname,
        if (r == NULL) {
                MEMERR("ldns_rr_list_new");
        }
-       if (protocol == LDNS_DANE_PROTOCOL_UNSPEC ||
-                       (protocol & LDNS_DANE_PROTOCOL_IPV4)) {
+       if (ai_family == AF_UNSPEC || ai_family == AF_INET) {
 
                s = dane_query(&as, res,
                                dname, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN,
@@ -572,8 +571,7 @@ dane_lookup_addresses(ldns_resolver* res, ldns_rdf* dname,
                        MEMERR("ldns_rr_list_push_rr_list");
                }
        }
-       if (protocol == LDNS_DANE_PROTOCOL_UNSPEC ||
-                       (protocol & LDNS_DANE_PROTOCOL_IPV6)) {
+       if (ai_family == AF_UNSPEC || ai_family == AF_INET6) {
 
                s = dane_query(&aaas, res,
                                dname, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN,
@@ -680,7 +678,7 @@ main(int argc, char **argv)
        ldns_rr*      address_rr;
        ldns_rdf*     address;
 
-       int           protocol  = LDNS_DANE_PROTOCOL_UNSPEC;
+       int           ai_family = AF_UNSPEC;
        int           transport = LDNS_DANE_TRANSPORT_TCP;
 
        char*         name_str;
@@ -719,10 +717,10 @@ main(int argc, char **argv)
                        print_usage("ldns-dane");
                        break;
                case '4':
-                       protocol = LDNS_DANE_PROTOCOL_IPV4;
+                       ai_family = AF_INET;
                        break;
                case '6':
-                       protocol = LDNS_DANE_PROTOCOL_IPV6;
+                       ai_family = AF_INET6;
                        break;
                case 'a':
                        s = ldns_str2rdf_a(&address, optarg);
@@ -810,11 +808,11 @@ main(int argc, char **argv)
         * and IPv6 addresses when -4 was given.
         */
        if (ldns_rr_list_rr_count(addresses) > 0 &&
-                       protocol != LDNS_DANE_PROTOCOL_UNSPEC) {
+                       ai_family != AF_UNSPEC) {
                /* TODO: resource leak, previous addresses */
                originals = addresses;
                addresses = rr_list_filter_rr_type(originals,
-                               (protocol == LDNS_DANE_PROTOCOL_IPV4
+                               (ai_family == AF_INET
                                 ? LDNS_RR_TYPE_A : LDNS_RR_TYPE_AAAA));
                ldns_rr_list_free(originals);
                if (addresses == NULL) {
@@ -983,7 +981,7 @@ main(int argc, char **argv)
                                        assume_dnssec_validity);
                        LDNS_ERR(s, "could not dane_setup_resolver");
                        ldns_rr_list_free(addresses);
-                       addresses = dane_lookup_addresses(res, name, protocol);
+                       addresses =dane_lookup_addresses(res, name, ai_family);
                        ldns_resolver_free(res);
                }
                if (ldns_rr_list_rr_count(addresses) == 0) {
index de191a837dfedb413b219810b066bf3f9fee3669..47d99ae68da036250c0f3b358d4de4e2c23e710f 100644 (file)
 extern "C" {
 #endif
 
+/**
+ * The different "Certificate usage" rdata field values for a TLSA RR.
+ */
 enum ldns_enum_tlsa_certificate_usage
 {
+       /** CA constraint */
        LDNS_TLSA_USAGE_CA_CONSTRAINT                   = 0,
+       /** Sevice certificate constraint */
        LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT  = 1,
+       /** Trust anchor assertion */
        LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION          = 2,
+       /** Domain issued certificate */
        LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE       = 3
 };
 typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage;
 
+/**
+ * The different "Selector" rdata field values for a TLSA RR.
+ */
 enum ldns_enum_tlsa_selector
 {
+       /** 
+        * Full certificate: the Certificate binary structure
+        * as defined in [RFC5280]
+        */
        LDNS_TLSA_SELECTOR_FULL_CERTIFICATE     = 0,
+
+       /** 
+        * SubjectPublicKeyInfo: DER-encoded binary structure
+        * as defined in [RFC5280]
+        */
        LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO = 1
 };
 typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector;
 
+/**
+ * The different "Matching type" rdata field values for a TLSA RR.
+ */
 enum ldns_enum_tlsa_matching_type
 {
+       /** Exact match on selected content */
        LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED    = 0,
+       /** SHA-256 hash of selected content [RFC6234] */
        LDNS_TLSA_MATCHING_TYPE_SHA256          = 1,
+       /** SHA-512 hash of selected content [RFC6234] */
        LDNS_TLSA_MATCHING_TYPE_SHA512          = 2
 };
 typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type;
 
-enum ldns_enum_dane_protocol
-{
-       LDNS_DANE_PROTOCOL_UNSPEC = 0,
-       LDNS_DANE_PROTOCOL_IPV4   = 1,
-       LDNS_DANE_PROTOCOL_IPV6   = 2,
-       LDNS_DANE_PROTOCOL_IP     = 3
-};
-typedef enum ldns_enum_dane_protocol ldns_dane_protocol;
-
+/**
+ * Known transports to use with TLSA owner names.
+ */
 enum ldns_enum_dane_transport
 {
+       /** TCP */
        LDNS_DANE_TRANSPORT_TCP  = 0,
+       /** UDP */
        LDNS_DANE_TRANSPORT_UDP  = 1,
+       /** SCTP */
        LDNS_DANE_TRANSPORT_SCTP = 2
 };
 typedef enum ldns_enum_dane_transport ldns_dane_transport;
 
 
 /**
- * Creates a dname consisting of the given name, prefixed by the service
- * port and protocol name of the transport:
- * _<port>._<protocol>.<name>
- * TODO: How to choose protocol SCTP?
+ * Creates a dname consisting of the given name, prefixed by the service port
+ * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>.
  *
  * \param[out] tlsa_owner The created dname.
- * \param[in] name The dname that should be prefixed by the service and
- *                 protocol.
- * \param[in] port The service port number.
+ * \param[in] name The dname that should be prefixed.
+ * \param[in] port The service port number for wich the name should be created.
  * \param[in] transport The transport for wich the name should be created.
  * \return LDNS_STATUS_OK on success or an error code otherwise.
  */
@@ -105,7 +124,7 @@ ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner,
  * \param[in] cert The certificate from which the data is selected
  * \param[in] selector The full certificate or the public key
  * \param[in] matching_type The full data or the SHA256 or SHA512 hash
- *                          of the selected data
+ *            of the selected data
  * \return LDNS_STATUS_OK on success or an error code otherwise.
  */
 ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
@@ -138,6 +157,7 @@ ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
  *            This can help to make sure that the intended (self signed)
  *            trust anchor is actually present in extra_certs (which is a
  *            DANE requirement).
+ *
  * \return LDNS_STATUS_OK on success or an error code otherwise.
  */
 ldns_status ldns_dane_select_certificate(X509** selected_cert,
@@ -158,18 +178,61 @@ ldns_status ldns_dane_select_certificate(X509** selected_cert,
  *
  * \return LDNS_STATUS_OK on success or an error code otherwise.
  */
-ldns_status
-ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
+ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
                ldns_tlsa_certificate_usage certificate_usage,
                ldns_tlsa_selector          selector,
                ldns_tlsa_matching_type     matching_type,
                X509* cert);
 
+/**
+ * Verify if the given TLSA resource record matces the given certificate.
+ * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH)
+ * is preferred over PKIX failure  (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE).
+ * So when PKIX validation is required by the TLSA Certificate usage,
+ * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH
+ * is returned whether the PKIX validated or not.
+ *
+ * \param[in] tlsa_rr The resource record that specifies what and how to
+ *            match the certificate. With tlsa_rr == NULL, regular PKIX
+ *            validation is performed.
+ * \param[in] cert The certificate to match (and validate)
+ * \param[in] extra_certs Intermediate certificates that might be necessary
+ *            creating the validation chain.
+ * \param[in] pkix_validation_store Used when the certificate usage is 
+ *            "CA constraint" or "Service Certificate Constraint" to 
+ *            validate the certificate.
+ *
+ * \return LDNS_STATUS_OK on success,
+ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch,
+ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched,
+ *         but the PKIX validation failed, or other ldns_status errors.
+ */
 ldns_status
 ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
                X509* cert, STACK_OF(X509)* extra_certs,
                X509_STORE* pkix_validation_store);
 
+/**
+ * Verify if any of the given TLSA resource records matces the given
+ * certificate.
+ *
+ * \param[in] tlsas The resource records that specify what and how to
+ *            match the certificate. One must match for this function
+ *            to succeed. With tlsas == NULL or the number of TLSA records
+ *            in tlsas == 0, regular PKIX validation is performed.
+ * \param[in] cert The certificate to match (and validate)
+ * \param[in] extra_certs Intermediate certificates that might be necessary
+ *            creating the validation chain.
+ * \param[in] pkix_validation_store Used when the certificate usage is 
+ *            "CA constraint" or "Service Certificate Constraint" to 
+ *            validate the certificate.
+ *
+ * \return LDNS_STATUS_OK on success,
+ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's
+ *         matched but the PKIX validation failed,
+ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched,
+ *         or other ldns_status errors.
+ */
 ldns_status
 ldns_dane_verify(ldns_rr_list* tlsas,
                X509* cert, STACK_OF(X509)* extra_certs,
index bc06a715a2e01a9db2fbe43139abdb4c3309217c..d4d712f3995c013acb4e701c708363ba4d7051ab 100644 (file)
@@ -182,7 +182,7 @@ bool ldns_dname_str_absolute(const char *dname_str);
  * \param[in] *dname a rdf representing the dname
  * \return true or false
  */
-bool ldns_dname_absolute(const ldns_rdf *rdf);
+bool ldns_dname_absolute(const ldns_rdf *dname);
 
 /**
  * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME
index 3325db94af466692e746acfbc3edd2f55c838354..ef94a55bd164296d6b237ecb27939c970983515d 100644 (file)
@@ -1399,7 +1399,7 @@ SEARCH_INCLUDES        = YES
 # contain include files that are not input files but should be processed by
 # the preprocessor.
 
-INCLUDE_PATH           =
+INCLUDE_PATH           = .
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the