]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
split up nsec-coverage functions to bitmap coverage and name coverage, because there...
authorJelte Jansen <jeltejan@NLnetLabs.nl>
Fri, 21 Apr 2006 08:52:59 +0000 (08:52 +0000)
committerJelte Jansen <jeltejan@NLnetLabs.nl>
Fri, 21 Apr 2006 08:52:59 +0000 (08:52 +0000)
drill chaser can now correctly handle nodata responses while chasing.

dnssec.c
drill/chasetrace.c
ldns/dnssec.h

index a195f0d18664885efae36de7abf9813b25eb16e2..7b4ec14e6f4f553d7486645a98165a7c1682788e 100644 (file)
--- a/dnssec.c
+++ b/dnssec.c
@@ -1117,41 +1117,45 @@ ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
 }
 
 bool
-ldns_nsec_covers_rrset(const ldns_rr *nsec, ldns_rdf *name, ldns_rr_type type)
+ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type)
 {
        uint8_t *bitmap;
        uint16_t i;
        uint8_t window_block_nr;
        
-       ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
-       ldns_rdf *nsec_next = ldns_rr_rdf(nsec, 0);
-       
-       if (ldns_dname_compare(nsec_owner, name) <= 0 &&
-           ldns_dname_compare(name, nsec_next) > 0) {
-               
-               /* Check the bitmap if our type is there */
-               bitmap = ldns_rdf_data(ldns_rr_rdf(nsec, 1));
-               window_block_nr = (uint8_t) (type / 256);
-               i = 0;
-               while (i < ldns_rdf_size(ldns_rr_rdf(nsec, 1))) {
-                       if (bitmap[i] == window_block_nr) {
-                               /* this is the right window, check the bit */
-                               if ((uint8_t) (type / 8) < bitmap[i + 1] &&
-                                   ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) {
-                                       return true;
-                               } else {
-                                       return false;
-                               }
+       /* Check the bitmap if our type is there */
+       bitmap = ldns_rdf_data(nsec_bitmap);
+       window_block_nr = (uint8_t) (type / 256);
+       i = 0;
+       while (i < ldns_rdf_size(nsec_bitmap)) {
+               if (bitmap[i] == window_block_nr) {
+                       /* this is the right window, check the bit */
+                       if ((uint8_t) (type / 8) < bitmap[i + 1] &&
+                           ldns_get_bit(&bitmap[i + 1 + (type / 8)], (size_t) (7 - (type % 8)))) {
+                               return true;
                        } else {
-                               /* this is the wrong window, go to the next */
-                               i++;
-                               i += bitmap[i];
+                               return false;
                        }
+               } else {
+                       /* this is the wrong window, go to the next */
+                       i++;
+                       i += bitmap[i];
                }
        }
+
        return false;
 }
 
+bool
+ldns_nsec_covers_name(const ldns_rr *nsec, ldns_rdf *name)
+{
+       ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
+       ldns_rdf *nsec_next = ldns_rr_rdf(nsec, 0);
+       
+       return (ldns_dname_compare(nsec_owner, name) <= 0 &&
+           ldns_dname_compare(name, nsec_next) > 0);
+}
+
 /* sig may be null - if so look in the packet */
 ldns_status
 ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
index 6203b3055f7051336b63a298913d60a0fb77eeef..a636adaa4278ef38bc76b23781dee2b9744f9df9 100644 (file)
@@ -280,132 +280,129 @@ do_chase(ldns_resolver *res, ldns_rdf *name, ldns_rr_type type, ldns_rr_class c,
                        LDNS_SECTION_ANY_NOQUESTION
                        );
        
-       for (sig_i = 0; sig_i < ldns_rr_list_rr_count(sigs); sig_i++) {
-               cur_sig = ldns_rr_clone(ldns_rr_list_rr(sigs, sig_i));
-               
-               keys = ldns_pkt_rr_list_by_name_and_type(pkt,
-                               ldns_rr_rdf(cur_sig, 7),
-                               LDNS_RR_TYPE_DNSKEY,
-                               LDNS_SECTION_ANY_NOQUESTION
-                               );
-               
-               if (qdebug != -1) {
-                       printf(";; Data set: ");
-                       ldns_rdf_print(stdout, name);
-
-                       lt = ldns_lookup_by_id(ldns_rr_classes, c);
-                       if (lt) {
-                               printf("\t%s\t", lt->name);
-                       } else {
-                               printf("\tCLASS%d\t", c);
-                       }
-
-                       descriptor = ldns_rr_descript(type);
-
-                       if (descriptor->_name) {
-                               printf("%s\t", descriptor->_name);
-                       } else {
-                               /* exceptions for qtype */
-                               if (type == 251) {
-                                       printf("IXFR ");
-                               } else if (type == 252) {
-                                       printf("AXFR ");
-                               } else if (type == 253) {
-                                       printf("MAILB ");
-                               } else if (type == 254) {
-                                       printf("MAILA ");
-                               } else if (type == 255) {
-                                       printf("ANY ");
-                               } else {
-                                       printf("TYPE%d\t", type);
-                               }
-                       }
+       if (rrset) {
+               for (sig_i = 0; sig_i < ldns_rr_list_rr_count(sigs); sig_i++) {
+                       cur_sig = ldns_rr_clone(ldns_rr_list_rr(sigs, sig_i));
                        
-                       printf("\n");
-                       printf(";; Signed by: ");
-                       ldns_rdf_print(stdout, ldns_rr_rdf(cur_sig, 7));
-                       printf("\n");
-               }
-
-               if (!keys) {
-                       ldns_pkt_free(pkt);
-                       pkt = NULL;
-                       pkt = ldns_resolver_query(res,
-                                       ldns_rr_rdf(cur_sig, 7),
-                                       LDNS_RR_TYPE_DNSKEY, c, qflags);
-                       if (!pkt) {
-                               ldns_rr_list_deep_free(rrset);
-                               ldns_rr_list_deep_free(sigs);
-                               return LDNS_STATUS_NETWORK_ERR;
-                       }
-
                        keys = ldns_pkt_rr_list_by_name_and_type(pkt,
                                        ldns_rr_rdf(cur_sig, 7),
                                        LDNS_RR_TYPE_DNSKEY,
                                        LDNS_SECTION_ANY_NOQUESTION
                                        );
-               }
-               if(!keys) {
-                       mesg("No key for data found in that zone!");
-                       ldns_rr_list_deep_free(rrset);
-                       ldns_rr_list_deep_free(sigs);
-                       ldns_pkt_free(pkt);
-                       ldns_rr_free(cur_sig);
-                       return LDNS_STATUS_CRYPTO_NO_DNSKEY;
-               } else {
-                       result = LDNS_STATUS_ERR;
-                       for (key_i = 0; key_i < ldns_rr_list_rr_count(keys); key_i++) {
-                               /* only check matching keys */
-
-                               if (ldns_calc_keytag(ldns_rr_list_rr(keys, key_i))
-                                   ==
-                                   ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig))
-                                  ) {
-                                       result = ldns_verify_rrsig(rrset, cur_sig, ldns_rr_list_rr(keys, key_i));
+                       
+                       if (qdebug != -1) {
+                               printf(";; Data set: ");
+                               ldns_rdf_print(stdout, name);
 
-                                       if (result == LDNS_STATUS_OK) {
-                                               for (tkey_i = 0; tkey_i < ldns_rr_list_rr_count(trusted_keys); tkey_i++) {
-                                                       if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_i),
-                                                                          ldns_rr_list_rr(trusted_keys, tkey_i)
-                                                                         )) {
-                                                               mesg("Key is trusted");
-                                                               ldns_rr_list_deep_free(rrset);
-                                                               ldns_rr_list_deep_free(sigs);
-                                                               ldns_rr_list_deep_free(keys);
-                                                               ldns_pkt_free(pkt);
-                                                               ldns_rr_free(cur_sig);
-                                                               return LDNS_STATUS_OK;
-                                                       }
-                                               }
-                                               result = do_chase(res, ldns_rr_rdf(cur_sig, 7), LDNS_RR_TYPE_DS, c, trusted_keys, pkt, qflags);
-                                               ldns_rr_list_deep_free(rrset);
-                                               ldns_rr_list_deep_free(sigs);
-                                               ldns_rr_list_deep_free(keys);
-                                               ldns_pkt_free(pkt);
-                                               ldns_rr_free(cur_sig);
-                                               return result;
+                               lt = ldns_lookup_by_id(ldns_rr_classes, c);
+                               if (lt) {
+                                       printf("\t%s\t", lt->name);
+                               } else {
+                                       printf("\tCLASS%d\t", c);
+                               }
+
+                               descriptor = ldns_rr_descript(type);
+
+                               if (descriptor->_name) {
+                                       printf("%s\t", descriptor->_name);
+                               } else {
+                                       /* exceptions for qtype */
+                                       if (type == 251) {
+                                               printf("IXFR ");
+                                       } else if (type == 252) {
+                                               printf("AXFR ");
+                                       } else if (type == 253) {
+                                               printf("MAILB ");
+                                       } else if (type == 254) {
+                                               printf("MAILA ");
+                                       } else if (type == 255) {
+                                               printf("ANY ");
+                                       } else {
+                                               printf("TYPE%d\t", type);
                                        }
                                }
-/*
- else {
-                                       result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
+                               
+                               printf("\n");
+                               printf(";; Signed by: ");
+                               ldns_rdf_print(stdout, ldns_rr_rdf(cur_sig, 7));
+                               printf("\n");
+                       }
+
+                       if (!keys) {
+                               ldns_pkt_free(pkt);
+                               pkt = NULL;
+                               pkt = ldns_resolver_query(res,
+                                               ldns_rr_rdf(cur_sig, 7),
+                                               LDNS_RR_TYPE_DNSKEY, c, qflags);
+                               if (!pkt) {
+                                       ldns_rr_list_deep_free(rrset);
+                                       ldns_rr_list_deep_free(sigs);
+                                       return LDNS_STATUS_NETWORK_ERR;
                                }
-*/
+
+                               keys = ldns_pkt_rr_list_by_name_and_type(pkt,
+                                               ldns_rr_rdf(cur_sig, 7),
+                                               LDNS_RR_TYPE_DNSKEY,
+                                               LDNS_SECTION_ANY_NOQUESTION
+                                               );
                        }
-                       if (result != LDNS_STATUS_OK) {
+                       if(!keys) {
+                               mesg("No key for data found in that zone!");
                                ldns_rr_list_deep_free(rrset);
                                ldns_rr_list_deep_free(sigs);
-                               ldns_rr_list_deep_free(keys);
                                ldns_pkt_free(pkt);
                                ldns_rr_free(cur_sig);
-                               return result;
+                               return LDNS_STATUS_CRYPTO_NO_DNSKEY;
+                       } else {
+                               result = LDNS_STATUS_ERR;
+                               for (key_i = 0; key_i < ldns_rr_list_rr_count(keys); key_i++) {
+                                       /* only check matching keys */
+
+                                       if (ldns_calc_keytag(ldns_rr_list_rr(keys, key_i))
+                                           ==
+                                           ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig))
+                                          ) {
+                                               result = ldns_verify_rrsig(rrset, cur_sig, ldns_rr_list_rr(keys, key_i));
+
+                                               if (result == LDNS_STATUS_OK) {
+                                                       for (tkey_i = 0; tkey_i < ldns_rr_list_rr_count(trusted_keys); tkey_i++) {
+                                                               if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_i),
+                                                                                  ldns_rr_list_rr(trusted_keys, tkey_i)
+                                                                                 )) {
+                                                                       mesg("Key is trusted");
+                                                                       ldns_rr_list_deep_free(rrset);
+                                                                       ldns_rr_list_deep_free(sigs);
+                                                                       ldns_rr_list_deep_free(keys);
+                                                                       ldns_pkt_free(pkt);
+                                                                       ldns_rr_free(cur_sig);
+                                                                       return LDNS_STATUS_OK;
+                                                               }
+                                                       }
+                                                       result = do_chase(res, ldns_rr_rdf(cur_sig, 7), LDNS_RR_TYPE_DS, c, trusted_keys, pkt, qflags);
+                                                       ldns_rr_list_deep_free(rrset);
+                                                       ldns_rr_list_deep_free(sigs);
+                                                       ldns_rr_list_deep_free(keys);
+                                                       ldns_pkt_free(pkt);
+                                                       ldns_rr_free(cur_sig);
+                                                       return result;
+                                               }
+                                       }
+                               }
+                               if (result != LDNS_STATUS_OK) {
+                                       ldns_rr_list_deep_free(rrset);
+                                       ldns_rr_list_deep_free(sigs);
+                                       ldns_rr_list_deep_free(keys);
+                                       ldns_pkt_free(pkt);
+                                       ldns_rr_free(cur_sig);
+                                       return result;
+                               }
+                               ldns_rr_list_deep_free(keys);
                        }
-                       ldns_rr_list_deep_free(keys);
+                       ldns_rr_free(cur_sig);
                }
