From 243797a3871a912f14c5d719157708e35179fc7f Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Sun, 6 Nov 2016 08:32:07 +0000 Subject: [PATCH] middleware/file: add nsec for wildcard expansion (#382) A NSEC record is need to deny any other name that might exist. Also don't blindly perform the interface conversion when getting glue for NS records as they now may include RRSIG - also add tests for that. --- middleware/file/closest.go | 2 +- middleware/file/dnssec_test.go | 11 +++++++++++ middleware/file/lookup.go | 23 ++++++++++++++--------- middleware/file/wildcard_test.go | 8 ++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/middleware/file/closest.go b/middleware/file/closest.go index 2ee14e6d8..172242669 100644 --- a/middleware/file/closest.go +++ b/middleware/file/closest.go @@ -6,7 +6,7 @@ import ( "github.com/miekg/dns" ) -// ClosestEncloser returns the closest encloser for rr. +// ClosestEncloser returns the closest encloser for qname. func (z *Zone) ClosestEncloser(qname string) (*tree.Elem, bool) { offset, end := dns.NextLabel(qname, 0) diff --git a/middleware/file/dnssec_test.go b/middleware/file/dnssec_test.go index 63099afb4..7f4a0916b 100644 --- a/middleware/file/dnssec_test.go +++ b/middleware/file/dnssec_test.go @@ -29,6 +29,17 @@ var dnssecTestCases = []test.Case{ }, Extra: []dns.RR{test.OPT(4096, true)}, }, + { + Qname: "miek.nl.", Qtype: dns.TypeNS, Do: true, + Answer: []dns.RR{ + test.NS("miek.nl. 1800 IN NS ext.ns.whyscream.net."), + test.NS("miek.nl. 1800 IN NS linode.atoom.net."), + test.NS("miek.nl. 1800 IN NS ns-ext.nlnetlabs.nl."), + test.NS("miek.nl. 1800 IN NS omval.tednet.nl."), + test.RRSIG("miek.nl. 1800 IN RRSIG NS 8 2 1800 20160426031301 20160327031301 12051 miek.nl. ZLtsQhwaz+lHfNpztFoR1Vxs="), + }, + Extra: []dns.RR{test.OPT(4096, true)}, + }, { Qname: "miek.nl.", Qtype: dns.TypeMX, Do: true, Answer: []dns.RR{ diff --git a/middleware/file/lookup.go b/middleware/file/lookup.go index 16325d3e9..95cd02e73 100644 --- a/middleware/file/lookup.go +++ b/middleware/file/lookup.go @@ -146,7 +146,9 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, // Haven't found the original name. + // Found wildcard. if wildElem != nil { + auth := []dns.RR{} if rrs := wildElem.Types(dns.TypeCNAME, qname); len(rrs) > 0 { return z.searchCNAME(rrs, qtype, do) @@ -154,26 +156,29 @@ func (z *Zone) Lookup(qname string, qtype uint16, do bool) ([]dns.RR, []dns.RR, rrs := wildElem.Types(qtype, qname) - // NODATA + // NODATA response. if len(rrs) == 0 { ret := z.soa(do) if do { - // Do we need to add closest encloser here as well. - // closest encloser - // ce, _ := z.ClosestEncloser(qname) - // println("CLOSEST ENCLOSER", ce.Name()) // need to add this too. nsec := z.typeFromElem(wildElem, dns.TypeNSEC, do) ret = append(ret, nsec...) } return nil, ret, nil, Success } + if do { + // An NSEC is needed to say no longer name exists under this wildcard. + if deny, found := z.Tree.Prev(qname); found { + nsec := z.typeFromElem(deny, dns.TypeNSEC, do) + auth = append(auth, nsec...) + } + sigs := wildElem.Types(dns.TypeRRSIG, qname) sigs = signatureForSubType(sigs, qtype) rrs = append(rrs, sigs...) } - return rrs, nil, nil, Success + return rrs, auth, nil, Success } rcode := NameError @@ -289,9 +294,9 @@ func signatureForSubType(rrs []dns.RR, subtype uint16) []dns.RR { // Glue returns any potential glue records for nsrrs. func (z *Zone) Glue(nsrrs []dns.RR) []dns.RR { glue := []dns.RR{} - for _, ns := range nsrrs { - if dns.IsSubDomain(ns.Header().Name, ns.(*dns.NS).Ns) { - glue = append(glue, z.searchGlue(ns.(*dns.NS).Ns)...) + for _, rr := range nsrrs { + if ns, ok := rr.(*dns.NS); ok && dns.IsSubDomain(ns.Header().Name, ns.Ns) { + glue = append(glue, z.searchGlue(ns.Ns)...) } } return glue diff --git a/middleware/file/wildcard_test.go b/middleware/file/wildcard_test.go index b3bd5915b..4acc21bde 100644 --- a/middleware/file/wildcard_test.go +++ b/middleware/file/wildcard_test.go @@ -31,6 +31,10 @@ var wildcardTestCases = []test.Case{ test.RRSIG("wild.dnssex.nl. 1800 IN RRSIG TXT 8 2 1800 20160428190224 20160329190224 14460 dnssex.nl. FUZSTyvZfeuuOpCm"), test.TXT(`wild.dnssex.nl. 1800 IN TXT "Doing It Safe Is Better"`), }, + Ns: []dns.RR{ + test.NSEC("a.dnssex.nl. 14400 IN NSEC www.dnssex.nl. A AAAA RRSIG NSEC"), + test.RRSIG("a.dnssex.nl. 14400 IN RRSIG NSEC 8 3 14400 20160428190224 20160329190224 14460 dnssex.nl. S+UMs2ySgRaaRY"), + }, Extra: []dns.RR{test.OPT(4096, true)}, }, { @@ -39,6 +43,10 @@ var wildcardTestCases = []test.Case{ test.RRSIG("a.wild.dnssex.nl. 1800 IN RRSIG TXT 8 2 1800 20160428190224 20160329190224 14460 dnssex.nl. FUZSTyvZfeuuOpCm"), test.TXT(`a.wild.dnssex.nl. 1800 IN TXT "Doing It Safe Is Better"`), }, + Ns: []dns.RR{ + test.NSEC("a.dnssex.nl. 14400 IN NSEC www.dnssex.nl. A AAAA RRSIG NSEC"), + test.RRSIG("a.dnssex.nl. 14400 IN RRSIG NSEC 8 3 14400 20160428190224 20160329190224 14460 dnssex.nl. S+UMs2ySgRaaRY"), + }, Extra: []dns.RR{test.OPT(4096, true)}, }, // nodata responses