From: Evan Hunt Date: Fri, 30 May 2025 00:27:12 +0000 (-0700) Subject: call zone syntax checks when running rndc addzone/modzone X-Git-Tag: v9.21.9~6^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d57c1e737d49872c5c77e66e04fd603c07361f1;p=thirdparty%2Fbind9.git call zone syntax checks when running rndc addzone/modzone the function that checks zone syntax in libisccfg was previously only called when loading named.conf, not when parsing an an "rndc addzone" or "rndc modzone" command. this has been corrected. note that some checks are still skipped: those that check for duplication of filenames, key directories, etc. to fix this, we'd need to export the symbol tables that are set up when loading named.conf and preserve them so they could be reused later. --- diff --git a/bin/named/server.c b/bin/named/server.c index 9d7d0e0c550..e539d778678 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -13062,6 +13062,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, bool redirect, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; + const cfg_obj_t *voptions = NULL; #ifndef HAVE_LMDB FILE *fp = NULL; bool cleanup_config = false; @@ -13120,6 +13121,18 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, } #endif /* HAVE_LMDB */ + /* Check zone syntax */ + if (cfg->vconfig != NULL) { + voptions = cfg_tuple_get(cfg->vconfig, "options"); + } + result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL, + NULL, NULL, NULL, view->name, + view->rdclass, cfg->actx, cfg->mctx); + if (result != ISC_R_SUCCESS) { + isc_loopmgr_resume(named_g_loopmgr); + goto cleanup; + } + /* Mark view unfrozen and configure zone */ dns_view_thaw(view); result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, @@ -13239,6 +13252,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, bool redirect, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; + const cfg_obj_t *voptions = NULL; bool added; #ifndef HAVE_LMDB FILE *fp = NULL; @@ -13305,6 +13319,18 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, } #endif /* HAVE_LMDB */ + /* Check zone syntax */ + if (cfg->vconfig != NULL) { + voptions = cfg_tuple_get(cfg->vconfig, "options"); + } + result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL, + NULL, NULL, NULL, view->name, + view->rdclass, cfg->actx, cfg->mctx); + if (result != ISC_R_SUCCESS) { + isc_loopmgr_resume(named_g_loopmgr); + goto cleanup; + } + /* Reconfigure the zone */ dns_view_thaw(view); result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, @@ -13352,8 +13378,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, view, cfg->conf_parser, cfg->config, dns_zone_getorigin(zone), NULL); } else { - const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, - "options"); + voptions = cfg_tuple_get(cfg->vconfig, "options"); result = delete_zoneconf( view, cfg->conf_parser, voptions, dns_zone_getorigin(zone), NULL); diff --git a/lib/isccfg/check.c b/lib/isccfg/check.c index 61625bdc0b6..e6d07fdd865 100644 --- a/lib/isccfg/check.c +++ b/lib/isccfg/check.c @@ -1531,7 +1531,7 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config, /* * Check send-report-channel. (Skip for zone level because we - * have an additional check in check_zoneconf() for that.) + * have an additional check in isccfg_check_zoneconf() for that.) */ if (optlevel != optlevel_zone) { obj = NULL; @@ -2921,12 +2921,13 @@ check: return result; } -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, - isc_symtab_t *files, isc_symtab_t *keydirs, isc_symtab_t *inview, - const char *viewname, dns_rdataclass_t defclass, - cfg_aclconfctx_t *actx, isc_mem_t *mctx) { +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, + isc_symtab_t *files, isc_symtab_t *keydirs, + isc_symtab_t *inview, const char *viewname, + dns_rdataclass_t defclass, cfg_aclconfctx_t *actx, + isc_mem_t *mctx) { const char *znamestr = NULL; const char *typestr = NULL; const char *target = NULL; @@ -3054,7 +3055,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(zconfig, ISC_LOG_ERROR, "zone '%s': is not a valid name", znamestr); result = ISC_R_FAILURE; - } else { + } else if (symtab != NULL && inview != NULL) { char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; char *key = NULL; @@ -3713,7 +3714,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Make sure there is no other zone with the same key directory (from * (key-directory or key-store/directory) and a different dnssec-policy. */ - if (zname != NULL) { + if (zname != NULL && keydirs != NULL) { if (has_dnssecpolicy) { tresult = check_keydir(config, zconfig, zname, kaspname, dir, keydirs, mctx); @@ -3789,7 +3790,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, "zone '%s': missing 'file' entry", znamestr); result = tresult; - } else if (tresult == ISC_R_SUCCESS && + } else if (tresult == ISC_R_SUCCESS && files != NULL && (ztype == CFG_ZONE_SECONDARY || ztype == CFG_ZONE_MIRROR || ddns || has_dnssecpolicy)) @@ -3798,7 +3799,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (tresult != ISC_R_SUCCESS) { result = tresult; } - } else if (tresult == ISC_R_SUCCESS && + } else if (tresult == ISC_R_SUCCESS && files != NULL && (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_HINT)) { @@ -5197,9 +5198,9 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, CFG_LIST_FOREACH (zones, element) { const cfg_obj_t *zone = cfg_listelt_value(element); - tresult = check_zoneconf(zone, voptions, config, symtab, files, - keydirs, inview, viewname, vclass, - actx, mctx); + tresult = isccfg_check_zoneconf(zone, voptions, config, symtab, + files, keydirs, inview, + viewname, vclass, actx, mctx); if (tresult != ISC_R_SUCCESS) { result = ISC_R_FAILURE; } diff --git a/lib/isccfg/include/isccfg/check.h b/lib/isccfg/include/isccfg/check.h index c4e5d2b3a24..9a670bbd3d0 100644 --- a/lib/isccfg/include/isccfg/check.h +++ b/lib/isccfg/include/isccfg/check.h @@ -17,6 +17,7 @@ #include +#include #include #ifndef MAX_MIN_CACHE_TTL @@ -66,3 +67,20 @@ isccfg_check_key(const cfg_obj_t *config); /*%< * Same as isccfg_check_namedconf(), but for a single 'key' statement. */ + +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, + isc_symtab_t *files, isc_symtab_t *keydirs, + isc_symtab_t *inview, const char *viewname, + dns_rdataclass_t defclass, cfg_aclconfctx_t *actx, + isc_mem_t *mctx); +/*%< + * Check the syntactic validity of a zone statement, either in a + * named.conf file or in an "rndc addzone" or "rndc modzone" command. + * + * The various isc_symtab_t parameters are used when parsing named.conf + * to ensure that names are not duplicated within the file. When + * checking syntax of an "rndc addzone" command, these are passed + * as NULL and the duplication checks are skipped. + */