Commit 62001974 authored by Marek Vavruša's avatar Marek Vavruša

iterator+rrcache: do not follow CNAME chains (if not DNSSEC-secured)

[1] shows an attack using spoofed CNAME targets to replace legitimate
entries in resolver cache by speeding up once-per-TTL attack opportunity

as a defense, the resolver almost always requeries CNAME targets and
doesn't store them in cache. the only exception is when the CNAME target
is within current authority, and the answer is DNSSEC-secured

thanks to Toshinori Maeno (@beyondDNS) for pointing this out [2]

[1]: https://tools.ietf.org/id/draft-weaver-dnsext-comprehensive-
resolver-00.html
[2]: https://moin.qmail.jp/DNS/KnotResolver/CNAMEpatch
parent b0e223c6
......@@ -363,10 +363,10 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req)
if (state == KNOT_STATE_FAIL) {
return state;
}
/* Follow chain only within current cut. */
/* Follow chain only within current cut (if secure). */
if (follow_chain) {
follow_cname_chain(&cname, rr, query);
if (!knot_dname_in(query->zone_cut.name, cname)) {
if (!(query->flags & QUERY_DNSSEC_WANT) || !knot_dname_in(query->zone_cut.name, cname)) {
follow_chain = false;
}
}
......
......@@ -260,8 +260,8 @@ static int stash_answer(struct kr_query *qry, knot_pkt_t *pkt, map_t *stash, mm_
continue;
}
kr_rrmap_add(stash, rr, KR_RANK_AUTH, pool);
/* Follow CNAME chain in current cut. */
if (rr->type == KNOT_RRTYPE_CNAME) {
/* Follow CNAME chain in current cut (if SECURE). */
if ((qry->flags & QUERY_DNSSEC_WANT) && rr->type == KNOT_RRTYPE_CNAME) {
const knot_dname_t *next_cname = knot_cname_name(&rr->rrs);
if (knot_dname_in(qry->zone_cut.name, next_cname)) {
cname = next_cname;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment