Просмотр исходного кода

fix: guard QueryCert against panic on short/empty QNAME (#1635)

* fix: guard QueryCert against panic on short/empty QNAME

QueryCert slices data[:len(data)-1] to strip a trailing dot, which
panics when data is empty (slice bounds [:-1]). Add a length check
to return early for inputs shorter than a minimal valid "x." form.

While miekg/dns currently rejects wire-format packets that would
produce an empty QNAME, the Nebula code should not rely on library
behavior for crash safety.

Made-with: Cursor

* fix merge conflicts

---------

Co-authored-by: JackDoan <me@jackdoan.com>
Guy Nesher 6 месяцев назад
Родитель
Сommit
2a1cc62001
2 измененных файлов с 29 добавлено и 0 удалено
  1. 3 0
      dns_server.go
  2. 26 0
      dns_server_test.go

+ 3 - 0
dns_server.go

@@ -241,6 +241,9 @@ func (d *dnsServer) Query(q uint16, data string) (netip.Addr, bool) {
 }
 }
 
 
 func (d *dnsServer) QueryCert(data string) string {
 func (d *dnsServer) QueryCert(data string) string {
+	if len(data) < 2 {
+		return ""
+	}
 	ip, err := netip.ParseAddr(data[:len(data)-1])
 	ip, err := netip.ParseAddr(data[:len(data)-1])
 	if err != nil {
 	if err != nil {
 		return ""
 		return ""

+ 26 - 0
dns_server_test.go

@@ -16,6 +16,19 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/require"
 )
 )
 
 
+type stubDNSWriter struct{}
+
+func (stubDNSWriter) LocalAddr() net.Addr { return &net.UDPAddr{} }
+func (stubDNSWriter) RemoteAddr() net.Addr {
+	return &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 5353}
+}
+func (stubDNSWriter) Write([]byte) (int, error) { return 0, nil }
+func (stubDNSWriter) WriteMsg(*dns.Msg) error   { return nil }
+func (stubDNSWriter) Close() error              { return nil }
+func (stubDNSWriter) TsigStatus() error         { return nil }
+func (stubDNSWriter) TsigTimersOnly(bool)       {}
+func (stubDNSWriter) Hijack()                   {}
+
 func TestParsequery(t *testing.T) {
 func TestParsequery(t *testing.T) {
 	l := logrus.New()
 	l := logrus.New()
 	hostMap := &HostMap{}
 	hostMap := &HostMap{}
@@ -70,6 +83,19 @@ func TestParsequery(t *testing.T) {
 	ds.parseQuery(m, nil)
 	ds.parseQuery(m, nil)
 	assert.Empty(t, m.Answer)
 	assert.Empty(t, m.Answer)
 	assert.Equal(t, dns.RcodeNameError, m.Rcode)
 	assert.Equal(t, dns.RcodeNameError, m.Rcode)
+
+	// short lookups should not fail
+	m = &dns.Msg{}
+	m.Question = []dns.Question{{Name: "", Qtype: dns.TypeTXT, Qclass: dns.ClassINET}}
+	ds.parseQuery(m, stubDNSWriter{})
+	assert.Empty(t, m.Answer)
+	assert.Equal(t, dns.RcodeNameError, m.Rcode)
+
+	m = &dns.Msg{}
+	m.Question = []dns.Question{{Name: ".", Qtype: dns.TypeTXT, Qclass: dns.ClassINET}}
+	ds.parseQuery(m, stubDNSWriter{})
+	assert.Empty(t, m.Answer)
+	assert.Equal(t, dns.RcodeNameError, m.Rcode)
 }
 }
 
 
 func Test_getDnsServerAddr(t *testing.T) {
 func Test_getDnsServerAddr(t *testing.T) {