diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c index c5a974477227277be47624c81453c271b6f42474..1f82482701a08c345c3df02d6f80edda0db7032a 100644 --- a/lib/dnssec/nsec.c +++ b/lib/dnssec/nsec.c @@ -400,6 +400,51 @@ int kr_nsec_empty_nonterminal_response_check(const knot_pkt_t *pkt, knot_section return kr_error(ENOENT); } +int kr_nsec_no_data(const knot_pkt_t *pkt, knot_section_t section_id, + const knot_dname_t *sname, uint16_t stype) +{ + const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id); + if (!sec || !sname) { + return kr_error(EINVAL); + } + + int ret; + int flags = 0; + for (unsigned i = 0; i < sec->count; ++i) { + const knot_rrset_t *rrset = knot_pkt_rr(sec, i); + if (rrset->type != KNOT_RRTYPE_NSEC) { + continue; + } + + /* No data. */ + if (knot_dname_is_equal(rrset->owner, sname)) { + ret = no_data_response_check_rrtype(&flags, rrset, stype); + if (ret != 0) { + return ret; + } + } + if (flags & FLG_NOEXIST_RRTYPE) { + return kr_ok(); + } + + /* Empty non-terminal. */ + if (nsec_empty_nonterminal(rrset, sname) == 0) { + return kr_ok(); + } + + /* Wild card no data. */ + ret = wildcard_no_data_response_check(&flags, rrset, sname, stype); + if (ret != 0) { + return ret; + } + if ((flags & FLG_NOEXIST_RRSET) && (flags & FLG_NOEXIST_CLOSER)) { + return kr_ok(); + } + } + + return kr_error(ENOENT); +} + int kr_nsec_existence_denial(const knot_pkt_t *pkt, knot_section_t section_id, const knot_dname_t *sname, uint16_t stype, mm_ctx_t *pool) { diff --git a/lib/dnssec/nsec.h b/lib/dnssec/nsec.h index 1f9d258c185567317d7f4b09904298398979244b..bb4cb210bb3f30705dca2c05fc83992e14e52dcb 100644 --- a/lib/dnssec/nsec.h +++ b/lib/dnssec/nsec.h @@ -85,6 +85,17 @@ int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t int kr_nsec_empty_nonterminal_response_check(const knot_pkt_t *pkt, knot_section_t section_id, const knot_dname_t *sname); +/** + * Authenticated denial of existence according to RFC4035 3.1.3.1 and 3.1.3.4. + * @param pkt Packet structure to be processed. + * @param section_id Packet section to be processed. + * @param sname Name to be checked. + * @param stype Type to be checked. + * @return 0 or error code. + */ +int kr_nsec_no_data(const knot_pkt_t *pkt, knot_section_t section_id, + const knot_dname_t *sname, uint16_t stype); + /** * Authenticated denial of existence according to RFC4035 5.4. * @note No RRSIGs are validated. diff --git a/lib/layer/validate.c b/lib/layer/validate.c index fa9d10fbdde7cf4dcbffdc2ac0fa2ab040a1a9c1..63d44701ea3d4ec9c6b329644d81e37b530cad78 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -392,13 +392,7 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) * ? merge the functionality together to share code/resources */ if (!has_nsec3) { - ret = kr_nsec_no_data_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt)); - if (ret != 0) { - ret = kr_nsec_wildcard_no_data_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt)); - } - if (ret != 0) { - ret = kr_nsec_empty_nonterminal_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt)); - } + ret = kr_nsec_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt)); } else { ret = kr_nsec3_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt)); }