diff --git a/nsecx.go b/nsecx.go index 5a6d1b39..3f5f0548 100644 --- a/nsecx.go +++ b/nsecx.go @@ -128,17 +128,53 @@ func Proof(nsecx []RR, qname string, qtype uint16) error { nsec++ } } - if nsec3 == len(nsecx)-1 { + if nsec3 == len(nsecx) { return proofNSEC3(nsecx, qname, qtype) } - if nsec == len(nsecx)-1 { + if nsec == len(nsecx) { return proofNSEC(nsecx, qname, qtype) } return ErrSig // ErrNotRRset? } // NSEC3 Helper -func proofNSEC3(nsecx []RR, qname string, qtype uint16) error { return nil } +func proofNSEC3(nsec3 []RR, qname string, qtype uint16) error { + indx := Split(qname) + ce := "" // Closest Encloser + nc := "" // Next Closer + wc := "" // Source of Synthesis (wildcard) +ClosestEncloser: + for i := 0; i < len(indx); i++ { + for j := 0; j < len(nsec3); j++ { + if nsec3[j].(*NSEC3).Match(qname[indx[i]:]) { + ce = qname[indx[i]:] + wc = "*." + ce + if i == 0 { + nc = qname + } else { + nc = qname[indx[i-1]:] + } + break ClosestEncloser + } + } + } + if ce == "" { + return ErrSig // ErrNoMatchingNSEC3 + } + covered := 0 // Both nc and wc must be covered + for i := 0; i < len(nsec3); i++ { + if nsec3[i].(*NSEC3).Cover(nc) { + covered++ + } + if nsec3[i].(*NSEC3).Cover(wc) { + covered++ + } + } + if covered != 2 { + return ErrSig + } + return nil +} // NSEC Helper func proofNSEC(nsecx []RR, qname string, qtype uint16) error { return nil } diff --git a/nsecx_test.go b/nsecx_test.go index ee1c5ff1..611e6628 100644 --- a/nsecx_test.go +++ b/nsecx_test.go @@ -35,3 +35,32 @@ func TestNsec3(t *testing.T) { t.Fail() } } + +func newNSEC3(rr string) *NSEC3 { + rr1, _ := NewRR(rr) + return rr1.(*NSEC3) +} + +func TestNsec3Proof(t *testing.T) { + // denies existence of 'snasajsksasasa.nl. A' + nsec3 := []RR{ + newNSEC3("sk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM"), + newNSEC3("39p91242oslggest5e6a7cci4iaeqvnk.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6 NS DS RRSIG"), + newNSEC3("t98kg1p1cjtdoc4ksb7g57jc9vulltcd.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 T98MULSKU3E499AGCTTRJK6H0L3E5T92 NS DS RRSIG")} + + err := Proof(nsec3, "snasajsksasasa.nl.", TypeA) + if err != nil { + t.Logf("Failed to validate NSEC3") + t.Fail() + } + nsec3 = []RR{ // closest encloser can not be found + newNSEC3("bk4e8fj94u78smusb40o1n0oltbblu2r.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 SK4F38CQ0ATIEI8MH3RGD0P5I4II6QAN NS SOA TXT RRSIG DNSKEY NSEC3PARAM"), + newNSEC3("39p91242oslggest5e6a7cci4iaeqvnk.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 39P99DCGG0MDLARTCRMCF6OFLLUL7PR6 NS DS RRSIG"), + newNSEC3("t98kg1p1cjtdoc4ksb7g57jc9vulltcd.nl. IN NSEC3 1 1 5 F10E9F7EA83FC8F3 T98MULSKU3E499AGCTTRJK6H0L3E5T92 NS DS RRSIG")} + + err = Proof(nsec3, "snasajsksasasa.nl.", TypeA) + if err == nil { + t.Logf("Should fail validate NSEC3") + t.Fail() + } +}