]> 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)
committerMichał Kępień <michal@isc.org>
Tue, 12 Jan 2021 14:21:14 +0000 (15:21 +0100)
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.

(cherry picked from commit f619708bbfed238a2f12028bfc71c7ed3b35a4a8)

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 678c9ac5f40ebbf5a86dca0fcf6e1f3ecc677bf7..85fdcb8ed38fd34fe51a75bf97de7b693898f08b 100644 (file)
@@ -567,37 +567,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) {
@@ -715,6 +724,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 39c92c0a43f7bfd1a33036bde2013ac846190856..d347f5f752c24158a51ea25d42d6f3b5b48101fc 100644 (file)
@@ -194,8 +194,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
@@ -219,7 +219,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 | * )
@@ -237,7 +237,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 ]; ... };
@@ -378,7 +378,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 | * ) ] [
@@ -519,6 +519,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
@@ -624,7 +638,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 | * )
@@ -636,7 +650,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 ]; ... };
@@ -756,7 +770,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 ];
@@ -897,7 +911,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 (
@@ -937,7 +951,7 @@ view 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\-journal\-size ( default | unlimited | sizeval );
@@ -952,13 +966,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 );
@@ -1005,7 +1023,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 | * )
@@ -1043,7 +1061,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\-journal\-size ( default | unlimited | sizeval );
@@ -1058,13 +1076,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 f98abd8e78c14a48270c8f5b74bce62fac044683..32749f04922aba1fd676c61565884cb759a09084 100644 (file)
@@ -168,16 +168,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
@@ -201,13 +198,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>;
@@ -557,9 +554,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 2c940e6668a4e4c92c4460d012b3a81aa8c6f34a..64d7aaeedfe529675db3c8a17823bc86f5f327f4 100644 (file)
@@ -1657,37 +1657,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) {
@@ -4777,6 +4875,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) {