diff options
-rw-r--r-- | middleware/file/closest.go | 42 | ||||
-rw-r--r-- | middleware/file/dnssec_test.go | 27 | ||||
-rw-r--r-- | middleware/file/lookup.go | 3 |
3 files changed, 70 insertions, 2 deletions
diff --git a/middleware/file/closest.go b/middleware/file/closest.go index 8f9d9a8ba..0c5fd722d 100644 --- a/middleware/file/closest.go +++ b/middleware/file/closest.go @@ -20,3 +20,45 @@ func (z *Zone) ClosestEncloser(rr dns.RR) string { return z.SOA.Header().Name } + +// nameErrorProof finds the closest encloser and return an NSEC that proofs +// the wildcard does not exist and an NSEC that proofs the name does no exist. +func (z *Zone) nameErrorProof(rr dns.RR) []dns.RR { + elem := z.Tree.Prev(rr) + if elem == nil { + return nil + } + nsec := z.lookupNSEC(elem, true) + nsecIndex := 0 + for i := 0; i < len(nsec); i++ { + if nsec[i].Header().Rrtype == dns.TypeNSEC { + nsecIndex = i + break + } + } + + ce := z.ClosestEncloser(rr) + wildcard := "*." + ce + rr.Header().Name = wildcard + elem = z.Tree.Prev(rr) + if elem == nil { + // Root? + return nil + } + nsec1 := z.lookupNSEC(elem, true) + nsec1Index := 0 + for i := 0; i < len(nsec1); i++ { + if nsec1[i].Header().Rrtype == dns.TypeNSEC { + nsec1Index = i + break + } + } + + // Check for duplicate NSEC. + if nsec[nsecIndex].Header().Name == nsec1[nsec1Index].Header().Name && + nsec[nsecIndex].(*dns.NSEC).NextDomain == nsec1[nsec1Index].(*dns.NSEC).NextDomain { + return nsec + } + + return append(nsec, nsec1...) +} diff --git a/middleware/file/dnssec_test.go b/middleware/file/dnssec_test.go index ed8b6a607..dc19235da 100644 --- a/middleware/file/dnssec_test.go +++ b/middleware/file/dnssec_test.go @@ -64,6 +64,33 @@ var dnssecTestCases = []coretest.Case{ Qname: "b.miek.nl.", Qtype: dns.TypeA, Do: true, Rcode: dns.RcodeNameError, Ns: []dns.RR{ + coretest.NSEC("archive.miek.nl. 14400 IN NSEC go.dns.miek.nl. CNAME RRSIG NSEC"), + coretest.RRSIG("archive.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. jEpx8lcp4do5fWXg="), + coretest.NSEC("miek.nl. 14400 IN NSEC a.miek.nl. A NS SOA MX AAAA RRSIG NSEC DNSKEY"), + coretest.RRSIG("miek.nl. 14400 IN RRSIG NSEC 8 2 14400 20160426031301 20160327031301 12051 miek.nl. mFfc3r/9PSC1H6oSpdC"), + coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), + coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), + }, + }, + { + Qname: "b.blaat.miek.nl.", Qtype: dns.TypeA, Do: true, + Rcode: dns.RcodeNameError, + Ns: []dns.RR{ + coretest.NSEC("archive.miek.nl. 14400 IN NSEC go.dns.miek.nl. CNAME RRSIG NSEC"), + coretest.RRSIG("archive.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. jEpx8lcp4do5fWXg="), + coretest.NSEC("miek.nl. 14400 IN NSEC a.miek.nl. A NS SOA MX AAAA RRSIG NSEC DNSKEY"), + coretest.RRSIG("miek.nl. 14400 IN RRSIG NSEC 8 2 14400 20160426031301 20160327031301 12051 miek.nl. mFfc3r/9PSC1H6oSpdC"), + coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), + coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), + }, + }, + { + Qname: "b.a.miek.nl.", Qtype: dns.TypeA, Do: true, + Rcode: dns.RcodeNameError, + Ns: []dns.RR{ + // dedupped NSEC, because 1 nsec tells all + coretest.NSEC("a.miek.nl. 14400 IN NSEC archive.miek.nl. A AAAA RRSIG NSEC"), + coretest.RRSIG("a.miek.nl. 14400 IN RRSIG NSEC 8 3 14400 20160426031301 20160327031301 12051 miek.nl. GqnF6cut/RRGPQ1QGQE1ipmSHEao="), coretest.RRSIG("miek.nl. 1800 IN RRSIG SOA 8 2 1800 20160426031301 20160327031301 12051 miek.nl. FIrzy07acBbtyQczy1dc="), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), }, diff --git a/middleware/file/lookup.go b/middleware/file/lookup.go index 10f308cf1..7c4d92abe 100644 --- a/middleware/file/lookup.go +++ b/middleware/file/lookup.go @@ -72,8 +72,7 @@ func (z *Zone) nameError(elem *tree.Elem, rr dns.RR, do bool) ([]dns.RR, []dns.R ret := []dns.RR{z.SOA} if do { ret = append(ret, z.SIG...) - // Now we need two NSEC, one to deny the wildcard and one to deny the name. - // Needs closest encloser!! + ret = append(ret, z.nameErrorProof(rr)...) } return nil, ret, nil, NameError } |