]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
prevent "primaries" lists from having duplicate names
authorEvan Hunt <each@isc.org>
Fri, 26 Jun 2020 04:59:56 +0000 (21:59 -0700)
committerEvan Hunt <each@isc.org>
Wed, 1 Jul 2020 18:11:34 +0000 (11:11 -0700)
it is now an error to have two primaries lists with the same
name. this is true regardless of whether the "primaries" or
"masters" keywords were used to define them.

bin/named/config.c
bin/tests/system/checkconf/bad-duplicate-primaries-1.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-duplicate-primaries-2.conf [new file with mode: 0644]
bin/tests/system/checkconf/good-masters-and-primaries.conf [new file with mode: 0644]
doc/man/named.conf.5in
doc/misc/options
lib/bind9/check.c

index a49503df0042b53e5ed56b0ff86c3bbd1e00a5fa..f073bcd328a6c4cf5ec1a17b86059ad915246077 100644 (file)
@@ -566,37 +566,46 @@ named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
        }
 }
 
-isc_result_t
-named_config_getprimariesdef(const cfg_obj_t *cctx, const char *name,
-                            const cfg_obj_t **ret) {
+static isc_result_t
+getprimariesdef(const cfg_obj_t *cctx, const char *list, const char *name,
+               const cfg_obj_t **ret) {
        isc_result_t result;
-       const cfg_obj_t *primaries = NULL;
+       const cfg_obj_t *obj = NULL;
        const cfg_listelt_t *elt;
 
-       result = cfg_map_get(cctx, "primaries", &primaries);
-       if (result != ISC_R_SUCCESS) {
-               result = cfg_map_get(cctx, "masters", &primaries);
-       }
+       REQUIRE(cctx != NULL);
+       REQUIRE(name != NULL);
+       REQUIRE(ret != NULL && *ret == NULL);
+
+       result = cfg_map_get(cctx, list, &obj);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
-
-       for (elt = cfg_list_first(primaries); elt != NULL;
-            elt = cfg_list_next(elt)) {
-               const cfg_obj_t *list;
-               const char *listname;
-
-               list = cfg_listelt_value(elt);
-               listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
-
-               if (strcasecmp(listname, name) == 0) {
-                       *ret = list;
+       elt = cfg_list_first(obj);
+       while (elt != NULL) {
+               obj = cfg_listelt_value(elt);
+               if (strcasecmp(cfg_obj_asstring(cfg_tuple_get(obj, "name")),
+                              name) == 0) {
+                       *ret = obj;
                        return (ISC_R_SUCCESS);
                }
+               elt = cfg_list_next(elt);
        }
        return (ISC_R_NOTFOUND);
 }
 
+isc_result_t
+named_config_getprimariesdef(const cfg_obj_t *cctx, const char *name,
+                            const cfg_obj_t **ret) {
+       isc_result_t result;
+
+       result = getprimariesdef(cctx, "primaries", name, ret);
+       if (result != ISC_R_SUCCESS) {
+               result = getprimariesdef(cctx, "masters", name, ret);
+       }
+       return (result);
+}
+
 isc_result_t
 named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                             isc_mem_t *mctx, dns_ipkeylist_t *ipkl) {
@@ -714,6 +723,7 @@ resume:
                        if (j < l) {
                                continue;
                        }
+                       list = NULL;
                        tresult = named_config_getprimariesdef(config, listname,
                                                               &list);
                        if (tresult == ISC_R_NOTFOUND) {
diff --git a/bin/tests/system/checkconf/bad-duplicate-primaries-1.conf b/bin/tests/system/checkconf/bad-duplicate-primaries-1.conf
new file mode 100644 (file)
index 0000000..cf10157
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 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/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+primaries duplicate { 1.2.3.4; };
+primaries duplicate { 4.3.2.1; };
diff --git a/bin/tests/system/checkconf/bad-duplicate-primaries-2.conf b/bin/tests/system/checkconf/bad-duplicate-primaries-2.conf
new file mode 100644 (file)
index 0000000..b7c6f21
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 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/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+masters duplicate { 1.2.3.4; };
+primaries duplicate { 4.3.2.1; };
diff --git a/bin/tests/system/checkconf/good-masters-and-primaries.conf b/bin/tests/system/checkconf/good-masters-and-primaries.conf
new file mode 100644 (file)
index 0000000..156c63c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 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/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+masters a { 1.2.3.4; };
+primaries b { 1.2.3.4; };
index 98266cd82cce0d7b147795c49ff36c04ffd44ddc..bc3319edd5094450aac2e4c15fde6c6d0360af3f 100644 (file)
@@ -193,8 +193,8 @@ managed\-keys { string ( static\-key
 .nf
 .ft C
 masters string [ port integer ] [ dscp
-    integer ] { ( masters | ipv4_address [
-    port integer ] | ipv6_address [ port
+    integer ] { ( primaries | ipv4_address
+    port integer ] | ipv6_address [ port
     integer ] ) [ key string ]; ... };
 .ft P
 .fi
@@ -218,7 +218,7 @@ options {
       allow\-transfer { address_match_element; ... };
       allow\-update { address_match_element; ... };
       allow\-update\-forwarding { address_match_element; ... };
-      also\-notify [ port integer ] [ dscp integer ] { ( masters |
+      also\-notify [ port integer ] [ dscp integer ] { ( primaries |
           ipv4_address [ port integer ] | ipv6_address [ port
           integer ] ) [ key string ]; ... };
       alt\-transfer\-source ( ipv4_address | * ) [ port ( integer | * )
@@ -236,7 +236,7 @@ options {
       blackhole { address_match_element; ... };
       cache\-file quoted_string;
       catalog\-zones { zone string [ default\-masters [ port integer ]
-          [ dscp integer ] { ( masters | ipv4_address [ port
+          [ dscp integer ] { ( primaries | ipv4_address [ port
           integer ] | ipv6_address [ port integer ] ) [ key
           string ]; ... } ] [ zone\-directory quoted_string ] [
           in\-memory boolean ] [ min\-update\-interval duration ]; ... };
@@ -375,7 +375,7 @@ options {
       new\-zones\-directory quoted_string;
       no\-case\-compress { address_match_element; ... };
       nocookie\-udp\-size integer;
-      notify ( explicit | master\-only | boolean );
+      notify ( explicit | master\-only | primary\-only | boolean );
       notify\-delay integer;
       notify\-rate integer;
       notify\-source ( ipv4_address | * ) [ port ( integer | * ) ] [
@@ -515,6 +515,20 @@ plugin ( query ) string [ { unspecified\-text
 .fi
 .UNINDENT
 .UNINDENT
+.SS PRIMARIES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+primaries string [ port integer ] [ dscp
+    integer ] { ( primaries | ipv4_address
+    [ port integer ] | ipv6_address [ port
+    integer ] ) [ key string ]; ... };
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
 .SS SERVER
 .INDENT 0.0
 .INDENT 3.5
@@ -620,7 +634,7 @@ view string [ class ] {
       allow\-transfer { address_match_element; ... };
       allow\-update { address_match_element; ... };
       allow\-update\-forwarding { address_match_element; ... };
-      also\-notify [ port integer ] [ dscp integer ] { ( masters |
+      also\-notify [ port integer ] [ dscp integer ] { ( primaries |
           ipv4_address [ port integer ] | ipv6_address [ port
           integer ] ) [ key string ]; ... };
       alt\-transfer\-source ( ipv4_address | * ) [ port ( integer | * )
@@ -632,7 +646,7 @@ view string [ class ] {
       auto\-dnssec ( allow | maintain | off );
       cache\-file quoted_string;
       catalog\-zones { zone string [ default\-masters [ port integer ]
-          [ dscp integer ] { ( masters | ipv4_address [ port
+          [ dscp integer ] { ( primaries | ipv4_address [ port
           integer ] | ipv6_address [ port integer ] ) [ key
           string ]; ... } ] [ zone\-directory quoted_string ] [
           in\-memory boolean ] [ min\-update\-interval duration ]; ... };
@@ -752,7 +766,7 @@ view string [ class ] {
       new\-zones\-directory quoted_string;
       no\-case\-compress { address_match_element; ... };
       nocookie\-udp\-size integer;
-      notify ( explicit | master\-only | boolean );
+      notify ( explicit | master\-only | primary\-only | boolean );
       notify\-delay integer;
       notify\-source ( ipv4_address | * ) [ port ( integer | * ) ] [
           dscp integer ];
@@ -892,7 +906,7 @@ view string [ class ] {
               allow\-update { address_match_element; ... };
               allow\-update\-forwarding { address_match_element; ... };
               also\-notify [ port integer ] [ dscp integer ] { (
-                  masters | ipv4_address [ port integer ] |
+                  primaries | ipv4_address [ port integer ] |
                   ipv6_address [ port integer ] ) [ key string ];
                   ... };
               alt\-transfer\-source ( ipv4_address | * ) [ port (
@@ -932,9 +946,10 @@ view string [ class ] {
               key\-directory quoted_string;
               masterfile\-format ( map | raw | text );
               masterfile\-style ( full | relative );
-              masters [ port integer ] [ dscp integer ] { ( masters
-                  | ipv4_address [ port integer ] | ipv6_address [
-                  port integer ] ) [ key string ]; ... };
+              masters [ port integer ] [ dscp integer ] { (
+                  primaries | ipv4_address [ port integer ] |
+                  ipv6_address [ port integer ] ) [ key string ];
+                  ... };
               max\-ixfr\-ratio ( unlimited | percentage );
               max\-journal\-size ( default | unlimited | sizeval );
               max\-records integer;
@@ -948,13 +963,17 @@ view string [ class ] {
               min\-refresh\-time integer;
               min\-retry\-time integer;
               multi\-master boolean;
-              notify ( explicit | master\-only | boolean );
+              notify ( explicit | master\-only | primary\-only | boolean );
               notify\-delay integer;
               notify\-source ( ipv4_address | * ) [ port ( integer | *
                   ) ] [ dscp integer ];
               notify\-source\-v6 ( ipv6_address | * ) [ port ( integer
                   | * ) ] [ dscp integer ];
               notify\-to\-soa boolean;
+              primaries [ port integer ] [ dscp integer ] { (
+                  primaries | ipv4_address [ port integer ] |
+                  ipv6_address [ port integer ] ) [ key string ];
+                  ... };
               request\-expire boolean;
               request\-ixfr boolean;
               serial\-update\-method ( date | increment | unixtime );
@@ -1001,7 +1020,7 @@ zone string [ class ] {
       allow\-transfer { address_match_element; ... };
       allow\-update { address_match_element; ... };
       allow\-update\-forwarding { address_match_element; ... };
-      also\-notify [ port integer ] [ dscp integer ] { ( masters |
+      also\-notify [ port integer ] [ dscp integer ] { ( primaries |
           ipv4_address [ port integer ] | ipv6_address [ port
           integer ] ) [ key string ]; ... };
       alt\-transfer\-source ( ipv4_address | * ) [ port ( integer | * )
@@ -1039,7 +1058,7 @@ zone string [ class ] {
       key\-directory quoted_string;
       masterfile\-format ( map | raw | text );
       masterfile\-style ( full | relative );
-      masters [ port integer ] [ dscp integer ] { ( masters |
+      masters [ port integer ] [ dscp integer ] { ( primaries |
           ipv4_address [ port integer ] | ipv6_address [ port
           integer ] ) [ key string ]; ... };
       max\-ixfr\-ratio ( unlimited | percentage );
@@ -1055,13 +1074,16 @@ zone string [ class ] {
       min\-refresh\-time integer;
       min\-retry\-time integer;
       multi\-master boolean;
-      notify ( explicit | master\-only | boolean );
+      notify ( explicit | master\-only | primary\-only | boolean );
       notify\-delay integer;
       notify\-source ( ipv4_address | * ) [ port ( integer | * ) ] [
           dscp integer ];
       notify\-source\-v6 ( ipv6_address | * ) [ port ( integer | * ) ]
           [ dscp integer ];
       notify\-to\-soa boolean;
+      primaries [ port integer ] [ dscp integer ] { ( primaries |
+          ipv4_address [ port integer ] | ipv6_address [ port
+          integer ] ) [ key string ]; ... };
       request\-expire boolean;
       request\-ixfr boolean;
       serial\-update\-method ( date | increment | unixtime );
index b6e5cc466fabcd9b14f3919d811d42c99dd4d023..0a648e8a461c6b47a1092646bef7eb2185b8af62 100644 (file)
@@ -166,16 +166,13 @@ options {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder |
-            resolver | update ) [ ( query | response ) ];
-            ... }; // not configured
-        dnstap-identity ( <quoted_string> | none |
-            hostname ); // not configured
-        dnstap-output ( file | unix ) <quoted_string> [
-            size ( unlimited | <size> ) ] [ versions (
-            unlimited | <integer> ) ] [ suffix ( increment
-            | timestamp ) ]; // not configured
-        dnstap-version ( <quoted_string> | none ); // not configured
+        dnstap { ( all | auth | client | forwarder | resolver | update ) [
+            ( query | response ) ]; ... };
+        dnstap-identity ( <quoted_string> | none | hostname );
+        dnstap-output ( file | unix ) <quoted_string> [ size ( unlimited |
+            <size> ) ] [ versions ( unlimited | <integer> ) ] [ suffix (
+            increment | timestamp ) ];
+        dnstap-version ( <quoted_string> | none );
         dscp <integer>;
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
@@ -199,13 +196,13 @@ options {
         forward ( first | only );
         forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
             | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
-        fstrm-set-buffer-hint <integer>; // not configured
-        fstrm-set-flush-timeout <integer>; // not configured
-        fstrm-set-input-queue-size <integer>; // not configured
-        fstrm-set-output-notify-threshold <integer>; // not configured
-        fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
-        fstrm-set-output-queue-size <integer>; // not configured
-        fstrm-set-reopen-interval <duration>; // not configured
+        fstrm-set-buffer-hint <integer>;
+        fstrm-set-flush-timeout <integer>;
+        fstrm-set-input-queue-size <integer>;
+        fstrm-set-output-notify-threshold <integer>;
+        fstrm-set-output-queue-model ( mpsc | spsc );
+        fstrm-set-output-queue-size <integer>;
+        fstrm-set-reopen-interval <duration>;
         geoip-directory ( <quoted_string> | none );
         geoip-use-ecs <boolean>; // obsolete
         glue-cache <boolean>;
@@ -555,9 +552,8 @@ view <string> [ <class> ] {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder |
-            resolver | update ) [ ( query | response ) ];
-            ... }; // not configured
+        dnstap { ( all | auth | client | forwarder | resolver | update ) [
+            ( query | response ) ]; ... };
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
             <integer> ] [ dscp <integer> ] | <ipv6_address> [ port
index f2078fc6c2012157141cb5c527aa43491dfab459..1b1ae19ecb02907717158159cd4384dc4fd99744 100644 (file)
@@ -1664,37 +1664,135 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
        return (result);
 }
 
+/*
+ * Check "primaries" style list.
+ */
 static isc_result_t
-get_primaries_def(const cfg_obj_t *cctx, const char *name,
-                 const cfg_obj_t **ret) {
-       isc_result_t result;
-       const cfg_obj_t *primaries = NULL;
+bind9_check_primarylist(const cfg_obj_t *cctx, const char *list,
+                       isc_log_t *logctx, isc_symtab_t *symtab,
+                       isc_mem_t *mctx) {
+       isc_symvalue_t symvalue;
+       isc_result_t result, tresult;
+       const cfg_obj_t *obj = NULL;
        const cfg_listelt_t *elt;
 
-       result = cfg_map_get(cctx, "primaries", &primaries);
+       result = cfg_map_get(cctx, list, &obj);
        if (result != ISC_R_SUCCESS) {
-               result = cfg_map_get(cctx, "masters", &primaries);
+               return (ISC_R_SUCCESS);
+       }
+
+       elt = cfg_list_first(obj);
+       while (elt != NULL) {
+               char *tmp;
+               const char *name;
+
+               obj = cfg_listelt_value(elt);
+               name = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
+
+               tmp = isc_mem_strdup(mctx, name);
+               symvalue.as_cpointer = obj;
+               tresult = isc_symtab_define(symtab, tmp, 1, symvalue,
+                                           isc_symexists_reject);
+               if (tresult == ISC_R_EXISTS) {
+                       const char *file = NULL;
+                       unsigned int line;
+
+                       RUNTIME_CHECK(
+                               isc_symtab_lookup(symtab, tmp, 1, &symvalue) ==
+                               ISC_R_SUCCESS);
+                       file = cfg_obj_file(symvalue.as_cpointer);
+                       line = cfg_obj_line(symvalue.as_cpointer);
+
+                       if (file == NULL) {
+                               file = "<unknown file>";
+                       }
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "primaries list '%s' is duplicated: "
+                                   "also defined at %s:%u",
+                                   name, file, line);
+                       isc_mem_free(mctx, tmp);
+                       result = tresult;
+                       break;
+               } else if (tresult != ISC_R_SUCCESS) {
+                       isc_mem_free(mctx, tmp);
+                       result = tresult;
+                       break;
+               }
+
+               elt = cfg_list_next(elt);
        }
+       return (result);
+}
+
+/*
+ * Check primaries lists for duplicates.
+ */
+static isc_result_t
+bind9_check_primarylists(const cfg_obj_t *cctx, isc_log_t *logctx,
+                        isc_mem_t *mctx) {
+       isc_result_t result, tresult;
+       isc_symtab_t *symtab = NULL;
+
+       result = isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
+       tresult = bind9_check_primarylist(cctx, "primaries", logctx, symtab,
+                                         mctx);
+       if (tresult != ISC_R_SUCCESS) {
+               result = tresult;
+       }
+       tresult = bind9_check_primarylist(cctx, "masters", logctx, symtab,
+                                         mctx);
+       if (tresult != ISC_R_SUCCESS) {
+               result = tresult;
+       }
+       isc_symtab_destroy(&symtab);
+       return (result);
+}
 
-       for (elt = cfg_list_first(primaries); elt != NULL;
-            elt = cfg_list_next(elt)) {
-               const cfg_obj_t *list;
+static isc_result_t
+get_primaries(const cfg_obj_t *cctx, const char *list, const char *name,
+             const cfg_obj_t **ret) {
+       isc_result_t result;
+       const cfg_obj_t *obj = NULL;
+       const cfg_listelt_t *elt = NULL;
+
+       result = cfg_map_get(cctx, list, &obj);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       }
+
+       elt = cfg_list_first(obj);
+       while (elt != NULL) {
                const char *listname;
 
-               list = cfg_listelt_value(elt);
-               listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+               obj = cfg_listelt_value(elt);
+               listname = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
 
                if (strcasecmp(listname, name) == 0) {
-                       *ret = list;
+                       *ret = obj;
                        return (ISC_R_SUCCESS);
                }
+
+               elt = cfg_list_next(elt);
        }
+
        return (ISC_R_NOTFOUND);
 }
 
+static isc_result_t
+get_primaries_def(const cfg_obj_t *cctx, const char *name,
+                 const cfg_obj_t **ret) {
+       isc_result_t result;
+
+       result = get_primaries(cctx, "primaries", name, ret);
+       if (result != ISC_R_SUCCESS) {
+               result = get_primaries(cctx, "masters", name, ret);
+       }
+       return (result);
+}
+
 static isc_result_t
 validate_primaries(const cfg_obj_t *obj, const cfg_obj_t *config,
                   uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx) {
@@ -4781,6 +4879,10 @@ bind9_check_namedconf(const cfg_obj_t *config, bool check_plugins,
                result = ISC_R_FAILURE;
        }
 
+       if (bind9_check_primarylists(config, logctx, mctx) != ISC_R_SUCCESS) {
+               result = ISC_R_FAILURE;
+       }
+
        (void)cfg_map_get(config, "view", &views);
 
        if (views != NULL && options != NULL) {