mirror of
https://github.com/coredns/coredns.git
synced 2026-10-09 12:05:22 -04:00
A CNAME whose target is its own owner name is chased by externalLookup until the depth cap, appending the same record on every pass. The reply was NOERROR with the CNAME repeated ten times. Self-referential DNAME already returns SERVFAIL, as do wildcard CNAME loops. Return SERVFAIL here too. The check runs on the CNAME chase path only, so normal responses are unaffected. Fixes #6421 Signed-off-by: baltasarblanco <baltablanco9008@gmail.com>
83 lines
2.6 KiB
Go
83 lines
2.6 KiB
Go
package test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/coredns/coredns/plugin/test"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
const loopDB = `example.com. 500 IN SOA ns1.outside.com. root.example.com. 3 604800 86400 2419200 604800
|
|
example.com. 500 IN NS ns1.outside.com.
|
|
a.example.com. 500 IN CNAME b.example.com.
|
|
alias.example.com. 500 IN DNAME alias.example.com.
|
|
redirect.example.com. 500 IN DNAME target.example.com.
|
|
www.target.example.com. 500 IN A 192.0.2.1
|
|
*.foo.example.com. 500 IN CNAME bar.foo.example.com.
|
|
self.example.com. 500 IN CNAME self.example.com.
|
|
c.example.com. 500 IN CNAME d.example.com.
|
|
d.example.com. 500 IN CNAME d.example.com.`
|
|
|
|
func TestFileLoop(t *testing.T) {
|
|
name, rm, err := test.TempFile(".", loopDB)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create zone: %s", err)
|
|
}
|
|
defer rm()
|
|
|
|
// Corefile with for example without proxy section.
|
|
corefile := `example.com:0 {
|
|
file ` + name + `
|
|
}`
|
|
|
|
i, udp, _, err := CoreDNSServerAndPorts(corefile)
|
|
if err != nil {
|
|
t.Fatalf("Could not get CoreDNS serving instance: %s", err)
|
|
}
|
|
defer i.Stop()
|
|
|
|
tests := []struct {
|
|
name string
|
|
qname string
|
|
wantRcode int
|
|
checkAnswer bool
|
|
wantAnswerTypes []uint16
|
|
}{
|
|
{"wildcard CNAME", "something.foo.example.com.", dns.RcodeServerFailure, false, nil},
|
|
{"self-referential DNAME", "www.alias.example.com.", dns.RcodeServerFailure, true, nil},
|
|
{"self-referential CNAME", "self.example.com.", dns.RcodeServerFailure, true, nil},
|
|
{"CNAME chain into self-referential CNAME", "c.example.com.", dns.RcodeServerFailure, true, nil},
|
|
{"non-looping DNAME", "www.redirect.example.com.", dns.RcodeSuccess, true, []uint16{dns.TypeDNAME, dns.TypeCNAME, dns.TypeA}},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
m := new(dns.Msg)
|
|
m.SetQuestion(tc.qname, dns.TypeA)
|
|
|
|
r, err := dns.Exchange(m, udp)
|
|
if err != nil {
|
|
t.Fatalf("Could not exchange msg: %s", err)
|
|
}
|
|
|
|
if r.Rcode != tc.wantRcode {
|
|
t.Errorf("Rcode should be %d, got %d", tc.wantRcode, r.Rcode)
|
|
}
|
|
if !tc.checkAnswer {
|
|
return
|
|
}
|
|
if len(r.Answer) != len(tc.wantAnswerTypes) {
|
|
t.Fatalf("Expected %d answer records, got %d", len(tc.wantAnswerTypes), len(r.Answer))
|
|
}
|
|
for i, qtype := range tc.wantAnswerTypes {
|
|
if r.Answer[i].Header().Rrtype != qtype {
|
|
t.Errorf("Answer %d should have type %s, got %s", i, dns.TypeToString[qtype], dns.TypeToString[r.Answer[i].Header().Rrtype])
|
|
}
|
|
}
|
|
if len(tc.wantAnswerTypes) == 0 && (len(r.Ns) != 0 || len(r.Extra) != 0) {
|
|
t.Errorf("Response sections should be empty, got %d answer, %d authority, and %d additional records", len(r.Answer), len(r.Ns), len(r.Extra))
|
|
}
|
|
})
|
|
}
|
|
}
|