From: Jelte Jansen Date: Fri, 21 Apr 2006 08:52:59 +0000 (+0000) Subject: split up nsec-coverage functions to bitmap coverage and name coverage, because there... X-Git-Tag: release-1.1.0~166 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8dd6dec3ece86abc5a57f0160587c268b8cdbe08;p=thirdparty%2Fldns.git split up nsec-coverage functions to bitmap coverage and name coverage, because there are more than 2 possible results. (do we have any standard place to put RR/RDATA convenience functions?) drill chaser can now correctly handle nodata responses while chasing. --- diff --git a/dnssec.c b/dnssec.c index a195f0d1..7b4ec14e 100644 --- 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, diff --git a/drill/chasetrace.c b/drill/chasetrace.c index 6203b305..a636adaa 100644 --- a/drill/chasetrace.c +++ b/drill/chasetrace.c @@ -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); diff --git a/ldns/dnssec.h b/ldns/dnssec.h index 865e80c8..c234eb6b 100644 --- a/ldns/dnssec.h +++ b/ldns/dnssec.h @@ -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