]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2605. [bug] Accept DS responses from delegation only zones.
authorMark Andrews <marka@isc.org>
Tue, 2 Jun 2009 06:04:40 +0000 (06:04 +0000)
committerMark Andrews <marka@isc.org>
Tue, 2 Jun 2009 06:04:40 +0000 (06:04 +0000)
                        [RT # 19296]

CHANGES
doc/arm/Bv9ARM-book.xml
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index 881a7de517afa6b1c17038ed4cbe775f7f4c07dd..5cfca9573fdcce665c3670058de332b0865c6df0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+2605.  [bug]           Accept DS responses from delegation only zones.
+                       [RT # 19296]
+
 2603.  [port]          win32: handle .exe extension of named-checkzone and
                        named-comilezone argv[0] names under windows.
                        [RT #19767]
index 458b9f578dbcee757f53a6efc5f15aa49e0b9caa..37690080df93ab62d9ca5c1ae6085adfac57129f 100644 (file)
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.108 2009/04/02 15:31:18 jreed Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.109 2009/06/02 06:04:40 marka Exp $ -->
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>BIND 9 Administrator Reference Manual</title>
 
@@ -4274,11 +4274,11 @@ category notify { null; };
                   </entry>
                   <entry colname="2">
                     <para>
-                      Delegation only.  Logs queries that have
-                      been forced to NXDOMAIN as the result of a
-                      delegation-only zone or
-                      a <command>delegation-only</command> in a
-                      hint or stub zone declaration.
+                     Delegation only.  Logs queries that have been
+                     forced to NXDOMAIN as the result of a
+                     delegation-only zone or a
+                     <command>delegation-only</command> in a hint
+                     or stub zone declaration.
                     </para>
                   </entry>
                 </row>
@@ -4776,17 +4776,45 @@ digits</varname>" + "<varname>tkey-domain</varname>". In most cases,
             </listitem>
           </varlistentry>
 
-          <varlistentry>
+          <varlistentry id="root_delegation_only">
             <term><command>root-delegation-only</command></term>
             <listitem>
               <para>
-                Turn on enforcement of delegation-only in TLDs (top level domains) and root zones
-                with an optional
-                exclude list.
+                Turn on enforcement of delegation-only in TLDs
+               (top level domains) and root zones with an optional
+               exclude list.
               </para>
+             <para>
+               DS queries are expected to be made to and be answered by
+               delegation only zones.  Such queries and responses are
+               treated as a exception to delegation-only processing
+               and are not converted to NXDOMAIN responses provided
+               a CNAME is not discovered at the query name.
+             </para>
+             <para>
+               If a delegation only zone server also serves a child
+               zone it is not always possible to determine whether
+               a answer comes from the delegation only zone or the
+               child zone.  SOA NS and DNSKEY records are apex
+               only records and a matching response that contains
+               these records or DS is treated as coming from a
+               child zone.  RRSIG records are also examined to see
+               if they are signed by a child zone or not.  The
+               authority section is also examined to see if there
+               is evidence that the answer is from the child zone.
+               Answers that are determined to be from a child zone
+               are not converted to NXDOMAIN responses.  Despite
+               all these checks there is still a possibility of
+               false negatives when a child zone is being served.
+             </para>
+             <para>
+               Similarly false positives can arise from empty nodes
+               (no records at the name) in the delegation only zone
+               when the query type is not ANY.
+             </para>
               <para>
-                Note some TLDs are not delegation only (e.g. "DE", "LV", "US"
-                and "MUSEUM").
+                Note some TLDs are not delegation only (e.g. "DE", "LV",
+               "US" and "MUSEUM").  This list is not exhaustive.
               </para>
 
 <programlisting>
@@ -8571,20 +8599,22 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
                     </entry>
                     <entry colname="2">
                       <para>
-                        This is used to enforce the delegation-only
-                        status of infrastructure zones (e.g. COM, NET, ORG).
-                        Any answer that
-                        is received without an explicit or implicit delegation
-                        in the authority
-                        section will be treated as NXDOMAIN.  This does not
-                        apply to the zone
-                        apex.  This should not be applied to leaf zones.
+                       This is used to enforce the delegation-only
+                       status of infrastructure zones (e.g. COM,
+                       NET, ORG).  Any answer that is received
+                       without an explicit or implicit delegation
+                       in the authority section will be treated
+                       as NXDOMAIN.  This does not apply to the
+                       zone apex.  This should not be applied to
+                       leaf zones.
                       </para>
                       <para>
                         <varname>delegation-only</varname> has no
-                        effect on answers received
-                        from forwarders.
+                        effect on answers received from forwarders.
                       </para>
+                     <para>
+                       See caveats in <xref linkend="root_delegation_only"/>.
+                     </para>
                     </entry>
                   </row>
                 </tbody>
@@ -8823,9 +8853,11 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
                   <para>
                     The flag only applies to hint and stub zones.  If set
                     to <userinput>yes</userinput>, then the zone will also be
-                    treated as if it
-                    is also a delegation-only type zone.
+                    treated as if it is also a delegation-only type zone.
                   </para>
+                 <para>
+                   See caveats in <xref linkend="root_delegation_only"/>.
+                 </para>
                 </listitem>
               </varlistentry>
 
index 319aec432bc157e3b729c211ae7e7766690935ea..998e2a48aca0c9f83adb4dc96575ece86cb96404 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.284.18.89 2009/05/11 02:36:58 tbox Exp $ */
+/* $Id: resolver.c,v 1.284.18.90 2009/06/02 06:04:40 marka Exp $ */
 
 /*! \file */
 
@@ -416,6 +416,30 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
        return (result);
 }
 
+static isc_boolean_t
+rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
+       dns_namereln_t namereln;
+       dns_rdata_rrsig_t rrsig;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       int order;
+       isc_result_t result;
+       unsigned int labels;
+
+       for (result = dns_rdataset_first(rdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(rdataset)) {
+               dns_rdataset_current(rdataset, &rdata);
+               result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
+                                               &order, &labels);
+               if (namereln == dns_namereln_subdomain)
+                       return (ISC_TRUE);
+               dns_rdata_reset(&rdata);
+       }
+       return (ISC_FALSE);
+}
+
 static isc_boolean_t
 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
        dns_name_t *name;
@@ -429,13 +453,43 @@ fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
                return (ISC_FALSE);
 
        /*
-        * Look for BIND 8 style delegations.
-        * Also look for answers to ANY queries where the duplicate NS RRset
-        * may have been stripped from the authority section.
+        * A DS RRset can appear anywhere in a zone, even for a delegation-only
+        * zone.  So a response to an explicit query for this type should be
+        * excluded from delegation-only fixup.
+        *
+        * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
+        * response to a query for these types can never violate the
+        * delegation-only assumption: if the query name is below a
+        * zone cut, the response should normally be a referral, which should
+        * be accepted; if the query name is below a zone cut but the server
+        * happens to have authority for the zone of the query name, the
+        * response is a (non-referral) answer.  But this does not violate
+        * delegation-only because the query name must be in a different zone
+        * due to the "apex-only" nature of these types.  Note that if the
+        * remote server happens to have authority for a child zone of a
+        * delegation-only zone, we may still incorrectly "fix" the response
+        * with NXDOMAIN for queries for other types.  Unfortunately it's
+        * generally impossible to differentiate this case from violation of
+        * the delegation-only assumption.  Once the resolver learns the
+        * correct zone cut, possibly via a separate query for an "apex-only"
+        * type, queries for other types will be resolved correctly.
+        *
+        * A query for type ANY will be accepted if it hits an exceptional
+        * type above in the answer section as it should be from a child
+        * zone.
+        *
+        * Also accept answers with RRSIG records from the child zone.
+        * Direct queries for RRSIG records should not be answered from
+        * the parent zone.
         */
+
        if (message->counts[DNS_SECTION_ANSWER] != 0 &&
            (fctx->type == dns_rdatatype_ns ||
-            fctx->type == dns_rdatatype_any)) {
+            fctx->type == dns_rdatatype_ds ||
+            fctx->type == dns_rdatatype_soa ||
+            fctx->type == dns_rdatatype_any ||
+            fctx->type == dns_rdatatype_rrsig ||
+            fctx->type == dns_rdatatype_dnskey)) {
                result = dns_message_firstname(message, DNS_SECTION_ANSWER);
                while (result == ISC_R_SUCCESS) {
                        name = NULL;
@@ -444,10 +498,32 @@ fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
                        for (rdataset = ISC_LIST_HEAD(name->list);
                             rdataset != NULL;
                             rdataset = ISC_LIST_NEXT(rdataset, link)) {
-                               type = rdataset->type;
-                               if (type != dns_rdatatype_ns)
+                               if (!dns_name_equal(name, &fctx->name))
                                        continue;
-                               if (dns_name_issubdomain(name, domain))
+                               type = rdataset->type;
+                               /*
+                                * RRsig from child?
+                                */
+                               if (type == dns_rdatatype_rrsig &&
+                                   rrsig_fromchildzone(fctx, rdataset))
+                                       return (ISC_FALSE);
+                               /*
+                                * Direct query for apex records or DS.
+                                */
+                               if (fctx->type == type &&
+                                   (type == dns_rdatatype_ds ||
+                                    type == dns_rdatatype_ns ||
+                                    type == dns_rdatatype_soa ||
+                                    type == dns_rdatatype_dnskey))
+                                       return (ISC_FALSE);
+                               /*
+                                * Indirect query for apex records or DS.
+                                */
+                               if (fctx->type == dns_rdatatype_any &&
+                                   (type == dns_rdatatype_ns ||
+                                    type == dns_rdatatype_ds ||
+                                    type == dns_rdatatype_soa ||
+                                    type == dns_rdatatype_dnskey))
                                        return (ISC_FALSE);
                        }
                        result = dns_message_nextname(message,
@@ -455,7 +531,14 @@ fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
                }
        }
 
-       /* Look for referral. */
+       /*
+        * A NODATA response to a DS query?
+        */
+       if (fctx->type == dns_rdatatype_ds &&
+           message->counts[DNS_SECTION_ANSWER] == 0)
+               return (ISC_FALSE);
+
+       /* Look for referral or indication of answer from child zone? */
        if (message->counts[DNS_SECTION_AUTHORITY] == 0)
                goto munge;
 
@@ -470,13 +553,37 @@ fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
                        if (type == dns_rdatatype_soa &&
                            dns_name_equal(name, domain))
                                keep_auth = ISC_TRUE;
+
                        if (type != dns_rdatatype_ns &&
-                           type != dns_rdatatype_soa)
+                           type != dns_rdatatype_soa &&
+                           type != dns_rdatatype_rrsig)
                                continue;
-                       if (dns_name_equal(name, domain))
-                               goto munge;
-                       if (dns_name_issubdomain(name, domain))
+
+                       if (type == dns_rdatatype_rrsig) {
+                               if (rrsig_fromchildzone(fctx, rdataset))
+                                       return (ISC_FALSE);
+                               else
+                                       continue;
+                       }
+
+                       /* NS or SOA records. */
+                       if (dns_name_equal(name, domain)) {
+                               /*
+                                * If a query for ANY causes a negative
+                                * response, we can be sure that this is
+                                * an empty node.  For other type of queries
+                                * we cannot differentiate an empty node
+                                * from a node that just doesn't have that
+                                * type of record.  We only accept the former
+                                * case.
+                                */
+                               if (message->counts[DNS_SECTION_ANSWER] == 0 &&
+                                   fctx->type == dns_rdatatype_any)
+                                       return (ISC_FALSE);
+                       } else if (dns_name_issubdomain(name, domain)) {
+                               /* Referral or answer from child zone. */
                                return (ISC_FALSE);
+                       }
                }
                result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
        }