]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1504. [func] New zone type "delegation-only".
authorMark Andrews <marka@isc.org>
Wed, 17 Sep 2003 05:24:43 +0000 (05:24 +0000)
committerMark Andrews <marka@isc.org>
Wed, 17 Sep 2003 05:24:43 +0000 (05:24 +0000)
CHANGES
bin/named/server.c
doc/arm/Bv9ARM-book.xml
lib/bind9/check.c
lib/dns/include/dns/log.h
lib/dns/include/dns/view.h
lib/dns/log.c
lib/dns/ncache.c
lib/dns/resolver.c
lib/dns/view.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 76a670b33d4a253a8014d5974138232d79bc8168..61d4461b30cd9c4a5868056b85f283740d3cb805 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+1504.  [func]          New zone type "delegation-only".
+
 1503.  [port]          win32: install libeay32.dll outside of system32.
 
 1502.  [bug]           nsupdate: adjust timeouts for UPDATE requests over TCP.
index 791d8b691a5c86ca797c7f2703005b804af978c4..5568dae3665f736229f1c83840aa04dfa096d224 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.400 2003/07/25 02:22:23 marka Exp $ */
+/* $Id: server.c,v 1.401 2003/09/17 05:24:41 marka Exp $ */
 
 #include <config.h>
 
@@ -1274,6 +1274,7 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
        cfg_obj_t *typeobj = NULL;
        cfg_obj_t *forwarders = NULL;
        cfg_obj_t *forwardtype = NULL;
+       cfg_obj_t *only = NULL;
        isc_result_t result;
        isc_buffer_t buffer;
        dns_fixedname_t fixorigin;
@@ -1374,6 +1375,14 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
                goto cleanup;
        }
 
+       /*
+        * "delegation-only zones" aren't zones either.
+        */
+       if (strcasecmp(ztypestr, "delegation-only") == 0) {
+               result = dns_view_adddelegationonly(view, origin);
+               goto cleanup;
+       }
+
        /*
         * Check for duplicates in the new zone table.
         */
@@ -1443,6 +1452,16 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
                                        forwardtype));
        }
 
+       /*
+        * Stub and forward zones may also refer to delegation only points.
+        */
+       only = NULL;
+       if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
+       {
+               if (cfg_obj_asboolean(only))
+                       CHECK(dns_view_adddelegationonly(view, origin));
+       }
+
        /*
         * Configure the zone.
         */
index f43713f8d02074e1d1cbf1c8d0317721edd2728b..1c9a3f681936bd84b4cc14e92629ba8764a25aca 100644 (file)
@@ -2,7 +2,7 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
                "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.222 2003/04/17 11:31:01 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.223 2003/09/17 05:24:41 marka Exp $ -->
 
 <book>
 <title>BIND 9 Administrator Reference Manual</title>
@@ -2634,6 +2634,14 @@ in remote servers, discovered by BIND 9 when trying to query
 those servers during resolution.
 </para></entry>
 </row>
+<row rowsep = "0">
+<entry colname = "1"><para><command>delegation-only</command></para></entry>
+<entry colname = "2"><para>Delegation only.  Logs queries that have have
+been forced to NXDOMAIN as the result of a delegation-only zone or
+a <command>delegation-only</command> in a stub or forward
+zone declartation.
+</para></entry>
+</row>
 </tbody>
 </tgroup></informaltable>
 </sect3>
