Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.3:Staging:A
bind
bind-CVE-2017-3135.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bind-CVE-2017-3135.patch of Package bind
Index: bind-9.9.9-P1/bin/tests/system/dname/ans3/ans.pl =================================================================== --- /dev/null +++ bind-9.9.9-P1/bin/tests/system/dname/ans3/ans.pl @@ -0,0 +1,95 @@ +#!/usr/bin/env perl +# +# Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use strict; +use warnings; + +use IO::File; +use Getopt::Long; +use Net::DNS::Nameserver; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my $localaddr = "10.53.0.3"; +my $localport = 5300; +my $verbose = 0; +my $ttl = 60; +my $zone = "example.broken"; +my $nsname = "ns3.$zone"; +my $synth = "synth-then-dname.$zone"; +my $synth2 = "synth2-then-dname.$zone"; + +sub reply_handler { + my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_; + my ($rcode, @ans, @auth, @add); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + if ($qname eq "example.broken") { + if ($qtype eq "SOA") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0"); + push @ans, $rr; + } elsif ($qtype eq "NS") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass NS $nsname"); + push @ans, $rr; + $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr"); + push @add, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "cname-to-$synth2") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2"); + push @ans, $rr; + $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name"); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "$synth" || $qname eq "$synth2") { + if ($qtype eq "DNAME") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME ."); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "name.$synth") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name."); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "name.$synth2") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name."); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + } else { + $rcode = "REFUSED"; + } + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); +} + +GetOptions( + 'port=i' => \$localport, + 'verbose!' => \$verbose, +); + +my $ns = Net::DNS::Nameserver->new( + LocalAddr => $localaddr, + LocalPort => $localport, + ReplyHandler => \&reply_handler, + Verbose => $verbose, +); + +$ns->main_loop; Index: bind-9.9.9-P1/bin/tests/system/dname/ns1/root.db =================================================================== --- bind-9.9.9-P1.orig/bin/tests/system/dname/ns1/root.db +++ bind-9.9.9-P1/bin/tests/system/dname/ns1/root.db @@ -12,8 +12,6 @@ ; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ; PERFORMANCE OF THIS SOFTWARE. -; $Id: root.db,v 1.2 2011/03/18 21:14:19 fdupont Exp $ - $TTL 300 . IN SOA gson.nominum.com. a.root.servers.nil. ( 2000042100 ; serial @@ -27,3 +25,6 @@ a.root-servers.nil. A 10.53.0.1 example. NS ns2.example. ns2.example. A 10.53.0.2 + +example.broken. NS ns3.example.broken. +ns3.example.broken. A 10.53.0.3 Index: bind-9.9.9-P1/bin/tests/system/dname/tests.sh =================================================================== --- bind-9.9.9-P1.orig/bin/tests/system/dname/tests.sh +++ bind-9.9.9-P1/bin/tests/system/dname/tests.sh @@ -20,6 +20,7 @@ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh status=0 +n=0 echo "I:checking short dname from authoritative" ret=0 @@ -63,6 +64,26 @@ grep "status: YXDOMAIN" dig.out.ns4.tool if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` -echo "I:exit status: $status" +n=`expr $n + 1` +echo "I:checking dname is returned with synthesized cname before dname ($n)" +ret=0 +$DIG @10.53.0.4 -p 5300 name.synth-then-dname.example.broken A > dig.out.test$n +grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep '^name.synth-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1 +grep '^synth-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` -exit $status +n=`expr $n + 1` +echo "I:checking dname is returned with cname to synthesized cname before dname ($n)" +ret=0 +$DIG @10.53.0.4 -p 5300 cname-to-synth2-then-dname.example.broken A > dig.out.test$n +grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep '^cname-to-synth2-then-dname\.example\.broken\..*CNAME.*name\.synth2-then-dname\.example\.broken.$' dig.out.test$n > /dev/null || ret=1 +grep '^name\.synth2-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1 +grep '^synth2-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:exit status: $status" +[ $status -eq 0 ] || exit 1 Index: bind-9.9.9-P1/bin/named/query.c =================================================================== --- bind-9.9.9-P1.orig/bin/named/query.c +++ bind-9.9.9-P1/bin/named/query.c @@ -5674,7 +5674,7 @@ query_find(ns_client_t *client, dns_fetc dns_rpz_st_t *rpz_st; isc_boolean_t resuming; int line = -1; - isc_boolean_t dns64_exclude, dns64; + isc_boolean_t dns64_exclude, dns64, rpz; isc_boolean_t nxrewrite = ISC_FALSE; isc_boolean_t redirected = ISC_FALSE; dns_clientinfomethods_t cm; @@ -5687,6 +5687,7 @@ query_find(ns_client_t *client, dns_fetc char mbuf[BUFSIZ]; char qbuf[DNS_NAME_FORMATSIZE]; #endif + dns_name_t *rpzqname; CTRACE(ISC_LOG_DEBUG(3), "query_find"); @@ -5712,7 +5713,7 @@ query_find(ns_client_t *client, dns_fetc zone = NULL; need_wildcardproof = ISC_FALSE; empty_wild = ISC_FALSE; - dns64_exclude = dns64 = ISC_FALSE; + dns64_exclude = dns64 = rpz = ISC_FALSE; options = 0; resuming = ISC_FALSE; is_zone = ISC_FALSE; @@ -5881,6 +5882,7 @@ query_find(ns_client_t *client, dns_fetc authoritative = ISC_FALSE; version = NULL; need_wildcardproof = ISC_FALSE; + rpz = ISC_FALSE; if (client->view->checknames && !dns_rdata_checkowner(client->query.qname, @@ -6016,11 +6018,29 @@ query_find(ns_client_t *client, dns_fetc } /* - * Now look for an answer in the database. + * Now look for an answer in the database. If this is a dns64 + * AAAA lookup on a rpz database adjust the qname. */ - result = dns_db_findext(db, client->query.qname, version, type, + if (dns64 && rpz) + rpzqname = client->query.rpz_st->qname; + else + rpzqname = client->query.qname; + + result = dns_db_findext(db, rpzqname, version, type, client->query.dboptions, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); + /* + * Fixup fname and sigrdataset. + */ + if (dns64 && rpz) { + isc_result_t rresult; + + rresult = dns_name_copy(client->query.qname, fname, NULL); + RUNTIME_CHECK(rresult == ISC_R_SUCCESS); + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + } resume: CTRACE(ISC_LOG_DEBUG(3), "query_find: resume"); @@ -6223,10 +6243,12 @@ query_find(ns_client_t *client, dns_fetc case DNS_RPZ_POLICY_NXDOMAIN: result = DNS_R_NXDOMAIN; nxrewrite = ISC_TRUE; + rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_NODATA: result = DNS_R_NXRRSET; nxrewrite = ISC_TRUE; + rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_RECORD: result = rpz_st->m.result; @@ -6246,6 +6268,7 @@ query_find(ns_client_t *client, dns_fetc rdataset->ttl = ISC_MIN(rdataset->ttl, rpz_st->m.ttl); } + rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_WILDCNAME: result = dns_rdataset_first(rdataset); @@ -6288,7 +6311,6 @@ query_find(ns_client_t *client, dns_fetc NS_CLIENTATTR_WANTAD); client->message->flags &= ~DNS_MESSAGEFLAG_AD; query_putrdataset(client, &sigrdataset); - rpz_st->q.is_zone = is_zone; is_zone = ISC_TRUE; rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, rpz_st->m.type, zone, rpz_st->qname); @@ -6671,15 +6693,6 @@ query_find(ns_client_t *client, dns_fetc rdataset = NULL; sigrdataset = NULL; type = qtype = dns_rdatatype_a; - rpz_st = client->query.rpz_st; - if (rpz_st != NULL) { - /* - * Arrange for RPZ rewriting of any A records. - */ - if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) - is_zone = rpz_st->q.is_zone; - rpz_st_clear(client); - } dns64 = ISC_TRUE; goto db_find; } @@ -6994,15 +7007,6 @@ query_find(ns_client_t *client, dns_fetc sigrdataset = NULL; fname = NULL; type = qtype = dns_rdatatype_a; - rpz_st = client->query.rpz_st; - if (rpz_st != NULL) { - /* - * Arrange for RPZ rewriting of any A records. - */ - if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) - is_zone = rpz_st->q.is_zone; - rpz_st_clear(client); - } dns64 = ISC_TRUE; goto db_find; } @@ -7516,15 +7520,6 @@ query_find(ns_client_t *client, dns_fetc rdataset = NULL; sigrdataset = NULL; type = qtype = dns_rdatatype_a; - rpz_st = client->query.rpz_st; - if (rpz_st != NULL) { - /* - * Arrange for RPZ rewriting of any A records. - */ - if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) - is_zone = rpz_st->q.is_zone; - rpz_st_clear(client); - } dns64_exclude = dns64 = ISC_TRUE; goto db_find; } Index: bind-9.9.9-P1/lib/dns/message.c =================================================================== --- bind-9.9.9-P1.orig/lib/dns/message.c +++ bind-9.9.9-P1/lib/dns/message.c @@ -1213,8 +1213,8 @@ getsection(isc_buffer_t *source, dns_mes { isc_region_t r; unsigned int count, rdatalen; - dns_name_t *name; - dns_name_t *name2; + dns_name_t *name = NULL; + dns_name_t *name2 = NULL; dns_offsets_t *offsets; dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; @@ -1224,7 +1224,7 @@ getsection(isc_buffer_t *source, dns_mes dns_rdata_t *rdata; dns_ttl_t ttl; dns_namelist_t *section; - isc_boolean_t free_name, free_rdataset; + isc_boolean_t free_name = ISC_FALSE, free_rdataset = ISC_FALSE; isc_boolean_t preserve_order, best_effort, seen_problem; isc_boolean_t issigzero; Index: bind-9.9.9-P1/lib/dns/rdataset.c =================================================================== --- bind-9.9.9-P1.orig/lib/dns/rdataset.c +++ bind-9.9.9-P1/lib/dns/rdataset.c @@ -337,6 +337,7 @@ towiresorted(dns_rdataset_t *rdataset, c */ REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); REQUIRE(countp != NULL); REQUIRE((order == NULL) == (order_arg == NULL)); REQUIRE(cctx != NULL && cctx->mctx != NULL); Index: bind-9.9.9-P1/lib/dns/resolver.c =================================================================== --- bind-9.9.9-P1.orig/lib/dns/resolver.c +++ bind-9.9.9-P1/lib/dns/resolver.c @@ -5818,9 +5818,13 @@ cname_target(dns_rdataset_t *rdataset, d return (ISC_R_SUCCESS); } +/*% + * Construct the synthesised CNAME from the existing QNAME and + * the DNAME RR and store it in 'target'. + */ static inline isc_result_t dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, - unsigned int nlabels, dns_fixedname_t *fixeddname) + unsigned int nlabels, dns_name_t *target) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -5840,14 +5844,33 @@ dname_target(dns_rdataset_t *rdataset, d dns_fixedname_init(&prefix); dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL); - dns_fixedname_init(fixeddname); result = dns_name_concatenate(dns_fixedname_name(&prefix), - &dname.dname, - dns_fixedname_name(fixeddname), NULL); + &dname.dname, target, NULL); dns_rdata_freestruct(&dname); return (result); } +/*% + * Check if it was possible to construct 'qname' from 'lastcname' + * and 'rdataset'. + */ +static inline isc_result_t +fromdname(dns_rdataset_t *rdataset, dns_name_t *lastcname, + unsigned int nlabels, const dns_name_t *qname) +{ + dns_fixedname_t fixed; + isc_result_t result; + dns_name_t *target; + + dns_fixedname_init(&fixed); + target = dns_fixedname_name(&fixed); + result = dname_target(rdataset, lastcname, nlabels, target); + if (result != ISC_R_SUCCESS || !dns_name_equal(qname, target)) + return (ISC_R_NOTFOUND); + + return (ISC_R_SUCCESS); +} + static isc_boolean_t is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, dns_rdataset_t *rdataset) @@ -6464,12 +6487,12 @@ answer_response(fetchctx_t *fctx) { isc_result_t result; dns_message_t *message; dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; - dns_name_t *cname = NULL; + dns_name_t *cname = NULL, *lastcname = NULL; dns_rdataset_t *rdataset, *ns_rdataset; - isc_boolean_t done, external, chaining, aa, found, want_chaining; + isc_boolean_t done, external, aa, found, want_chaining; isc_boolean_t have_answer, found_cname, found_dname, found_type; isc_boolean_t wanted_chaining; - unsigned int aflag; + unsigned int aflag, chaining; dns_rdatatype_t type; dns_fixedname_t fdname, fqname, fqdname; dns_view_t *view; @@ -6487,7 +6510,7 @@ answer_response(fetchctx_t *fctx) { found_cname = ISC_FALSE; found_dname = ISC_FALSE; found_type = ISC_FALSE; - chaining = ISC_FALSE; + chaining = 0; have_answer = ISC_FALSE; want_chaining = ISC_FALSE; POST(want_chaining); @@ -6501,16 +6524,14 @@ answer_response(fetchctx_t *fctx) { dns_fixedname_init(&fqdname); result = dns_message_firstname(message, DNS_SECTION_ANSWER); while (!done && result == ISC_R_SUCCESS) { - dns_namereln_t namereln, dnamereln; - int order; - unsigned int nlabels; + dns_namereln_t namereln, lastreln; + int order, lastorder; + unsigned int nlabels, lastnlabels; name = NULL; dns_message_currentname(message, DNS_SECTION_ANSWER, &name); external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); namereln = dns_name_fullcompare(qname, name, &order, &nlabels); - dnamereln = dns_name_fullcompare(dqname, name, &order, - &nlabels); if (namereln == dns_namereln_equal) { wanted_chaining = ISC_FALSE; for (rdataset = ISC_LIST_HEAD(name->list); @@ -6616,6 +6637,7 @@ answer_response(fetchctx_t *fctx) { &fctx->domain)) { return (DNS_R_SERVFAIL); } + lastcname = name; } else if (rdataset->type == dns_rdatatype_rrsig && rdataset->covers == dns_rdatatype_cname @@ -6639,7 +6661,7 @@ answer_response(fetchctx_t *fctx) { rdataset->attributes |= DNS_RDATASETATTR_CACHE; rdataset->trust = dns_trust_answer; - if (!chaining) { + if (chaining == 0) { /* * This data is "the" answer * to our question only if @@ -6716,10 +6738,22 @@ answer_response(fetchctx_t *fctx) { * cause us to ignore the signatures of * CNAMEs. */ - if (wanted_chaining) - chaining = ISC_TRUE; + if (wanted_chaining && chaining < 2U) + chaining++; + } else { dns_rdataset_t *dnameset = NULL; + isc_boolean_t synthcname = ISC_FALSE; + + if (lastcname != NULL) { + lastreln = dns_name_fullcompare(lastcname, + name, + &lastorder, + &lastnlabels); + if (lastreln == dns_namereln_subdomain && + lastnlabels == dns_name_countlabels(name)) + synthcname = ISC_TRUE; + } /* * Look for a DNAME (or its SIG). Anything else is @@ -6748,7 +6782,7 @@ answer_response(fetchctx_t *fctx) { * If we're not chaining, then the DNAME and * its signature should not be external. */ - if (!chaining && external) { + if (chaining == 0 && external) { char qbuf[DNS_NAME_FORMATSIZE]; char obuf[DNS_NAME_FORMATSIZE]; @@ -6763,7 +6797,7 @@ answer_response(fetchctx_t *fctx) { return (DNS_R_FORMERR); } - if (dnamereln != dns_namereln_subdomain) { + if (namereln != dns_namereln_subdomain && !synthcname) { char qbuf[DNS_NAME_FORMATSIZE]; char obuf[DNS_NAME_FORMATSIZE]; @@ -6782,8 +6816,19 @@ answer_response(fetchctx_t *fctx) { want_chaining = ISC_TRUE; POST(want_chaining); aflag = DNS_RDATASETATTR_ANSWER; - result = dname_target(rdataset, dqname, - nlabels, &fdname); + dns_fixedname_init(&fdname); + dname = dns_fixedname_name(&fdname); + if (synthcname) { + result = fromdname(rdataset, + lastcname, + lastnlabels, + qname); + } else { + result = dname_target(rdataset, + qname, + nlabels, + dname); + } if (result == ISC_R_NOSPACE) { /* * We can't construct the @@ -6796,9 +6841,8 @@ answer_response(fetchctx_t *fctx) { return (result); else dnameset = rdataset; - - dname = dns_fixedname_name(&fdname); - if (!is_answertarget_allowed(view, + if (!synthcname && + !is_answertarget_allowed(view, dqname, rdataset->type, dname, &fctx->domain)) { @@ -6821,7 +6865,13 @@ answer_response(fetchctx_t *fctx) { name->attributes |= DNS_NAMEATTR_CACHE; rdataset->attributes |= DNS_RDATASETATTR_CACHE; rdataset->trust = dns_trust_answer; - if (!chaining) { + /* + * If we are not chaining or the first CNAME + * is a synthesised CNAME before the DNAME. + */ + if ((chaining == 0) || + (chaining == 1U && synthcname)) + { /* * This data is "the" answer to * our question only if we're @@ -6831,9 +6881,11 @@ answer_response(fetchctx_t *fctx) { if (aflag == DNS_RDATASETATTR_ANSWER) { have_answer = ISC_TRUE; found_dname = ISC_TRUE; - if (cname != NULL) + if (cname != NULL && synthcname) + { cname->attributes &= ~DNS_NAMEATTR_ANSWER; + } name->attributes |= DNS_NAMEATTR_ANSWER; } @@ -6851,26 +6903,35 @@ answer_response(fetchctx_t *fctx) { * DNAME chaining. */ if (dnameset != NULL) { - /* - * Copy the dname into the qname fixed name. - * - * Although we check for failure of the copy - * operation, in practice it should never fail - * since we already know that the result fits - * in a fixedname. - */ - dns_fixedname_init(&fqname); - qname = dns_fixedname_name(&fqname); - result = dns_name_copy(dname, qname, NULL); - if (result != ISC_R_SUCCESS) - return (result); + if (!synthcname) { + /* + * Copy the dname into the qname fixed + * name. + * + * Although we check for failure of the + * copy operation, in practice it + * should never fail since we already + * know that the result fits in a + * fixedname. + */ + dns_fixedname_init(&fqname); + qname = dns_fixedname_name(&fqname); + result = dns_name_copy(dname, qname, + NULL); + if (result != ISC_R_SUCCESS) + return (result); + } wanted_chaining = ISC_TRUE; name->attributes |= DNS_NAMEATTR_CHAINING; dnameset->attributes |= DNS_RDATASETATTR_CHAINING; } - if (wanted_chaining) - chaining = ISC_TRUE; + /* + * Ensure that we can't ever get chaining == 1 + * above if we have processed a DNAME. + */ + if (wanted_chaining && chaining < 2U) + chaining += 2; } result = dns_message_nextname(message, DNS_SECTION_ANSWER); } @@ -6895,7 +6956,7 @@ answer_response(fetchctx_t *fctx) { /* * Did chaining end before we got the final answer? */ - if (chaining) { + if (chaining != 0) { /* * Yes. This may be a negative reply, so hand off * authority section processing to the noanswer code. @@ -6944,7 +7005,7 @@ answer_response(fetchctx_t *fctx) { DNS_NAMEATTR_CACHE; rdataset->attributes |= DNS_RDATASETATTR_CACHE; - if (aa && !chaining) + if (aa && chaining == 0) rdataset->trust = dns_trust_authauthority; else
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor