diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 0cf76c3269..899d83bbcd 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -968,18 +968,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, result = cfg_map_get(zoptions, "dlz", &obj); if (result == ISC_R_SUCCESS) { const char *dlzname = cfg_obj_asstring(obj); - size_t len; - - if (cpval != default_dbtype) { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, - "zone '%s': both 'database' and 'dlz' " - "specified", - zname); - CHECK(ISC_R_FAILURE); - } - - len = strlen(dlzname) + 5; + size_t len = strlen(dlzname) + 5; cpval = isc_mem_allocate(mctx, len); snprintf(cpval, len, "dlz %s", dlzname); } @@ -1007,19 +996,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, filename = cfg_obj_asstring(obj); } - /* - * Unless we're using some alternative database, a primary zone - * will be needing a master file. - */ - if (ztype == dns_zone_primary && cpval == default_dbtype && - filename == NULL) - { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, - ISC_LOG_ERROR, "zone '%s': 'file' not specified", - zname); - CHECK(ISC_R_FAILURE); - } - if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { masterformat = dns_masterformat_raw; } else { @@ -1032,10 +1008,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, if (strcasecmp(masterformatstr, "text") == 0) { masterformat = dns_masterformat_text; - } else if (strcasecmp(masterformatstr, "raw") == 0) { - masterformat = dns_masterformat_raw; } else { - UNREACHABLE(); + masterformat = dns_masterformat_raw; } } @@ -1043,22 +1017,10 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, result = named_config_get(maps, "masterfile-style", &obj); if (result == ISC_R_SUCCESS) { const char *masterstylestr = cfg_obj_asstring(obj); - - if (masterformat != dns_masterformat_text) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "zone '%s': 'masterfile-style' " - "can only be used with " - "'masterfile-format text'", - zname); - CHECK(ISC_R_FAILURE); - } - if (strcasecmp(masterstylestr, "full") == 0) { masterstyle = &dns_master_style_full; - } else if (strcasecmp(masterstylestr, "relative") == 0) { - masterstyle = &dns_master_style_default; } else { - UNREACHABLE(); + masterstyle = &dns_master_style_default; } } @@ -1329,16 +1291,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, journal_size = -1; } } else { - uint64_t value = cfg_obj_asuint64(obj); - if (value > DNS_JOURNAL_SIZE_MAX) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "'max-journal-size " - "%" PRId64 "' " - "is too large", - value); - CHECK(ISC_R_RANGE); - } - journal_size = (uint32_t)value; + journal_size = (uint32_t)cfg_obj_asuint64(obj); } if (raw != NULL) { dns_zone_setjournalsize(raw, journal_size); @@ -1529,16 +1482,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, journal_size = -1; } } else { - uint64_t value = cfg_obj_asuint64(obj); - if (value > DNS_JOURNAL_SIZE_MAX) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "'max-journal-size " - "%" PRId64 "' " - "is too large", - value); - CHECK(ISC_R_RANGE); - } - journal_size = (uint32_t)value; + journal_size = (uint32_t)cfg_obj_asuint64(obj); } dns_zone_setjournalsize(zone, journal_size); } @@ -1877,22 +1821,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes")); uint32_t time_minutes = cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes")); - if (traffic_bytes == 0) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "zone '%s': 'min-transfer-rate-in' bytes" - "value can not be '0'", - zname); - CHECK(ISC_R_FAILURE); - } - /* Max. 28 days (in minutes). */ - const unsigned int time_minutes_max = 28 * 24 * 60; - if (time_minutes < 1 || time_minutes > time_minutes_max) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "zone '%s': 'min-transfer-rate-in' minutes" - "value is out of range (1..%u)", - zname, time_minutes_max); - CHECK(ISC_R_FAILURE); - } dns_zone_setminxfrratein(mayberaw, traffic_bytes, transferinsecs ? time_minutes : time_minutes * 60); diff --git a/bin/tests/system/checkconf/bad-journalsize.conf b/bin/tests/system/checkconf/bad-journalsize.conf new file mode 100644 index 0000000000..af21d75548 --- /dev/null +++ b/bin/tests/system/checkconf/bad-journalsize.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "clone" { + type secondary; + primaries { ::1; }; + file "xxx"; + max-journal-size 3g; +}; diff --git a/bin/tests/system/checkconf/bad-masterfile-masterstyle.conf b/bin/tests/system/checkconf/bad-masterfile-masterstyle.conf new file mode 100644 index 0000000000..6da75ffba2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-masterfile-masterstyle.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + file "filename"; + masterfile-format raw; + masterfile-style relative; +}; diff --git a/bin/tests/system/checkconf/bad-transfersize-1.conf b/bin/tests/system/checkconf/bad-transfersize-1.conf new file mode 100644 index 0000000000..7bccf9003e --- /dev/null +++ b/bin/tests/system/checkconf/bad-transfersize-1.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "clone" { + type secondary; + primaries { ::1; }; + file "xxx"; + min-transfer-rate-in 0 28800; +}; diff --git a/bin/tests/system/checkconf/bad-transfersize-2.conf b/bin/tests/system/checkconf/bad-transfersize-2.conf new file mode 100644 index 0000000000..ed7bc96ac2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-transfersize-2.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "clone" { + type secondary; + primaries { ::1; }; + file "xxx"; + min-transfer-rate-in 1024 65536; +}; diff --git a/lib/isccfg/check.c b/lib/isccfg/check.c index e6d07fdd86..22cb3df899 100644 --- a/lib/isccfg/check.c +++ b/lib/isccfg/check.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -2921,6 +2922,32 @@ check: return result; } +/* + * Try to find a zone option in one of up to three levels of options: + * for example, the zone, view, and global option blocks. + * (Fewer levels can be specified for options that aren't defined at + * all three levels.) + */ +static isc_result_t +get_zoneopt(const cfg_obj_t *opts1, const cfg_obj_t *opts2, + const cfg_obj_t *opts3, const char *name, const cfg_obj_t **objp) { + isc_result_t result = ISC_R_NOTFOUND; + + REQUIRE(*objp == NULL); + + if (opts1 != NULL) { + result = cfg_map_get(opts1, name, objp); + } + if (*objp == NULL && opts2 != NULL) { + result = cfg_map_get(opts2, name, objp); + } + if (*objp == NULL && opts3 != NULL) { + result = cfg_map_get(opts3, name, objp); + } + + return result; +} + isc_result_t isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, const cfg_obj_t *config, isc_symtab_t *symtab, @@ -3168,13 +3195,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Check if a dnssec-policy is set. */ obj = NULL; - (void)cfg_map_get(zoptions, "dnssec-policy", &obj); - if (obj == NULL && voptions != NULL) { - (void)cfg_map_get(voptions, "dnssec-policy", &obj); - } - if (obj == NULL && goptions != NULL) { - (void)cfg_map_get(goptions, "dnssec-policy", &obj); - } + (void)get_zoneopt(zoptions, voptions, goptions, "dnssec-policy", &obj); if (obj != NULL) { kaspname = cfg_obj_asstring(obj); if (strcmp(kaspname, "default") == 0) { @@ -3237,13 +3258,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * */ if (has_dnssecpolicy) { obj = NULL; - (void)cfg_map_get(zoptions, "max-zone-ttl", &obj); - if (obj == NULL && voptions != NULL) { - (void)cfg_map_get(voptions, "max-zone-ttl", &obj); - } - if (obj == NULL && goptions != NULL) { - (void)cfg_map_get(goptions, "max-zone-ttl", &obj); - } + (void)get_zoneopt(zoptions, voptions, goptions, "max-zone-ttl", + &obj); if (obj != NULL) { cfg_obj_log(obj, ISC_LOG_ERROR, "zone '%s': option 'max-zone-ttl' " @@ -3305,13 +3321,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, bool donotify = true; obj = NULL; - tresult = cfg_map_get(zoptions, "notify", &obj); - if (tresult != ISC_R_SUCCESS && voptions != NULL) { - tresult = cfg_map_get(voptions, "notify", &obj); - } - if (tresult != ISC_R_SUCCESS && goptions != NULL) { - tresult = cfg_map_get(goptions, "notify", &obj); - } + tresult = get_zoneopt(zoptions, voptions, goptions, "notify", + &obj); if (tresult == ISC_R_SUCCESS) { if (cfg_obj_isboolean(obj)) { donotify = cfg_obj_asboolean(obj); @@ -3334,11 +3345,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, "'notify' is disabled", znamestr); } - if (tresult != ISC_R_SUCCESS && voptions != NULL) { - tresult = cfg_map_get(voptions, "also-notify", &obj); - } - if (tresult != ISC_R_SUCCESS && goptions != NULL) { - tresult = cfg_map_get(goptions, "also-notify", &obj); + if (tresult != ISC_R_SUCCESS) { + tresult = get_zoneopt(voptions, goptions, NULL, + "also-notify", &obj); } if (tresult == ISC_R_SUCCESS && donotify) { uint32_t count; @@ -3467,11 +3476,9 @@ isccfg_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. */ - if (res1 != ISC_R_SUCCESS && voptions != NULL) { - res1 = cfg_map_get(voptions, "allow-update", &au); - } - if (res1 != ISC_R_SUCCESS && goptions != NULL) { - res1 = cfg_map_get(goptions, "allow-update", &au); + if (res1 != ISC_R_SUCCESS) { + res1 = get_zoneopt(voptions, goptions, NULL, + "allow-update", &au); } if (res2 == ISC_R_SUCCESS) { @@ -3550,12 +3557,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, */ obj = NULL; if (root) { - if (voptions != NULL) { - (void)cfg_map_get(voptions, "forwarders", &obj); - } - if (obj == NULL && goptions != NULL) { - (void)cfg_map_get(goptions, "forwarders", &obj); - } + (void)get_zoneopt(voptions, goptions, NULL, "forwarders", &obj); } if (check_forward(config, zoptions, obj) != ISC_R_SUCCESS) { result = ISC_R_FAILURE; @@ -3572,12 +3574,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, /* * Forward mode not explicitly configured. */ - if (voptions != NULL) { - cfg_map_get(voptions, "forward", &obj); - } - if (obj == NULL && goptions != NULL) { - cfg_map_get(goptions, "forward", &obj); - } + (void)get_zoneopt(voptions, goptions, NULL, "forward", + &obj); if (obj == NULL || strcasecmp(cfg_obj_asstring(obj), "first") == 0) { @@ -3679,13 +3677,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Warn if key-directory doesn't exist */ obj = NULL; - (void)cfg_map_get(zoptions, "key-directory", &obj); - if (obj == NULL && voptions != NULL) { - (void)cfg_map_get(voptions, "key-directory", &obj); - } - if (obj == NULL && goptions != NULL) { - (void)cfg_map_get(goptions, "key-directory", &obj); - } + (void)get_zoneopt(zoptions, voptions, goptions, "key-directory", &obj); if (obj != NULL) { dir = cfg_obj_asstring(obj); @@ -3706,7 +3698,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(obj, ISC_LOG_WARNING, "key-directory: '%s' %s", dir, isc_result_totext(tresult)); - result = tresult; + if (result == ISC_R_SUCCESS) { + result = tresult; + } } } @@ -3722,7 +3716,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, tresult = keydirexist(zconfig, "key-directory", zname, dir, kaspname, keydirs, mctx); } - if (tresult != ISC_R_SUCCESS) { + if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) { result = tresult; } } @@ -3739,7 +3733,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(zconfig, ISC_LOG_ERROR, "'log-report-channel' cannot be set in " "the root zone"); - result = ISC_R_FAILURE; + if (result == ISC_R_SUCCESS) { + result = ISC_R_FAILURE; + } } } @@ -3747,7 +3743,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Check various options. */ tresult = check_options(zoptions, config, false, mctx, optlevel_zone); - if (tresult != ISC_R_SUCCESS) { + if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) { result = tresult; } @@ -3770,7 +3766,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, "zone '%s': cannot specify both 'dlz' " "and 'database'", znamestr); - result = ISC_R_FAILURE; + if (result == ISC_R_SUCCESS) { + result = ISC_R_FAILURE; + } } else if (!dlz && (tresult == ISC_R_NOTFOUND || (tresult == ISC_R_SUCCESS && @@ -3789,14 +3787,17 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(zconfig, ISC_LOG_ERROR, "zone '%s': missing 'file' entry", znamestr); - result = tresult; + if (result == ISC_R_SUCCESS) { + result = tresult; + } } else if (tresult == ISC_R_SUCCESS && files != NULL && (ztype == CFG_ZONE_SECONDARY || ztype == CFG_ZONE_MIRROR || ddns || has_dnssecpolicy)) { tresult = fileexist(fileobj, files, true); - if (tresult != ISC_R_SUCCESS) { + if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) + { result = tresult; } } else if (tresult == ISC_R_SUCCESS && files != NULL && @@ -3804,12 +3805,84 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, ztype == CFG_ZONE_HINT)) { tresult = fileexist(fileobj, files, false); - if (tresult != ISC_R_SUCCESS) { + if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) + { result = tresult; } } } + /* + * Check that masterfile-format and masterfile-style are + * consistent. + */ + obj = NULL; + tresult = get_zoneopt(zoptions, voptions, goptions, "masterfile-format", + &obj); + if (tresult == ISC_R_SUCCESS && + strcasecmp(cfg_obj_asstring(obj), "raw") == 0) + { + obj = NULL; + tresult = get_zoneopt(zoptions, voptions, goptions, + "masterfile-style", &obj); + if (tresult == ISC_R_SUCCESS) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "zone '%s': 'masterfile-style' " + "can only be used with " + "'masterfile-format text'", + znamestr); + if (result == ISC_R_SUCCESS) { + result = ISC_R_FAILURE; + } + } + } + + obj = NULL; + (void)get_zoneopt(zoptions, voptions, goptions, "max-journal-size", + &obj); + if (obj != NULL && cfg_obj_isuint64(obj)) { + uint64_t value = cfg_obj_asuint64(obj); + if (value > DNS_JOURNAL_SIZE_MAX) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "'max-journal-size %" PRId64 "' " + "is too large", + value); + if (result == ISC_R_SUCCESS) { + result = ISC_R_RANGE; + } + } + } + + obj = NULL; + (void)get_zoneopt(zoptions, voptions, goptions, "min-transfer-rate-in", + &obj); + if (obj != NULL) { + uint32_t traffic_bytes = + cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes")); + uint32_t time_minutes = + cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes")); + if (traffic_bytes == 0) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "zone '%s': 'min-transfer-rate-in' bytes " + "value cannot be '0'", + znamestr); + if (result == ISC_R_SUCCESS) { + result = ISC_R_RANGE; + } + } + /* Max. 28 days (in minutes). */ + const unsigned int time_minutes_max = 28 * 24 * 60; + if (time_minutes < 1 || time_minutes > time_minutes_max) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "zone '%s': 'min-transfer-rate-in' minutes " + "value is out of range (1..%u)", + znamestr, time_minutes_max); + if (result == ISC_R_SUCCESS) { + result = ISC_R_RANGE; + } + } + } + return result; }