@@ -4428,7 +4436,7 @@ view "external" {
 <sect2 id="zone_statement_grammar"><title><command>zone</command>
 Statement Grammar</title>
       <programlisting>zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> <optional>{ 
-    type ( master | slave | hint | stub | forward ) ;
+    type ( master | slave | hint | stub | forward /| delegation-only ) ;
     <optional> allow-notify { <replaceable>address_match_list</replaceable> } ; </optional>
     <optional> allow-query { <replaceable>address_match_list</replaceable> } ; </optional>
     <optional> allow-transfer { <replaceable>address_match_list</replaceable> } ; </optional>
@@ -4438,6 +4446,7 @@ Statement Grammar</title>
     <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
     <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
     <optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
+    <optional> delegation-only <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> file <replaceable>string</replaceable> ; </optional>
     <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
     <optional> forwarders { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
@@ -4567,6 +4576,14 @@ list of root name servers. If no hint zone is specified for class
 IN, the server uses a compiled-in default set of root servers hints.
 Classes other than IN have no built-in defaults hints.</para></entry>
 </row>
+<row rowsep = "0">
+<entry colname = "1"><para><varname>delegation-only</varname></para></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 a explicit or implict 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></entry>
+</row>
 </tbody>
 </tgroup></informaltable></sect3>
 
@@ -4663,6 +4680,13 @@ with the distribution but none are linked in by default.</para>
 <command>dialup</command> in <xref linkend="boolean_options"/>.</para>
 </listitem></varlistentry>
 
+<varlistentry><term><command>delegation-only</command></term>
+<listitem><para>The flag only applies to forward 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.
+</para>
+</listitem></varlistentry>
+
 <varlistentry><term><command>forward</command></term>
 <listitem><para>Only meaningful if the zone has a forwarders
 list. The <command>only</command> value causes the lookup to fail
index 9e273e50969c41efeabfbcf9b0b61132d4e0f95a..a285e1a3381e7644a3b01874bc1264f6d4e20f16 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: check.c,v 1.37 2003/07/18 06:00:41 marka Exp $ */
+/* $Id: check.c,v 1.38 2003/09/17 05:24:42 marka Exp $ */
 
 #include <config.h>
 
@@ -407,6 +407,7 @@ validate_masters(cfg_obj_t *obj, cfg_obj_t *config, isc_uint32_t *countp,
 #define STUBZONE       4
 #define HINTZONE       8
 #define FORWARDZONE    16
+#define DELEGATIONZONE 32
 
 typedef struct {
        const char *name;
@@ -437,6 +438,7 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
        { "notify", MASTERZONE | SLAVEZONE },
        { "also-notify", MASTERZONE | SLAVEZONE },
        { "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
+       { "delegation-only", STUBZONE | FORWARDZONE},
        { "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
        { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
        { "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
@@ -497,6 +499,8 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
                ztype = FORWARDZONE;
        else if (strcasecmp(typestr, "hint") == 0)
                ztype = HINTZONE;
+       else if (strcasecmp(typestr, "delegation-only") == 0)
+               ztype = DELEGATIONZONE;
        else {
                cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
                            "zone '%s': invalid type %s",
index e08ad9b4f92885706452bf8698393a73ff3bcc83..525a0abdf9e7d2db2d07f7b10c7470fedb131a1c 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: log.h,v 1.31 2001/10/11 01:16:18 gson Exp $ */
+/* $Id: log.h,v 1.32 2003/09/17 05:24:43 marka Exp $ */
 
 /* Principal Authors: DCL */
 
@@ -39,6 +39,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
 #define DNS_LOGCATEGORY_XFER_OUT       (&dns_categories[7])
 #define DNS_LOGCATEGORY_DISPATCH       (&dns_categories[8])
 #define DNS_LOGCATEGORY_LAME_SERVERS   (&dns_categories[9])
+#define DNS_LOGCATEGORY_DELEGATION_ONLY        (&dns_categories[10])
 
 /* Backwards compatibility. */
 #define DNS_LOGCATEGORY_GENERAL                ISC_LOGCATEGORY_GENERAL
index af43f114af7cf4f3cdc8329a6690c86aae16e04c..d2a4fa4d5ea1093bfba3a00e9f9ffc67c1186000 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.82 2003/07/25 02:22:25 marka Exp $ */
+/* $Id: view.h,v 1.83 2003/09/17 05:24:43 marka Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -119,6 +119,7 @@ struct dns_view {
        dns_aclenv_t                    aclenv;
        dns_rdatatype_t                 preferred_glue;
        isc_boolean_t                   flush;
+       dns_namelist_t *                delonly;
 
        /*
         * Configurable data for server use only,
@@ -715,6 +716,35 @@ dns_view_flushname(dns_view_t *view, dns_name_t *);
  *     other returns are failures.
  */
 
+isc_result_t
+dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
+/*
+ * Add the given name to the delegation only table.
+ *
+ * Requires:
+ *     'view' is valid.
+ *     'name' is valid.
+ *
+ * Returns:
+ *     ISC_R_SUCCESS
+ *     ISC_R_NOMEMORY
+ */
+
+isc_boolean_t
+dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name);
+/*
+ * Check if 'name' is in the delegation only table.
+ *
+ * Requires:
+ *     'view' is valid.
+ *     'name' is valid.
+ *
+ * Returns:
+ *     ISC_TRUE if the name is is the table.
+ *     ISC_FALSE othewise.
+ */
+
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_VIEW_H */
index e738e532167b85a439dd33bb9c30cb6d1bee1675..b64aa89f53819fd93cc668801f7d7c47a1bdbf76 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: log.c,v 1.34 2001/10/11 01:16:17 gson Exp $ */
+/* $Id: log.c,v 1.35 2003/09/17 05:24:42 marka Exp $ */
 
 /* Principal Authors: DCL */
 
@@ -40,6 +40,7 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
        { "xfer-out",   0 },
        { "dispatch",   0 },
        { "lame-servers", 0 },
+       { "delegation-only", 0 },
        { NULL,         0 }
 };
 
index 67a029fbe67c859d97bbc6a4587b837c18564a46..bba7ab0ecdee6eaa3da8156b414c9cc7030b27a2 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ncache.c,v 1.32 2003/02/26 23:52:29 marka Exp $ */
+/* $Id: ncache.c,v 1.33 2003/09/17 05:24:42 marka Exp $ */
 
 #include <config.h>
 
@@ -121,7 +121,10 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
        ttl = maxttl;
        trust = 0xffff;
        isc_buffer_init(&buffer, data, sizeof(data));
-       result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+       if (message->counts[DNS_SECTION_AUTHORITY])
+               result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+       else
+               result = ISC_R_NOMORE;
        while (result == ISC_R_SUCCESS) {
                name = NULL;
                dns_message_currentname(message, DNS_SECTION_AUTHORITY,
index 6d73b8883b768d5d9a34f91d956706c2f16f1904..54c42dab5c2c47bcff3df144fceece0dcc50c19d 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.264 2003/07/18 04:30:01 marka Exp $ */
+/* $Id: resolver.c,v 1.265 2003/09/17 05:24:42 marka Exp $ */
 
 #include <config.h>
 
@@ -326,6 +326,53 @@ static isc_result_t ncache_adderesult(dns_message_t *message,
                                      dns_rdataset_t *ardataset,
                                      isc_result_t *eresultp);
 
+static isc_boolean_t
+fix_mustbedelegationornxdomain(dns_message_t *message, dns_name_t *domain) {
+
+       dns_name_t *name;
+       dns_rdataset_t *rdataset;
+       dns_rdatatype_t type;
+       isc_result_t result;
+       isc_boolean_t keep_auth = ISC_FALSE;
+
+       if (message->rcode == dns_rcode_nxdomain)
+               return (ISC_FALSE);
+
+       /* Look for referral. */
+       if (message->counts[DNS_SECTION_AUTHORITY] == 0)
+               goto munge;
+
+       result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+       while (result == ISC_R_SUCCESS) {
+               name = NULL;
+               dns_message_currentname(message, DNS_SECTION_AUTHORITY,
+                                       &name);
+               for (rdataset = ISC_LIST_HEAD(name->list);
+                    rdataset != NULL;
+                    rdataset = ISC_LIST_NEXT(rdataset, link)) {
+                       type = rdataset->type;
+                       if (type == dns_rdatatype_soa &&
+                           dns_name_equal(name, domain))
+                               keep_auth = ISC_TRUE;
+                       if (type != dns_rdatatype_ns)
+                               continue;
+                       if (dns_name_equal(name, domain))
+                               goto munge;
+                       if (dns_name_issubdomain(name, domain))
+                               return (ISC_FALSE);
+               }
+               result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
+       }
+
+ munge:
+       message->rcode = dns_rcode_nxdomain;
+       message->counts[DNS_SECTION_ANSWER] = 0;
+       if (!keep_auth)
+               message->counts[DNS_SECTION_AUTHORITY] = 0;
+       message->counts[DNS_SECTION_ADDITIONAL] = 0;
+       return (ISC_TRUE);
+}
+
 static inline isc_result_t
 fctx_starttimer(fetchctx_t *fctx) {
        /*
@@ -4917,6 +4964,24 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                goto done;
        }
 
+       /*
+        * Enforce delegations only zones like NET and COM.
+        */
+       if (dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
+           !dns_name_equal(&fctx->domain, &fctx->name) &&
+           fix_mustbedelegationornxdomain(message, &fctx->domain)) {
+               char namebuf[DNS_NAME_FORMATSIZE];
+               char domainbuf[DNS_NAME_FORMATSIZE];
+
+               dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+               dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
+                            DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+                            "enforced delegation-only for '%s' (%s)",
+                            domainbuf, namebuf);
+       }
+
        /*
         * Did we get any answers?
         */
index 322a55ab7468b29456b6984ba71a4c3b5ac98b4e..9b4b7d20cc0a9a57c81c1c5f2a261063bc138076 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.116 2003/07/25 02:22:24 marka Exp $ */
+/* $Id: view.c,v 1.117 2003/09/17 05:24:43 marka Exp $ */
 
 #include <config.h>
 
@@ -47,6 +47,8 @@
 #define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
 #define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
 
+#define DNS_VIEW_DELONLYHASH 111
+
 static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
 static void adb_shutdown(isc_task_t *task, isc_event_t *event);
 static void req_shutdown(isc_task_t *task, isc_event_t *event);
@@ -142,6 +144,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
                goto cleanup_fwdtable;
        view->peers = NULL;
        view->order = NULL;
+       view->delonly = NULL;
 
        /*
         * Initialize configuration data with default values.
@@ -265,6 +268,23 @@ destroy(dns_view_t *view) {
                dns_acl_detach(&view->recursionacl);
        if (view->sortlist != NULL)
                dns_acl_detach(&view->sortlist);
+       if (view->delonly != NULL) {
+               dns_name_t *name;
+               int i;
+
+               for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
+                       name = ISC_LIST_HEAD(view->delonly[i]);
+                       while (name != NULL) {
+                               ISC_LIST_UNLINK(view->delonly[i], name, link);
+                               dns_name_free(name, view->mctx);
+                               isc_mem_put(view->mctx, name, sizeof(*name));
+                               name = ISC_LIST_HEAD(view->delonly[i]);
+                       }
+               }
+               isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
+                           DNS_VIEW_DELONLYHASH);
+               view->delonly = NULL;
+       }
        dns_keytable_detach(&view->trustedkeys);
        dns_keytable_detach(&view->secroots);
        dns_fwdtable_destroy(&view->fwdtable);
@@ -1168,3 +1188,57 @@ dns_view_flushname(dns_view_t *view, dns_name_t *name) {
                return (ISC_R_SUCCESS);
        return (dns_cache_flushname(view->cache, name));
 }
+
+isc_result_t
+dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
+       isc_result_t result;
+       dns_name_t *new;
+       isc_uint32_t hash;
+
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       if (view->delonly == NULL) {
+               view->delonly = isc_mem_get(view->mctx,
+                                           sizeof(dns_namelist_t) *
+                                           DNS_VIEW_DELONLYHASH);
+               if (view->delonly == NULL)
+                       return (ISC_R_NOMEMORY);
+               for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
+                       ISC_LIST_INIT(view->delonly[hash]);
+       }
+       hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
+       new = ISC_LIST_HEAD(view->delonly[hash]);
+       while (new != NULL && !dns_name_equal(new, name))
+               new = ISC_LIST_NEXT(new, link);
+       if (new != NULL)
+               return (ISC_R_SUCCESS);
+       new = isc_mem_get(view->mctx, sizeof(*new));
+       if (new == NULL)
+               return (ISC_R_NOMEMORY);
+       dns_name_init(new, NULL);
+       result = dns_name_dup(name, view->mctx, new);
+       if (result == ISC_R_SUCCESS)
+               ISC_LIST_APPEND(view->delonly[hash], new, link);
+       else
+               isc_mem_put(view->mctx, new, sizeof(*new));
+       return (result);
+}
+
+isc_result_t
+dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
+       dns_name_t *new;
+       isc_uint32_t hash;
+
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       if (view->delonly == NULL)
+               return (ISC_FALSE);
+
+       hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
+       new = ISC_LIST_HEAD(view->delonly[hash]);
+       while (new != NULL && !dns_name_equal(new, name))
+               new = ISC_LIST_NEXT(new, link);
+       if (new == NULL)
+               return (ISC_FALSE);
+       return (ISC_TRUE);
+}
index 874bcf7d27d310c3a639cc2e9ebe71f3512d8fe2..dfc791b8a8a8648da8d15be4a97540fdb5675609 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: namedconf.c,v 1.21 2003/04/17 03:26:58 marka Exp $ */
+/* $Id: namedconf.c,v 1.22 2003/09/17 05:24:43 marka Exp $ */
 
 #include <config.h>
 
@@ -390,7 +390,7 @@ static cfg_type_t cfg_type_forwardtype = {
 };
 
 static const char *zonetype_enums[] = {
-       "master", "slave", "stub", "hint", "forward", NULL };
+       "master", "slave", "stub", "hint", "forward", "delegation-only", NULL };
 static cfg_type_t cfg_type_zonetype = {
        "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
        &zonetype_enums
@@ -720,6 +720,7 @@ zone_only_clauses[] = {
          CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
        { "update-policy", &cfg_type_updatepolicy, 0 },
        { "database", &cfg_type_astring, 0 },
+       { "delegation-only", &cfg_type_boolean, 0 },
        /*
         * Note that the format of the check-names option is different between
         * the zone options and the global/view options.  Ugh.