From: Evan Hunt Date: Fri, 7 Feb 2014 03:37:26 +0000 (-0800) Subject: [master] add no-case-compress X-Git-Tag: v9.10.0b1~147^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=166341d55424ca522eb456a1c7d0211e391f1ac8;p=thirdparty%2Fbind9.git [master] add no-case-compress 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] --- diff --git a/CHANGES b/CHANGES index aad5f8be881..c596182538e 100644 --- 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] diff --git a/bin/named/client.c b/bin/named/client.c index 77d89435743..61082e76c87 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -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); diff --git a/bin/named/server.c b/bin/named/server.c index 15b822e016f..f86aa6733b8 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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 index 00000000000..7d989111621 --- /dev/null +++ b/bin/tests/system/case/ns2/named.conf @@ -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; }; +}; diff --git a/bin/tests/system/case/tests.sh b/bin/tests/system/case/tests.sh index d9c159bffc1..2c235c3c88a 100644 --- a/bin/tests/system/case/tests.sh +++ b/bin/tests/system/case/tests.sh @@ -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` diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 16490079ae8..8cc26892297 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -4813,6 +4813,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] try-tcp-refresh yes_or_no; allow-v6-synthesis { address_match_list }; blackhole { address_match_list }; + no-case-compress { address_match_list }; use-v4-udp-ports { port_list }; avoid-v4-udp-ports { port_list }; use-v6-udp-ports { port_list }; @@ -7181,6 +7182,59 @@ options { + + no-case-compress + + Specifies a list of addresses which require responses + to use case-insensitive compression. This ACL can be + used when named 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. + + + If left undefined, the ACL defaults to + none: 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. + + + 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. + + + Case-insensitive compression is always + used in AXFR and IXFR responses, regardless of whether + the client matches this ACL. + + + There are circusmstances in which named + 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 first 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. + + + + resolver-query-timeout diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index cff940b7342..676eef336dc 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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; diff --git a/lib/dns/view.c b/lib/dns/view.c index 35969134b14..e5af1be76d4 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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) diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index dc979c6935e..3a95962bb0d 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -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