-               ldns_rr_free(cur_sig);
+               ldns_rr_list_deep_free(rrset);
        }
-       ldns_rr_list_deep_free(rrset);
-       if (ldns_rr_list_rr_count(sigs) > 0) {
+       if (rrset && ldns_rr_list_rr_count(sigs) > 0) {
                ldns_rr_list_deep_free(sigs);
                ldns_pkt_free(pkt);
                return LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
@@ -415,13 +412,35 @@ do_chase(ldns_resolver *res, ldns_rdf *name, ldns_rr_type type, ldns_rr_class c,
                result = LDNS_STATUS_CRYPTO_NO_RRSIG;
                
                for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) {
-                       if (ldns_nsec_covers_rrset(ldns_rr_list_rr(nsecs, nsec_i), name, type)) {
+                       /* there are four options:
+                        * - name equals ownername and is covered by the type bitmap
+                        * - name equals ownername but is not covered by the type bitmap
+                        * - name falls within nsec coverage but is not equal to the owner name
+                        * - name falls outside of nsec coverage
+                        */
+                       if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) {
+                               if (ldns_nsec_bitmap_covers_type(ldns_rr_rdf(ldns_rr_list_rr(nsecs, nsec_i), 1), type)) {
+                                       /* Error, according to the nsec this rrset is signed */
+                                       result = LDNS_STATUS_CRYPTO_NO_RRSIG;
+                               } else {
+                                       /* ok nsec denies existence, chase the nsec now */
+                                       result = do_chase(res, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, c, trusted_keys, pkt, qflags);
+                                       if (result == LDNS_STATUS_OK) {
+                                               ldns_pkt_free(pkt);
+                                               printf(";; Verifiably insecure.\n");
+                                               return result;
+                                       }
+                               }
+                       } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) {
                                /* Verifably insecure? chase the covering nsec */
                                result = do_chase(res, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, c, trusted_keys, pkt, qflags);
                                if (result == LDNS_STATUS_OK) {
                                        ldns_pkt_free(pkt);
+                                       printf(";; Verifiably insecure.\n");
                                        return result;
                                }
+                       } else {
+                               /* nsec has nothing to do with this data */
                        }
                }
                ldns_pkt_free(pkt);
index 865e80c85a0c886c69b246217386cee67841177a..c234eb6b6705bccddbd5eba94ba59eb39c7e2047 100644 (file)
@@ -163,13 +163,21 @@ ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key);
 ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs);
 
 /**
- * Checks coverage of NSEC RR
+ * Checks coverage of NSEC RR type bitmap
+ * \param[in] nsec The NSEC bitmap rdata field to check
+ * \param[in] type The type to check
+ * \return true if the NSEC RR covers the type
+ */
+bool ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type);
+
+/**
+ * Checks coverage of NSEC RR name span
  * \param[in] nsec The NSEC RR to check
  * \param[in] name The owner dname to check
  * \param[in] type The type to check
- * \return true if the NSEC RR covers the owner name and type
+ * \return true if the NSEC RR covers the owner name
  */
-bool ldns_nsec_covers_rrset(const ldns_rr *nsec, ldns_rdf *name, ldns_rr_type type);
+bool ldns_nsec_covers_name(const ldns_rr *nsec, ldns_rdf *name);
 
 /**
  * verify a packet