]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3958. [bug] Detect when writeable files have multiple references
authorMark Andrews <marka@isc.org>
Mon, 29 Sep 2014 00:50:39 +0000 (10:50 +1000)
committerMark Andrews <marka@isc.org>
Mon, 29 Sep 2014 02:08:52 +0000 (12:08 +1000)
                        in named.conf. [RT #37172]

(cherry picked from commit 386d6c08167bc048dfd20e3bba051a5f9d3cc545)

CHANGES
bin/tests/system/checkconf/bad-sharedwritable1.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-sharedwritable2.conf [new file with mode: 0644]
bin/tests/system/checkconf/good.conf
lib/bind9/check.c

diff --git a/CHANGES b/CHANGES
index 40c0db67f34a004dc801a7fbedc6046beda1d8be..a82fe34d015aeb41d001fe1153a76bf6552ce05e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3958.  [bug]           Detect when writeable files have multiple references
+                       in named.conf. [RT #37172]
+
 3957.  [bug]           "dnssec-keygen -S" failed for ECCGOST, ECDSAP256SHA256
                        and ECDSAP384SHA384. [RT #37183]
 
diff --git a/bin/tests/system/checkconf/bad-sharedwritable1.conf b/bin/tests/system/checkconf/bad-sharedwritable1.conf
new file mode 100644 (file)
index 0000000..4997d51
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014  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.
+ */
+
+zone a {
+       type master;
+       file "shared.db";
+};
+zone b {
+       type slave;
+       file "shared.db";
+       masters { 1.2.3.4; };
+};
diff --git a/bin/tests/system/checkconf/bad-sharedwritable2.conf b/bin/tests/system/checkconf/bad-sharedwritable2.conf
new file mode 100644 (file)
index 0000000..c9bdc43
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014  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.
+ */
+
+zone a {
+       type slave;
+       file "shared.db";
+       masters { 1.2.3.4; };
+};
+zone b {
+       type slave;
+       file "shared.db";
+       masters { 1.2.3.4; };
+};
index 008869a2acf0e3c27bf683d84d6aad976eaf44bf..100fc6fd5eedc8f380e73013763160bac3e8895f 100644 (file)
@@ -83,7 +83,7 @@ view "second" {
        };
        zone "example1" {
                type master;
-               file "yyy";
+               file "zzz";
                update-policy local;
        };
        zone "example2" {
index 7e55b1c5cf45976fb70980a388754b55b50a6f79..03334a74afe6482c791cac10788f01024e3df4fc 100644 (file)
 
 #include <bind9/check.h>
 
+static isc_result_t
+fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, isc_boolean_t writeable,
+         isc_log_t *logctxlogc);
+
 static void
 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
        UNUSED(type);
@@ -1279,8 +1283,8 @@ check_nonzero(const cfg_obj_t *options, isc_log_t *logctx) {
 static isc_result_t
 check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
               const cfg_obj_t *config, isc_symtab_t *symtab,
-              dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
-              isc_log_t *logctx, isc_mem_t *mctx)
+              isc_symtab_t *files, dns_rdataclass_t defclass,
+              cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx)
 {
        const char *znamestr;
        const char *typestr;
@@ -1296,6 +1300,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
        isc_buffer_t b;
        isc_boolean_t root = ISC_FALSE;
        const cfg_listelt_t *element;
+       isc_boolean_t ddns = ISC_FALSE;
 
        static optionstable options[] = {
        { "allow-notify", SLAVEZONE | CHECKACL },
@@ -1527,7 +1532,6 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
         * Master zones can't have both "allow-update" and "update-policy".
         */
        if (ztype == MASTERZONE) {
-               isc_boolean_t ddns = ISC_FALSE;
                isc_result_t res1, res2, res3;
                const cfg_obj_t *au = NULL;
                const char *arg;
@@ -1553,7 +1557,6 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                 * we should also check for allow-update at the
                 * view and options levels.
                 */
-               obj = NULL;
                if (res1 != ISC_R_SUCCESS && voptions != NULL)
                        res1 = cfg_map_get(voptions, "allow-update", &au);
                if (res1 != ISC_R_SUCCESS && goptions != NULL)
@@ -1772,14 +1775,24 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
            (tresult == ISC_R_SUCCESS &&
             (strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
              strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) {
-               obj = NULL;
-               tresult = cfg_map_get(zoptions, "file", &obj);
+               const cfg_obj_t *fileobj = NULL;
+               tresult = cfg_map_get(zoptions, "file", &fileobj);
                if (tresult != ISC_R_SUCCESS &&
                    (ztype == MASTERZONE || ztype == HINTZONE)) {
                        cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
                                    "zone '%s': missing 'file' entry",
                                    znamestr);
                        result = tresult;
+               } else if (tresult == ISC_R_SUCCESS &&
+                          (ztype == SLAVEZONE || ddns)) {
+                       tresult = fileexist(fileobj, files, ISC_TRUE, logctx);
+                       if (tresult != ISC_R_SUCCESS)
+                               result = tresult;
+               } else if (tresult == ISC_R_SUCCESS &&
+                          (ztype == MASTERZONE || ztype == HINTZONE)) {
+                       tresult = fileexist(fileobj, files, ISC_FALSE, logctx);
+                       if (tresult != ISC_R_SUCCESS)
+                               result = tresult;
                }
        }
 
@@ -1885,6 +1898,47 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
        return (ISC_R_SUCCESS);
 }
 
+static isc_result_t
+fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, isc_boolean_t writeable,
+         isc_log_t *logctx)
+{
+       isc_result_t result;
+       isc_symvalue_t symvalue;
+       unsigned int line;
+       const char *file;
+
+       result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 0, &symvalue);
+       if (result == ISC_R_SUCCESS) {
+               if (writeable) {
+                       file = cfg_obj_file(symvalue.as_cpointer);
+                       line = cfg_obj_line(symvalue.as_cpointer);
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "writeable file '%s': already in use: "
+                                   "%s:%u", cfg_obj_asstring(obj),
+                                   file, line);
+                       return (ISC_R_EXISTS);
+               }
+               result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 2,
+                                          &symvalue);
+               if (result == ISC_R_SUCCESS) {
+                       file = cfg_obj_file(symvalue.as_cpointer);
+                       line = cfg_obj_line(symvalue.as_cpointer);
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "writeable file '%s': already in use: "
+                                   "%s:%u", cfg_obj_asstring(obj),
+                                   file, line);
+                       return (ISC_R_EXISTS);
+               }
+               return (ISC_R_SUCCESS);
+       }
+
+       symvalue.as_cpointer = obj;
+       result = isc_symtab_define(symtab, cfg_obj_asstring(obj),
+                                  writeable ? 2 : 1, symvalue,
+                                  isc_symexists_reject);
+       return (result);
+}
+
 /*
  * Check key list for duplicates key names and that the key names
  * are valid domain names as these keys are used for TSIG.
@@ -2192,7 +2246,7 @@ check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed,
 static isc_result_t
 check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
               const char *viewname, dns_rdataclass_t vclass,
-              isc_log_t *logctx, isc_mem_t *mctx)
+              isc_symtab_t *files, isc_log_t *logctx, isc_mem_t *mctx)
 {
        const cfg_obj_t *zones = NULL;
        const cfg_obj_t *keys = NULL;
@@ -2235,7 +2289,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                const cfg_obj_t *zone = cfg_listelt_value(element);
 
                tresult = check_zoneconf(zone, voptions, config, symtab,
-                                        vclass, actx, logctx, mctx);
+                                        files, vclass, actx, logctx,
+                                        mctx);
                if (tresult != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        }
@@ -2696,6 +2751,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
        isc_result_t result = ISC_R_SUCCESS;
        isc_result_t tresult;
        isc_symtab_t *symtab = NULL;
+       isc_symtab_t *files = NULL;
 
        static const char *builtin[] = { "localhost", "localnets",
                                         "any", "none"};
@@ -2723,9 +2779,19 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
                if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
 
+       /*
+        * Use case insensitve comparision as not all file systems are
+        * case sensitive. This will prevent people using FOO.DB and foo.db
+        * on case sensitive file systems but that shouldn't be a major issue.
+        */
+       tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE,
+                                   &files);
+       if (tresult != ISC_R_SUCCESS)
+               result = tresult;
+
        if (views == NULL) {
                if (check_viewconf(config, NULL, NULL, dns_rdataclass_in,
-                                  logctx, mctx) != ISC_R_SUCCESS)
+                                  files, logctx, mctx) != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        } else {
                const cfg_obj_t *zones = NULL;
@@ -2796,13 +2862,15 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
                        }
                }
                if (tresult == ISC_R_SUCCESS)
-                       tresult = check_viewconf(config, voptions, key,
-                                                vclass, logctx, mctx);
+                       tresult = check_viewconf(config, voptions, key, vclass,
+                                                files, logctx, mctx);
                if (tresult != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        }
        if (symtab != NULL)
                isc_symtab_destroy(&symtab);
+       if (files != NULL)
+               isc_symtab_destroy(&files);
 
        if (views != NULL && options != NULL) {
                obj = NULL;