diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index fd42f81f5736cf1774c70d445b53f74c1770a188..1b9a702c93e0a7b944194697649fef172f4fe91e 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -382,15 +382,13 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral, uint8_t rank = !(query->flags & QUERY_DNSSEC_WANT) || (query->flags & QUERY_CACHED) ? KR_VLDRANK_SECURE : KR_VLDRANK_INITIAL; bool is_final = (query->parent == NULL); - bool can_follow = false; + uint32_t iter_count = 0; bool strict_mode = (query->flags & QUERY_STRICT); do { /* CNAME was found at previous iteration, but records may not follow the correct order. * Try to find records for pending_cname owner from section start. */ cname = pending_cname; pending_cname = NULL; - /* If not secure, always follow cname chain. */ - can_follow = !(query->flags & QUERY_DNSSEC_WANT); for (unsigned i = 0; i < an->count; ++i) { const knot_rrset_t *rr = knot_pkt_rr(an, i); @@ -422,12 +420,6 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral, if (state != kr_ok()) { return KR_STATE_FAIL; } - /* can_follow is false, therefore QUERY_DNSSEC_WANT flag is set. - * Follow cname chain only if rrsig exists. */ - if (!can_follow && rr->type == KNOT_RRTYPE_RRSIG && - is_rrsig_type_covered(rr, KNOT_RRTYPE_CNAME)) { - can_follow = true; - } /* Jump to next CNAME target */ if ((query->stype == KNOT_RRTYPE_CNAME) || (rr->type != KNOT_RRTYPE_CNAME)) { continue; @@ -468,7 +460,11 @@ static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral, cname = pending_cname; break; } - } while (can_follow); + } while (++iter_count < KR_CNAME_CHAIN_LIMIT); + if (iter_count >= KR_CNAME_CHAIN_LIMIT) { + VERBOSE_MSG("<= too long cname chain\n"); + return KR_STATE_FAIL; + } *cname_ret = cname; return kr_ok(); }