diff options
Diffstat (limited to 'main/gdnsd/0001-Fix-auth-section-of-ANY-query-on-CNAME.patch')
-rw-r--r-- | main/gdnsd/0001-Fix-auth-section-of-ANY-query-on-CNAME.patch | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/main/gdnsd/0001-Fix-auth-section-of-ANY-query-on-CNAME.patch b/main/gdnsd/0001-Fix-auth-section-of-ANY-query-on-CNAME.patch new file mode 100644 index 0000000000..fb703b352d --- /dev/null +++ b/main/gdnsd/0001-Fix-auth-section-of-ANY-query-on-CNAME.patch @@ -0,0 +1,265 @@ +From 22b0dcf8a19aaeb1e6f32ad9f0aad95ab26b8a61 Mon Sep 17 00:00:00 2001 +From: Brandon Black <blblack@gmail.com> +Date: Thu, 11 Jul 2013 14:37:57 -0500 +Subject: [PATCH] Fix auth section of ANY-query on CNAME + +Queries with QTYPE=ANY for a name which has a CNAME RR + should be treated as if QTYPE=CNAME. Prior to this + fix, they were being treated more like QTYPE=A. Given + it's QTYPE=ANY and the effects seem to be limited to + the auth section, I doubt this is a production concern + for anyone, but it's good to be correct. + +Fixes Issue #51 (thanks Timo!) +--- + gdnsd/dnspacket.c | 11 ++- + t/012cname/001cname.t | 157 +++++++++++++++++++++++++++++++++++++++++++ + t/012cname/gdnsd.conf | 11 +++ + t/012cname/zones/example.com | 24 +++++++ + 4 files changed, 201 insertions(+), 2 deletions(-) + create mode 100644 t/012cname/001cname.t + create mode 100644 t/012cname/gdnsd.conf + create mode 100644 t/012cname/zones/example.com + +diff --git a/gdnsd/dnspacket.c b/gdnsd/dnspacket.c +index 3c26d83..db7e26a 100644 +--- a/gdnsd/dnspacket.c ++++ b/gdnsd/dnspacket.c +@@ -1190,6 +1190,9 @@ static unsigned int encode_rrs_any(dnspacket_context_t* c, unsigned int offset, + case DNS_TYPE_SOA: + offset = encode_rr_soa(c, offset, (const void*)rrset, true); + break; ++ case DNS_TYPE_CNAME: ++ offset = encode_rr_cname(c, offset, (const void*)rrset, true); ++ break; + case DNS_TYPE_NS: + offset = encode_rrs_ns(c, offset, (const void*)rrset, true); + break; +@@ -1659,8 +1662,12 @@ static unsigned int answer_from_db(dnspacket_context_t* c, const uint8_t* qname, + // for the normal response handling code below. The explicit check of the first + // rrsets entry works because if CNAME exists at all, by definition it is the only + // type of rrset at this node. +- while(resdom && resdom->rrsets +- && resdom->rrsets->gen.type == DNS_TYPE_CNAME && c->qtype != DNS_TYPE_CNAME) { ++ while(resdom ++ && resdom->rrsets ++ && resdom->rrsets->gen.type == DNS_TYPE_CNAME ++ && c->qtype != DNS_TYPE_CNAME ++ && c->qtype != DNS_TYPE_ANY) { ++ + dmn_assert(status == DNAME_AUTH); + + res_hdr->flags1 |= 4; // AA bit +diff --git a/t/012cname/001cname.t b/t/012cname/001cname.t +new file mode 100644 +index 0000000..6e96335 +--- /dev/null ++++ b/t/012cname/001cname.t +@@ -0,0 +1,157 @@ ++ ++# CNAME test, with include_optional_ns to get the auth section right... ++# this is basically going through A, CNAME, and ANY queries against ++# five different classes of CNAME targets (local nonexistent, ++# local existent, delegation, delegation glue record, and external). ++# CNAME and ANY responses should be identical (this was the bug that ++# triggered writing these testcases - ANY was being treated more like A). ++ ++use _GDT (); ++use FindBin (); ++use File::Spec (); ++use Test::More tests => 17; ++ ++my $standard_soa = 'example.com 21600 SOA ns1.example.com hmaster.example.net 1 7200 1800 259200 900'; ++ ++my $pid = _GDT->test_spawn_daemon(File::Spec->catfile($FindBin::Bin, 'gdnsd.conf')); ++ ++_GDT->test_dns( ++ qname => 'cn-nx.example.com', qtype => 'A', ++ header => { rcode => 'NXDOMAIN' }, ++ answer => 'cn-nx.example.com 21600 CNAME nx.example.com', ++ auth => $standard_soa, ++ stats => [qw/udp_reqs nxdomain/], ++); ++ ++foreach my $qt (qw/CNAME ANY/) { ++ _GDT->test_dns( ++ qname => 'cn-nx.example.com', qtype => $qt, ++ answer => 'cn-nx.example.com 21600 CNAME nx.example.com', ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns1.example.com 21600 A 192.0.2.1', ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++ ); ++} ++ ++_GDT->test_dns( ++ qname => 'cn-local.example.com', qtype => 'A', ++ answer => [ ++ 'cn-local.example.com 21600 CNAME ns1.example.com', ++ 'ns1.example.com 21600 A 192.0.2.1', ++ ], ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++); ++ ++foreach my $qt (qw/CNAME ANY/) { ++ _GDT->test_dns( ++ qname => 'cn-local.example.com', qtype => $qt, ++ answer => [ ++ 'cn-local.example.com 21600 CNAME ns1.example.com' ++ ], ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns1.example.com 21600 A 192.0.2.1', ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++ ); ++} ++ ++_GDT->test_dns( ++ qname => 'cn-deleg.example.com', qtype => 'A', ++ answer => [ ++ 'cn-deleg.example.com 21600 CNAME foo.subz.example.com', ++ ], ++ auth => [ ++ 'subz.example.com 21600 NS ns1.subz.example.com', ++ 'subz.example.com 21600 NS ns2.subz.example.com', ++ ], ++ addtl => [ ++ 'ns1.subz.example.com 21600 A 192.0.2.10', ++ 'ns2.subz.example.com 21600 A 192.0.2.20', ++ ], ++); ++ ++foreach my $qt (qw/CNAME ANY/) { ++ _GDT->test_dns( ++ qname => 'cn-deleg.example.com', qtype => $qt, ++ answer => [ ++ 'cn-deleg.example.com 21600 CNAME foo.subz.example.com', ++ ], ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns1.example.com 21600 A 192.0.2.1', ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++ ); ++} ++ ++_GDT->test_dns( ++ qname => 'cn-deleg-glue.example.com', qtype => 'A', ++ answer => [ ++ 'cn-deleg-glue.example.com 21600 CNAME ns1.subz.example.com', ++ ], ++ auth => [ ++ 'subz.example.com 21600 NS ns1.subz.example.com', ++ 'subz.example.com 21600 NS ns2.subz.example.com', ++ ], ++ addtl => [ ++ 'ns1.subz.example.com 21600 A 192.0.2.10', ++ 'ns2.subz.example.com 21600 A 192.0.2.20', ++ ], ++); ++ ++foreach my $qt (qw/CNAME ANY/) { ++ _GDT->test_dns( ++ qname => 'cn-deleg-glue.example.com', qtype => $qt, ++ answer => [ ++ 'cn-deleg-glue.example.com 21600 CNAME ns1.subz.example.com', ++ ], ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns1.example.com 21600 A 192.0.2.1', ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++ ); ++} ++ ++_GDT->test_dns( ++ qname => 'cn-ext.example.com', qtype => 'A', ++ answer => 'cn-ext.example.com 21600 CNAME www.example.net', ++); ++ ++foreach my $qt (qw/CNAME ANY/) { ++ _GDT->test_dns( ++ qname => 'cn-ext.example.com', qtype => $qt, ++ answer => 'cn-ext.example.com 21600 CNAME www.example.net', ++ auth => [ ++ 'example.com 21600 NS ns1.example.com', ++ 'example.com 21600 NS ns2.example.com', ++ ], ++ addtl => [ ++ 'ns1.example.com 21600 A 192.0.2.1', ++ 'ns2.example.com 21600 A 192.0.2.2', ++ ], ++ ); ++} ++ ++_GDT->test_kill_daemon($pid); +diff --git a/t/012cname/gdnsd.conf b/t/012cname/gdnsd.conf +new file mode 100644 +index 0000000..2bc6c92 +--- /dev/null ++++ b/t/012cname/gdnsd.conf +@@ -0,0 +1,11 @@ ++options => { ++ listen => @dns_lspec@ ++ http_listen => @http_lspec@ ++ dns_port => @dns_port@ ++ http_port => @http_port@ ++ zones_default_ttl = 21600 ++ realtime_stats = true ++ max_response = 62464 ++ chaos_response = "some random string" ++ include_optional_ns = true ++} +diff --git a/t/012cname/zones/example.com b/t/012cname/zones/example.com +new file mode 100644 +index 0000000..94a452f +--- /dev/null ++++ b/t/012cname/zones/example.com +@@ -0,0 +1,24 @@ ++ ++@ SOA ns1 hmaster.example.net. ( ++ 1 ; serial ++ 7200 ; refresh ++ 1800 ; retry ++ 259200 ; expire ++ 900 ; ncache ++) ++ ++@ NS ns1 ++@ NS ns2 ++ns1 A 192.0.2.1 ++ns2 A 192.0.2.2 ++ ++subz NS ns1.subz ++subz NS ns2.subz ++ns1.subz A 192.0.2.10 ++ns2.subz A 192.0.2.20 ++ ++cn-nx CNAME nx ++cn-local CNAME ns1 ++cn-deleg CNAME foo.subz ++cn-deleg-glue CNAME ns1.subz ++cn-ext CNAME www.example.net. +-- +1.8.3.2 + |