]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
call zone syntax checks when running rndc addzone/modzone
authorEvan Hunt <each@isc.org>
Fri, 30 May 2025 00:27:12 +0000 (17:27 -0700)
committerEvan Hunt <each@isc.org>
Tue, 3 Jun 2025 18:15:40 +0000 (11:15 -0700)
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.

bin/named/server.c
lib/isccfg/check.c
lib/isccfg/include/isccfg/check.h

index 9d7d0e0c550f8f84cafc8749bd20a026440d2d7b..e539d77867863197f8ac7ba02da59db5d4008233 100644 (file)
@@ -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);
index 61625bdc0b647e038e0e05db2950750bfe1928ff..e6d07fdd865e108a8fd8295f8ddfbd7af0579d36 100644 (file)
@@ -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;
                }
index c4e5d2b3a247b8743ecb7a224081f4c08ab1e9db..9a670bbd3d028f99749a7f424ba566bdf3d5d403 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <isc/types.h>
 
+#include <isccfg/aclconf.h>
 #include <isccfg/cfg.h>
 
 #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.
+ */