From: Vladimír Čunát Date: Wed, 8 Jul 2026 13:25:10 +0000 (+0200) Subject: restrict RRSIGs claiming wildcard reach out of the zone [QZKF-005] X-Git-Tag: v5.7.7^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a7ee59ebee2a3dab6f5c1104b4c7c9c11095fd3f;p=thirdparty%2Fknot-resolver.git restrict RRSIGs claiming wildcard reach out of the zone [QZKF-005] This issue was reported by Qifan Zhang from Palo Alto Networks. Nit: this assignments of `ret` aren't important, but they might be a bit useful when debugging. (cherry picked from commit 29b55ceb426efaafcc955181637072a36a99486e) --- diff --git a/lib/cache/api.c b/lib/cache/api.c index 73279039b..ddcf9f466 100644 --- a/lib/cache/api.c +++ b/lib/cache/api.c @@ -509,17 +509,39 @@ static ssize_t stash_rrset(struct kr_cache *cache, const struct kr_query *qry, return kr_error(EINVAL); int ret = kr_ok(); - if (rrset_has_min_range_or_weird(rr, qry)) + if (rrset_has_min_range_or_weird(rr, qry)) { + ret = kr_error(ERANGE); goto return_needs_pkt; + } + const int wild_labels = rr_sigs == NULL ? 0 : knot_dname_labels(rr->owner, NULL) - knot_rrsig_labels(rr_sigs->rrs.rdata); - if (wild_labels < 0) + if (wild_labels < 0) { + ret = kr_error(ERANGE); goto return_needs_pkt; + } const knot_dname_t *encloser = rr->owner; /**< the closest encloser name */ for (int i = 0; i < wild_labels; ++i) { encloser = knot_dname_next_label(encloser); } + /* Sanity-check that encloser didn't get too short, + * in particular not outside the zone which signed it. + * As we don't know which RRSIG succeeded, we take the maximum to be safe. */ + if (rr_sigs && wild_labels) { + int signer_labels = 0; + const int count = rr_sigs->rrs.count; + knot_rdata_t *rd = rr_sigs->rrs.rdata; + for (int i = 0; i < count; ++i, rd = knot_rdataset_next(rd)) { + int l = knot_dname_labels(knot_rrsig_signer_name(rd), NULL); + signer_labels = MAX(signer_labels, l); + } + if (knot_dname_labels(encloser, NULL) < signer_labels) { + ret = kr_error(ERANGE); + goto return_needs_pkt; + } + } + /* Construct the key under which RRs will be stored, * and add corresponding nsec_pmap item (if necessary). */ struct key k_storage, *k = &k_storage; diff --git a/lib/dnssec.c b/lib/dnssec.c index cad1e47eb..4be6db61d 100644 --- a/lib/dnssec.c +++ b/lib/dnssec.c @@ -84,6 +84,11 @@ static int validate_rrsig_rr(int *flags, int cov_labels, if (rrsig_labels < cov_labels) { *flags |= FLG_WILDCARD_EXPANSION; } + /* Also refuse if RRSIG claims rrsig_labels outside the zone. */ + if (rrsig_labels < knot_dname_labels(signer_name, NULL)) { + vctx->rrs_counters.labels_invalid++; + return kr_error(EINVAL); + } } /* bullet 7