Commit 21b1bf82 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'fix-cname-query-nsec' into 'master'

No CNAME following for NSEC query

See merge request !397
parents 77402c00 340ab89c
...@@ -408,6 +408,7 @@ static int name_found(knot_pkt_t *pkt, struct query_data *qdata) ...@@ -408,6 +408,7 @@ static int name_found(knot_pkt_t *pkt, struct query_data *qdata)
if (node_rrtype_exists(qdata->node, KNOT_RRTYPE_CNAME) if (node_rrtype_exists(qdata->node, KNOT_RRTYPE_CNAME)
&& qtype != KNOT_RRTYPE_CNAME && qtype != KNOT_RRTYPE_CNAME
&& qtype != KNOT_RRTYPE_RRSIG && qtype != KNOT_RRTYPE_RRSIG
&& qtype != KNOT_RRTYPE_NSEC
&& qtype != KNOT_RRTYPE_ANY) { && qtype != KNOT_RRTYPE_ANY) {
dbg_ns("%s: solving CNAME\n", __func__); dbg_ns("%s: solving CNAME\n", __func__);
return follow_cname(pkt, KNOT_RRTYPE_CNAME, qdata); return follow_cname(pkt, KNOT_RRTYPE_CNAME, qdata);
......
$ORIGIN follow.
$TTL 10
@ SOA @ admin 1 10 10 120 10
NS @
A 10.0.0.1
AAAA fd00::a1
DNSKEY 256 3 13 Yg==
test CNAME @
@ NSEC test A NS SOA AAAA RRSIG NSEC DNSKEY
test NSEC @ CNAME RRSIG NSEC
@ RRSIG SOA 13 1 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG A 13 1 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG NS 13 1 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG AAAA 13 1 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG DNSKEY 13 1 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG NSEC 13 1 10 20150810112233 20250810112233 26125 @ YQ==
test RRSIG CNAME 13 2 10 20150810112233 20250810112233 26125 @ YQ==
RRSIG NSEC 13 2 10 20150810112233 20250810112233 26125 @ YQ==
#!/usr/bin/env python3
"""
Basic checks for CNAME following.
- Query for CNAME, NSEC, RRSIG is not followed.
- Query for ANY meta type is not followed.
- Query for any other type is followed.
"""
from dnstest.test import Test
t = Test()
knot = t.server("knot")
zone = t.zone("follow", storage=".")
t.link(zone, knot)
t.start()
# follow CNAME (type exists)
resp = knot.dig("test.follow", "AAAA")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "CNAME")
resp.check_rr("answer", "follow", "AAAA")
resp.check_empty("authority")
# follow CNAME (type doesn't exist)
resp = knot.dig("test.follow", "TXT")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "CNAME")
resp.check_no_rr("answer", "test")
resp.check_rr("authority", "follow", "SOA")
# query for CNAME
resp = knot.dig("test.follow", "CNAME")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "CNAME")
resp.check_no_rr("answer", "test")
resp.check_empty("authority")
# query for RRSIG
resp = knot.dig("test.follow", "RRSIG")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "RRSIG")
resp.check_no_rr("answer", "test")
resp.check_empty("authority")
# query for NSEC
resp = knot.dig("test.follow", "NSEC")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "NSEC")
resp.check_no_rr("answer", "test")
resp.check_empty("authority")
# query for ANY
resp = knot.dig("test.follow", "ANY")
resp.check(rcode="NOERROR", flags="AA")
resp.check_rr("answer", "test.follow", "CNAME")
resp.check_rr("answer", "test.follow", "NSEC")
resp.check_rr("answer", "test.follow", "RRSIG")
resp.check_no_rr("answer", "test")
resp.check_empty("authority")
t.end()
...@@ -56,34 +56,48 @@ class Response(object): ...@@ -56,34 +56,48 @@ class Response(object):
flag_val = dns.flags.edns_from_text(flag) flag_val = dns.flags.edns_from_text(flag)
isset(not(self.resp.ednsflags & flag_val), "NO %s FLAG" % flag) isset(not(self.resp.ednsflags & flag_val), "NO %s FLAG" % flag)
def check_rr(self, section="answer", rname=None, rtype=None): def _check_rr(self, expect, section=None, rname=None, rtype=None):
""" """
Check for a presence of a RR with given name and type. Check for a presence of a RR with given name and type.
""" """
section_rrsets = getattr(self.resp, section) if section is None:
section = "answer"
if rname is not None: if rname is not None:
rname = dns.name.from_text(rname) rname = dns.name.from_text(rname)
if rtype is not None: if rtype is not None:
rtype = dns.rdatatype.from_text(rtype) rtype = dns.rdatatype.from_text(rtype)
assert section in ["answer", "authority", "additional"]
assert rname or rtype assert rname or rtype
section_rrsets = getattr(self.resp, section)
for rrset in section_rrsets: for rrset in section_rrsets:
if rname is not None and rname != rrset.name: if rname is not None and rname != rrset.name:
continue continue
if rtype is not None and rtype != rrset.rdtype: if rtype is not None and rtype != rrset.rdtype:
continue continue
found = True
break break
else: else:
found = False
if found != expect:
set_err("CHECK RR PRESENCE") set_err("CHECK RR PRESENCE")
check_log("ERROR: CHECK RR PRESENCE") check_log("ERROR: CHECK RR PRESENCE")
detail_log("!Missing RR name=%s type=%s section=%s" % ( detail_log("!%s RR name=%s type=%s section=%s" % (
"Missing" if expect else "Extra",
str(rname) if rname is not None else "", str(rname) if rname is not None else "",
dns.rdatatype.to_text(rtype) if rtype is not None else "", dns.rdatatype.to_text(rtype) if rtype is not None else "",
section section
)) ))
detail_log(SEP) detail_log(SEP)
def check_rr(self, section=None, rname=None, rtype=None):
self._check_rr(True, section, rname, rtype)
def check_no_rr(self, section=None, rname=None, rtype=None):
self._check_rr(False, section, rname, rtype)
def check_record(self, section="answer", rtype=None, ttl=None, rdata=None, def check_record(self, section="answer", rtype=None, ttl=None, rdata=None,
nordata=None): nordata=None):
'''Checks given section for particular record/rdata''' '''Checks given section for particular record/rdata'''
......
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