diff options
Diffstat (limited to 'lib/dnssec')
-rw-r--r-- | lib/dnssec/nsec.c | 57 | ||||
-rw-r--r-- | lib/dnssec/nsec.h | 9 | ||||
-rw-r--r-- | lib/dnssec/nsec3.c | 8 |
3 files changed, 57 insertions, 17 deletions
diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c index 4ae13b23..0a3edf68 100644 --- a/lib/dnssec/nsec.c +++ b/lib/dnssec/nsec.c @@ -24,11 +24,42 @@ #include <libknot/rrtype/nsec.h> #include <libknot/rrtype/rrsig.h> #include <libdnssec/error.h> -#include <libdnssec/nsec.h> #include "lib/defines.h" #include "lib/dnssec/nsec.h" +bool kr_nsec_bitmap_contains_type(const uint8_t *bm, uint16_t bm_size, uint16_t type) +{ + if (!bm || bm_size == 0) { + assert(bm); + return false; + } + + const uint8_t type_hi = (type >> 8); + const uint8_t type_lo = (type & 0xff); + const uint8_t bitmap_idx = (type_lo >> 3); + const uint8_t bitmap_bit_mask = 1 << (7 - (type_lo & 0x07)); + + size_t bm_pos = 0; + while (bm_pos + 3 <= bm_size) { + uint8_t win = bm[bm_pos++]; + uint8_t win_size = bm[bm_pos++]; + /* Check remaining window length. */ + if (win_size < 1 || bm_pos + win_size > bm_size) + return false; + /* Check that we have a correct window. */ + if (win == type_hi) { + if (bitmap_idx < win_size) { + return bm[bm_pos + bitmap_idx] & bitmap_bit_mask; + } + return false; + } else { + bm_pos += win_size; + } + } + + return false; +} int kr_nsec_children_in_zone_check(const uint8_t *bm, uint16_t bm_size) { @@ -36,9 +67,9 @@ int kr_nsec_children_in_zone_check(const uint8_t *bm, uint16_t bm_size) return kr_error(EINVAL); } const bool parent_side = - dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_DNAME) - || (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS) - && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA) + kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_DNAME) + || (kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_NS) + && !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_SOA) ); return parent_side ? abs(ENOENT) : kr_ok(); /* LATER: after refactoring, probably also check if signer name equals owner, @@ -231,12 +262,12 @@ int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t ty if (!bm || !owner) { return kr_error(EINVAL); } - if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) { + if (kr_nsec_bitmap_contains_type(bm, bm_size, type)) { return NO_PROOF; } if (type != KNOT_RRTYPE_CNAME - && dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_CNAME)) { + && kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_CNAME)) { return NO_PROOF; } /* Special behavior around zone cuts. */ @@ -248,7 +279,7 @@ int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t ty * See RFC4035 5.2, next-to-last paragraph. * This doesn't apply for root DS as it doesn't exist in DNS hierarchy. */ - if (owner[0] != '\0' && dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)) { + if (owner[0] != '\0' && kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_SOA)) { return NO_PROOF; } break; @@ -260,8 +291,8 @@ int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t ty default: /* Parent-side delegation record isn't authoritative for non-DS; * see RFC6840 4.1. */ - if (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS) - && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)) { + if (kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_NS) + && !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_SOA)) { return NO_PROOF; } /* LATER(opt): perhaps short-circuit test if we repeat it here. */ @@ -489,11 +520,11 @@ int kr_nsec_ref_to_unsigned(const knot_pkt_t *pkt) if (!bm) { return kr_error(EINVAL); } - if (dnssec_nsec_bitmap_contains(bm, bm_size, + if (kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_NS) && - !dnssec_nsec_bitmap_contains(bm, bm_size, + !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_DS) && - !dnssec_nsec_bitmap_contains(bm, bm_size, + !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_SOA)) { /* rfc4035, 5.2 */ return kr_ok(); @@ -532,7 +563,7 @@ int kr_nsec_matches_name_and_type(const knot_rrset_t *nsec, if (!bm) { return kr_error(EINVAL); } - if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) { + if (kr_nsec_bitmap_contains_type(bm, bm_size, type)) { return kr_ok(); } else { return kr_error(ENOENT); diff --git a/lib/dnssec/nsec.h b/lib/dnssec/nsec.h index 9439a882..58542414 100644 --- a/lib/dnssec/nsec.h +++ b/lib/dnssec/nsec.h @@ -19,6 +19,15 @@ #include <libknot/packet/pkt.h> /** + * Check whether bitmap contains given type. + * @param bm Bitmap from NSEC or NSEC3. + * @param bm_size Bitmap size. + * @param type RR type to search for. + * @return True if bitmap contains type. + */ +bool kr_nsec_bitmap_contains_type(const uint8_t *bm, uint16_t bm_size, uint16_t type); + +/** * Check bitmap that child names are contained in the same zone. * @note see RFC6840 4.1. * @param bm Bitmap from NSEC or NSEC3. diff --git a/lib/dnssec/nsec3.c b/lib/dnssec/nsec3.c index 2f61b035..c71cadd0 100644 --- a/lib/dnssec/nsec3.c +++ b/lib/dnssec/nsec3.c @@ -708,11 +708,11 @@ int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt) if (!bm) { return kr_error(EINVAL); } - if (dnssec_nsec_bitmap_contains(bm, bm_size, + if (kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_NS) && - !dnssec_nsec_bitmap_contains(bm, bm_size, + !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_DS) && - !dnssec_nsec_bitmap_contains(bm, bm_size, + !kr_nsec_bitmap_contains_type(bm, bm_size, KNOT_RRTYPE_SOA)) { /* Satisfies rfc5155, 8.9. paragraph 2 */ return kr_ok(); @@ -768,7 +768,7 @@ int kr_nsec3_matches_name_and_type(const knot_rrset_t *nsec3, if (!bm) { return kr_error(EINVAL); } - if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) { + if (kr_nsec_bitmap_contains_type(bm, bm_size, type)) { return kr_ok(); } else { return kr_error(ENOENT); |