]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] add no-case-compress
authorEvan Hunt <each@isc.org>
Fri, 7 Feb 2014 03:37:26 +0000 (19:37 -0800)
committerEvan Hunt <each@isc.org>
Fri, 7 Feb 2014 03:37:26 +0000 (19:37 -0800)
3731. [func] Added a "no-case-compress" ACL, which causes
named to use case-insensitive compression
(disabling change #3645) for specified
clients. (This is useful when dealing
with broken client implementations that
use case-sensitive name comparisons,
rejecting responses that fail to match the
capitalization of the query that was sent.)
[RT #35300]

CHANGES
bin/named/client.c
bin/named/server.c
bin/tests/system/case/ns2/named.conf [new file with mode: 0644]
bin/tests/system/case/tests.sh
doc/arm/Bv9ARM-book.xml
lib/dns/include/dns/view.h
lib/dns/view.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index aad5f8be881db68777793a6c47d17d122437f6e4..c596182538ef07825ac58be534f50fa6298f653a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+3731.  [func]          Added a "no-case-compress" ACL, which causes
+                       named to use case-insensitive compression
+                       (disabling change #3645) for specified
+                       clients. (This is useful when dealing
+                       with broken client implementations that
+                       use case-sensitive name comparisons,
+                       rejecting responses that fail to match the
+                       capitalization of the query that was sent.)
+                       [RT #35300]
+
 3730.  [cleanup]       Added "never" as a synonym for "none" when
                        configuring key event dates in the dnssec tools.
                        [RT #35277]
index 77d89435743957e47608171aa588c2596d6fe66d..61082e76c87d9747bd6f633a3e53811e4ea089ad 100644 (file)
@@ -233,6 +233,8 @@ static void client_request(isc_task_t *task, isc_event_t *event);
 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
 static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
                               dns_dispatch_t *disp, isc_boolean_t tcp);
+static inline isc_boolean_t
+allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl);
 
 void
 ns_client_recursing(ns_client_t *client) {
@@ -994,7 +996,19 @@ client_send(ns_client_t *client) {
        result = dns_compress_init(&cctx, -1, client->mctx);
        if (result != ISC_R_SUCCESS)
                goto done;
-       dns_compress_setsensitive(&cctx, ISC_TRUE);
+       if (client->peeraddr_valid && client->view != NULL) {
+               isc_netaddr_t netaddr;
+               dns_name_t *name = NULL;
+
+               isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+               if (client->message->tsigkey != NULL)
+                       name = &client->message->tsigkey->name;
+               if (client->view->nocasecompress == NULL ||
+                   !allowed(&netaddr, name, client->view->nocasecompress))
+               {
+                       dns_compress_setsensitive(&cctx, ISC_TRUE);
+               }
+       }
        cleanup_cctx = ISC_TRUE;
 
        result = dns_message_renderbegin(client->message, &cctx, &buffer);
index 15b822e016f9dc87fe1c68a67f61f55392257d68..f86aa6733b8c854d9923c8e6190eed471008990a 100644 (file)
@@ -3306,6 +3306,14 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
                        CHECK(dns_acl_none(mctx, &view->cacheacl));
        }
 
+       /*
+        * Ignore case when compressing responses to the specified
+        * clients. This causes case not always to be presrerved,
+        * and is needed by some broken clients.
+        */
+       CHECK(configure_view_acl(vconfig, config, "no-case-compress", NULL,
+                                actx, ns_g_mctx, &view->nocasecompress));
+
        /*
         * Filter setting on addresses in the answer section.
         */
diff --git a/bin/tests/system/case/ns2/named.conf b/bin/tests/system/case/ns2/named.conf
new file mode 100644 (file)
index 0000000..7d98911
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       query-source address 10.53.0.2;
+       notify-source 10.53.0.2;
+       transfer-source 10.53.0.2;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.2; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+       ixfr-from-differences yes;
+       check-integrity no;
+       no-case-compress { 10.53.0.2; };
+};
+
+zone "example" {
+       type slave;
+       file "example.bk";
+       masters { 10.53.0.1; };
+};
index d9c159bffc11ad87ac437ec76889ba8911b9b368..2c235c3c88ad6961bf429d3fd5a5428f37baa43d 100644 (file)
@@ -23,11 +23,28 @@ status=0
 n=0
 
 n=`expr $n + 1`
-echo "I:testing case sensitive responses ($n)"
+echo "I:testing case preserving responses - no acl ($n)"
 ret=0
-$DIG $DIGOPTS mx example. @10.53.0.1 -p 5300 > dig.n1.test$n
-grep "0.mail.eXaMpLe" dig.n1.test$n > /dev/null || ret=1
-grep "mAiL.example" dig.n1.test$n > /dev/null || ret=1
+$DIG $DIGOPTS mx example. @10.53.0.1 -p 5300 > dig.ns1.test$n
+grep "0.mail.eXaMpLe" dig.ns1.test$n > /dev/null || ret=1
+grep "mAiL.example" dig.ns1.test$n > /dev/null || ret=1
+test $ret -eq 0 || echo "I:failed"
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:testing no-case-compress acl '{ 10.53.0.2; }' ($n)"
+ret=0
+
+# check that we preserve zone case for non-matching query (10.53.0.1)
+$DIG $DIGOPTS mx example. -b 10.53.0.1 @10.53.0.1 -p 5300 > dig.ns1.test$n
+grep "0.mail.eXaMpLe" dig.ns1.test$n > /dev/null || ret=1
+grep "mAiL.example" dig.ns1.test$n > /dev/null || ret=1
+
+# check that we don't preserve zone case for match (10.53.0.2)
+$DIG $DIGOPTS mx example. -b 10.53.0.2 @10.53.0.2 -p 5300 > dig.ns2.test$n
+grep "0.mail.example" dig.ns2.test$n > /dev/null || ret=1
+grep "mail.example" dig.ns2.test$n > /dev/null || ret=1
+
 test $ret -eq 0 || echo "I:failed"
 status=`expr $status + $ret`
 
index 16490079ae805801eab51548a1f2115d8138e68e..8cc268922970ad8456c112fb0f12cc020ed1e63a 100644 (file)
@@ -4813,6 +4813,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
     <optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
     <optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
+    <optional> no-case-compress { <replaceable>address_match_list</replaceable> }; </optional>
     <optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
@@ -7181,6 +7182,59 @@ options {
              </listitem>
            </varlistentry>
 
+           <varlistentry>
+             <term><command>no-case-compress</command></term> <listitem>
+               <para>
+                  Specifies a list of addresses which require responses
+                  to use case-insensitive compression.  This ACL can be
+                  used when <command>named</command> needs to work with
+                  clients that do not comply with the requirement in RFC
+                  1034 to use case-insensitive name comparisons when
+                  checking for matching domain names.
+                </para>
+                <para>
+                  If left undefined, the ACL defaults to
+                  <command>none</command>: case-insensitive compression
+                  will be used for all clients.  If the ACL is defined and
+                  matches a client, then case will be ignored when
+                  compressing domain names in DNS responses sent to that
+                  client.
+                </para>
+                <para>
+                  This can result in slightly smaller responses: if
+                  a response contains the names "example.com" and
+                  "example.COM", case-insensitive compression would treat
+                  the second one as a duplicate.  It also ensures
+                  that the case of the query name exactly matches the
+                  case of the owner names of returned records, rather
+                  than matching the case of the records entered in
+                  the zone file.  This allows responses to exactly
+                  match the query, which is required by some clients
+                  due to incorrect use of case-sensitive comparisions.
+                </para>
+                <para>
+                  Case-insensitive compression is <emphasis>always</emphasis>
+                  used in AXFR and IXFR responses, regardless of whether
+                  the client matches this ACL.
+                </para>
+                <para>
+                  There are circusmstances in which <command>named</command>
+                  will not preserve the case of owner names of records:
+                  if a zone file defines records of different types with
+                  the same name, but the capitalization of the name is
+                  different (e.g., "www.example.com/A" and
+                  "WWW.EXAMPLE.COM/AAAA"), then all resposnes for that
+                  name will use the <emphasis>first</emphasis> version
+                  of the name that was used in the zone file.  This
+                  limitation may be addressed in a future release.  However,
+                  domain names specified in the rdata of resource records
+                  (i.e., records of type NS, MX, CNAME, etc) will always
+                  have their case preserved unless the client matches this
+                  ACL.
+                </para>
+             </listitem>
+           </varlistentry>
+
            <varlistentry>
              <term><command>resolver-query-timeout</command></term>
              <listitem>
index cff940b7342b5737be8900b0352402f374eb61bd..676eef336dcd9afdbaf48cc5ca5d48c87a9708cf 100644 (file)
@@ -141,6 +141,7 @@ struct dns_view {
        dns_acl_t *                     updateacl;
        dns_acl_t *                     upfwdacl;
        dns_acl_t *                     denyansweracl;
+       dns_acl_t *                     nocasecompress;
        dns_rbt_t *                     answeracl_exclude;
        dns_rbt_t *                     denyanswernames;
        dns_rbt_t *                     answernames_exclude;
index 35969134b14686b8ed4813762c2d46264334649a..e5af1be76d4877ce7e6baee90cc7041704f9791b 100644 (file)
@@ -182,6 +182,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->updateacl = NULL;
        view->upfwdacl = NULL;
        view->denyansweracl = NULL;
+       view->nocasecompress = NULL;
        view->answeracl_exclude = NULL;
        view->denyanswernames = NULL;
        view->answernames_exclude = NULL;
@@ -357,6 +358,8 @@ destroy(dns_view_t *view) {
                dns_db_detach(&view->cachedb);
        if (view->cache != NULL)
                dns_cache_detach(&view->cache);
+       if (view->nocasecompress != NULL)
+               dns_acl_detach(&view->nocasecompress);
        if (view->matchclients != NULL)
                dns_acl_detach(&view->matchclients);
        if (view->matchdestinations != NULL)
index dc979c6935eb581e13c9b79d5c7b6d2fddfb7386..3a95962bb0d30fa3d694cc32719f4cc7ae1a536c 100644 (file)
@@ -1522,6 +1522,7 @@ view_clauses[] = {
        { "minimal-responses", &cfg_type_boolean, 0 },
        { "prefetch", &cfg_type_prefetch, 0 },
        { "preferred-glue", &cfg_type_astring, 0 },
+       { "no-case-compress", &cfg_type_bracketed_aml, 0 },
        { "provide-ixfr", &cfg_type_boolean, 0 },
        /*
         * Note that the query-source option syntax is different