From: Mark Andrews Date: Mon, 29 Sep 2014 00:50:39 +0000 (+1000) Subject: 3958. [bug] Detect when writeable files have multiple references X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=165dec96ce57eaa84756cd7a0bd1e1565d2ac110;p=thirdparty%2Fbind9.git 3958. [bug] Detect when writeable files have multiple references in named.conf. [RT #37172] (cherry picked from commit 386d6c08167bc048dfd20e3bba051a5f9d3cc545) --- diff --git a/CHANGES b/CHANGES index 40c0db67f34..a82fe34d015 100644 --- 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 index 00000000000..4997d51a734 --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedwritable1.conf @@ -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 index 00000000000..c9bdc43a63f --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedwritable2.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf index 008869a2acf..100fc6fd5ee 100644 --- a/bin/tests/system/checkconf/good.conf +++ b/bin/tests/system/checkconf/good.conf @@ -83,7 +83,7 @@ view "second" { }; zone "example1" { type master; - file "yyy"; + file "zzz"; update-policy local; }; zone "example2" { diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 7e55b1c5cf4..03334a74afe 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -48,6 +48,10 @@ #include +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;