|
|
7e32a4 |
From e92ac3b83209ddc46ca9a3facd7edf1f14052edf Mon Sep 17 00:00:00 2001
|
|
|
7e32a4 |
From: rpm-build <rpm-build>
|
|
|
7e32a4 |
Date: Wed, 8 Feb 2017 13:49:47 +0100
|
|
|
7e32a4 |
Subject: [PATCH] 4558. [bug] Synthesised CNAME before matching DNAME
|
|
|
7e32a4 |
was still being cached when it should not have been. [RT
|
|
|
7e32a4 |
#44318]
|
|
|
7e32a4 |
|
|
|
7e32a4 |
Fixes and tests last case fixed by CVE-2016-9147
|
|
|
7e32a4 |
---
|
|
|
7e32a4 |
bin/tests/system/dname/ans3/ans.pl | 95 +++++++++++++++++++++++
|
|
|
7e32a4 |
bin/tests/system/dname/ns1/root.db | 5 +-
|
|
|
7e32a4 |
bin/tests/system/dname/tests.sh | 25 ++++++-
|
|
|
7e32a4 |
lib/dns/resolver.c | 150 +++++++++++++++++++++++++------------
|
|
|
7e32a4 |
4 files changed, 225 insertions(+), 50 deletions(-)
|
|
|
7e32a4 |
create mode 100644 bin/tests/system/dname/ans3/ans.pl
|
|
|
7e32a4 |
|
|
|
7e32a4 |
diff --git a/bin/tests/system/dname/ans3/ans.pl b/bin/tests/system/dname/ans3/ans.pl
|
|
|
7e32a4 |
new file mode 100644
|
|
|
7e32a4 |
index 0000000..271fc7d
|
|
|
7e32a4 |
--- /dev/null
|
|
|
7e32a4 |
+++ b/bin/tests/system/dname/ans3/ans.pl
|
|
|
7e32a4 |
@@ -0,0 +1,95 @@
|
|
|
7e32a4 |
+#!/usr/bin/env perl
|
|
|
7e32a4 |
+#
|
|
|
7e32a4 |
+# Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
|
|
|
7e32a4 |
+#
|
|
|
7e32a4 |
+# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
7e32a4 |
+# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
7e32a4 |
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+use strict;
|
|
|
7e32a4 |
+use warnings;
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+use IO::File;
|
|
|
7e32a4 |
+use Getopt::Long;
|
|
|
7e32a4 |
+use Net::DNS::Nameserver;
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
|
|
|
7e32a4 |
+print $pidf "$$\n" or die "cannot write pid file: $!";
|
|
|
7e32a4 |
+$pidf->close or die "cannot close pid file: $!";
|
|
|
7e32a4 |
+sub rmpid { unlink "ans.pid"; exit 1; };
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+$SIG{INT} = \&rmpid;
|
|
|
7e32a4 |
+$SIG{TERM} = \&rmpid;
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+my $localaddr = "10.53.0.3";
|
|
|
7e32a4 |
+my $localport = 5300;
|
|
|
7e32a4 |
+my $verbose = 0;
|
|
|
7e32a4 |
+my $ttl = 60;
|
|
|
7e32a4 |
+my $zone = "example.broken";
|
|
|
7e32a4 |
+my $nsname = "ns3.$zone";
|
|
|
7e32a4 |
+my $synth = "synth-then-dname.$zone";
|
|
|
7e32a4 |
+my $synth2 = "synth2-then-dname.$zone";
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+sub reply_handler {
|
|
|
7e32a4 |
+ my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
|
|
|
7e32a4 |
+ my ($rcode, @ans, @auth, @add);
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+ print ("request: $qname/$qtype\n");
|
|
|
7e32a4 |
+ STDOUT->flush();
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+ if ($qname eq "example.broken") {
|
|
|
7e32a4 |
+ if ($qtype eq "SOA") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ } elsif ($qtype eq "NS") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass NS $nsname");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr");
|
|
|
7e32a4 |
+ push @add, $rr;
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
+ $rcode = "NOERROR";
|
|
|
7e32a4 |
+ } elsif ($qname eq "cname-to-$synth2") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME .");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rcode = "NOERROR";
|
|
|
7e32a4 |
+ } elsif ($qname eq "$synth" || $qname eq "$synth2") {
|
|
|
7e32a4 |
+ if ($qtype eq "DNAME") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME .");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
+ $rcode = "NOERROR";
|
|
|
7e32a4 |
+ } elsif ($qname eq "name.$synth") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rr = new Net::DNS::RR("$synth $ttl $qclass DNAME .");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rcode = "NOERROR";
|
|
|
7e32a4 |
+ } elsif ($qname eq "name.$synth2") {
|
|
|
7e32a4 |
+ my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME .");
|
|
|
7e32a4 |
+ push @ans, $rr;
|
|
|
7e32a4 |
+ $rcode = "NOERROR";
|
|
|
7e32a4 |
+ } else {
|
|
|
7e32a4 |
+ $rcode = "REFUSED";
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
+ return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
|
|
|
7e32a4 |
+}
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+GetOptions(
|
|
|
7e32a4 |
+ 'port=i' => \$localport,
|
|
|
7e32a4 |
+ 'verbose!' => \$verbose,
|
|
|
7e32a4 |
+);
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+my $ns = Net::DNS::Nameserver->new(
|
|
|
7e32a4 |
+ LocalAddr => $localaddr,
|
|
|
7e32a4 |
+ LocalPort => $localport,
|
|
|
7e32a4 |
+ ReplyHandler => \&reply_handler,
|
|
|
7e32a4 |
+ Verbose => $verbose,
|
|
|
7e32a4 |
+);
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+$ns->main_loop;
|
|
|
7e32a4 |
diff --git a/bin/tests/system/dname/ns1/root.db b/bin/tests/system/dname/ns1/root.db
|
|
|
7e32a4 |
index 7049e77..2e84ae0 100644
|
|
|
7e32a4 |
--- a/bin/tests/system/dname/ns1/root.db
|
|
|
7e32a4 |
+++ b/bin/tests/system/dname/ns1/root.db
|
|
|
7e32a4 |
@@ -12,8 +12,6 @@
|
|
|
7e32a4 |
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
7e32a4 |
; PERFORMANCE OF THIS SOFTWARE.
|
|
|
7e32a4 |
|
|
|
7e32a4 |
-; $Id: root.db,v 1.2 2011/03/18 21:14:19 fdupont Exp $
|
|
|
7e32a4 |
-
|
|
|
7e32a4 |
$TTL 300
|
|
|
7e32a4 |
. IN SOA gson.nominum.com. a.root.servers.nil. (
|
|
|
7e32a4 |
2000042100 ; serial
|
|
|
7e32a4 |
@@ -27,3 +25,6 @@ a.root-servers.nil. A 10.53.0.1
|
|
|
7e32a4 |
|
|
|
7e32a4 |
example. NS ns2.example.
|
|
|
7e32a4 |
ns2.example. A 10.53.0.2
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+example.broken. NS ns3.example.broken.
|
|
|
7e32a4 |
+ns3.example.broken. A 10.53.0.3
|
|
|
7e32a4 |
diff --git a/bin/tests/system/dname/tests.sh b/bin/tests/system/dname/tests.sh
|
|
|
7e32a4 |
index 04bfcb2..6dc9e88 100644
|
|
|
7e32a4 |
--- a/bin/tests/system/dname/tests.sh
|
|
|
7e32a4 |
+++ b/bin/tests/system/dname/tests.sh
|
|
|
7e32a4 |
@@ -20,6 +20,7 @@ SYSTEMTESTTOP=..
|
|
|
7e32a4 |
. $SYSTEMTESTTOP/conf.sh
|
|
|
7e32a4 |
|
|
|
7e32a4 |
status=0
|
|
|
7e32a4 |
+n=0
|
|
|
7e32a4 |
|
|
|
7e32a4 |
echo "I:checking short dname from authoritative"
|
|
|
7e32a4 |
ret=0
|
|
|
7e32a4 |
@@ -81,6 +82,26 @@ grep '^a.target.example.' dig.out.ns4.cname > /dev/null || ret=1
|
|
|
7e32a4 |
if [ $ret != 0 ]; then echo "I:failed"; fi
|
|
|
7e32a4 |
status=`expr $status + $ret`
|
|
|
7e32a4 |
|
|
|
7e32a4 |
-echo "I:exit status: $status"
|
|
|
7e32a4 |
+n=`expr $n + 1`
|
|
|
7e32a4 |
+echo "I:checking dname is returned with synthesized cname before dname ($n)"
|
|
|
7e32a4 |
+ret=0
|
|
|
7e32a4 |
+$DIG @10.53.0.4 -p 5300 name.synth-then-dname.example.broken A > dig.out.test$n
|
|
|
7e32a4 |
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+grep '^name.synth-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+grep '^synth-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+if [ $ret != 0 ]; then echo "I:failed"; fi
|
|
|
7e32a4 |
+status=`expr $status + $ret`
|
|
|
7e32a4 |
|
|
|
7e32a4 |
-exit $status
|
|
|
7e32a4 |
+n=`expr $n + 1`
|
|
|
7e32a4 |
+echo "I:checking dname is returned with cname to synthesized cname before dname ($n)"
|
|
|
7e32a4 |
+ret=0
|
|
|
7e32a4 |
+$DIG @10.53.0.4 -p 5300 cname-to-synth2-then-dname.example.broken A > dig.out.test$n
|
|
|
7e32a4 |
+grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+grep '^cname-to-synth2-then-dname\.example\.broken\..*CNAME.*name\.synth2-then-dname\.example\.broken.$' dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+grep '^name\.synth2-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+grep '^synth2-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
|
|
|
7e32a4 |
+if [ $ret != 0 ]; then echo "I:failed"; fi
|
|
|
7e32a4 |
+status=`expr $status + $ret`
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+echo "I:exit status: $status"
|
|
|
7e32a4 |
+[ $status -eq 0 ] || exit 1
|
|
|
7e32a4 |
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
|
|
|
7e32a4 |
index bfd4dcb..c3607fa 100644
|
|
|
7e32a4 |
--- a/lib/dns/resolver.c
|
|
|
7e32a4 |
+++ b/lib/dns/resolver.c
|
|
|
7e32a4 |
@@ -5406,9 +5406,13 @@ cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
|
|
|
7e32a4 |
return (ISC_R_SUCCESS);
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
|
|
|
7e32a4 |
+/*%
|
|
|
7e32a4 |
+ * Construct the synthesised CNAME from the existing QNAME and
|
|
|
7e32a4 |
+ * the DNAME RR and store it in 'target'.
|
|
|
7e32a4 |
+ */
|
|
|
7e32a4 |
static inline isc_result_t
|
|
|
7e32a4 |
dname_target(dns_rdataset_t *rdataset, dns_name_t *qname,
|
|
|
7e32a4 |
- unsigned int nlabels, dns_fixedname_t *fixeddname)
|
|
|
7e32a4 |
+ unsigned int nlabels, dns_name_t *target)
|
|
|
7e32a4 |
{
|
|
|
7e32a4 |
isc_result_t result;
|
|
|
7e32a4 |
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
7e32a4 |
@@ -5428,14 +5432,33 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname,
|
|
|
7e32a4 |
|
|
|
7e32a4 |
dns_fixedname_init(&prefix);
|
|
|
7e32a4 |
dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
|
|
|
7e32a4 |
- dns_fixedname_init(fixeddname);
|
|
|
7e32a4 |
result = dns_name_concatenate(dns_fixedname_name(&prefix),
|
|
|
7e32a4 |
- &dname.dname,
|
|
|
7e32a4 |
- dns_fixedname_name(fixeddname), NULL);
|
|
|
7e32a4 |
+ &dname.dname, target, NULL);
|
|
|
7e32a4 |
dns_rdata_freestruct(&dname);
|
|
|
7e32a4 |
return (result);
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
|
|
|
7e32a4 |
+/*%
|
|
|
7e32a4 |
+ * Check if it was possible to construct 'qname' from 'lastcname'
|
|
|
7e32a4 |
+ * and 'rdataset'.
|
|
|
7e32a4 |
+ */
|
|
|
7e32a4 |
+static inline isc_result_t
|
|
|
7e32a4 |
+fromdname(dns_rdataset_t *rdataset, dns_name_t *lastcname,
|
|
|
7e32a4 |
+ unsigned int nlabels, const dns_name_t *qname)
|
|
|
7e32a4 |
+{
|
|
|
7e32a4 |
+ dns_fixedname_t fixed;
|
|
|
7e32a4 |
+ isc_result_t result;
|
|
|
7e32a4 |
+ dns_name_t *target;
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+ dns_fixedname_init(&fixed);
|
|
|
7e32a4 |
+ target = dns_fixedname_name(&fixed);
|
|
|
7e32a4 |
+ result = dname_target(rdataset, lastcname, nlabels, target);
|
|
|
7e32a4 |
+ if (result != ISC_R_SUCCESS || !dns_name_equal(qname, target))
|
|
|
7e32a4 |
+ return (ISC_R_NOTFOUND);
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+ return (ISC_R_SUCCESS);
|
|
|
7e32a4 |
+}
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
static isc_boolean_t
|
|
|
7e32a4 |
is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
|
|
|
7e32a4 |
dns_rdataset_t *rdataset)
|
|
|
7e32a4 |
@@ -6039,12 +6062,12 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
isc_result_t result;
|
|
|
7e32a4 |
dns_message_t *message;
|
|
|
7e32a4 |
dns_name_t *name, *dname = NULL, *qname, tname, *ns_name;
|
|
|
7e32a4 |
- dns_name_t *cname = NULL;
|
|
|
7e32a4 |
+ dns_name_t *cname = NULL, *lastcname = NULL;
|
|
|
7e32a4 |
dns_rdataset_t *rdataset, *ns_rdataset;
|
|
|
7e32a4 |
- isc_boolean_t done, external, chaining, aa, found, want_chaining;
|
|
|
7e32a4 |
+ isc_boolean_t done, external, aa, found, want_chaining;
|
|
|
7e32a4 |
isc_boolean_t have_answer, found_cname, found_dname, found_type;
|
|
|
7e32a4 |
isc_boolean_t wanted_chaining;
|
|
|
7e32a4 |
- unsigned int aflag;
|
|
|
7e32a4 |
+ unsigned int aflag, chaining;
|
|
|
7e32a4 |
dns_rdatatype_t type;
|
|
|
7e32a4 |
dns_fixedname_t fdname, fqname;
|
|
|
7e32a4 |
dns_view_t *view;
|
|
|
7e32a4 |
@@ -6062,9 +6085,9 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
found_cname = ISC_FALSE;
|
|
|
7e32a4 |
found_dname = ISC_FALSE;
|
|
|
7e32a4 |
found_type = ISC_FALSE;
|
|
|
7e32a4 |
- chaining = ISC_FALSE;
|
|
|
7e32a4 |
have_answer = ISC_FALSE;
|
|
|
7e32a4 |
want_chaining = ISC_FALSE;
|
|
|
7e32a4 |
+ chaining = 0;
|
|
|
7e32a4 |
POST(want_chaining);
|
|
|
7e32a4 |
if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
|
|
|
7e32a4 |
aa = ISC_TRUE;
|
|
|
7e32a4 |
@@ -6075,14 +6098,15 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
view = fctx->res->view;
|
|
|
7e32a4 |
result = dns_message_firstname(message, DNS_SECTION_ANSWER);
|
|
|
7e32a4 |
while (!done && result == ISC_R_SUCCESS) {
|
|
|
7e32a4 |
- dns_namereln_t namereln;
|
|
|
7e32a4 |
- int order;
|
|
|
7e32a4 |
- unsigned int nlabels;
|
|
|
7e32a4 |
+ dns_namereln_t namereln, lastreln;
|
|
|
7e32a4 |
+ int order, lastorder;
|
|
|
7e32a4 |
+ unsigned int nlabels, lastnlabels;
|
|
|
7e32a4 |
|
|
|
7e32a4 |
name = NULL;
|
|
|
7e32a4 |
dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
|
|
|
7e32a4 |
external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
|
|
|
7e32a4 |
namereln = dns_name_fullcompare(qname, name, &order, &nlabels);
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
if (namereln == dns_namereln_equal) {
|
|
|
7e32a4 |
wanted_chaining = ISC_FALSE;
|
|
|
7e32a4 |
for (rdataset = ISC_LIST_HEAD(name->list);
|
|
|
7e32a4 |
@@ -6188,6 +6212,7 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
&fctx->domain)) {
|
|
|
7e32a4 |
return (DNS_R_SERVFAIL);
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
+ lastcname = name;
|
|
|
7e32a4 |
} else if (rdataset->type == dns_rdatatype_rrsig
|
|
|
7e32a4 |
&& rdataset->covers ==
|
|
|
7e32a4 |
dns_rdatatype_cname
|
|
|
7e32a4 |
@@ -6211,7 +6236,7 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
rdataset->attributes |=
|
|
|
7e32a4 |
DNS_RDATASETATTR_CACHE;
|
|
|
7e32a4 |
rdataset->trust = dns_trust_answer;
|
|
|
7e32a4 |
- if (!chaining) {
|
|
|
7e32a4 |
+ if (chaining == 0) {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* This data is "the" answer
|
|
|
7e32a4 |
* to our question only if
|
|
|
7e32a4 |
@@ -6288,10 +6313,21 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
* cause us to ignore the signatures of
|
|
|
7e32a4 |
* CNAMEs.
|
|
|
7e32a4 |
*/
|
|
|
7e32a4 |
- if (wanted_chaining)
|
|
|
7e32a4 |
- chaining = ISC_TRUE;
|
|
|
7e32a4 |
+ if (wanted_chaining && chaining < 2U)
|
|
|
7e32a4 |
+ chaining++;
|
|
|
7e32a4 |
} else {
|
|
|
7e32a4 |
dns_rdataset_t *dnameset = NULL;
|
|
|
7e32a4 |
+ isc_boolean_t synthcname = ISC_FALSE;
|
|
|
7e32a4 |
+
|
|
|
7e32a4 |
+ if (lastcname != NULL) {
|
|
|
7e32a4 |
+ lastreln = dns_name_fullcompare(lastcname,
|
|
|
7e32a4 |
+ name,
|
|
|
7e32a4 |
+ &lastorder,
|
|
|
7e32a4 |
+ &lastnlabels);
|
|
|
7e32a4 |
+ if (lastreln == dns_namereln_subdomain &&
|
|
|
7e32a4 |
+ lastnlabels == dns_name_countlabels(name))
|
|
|
7e32a4 |
+ synthcname = ISC_TRUE;
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* Look for a DNAME (or its SIG). Anything else is
|
|
|
7e32a4 |
@@ -6320,7 +6356,7 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
* If we're not chaining, then the DNAME and
|
|
|
7e32a4 |
* its signature should not be external.
|
|
|
7e32a4 |
*/
|
|
|
7e32a4 |
- if (!chaining && external) {
|
|
|
7e32a4 |
+ if (chaining == 0 && external) {
|
|
|
7e32a4 |
char qbuf[DNS_NAME_FORMATSIZE];
|
|
|
7e32a4 |
char obuf[DNS_NAME_FORMATSIZE];
|
|
|
7e32a4 |
|
|
|
7e32a4 |
@@ -6338,16 +6374,9 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* If DNAME + synthetic CNAME then the
|
|
|
7e32a4 |
* namereln is dns_namereln_subdomain.
|
|
|
7e32a4 |
- *
|
|
|
7e32a4 |
- * If synthetic CNAME + DNAME then the
|
|
|
7e32a4 |
- * namereln is dns_namereln_commonancestor
|
|
|
7e32a4 |
- * and the number of label must match the
|
|
|
7e32a4 |
- * DNAME. This order is not RFC compliant.
|
|
|
7e32a4 |
*/
|
|
|
7e32a4 |
-
|
|
|
7e32a4 |
if (namereln != dns_namereln_subdomain &&
|
|
|
7e32a4 |
- (namereln != dns_namereln_commonancestor ||
|
|
|
7e32a4 |
- nlabels != dns_name_countlabels(name)))
|
|
|
7e32a4 |
+ !synthcname)
|
|
|
7e32a4 |
{
|
|
|
7e32a4 |
char qbuf[DNS_NAME_FORMATSIZE];
|
|
|
7e32a4 |
char obuf[DNS_NAME_FORMATSIZE];
|
|
|
7e32a4 |
@@ -6367,8 +6396,19 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
want_chaining = ISC_TRUE;
|
|
|
7e32a4 |
POST(want_chaining);
|
|
|
7e32a4 |
aflag = DNS_RDATASETATTR_ANSWER;
|
|
|
7e32a4 |
- result = dname_target(rdataset, qname,
|
|
|
7e32a4 |
- nlabels, &fdname);
|
|
|
7e32a4 |
+ dns_fixedname_init(&fdname);
|
|
|
7e32a4 |
+ dname = dns_fixedname_name(&fdname);
|
|
|
7e32a4 |
+ if (synthcname) {
|
|
|
7e32a4 |
+ result = fromdname(rdataset,
|
|
|
7e32a4 |
+ lastcname,
|
|
|
7e32a4 |
+ lastnlabels,
|
|
|
7e32a4 |
+ qname);
|
|
|
7e32a4 |
+ } else {
|
|
|
7e32a4 |
+ result = dname_target(rdataset,
|
|
|
7e32a4 |
+ qname,
|
|
|
7e32a4 |
+ nlabels,
|
|
|
7e32a4 |
+ dname);
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
if (result == ISC_R_NOSPACE) {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* We can't construct the
|
|
|
7e32a4 |
@@ -6382,8 +6422,8 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
else
|
|
|
7e32a4 |
dnameset = rdataset;
|
|
|
7e32a4 |
|
|
|
7e32a4 |
- dname = dns_fixedname_name(&fdname);
|
|
|
7e32a4 |
- if (!is_answertarget_allowed(view,
|
|
|
7e32a4 |
+ if (!synthcname &&
|
|
|
7e32a4 |
+ !is_answertarget_allowed(view,
|
|
|
7e32a4 |
qname, rdataset->type,
|
|
|
7e32a4 |
dname, &fctx->domain))
|
|
|
7e32a4 |
{
|
|
|
7e32a4 |
@@ -6404,7 +6444,13 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
name->attributes |= DNS_NAMEATTR_CACHE;
|
|
|
7e32a4 |
rdataset->attributes |= DNS_RDATASETATTR_CACHE;
|
|
|
7e32a4 |
rdataset->trust = dns_trust_answer;
|
|
|
7e32a4 |
- if (!chaining) {
|
|
|
7e32a4 |
+ /*
|
|
|
7e32a4 |
+ * If we are not chaining or the first CNAME
|
|
|
7e32a4 |
+ * is a synthesised CNAME before the DNAME.
|
|
|
7e32a4 |
+ */
|
|
|
7e32a4 |
+ if ((chaining == 0) ||
|
|
|
7e32a4 |
+ (chaining == 1U && synthcname))
|
|
|
7e32a4 |
+ {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* This data is "the" answer to
|
|
|
7e32a4 |
* our question only if we're
|
|
|
7e32a4 |
@@ -6414,9 +6460,12 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
if (aflag == DNS_RDATASETATTR_ANSWER) {
|
|
|
7e32a4 |
have_answer = ISC_TRUE;
|
|
|
7e32a4 |
found_dname = ISC_TRUE;
|
|
|
7e32a4 |
- if (cname != NULL)
|
|
|
7e32a4 |
+ if (cname != NULL &&
|
|
|
7e32a4 |
+ synthcname)
|
|
|
7e32a4 |
+ {
|
|
|
7e32a4 |
cname->attributes &=
|
|
|
7e32a4 |
~DNS_NAMEATTR_ANSWER;
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
name->attributes |=
|
|
|
7e32a4 |
DNS_NAMEATTR_ANSWER;
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
@@ -6434,26 +6483,35 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
* DNAME chaining.
|
|
|
7e32a4 |
*/
|
|
|
7e32a4 |
if (dnameset != NULL) {
|
|
|
7e32a4 |
- /*
|
|
|
7e32a4 |
- * Copy the dname into the qname fixed name.
|
|
|
7e32a4 |
- *
|
|
|
7e32a4 |
- * Although we check for failure of the copy
|
|
|
7e32a4 |
- * operation, in practice it should never fail
|
|
|
7e32a4 |
- * since we already know that the result fits
|
|
|
7e32a4 |
- * in a fixedname.
|
|
|
7e32a4 |
- */
|
|
|
7e32a4 |
- dns_fixedname_init(&fqname);
|
|
|
7e32a4 |
- qname = dns_fixedname_name(&fqname);
|
|
|
7e32a4 |
- result = dns_name_copy(dname, qname, NULL);
|
|
|
7e32a4 |
- if (result != ISC_R_SUCCESS)
|
|
|
7e32a4 |
- return (result);
|
|
|
7e32a4 |
+ if (!synthcname) {
|
|
|
7e32a4 |
+ /*
|
|
|
7e32a4 |
+ * Copy the dname into the qname fixed
|
|
|
7e32a4 |
+ * name.
|
|
|
7e32a4 |
+ *
|
|
|
7e32a4 |
+ * Although we check for failure of the
|
|
|
7e32a4 |
+ * copy operation, in practice it
|
|
|
7e32a4 |
+ * should never fail since we already
|
|
|
7e32a4 |
+ * know that the result fits in a
|
|
|
7e32a4 |
+ * fixedname.
|
|
|
7e32a4 |
+ */
|
|
|
7e32a4 |
+ dns_fixedname_init(&fqname);
|
|
|
7e32a4 |
+ qname = dns_fixedname_name(&fqname);
|
|
|
7e32a4 |
+ result = dns_name_copy(dname, qname,
|
|
|
7e32a4 |
+ NULL);
|
|
|
7e32a4 |
+ if (result != ISC_R_SUCCESS)
|
|
|
7e32a4 |
+ return (result);
|
|
|
7e32a4 |
+ }
|
|
|
7e32a4 |
wanted_chaining = ISC_TRUE;
|
|
|
7e32a4 |
name->attributes |= DNS_NAMEATTR_CHAINING;
|
|
|
7e32a4 |
dnameset->attributes |=
|
|
|
7e32a4 |
DNS_RDATASETATTR_CHAINING;
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
- if (wanted_chaining)
|
|
|
7e32a4 |
- chaining = ISC_TRUE;
|
|
|
7e32a4 |
+ /*
|
|
|
7e32a4 |
+ * Ensure that we can't ever get chaining == 1
|
|
|
7e32a4 |
+ * above if we have processed a DNAME.
|
|
|
7e32a4 |
+ */
|
|
|
7e32a4 |
+ if (wanted_chaining && chaining < 2U)
|
|
|
7e32a4 |
+ chaining += 2;
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
result = dns_message_nextname(message, DNS_SECTION_ANSWER);
|
|
|
7e32a4 |
}
|
|
|
7e32a4 |
@@ -6478,7 +6536,7 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* Did chaining end before we got the final answer?
|
|
|
7e32a4 |
*/
|
|
|
7e32a4 |
- if (chaining) {
|
|
|
7e32a4 |
+ if (chaining != 0) {
|
|
|
7e32a4 |
/*
|
|
|
7e32a4 |
* Yes. This may be a negative reply, so hand off
|
|
|
7e32a4 |
* authority section processing to the noanswer code.
|
|
|
7e32a4 |
@@ -6527,7 +6585,7 @@ answer_response(fetchctx_t *fctx) {
|
|
|
7e32a4 |
DNS_NAMEATTR_CACHE;
|
|
|
7e32a4 |
rdataset->attributes |=
|
|
|
7e32a4 |
DNS_RDATASETATTR_CACHE;
|
|
|
7e32a4 |
- if (aa && !chaining)
|
|
|
7e32a4 |
+ if (aa && chaining == 0)
|
|
|
7e32a4 |
rdataset->trust =
|
|
|
7e32a4 |
dns_trust_authauthority;
|
|
|
7e32a4 |
else
|
|
|
7e32a4 |
--
|
|
|
7e32a4 |
2.9.3
|
|
|
7e32a4 |
|