return kr_error(ENOENT);
}
-int kr_nsec_ref_to_unsigned(const knot_pkt_t *pkt)
+int kr_nsec_ref_to_unsigned(const ranked_rr_array_t *rrrs, uint32_t qry_uid,
+ const knot_dname_t *sname)
{
- int nsec_found = 0;
- const knot_pktsection_t *sec = knot_pkt_section(pkt, KNOT_AUTHORITY);
- if (!sec)
- return kr_error(EINVAL);
- for (unsigned i = 0; i < sec->count; ++i) {
- const knot_rrset_t *ns = knot_pkt_rr(sec, i);
- if (ns->type == KNOT_RRTYPE_DS)
- return kr_error(EEXIST);
- if (ns->type != KNOT_RRTYPE_NS)
- continue;
- nsec_found = 0;
- for (unsigned j = 0; j < sec->count; ++j) {
- const knot_rrset_t *nsec = knot_pkt_rr(sec, j);
- if (nsec->type == KNOT_RRTYPE_DS)
- return kr_error(EEXIST);
- if (nsec->type != KNOT_RRTYPE_NSEC)
- continue;
- /* nsec found
- * check if owner name matches the delegation name
- */
- if (!knot_dname_is_equal(nsec->owner, ns->owner)) {
- /* nsec does not match the delegation */
- continue;
- }
- nsec_found = 1;
- const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
- uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
- if (!bm)
- return kr_error(EINVAL);
- if (dnssec_nsec_bitmap_contains(bm, bm_size,
- KNOT_RRTYPE_NS) &&
- !dnssec_nsec_bitmap_contains(bm, bm_size,
- KNOT_RRTYPE_DS) &&
- !dnssec_nsec_bitmap_contains(bm, bm_size,
- KNOT_RRTYPE_SOA)) {
- /* rfc4035, 5.2 */
- return kr_ok();
- }
- }
- if (nsec_found) {
- /* nsec which owner matches
- * the delegation name was found,
- * but nsec type bitmap contains wrong types
- */
- return kr_error(EINVAL);
- } else {
- /* nsec that matches delegation was not found */
- return kr_error(DNSSEC_NOT_FOUND);
- }
- }
+ for (int i = rrrs->len - 1; i >= 0; --i) { // NSECs near the end typically
+ const knot_rrset_t *nsec = rrrs->at[i]->rr;
+ bool ok = rrrs->at[i]->qry_uid == qry_uid
+ && nsec->type == KNOT_RRTYPE_NSEC
+ && kr_rank_test(rrrs->at[i]->rank, KR_RANK_SECURE)
+ // avoid any possibility of getting tricked in deeper zones
+ && knot_dname_in_bailiwick(sname, nsec->owner) >= 0;
+ if (!ok) continue;
- return kr_error(EINVAL);
+ kr_assert(nsec->rrs.rdata);
+ const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
+ ok = ok && dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS)
+ && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_DS)
+ && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA);
+ if (ok) return kr_ok();
+ }
+ return kr_error(DNSSEC_NOT_FOUND);
}
int kr_nsec_matches_name_and_type(const knot_rrset_t *nsec,
/**
* Referral to unsigned subzone check (RFC4035 5.2).
- * @note No RRSIGs are validated.
- * @param pkt Packet structure to be processed.
- * @return 0 or error code:
- * DNSSEC_NOT_FOUND - neither ds nor nsec records
- * were not found.
- * EEXIST - ds record was found.
- * EINVAL - bogus.
+ *
+ * @param rrrs list of RRs to search; typically kr_request::auth_selected
+ * @param qry_uid only consider NSECs from this packet, for better efficiency
+ * @return 0 or negative error code, in particular DNSSEC_NOT_FOUND
*/
-int kr_nsec_ref_to_unsigned(const knot_pkt_t *pkt);
+int kr_nsec_ref_to_unsigned(const ranked_rr_array_t *rrrs, uint32_t qry_uid,
+ const knot_dname_t *sname);
/**
* Checks whether supplied NSEC RR matches the supplied name and type.