Skip to content

Commit 156a47c

Browse files
committed
Merge !1659: validator: accept a confusing NODATA proof with insecure delegation
2 parents 7345b2e + 91ca292 commit 156a47c

File tree

6 files changed

+33
-11
lines changed

6 files changed

+33
-11
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Improvements
1313
- manager: allow multiple instances with different rundirs (!1656)
1414
- tests: disable problematic config.http test (#925, !1662)
1515
- /management/unix-socket: allow path relative to rundir (!1657)
16+
- validator: accept a confusing NODATA proof with insecure delegation (!1659)
1617

1718

1819
Knot Resolver 6.0.10 (2025-01-20)

lib/dnssec/nsec.c

+14-5
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,16 @@ int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t ty
161161
break;
162162
default:
163163
/* Parent-side delegation record isn't authoritative for non-DS;
164-
* see RFC6840 4.1. */
164+
* see RFC6840 4.1.
165+
*
166+
* Additionally, we signal if the NODATA would belong
167+
* to an *insecure* child zone.
168+
*/
165169
if (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS)
166170
&& !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)) {
167-
return NO_PROOF;
171+
return dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_DS)
172+
? NO_PROOF
173+
: KNOT_EDOWNGRADED;
168174
}
169175
/* LATER(opt): perhaps short-circuit test if we repeat it here. */
170176
}
@@ -218,9 +224,12 @@ int kr_nsec_negative(const ranked_rr_array_t *rrrs, uint32_t qry_uid,
218224
&& kr_rank_test(rrrs->at[i]->rank, KR_RANK_SECURE);
219225
if (!ok) continue;
220226
const int covers = nsec_covers(nsec, sname);
221-
if (covers == abs(EEXIST)
222-
&& no_data_response_check_rrtype(nsec, stype) == 0) {
223-
return PKT_NODATA; // proven NODATA by matching NSEC
227+
if (covers == abs(EEXIST)) {
228+
int ret = no_data_response_check_rrtype(nsec, stype);
229+
if (ret == 0)
230+
return PKT_NODATA; // proven NODATA by matching NSEC
231+
if (ret == KNOT_EDOWNGRADED)
232+
return ret;
224233
}
225234
if (covers != 0) continue;
226235

lib/dnssec/nsec.h

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "lib/layer/iterate.h"
1010

11+
#define KNOT_EDOWNGRADED (KNOT_ERROR_MIN - 1)
12+
1113
/**
1214
* Check bitmap that child names are contained in the same zone.
1315
* @note see RFC6840 4.1.
@@ -25,6 +27,7 @@ int kr_nsec_children_in_zone_check(const uint8_t *bm, uint16_t bm_size);
2527
* @param owner NSEC record owner.
2628
* @note This includes special checks for zone cuts, e.g. from RFC 6840 sec. 4.
2729
* @return 0, abs(ENOENT) (no proof), kr_error(EINVAL)
30+
* KNOT_EDOWNGRADED: special case where the RR would be in an insecure child zone.
2831
*/
2932
int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t type, const knot_dname_t *owner);
3033

@@ -44,6 +47,7 @@ int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t
4447
* @param rrrs list of RRs to search; typically kr_request::auth_selected
4548
* @param qry_uid only consider NSECs from this packet, for better efficiency
4649
* @return negative error code, or PKT_NXDOMAIN | PKT_NODATA (both for NXDOMAIN)
50+
* KNOT_EDOWNGRADED: special case where the RR would be in an insecure child zone.
4751
*/
4852
int kr_nsec_negative(const ranked_rr_array_t *rrrs, uint32_t qry_uid,
4953
const knot_dname_t *sname, uint16_t stype);

lib/dnssec/nsec3.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ int kr_nsec3_name_error_response_check(const knot_pkt_t *pkt, knot_section_t sec
507507
* @param sname Name to be checked.
508508
* @param stype Type to be checked.
509509
* @return 0 or error code.
510+
* KNOT_EDOWNGRADED: special case where the RR would be in an insecure child zone.
510511
* @note This does NOT check the opt-out case if type is DS;
511512
* see RFC 5155 8.6.
512513
*/
@@ -528,8 +529,9 @@ static int nodata_find(const knot_pkt_t *pkt, knot_section_t section_id,
528529

529530
const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata);
530531
uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata);
531-
if (kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec3->owner) == kr_ok())
532-
return kr_ok();
532+
int ret = kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec3->owner);
533+
if (ret == kr_ok() || ret == KNOT_EDOWNGRADED)
534+
return ret;
533535
}
534536

535537
return kr_error(ENOENT);
@@ -602,8 +604,8 @@ int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
602604
{
603605
/* DS record may be also matched by an existing NSEC3 RR. */
604606
int ret = nodata_find(pkt, section_id, sname, stype);
605-
if (ret == 0) {
606-
/* Satisfies RFC5155 8.5 and 8.6, both first paragraph. */
607+
if (ret == 0 || ret == KNOT_EDOWNGRADED) {
608+
/* If 0, satisfies RFC5155 8.5 and 8.6, both first paragraph. */
607609
return ret;
608610
}
609611

lib/dnssec/nsec3.h

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_
8787
* @return 0 or error code:
8888
* DNSSEC_NOT_FOUND - neither ds nor nsec records
8989
* were not found.
90+
* KNOT_EDOWNGRADED - special case where
91+
* the RR would be in an insecure child zone.
9092
* KNOT_ERANGE - denial of existence can't be proven
9193
* due to opt-out, otherwise - bogus.
9294
*/

lib/layer/validate.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ static bool maybe_downgrade_nsec3(const ranked_rr_array_entry_t *e, struct kr_qu
146146
return true;
147147
}
148148

149-
#define KNOT_EDOWNGRADED (KNOT_ERROR_MIN - 1)
150-
151149
static int validate_section(kr_rrset_validation_ctx_t *vctx, struct kr_query *qry,
152150
knot_mm_t *pool)
153151
{
@@ -1323,6 +1321,12 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
13231321
* we must continue, validate NSEC\NSEC3 and
13241322
* call update_parent_keys() to mark
13251323
* parent queries as insecure */
1324+
} else if (ret == KNOT_EDOWNGRADED) { // either NSEC3 or NSEC
1325+
VERBOSE_MSG(qry, "<= DNSSEC downgraded by a weird proof confusing NODATA with insecure delegation\n");
1326+
qry->flags.DNSSEC_WANT = false;
1327+
qry->flags.DNSSEC_INSECURE = true;
1328+
rank_records(qry, true, KR_RANK_INSECURE, qry->sname);
1329+
mark_insecure_parents(qry);
13261330
} else {
13271331
VERBOSE_MSG(qry, "<= bad NODATA proof\n");
13281332
kr_request_set_extended_error(req, KNOT_EDNS_EDE_NSEC_MISS, "AHXI");

0 commit comments

Comments
 (0)