diff --git a/CHANGES b/CHANGES index c5a1582d87..592e20e84b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4539. [bug] Referencing a nonexistant zone with rpz could lead + to a assertion failure when configuring. [RT #43787] + 4538. [bug] Call dns_client_startresolve from client->task. [RT #43896] diff --git a/bin/named/server.c b/bin/named/server.c index 52d625f598..c311d98cd0 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2160,7 +2160,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; unsigned int query_timeout, ndisp; struct cfg_context *nzctx; - dns_rpz_zone_t *rpz; REQUIRE(DNS_VIEW_VALID(view)); @@ -2319,22 +2318,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, actx, ISC_FALSE)); } - for (rpz = ISC_LIST_HEAD(view->rpz_zones); - rpz != NULL; - rpz = ISC_LIST_NEXT(rpz, link)) - { - if (!rpz->defined) { - char namebuf[DNS_NAME_FORMATSIZE]; - - dns_name_format(&rpz->origin, namebuf, sizeof(namebuf)); - cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "'%s' is not a master or slave zone", - namebuf); - result = ISC_R_NOTFOUND; - goto cleanup; - } - } - /* * If we're allowing added zones, then load zone configuration * from the newzone file for zones that were added during previous diff --git a/bin/tests/system/checkconf/bad-rpz-zone.conf b/bin/tests/system/checkconf/bad-rpz-zone.conf new file mode 100644 index 0000000000..2b9399d05f --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-zone.conf @@ -0,0 +1,5 @@ +options { + response-policy { + zone "nonexistent"; + }; +}; diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index e962b2c672..8692a95821 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -48,8 +48,10 @@ for bad in bad*.conf do ret=0 echo "I: checking that named-checkconf detects error in $bad" - $CHECKCONF $bad > /dev/null 2>&1 - if [ $? != 1 ]; then echo "I:failed"; ret=1; fi + $CHECKCONF $bad > checkconf.out 2>&1 + if [ $? != 1 ]; then ret=1; fi + grep "^$bad:[0-9]*: " checkconf.out > /dev/null || ret=1 + if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` done diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 00da5569ed..13d6846ece 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -2495,6 +2495,53 @@ check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed, return (result); } +static isc_result_t +check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj, + const char *viewname, isc_symtab_t *symtab, isc_log_t *logctx) +{ + const cfg_listelt_t *element; + const cfg_obj_t *obj, *nameobj, *zoneobj; + const char *zonename, *zonetype; + const char *forview = " for view "; + isc_symvalue_t value; + isc_result_t result, tresult; + + if (viewname == NULL) { + viewname = ""; + forview = ""; + } + result = ISC_R_SUCCESS; + + obj = cfg_tuple_get(rpz_obj, "zone list"); + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) { + obj = cfg_listelt_value(element); + nameobj = cfg_tuple_get(obj, "zone name"); + zonename = cfg_obj_asstring(nameobj); + zonetype = ""; + tresult = isc_symtab_lookup(symtab, zonename, 3, &value); + if (tresult == ISC_R_SUCCESS) { + obj = NULL; + zoneobj = value.as_cpointer; + if (zoneobj != NULL && cfg_obj_istuple(zoneobj)) + zoneobj = cfg_tuple_get(zoneobj, "options"); + if (zoneobj != NULL && cfg_obj_ismap(zoneobj)) + (void)cfg_map_get(zoneobj, "type", &obj); + if (obj != NULL) + zonetype = cfg_obj_asstring(obj); + } + if (strcasecmp(zonetype, "master") != 0 && + strcasecmp(zonetype, "slave") != 0) { + cfg_obj_log(nameobj, logctx, ISC_LOG_ERROR, + "%s '%s'%s%s is not a master or slave zone", + rpz_catz, zonename, forview, viewname); + result = ISC_R_FAILURE; + } + } + return (result); +} + static isc_result_t check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, const char *viewname, dns_rdataclass_t vclass, @@ -2509,6 +2556,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, cfg_aclconfctx_t *actx = NULL; const cfg_obj_t *obj; const cfg_obj_t *options = NULL; + const cfg_obj_t *opts = NULL; isc_boolean_t enablednssec, enablevalidation; const char *valstr = "no"; @@ -2517,6 +2565,14 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, */ (void)cfg_map_get(config, "options", &options); + /* + * The most relevant options for this view + */ + if (voptions != NULL) + opts = voptions; + else + opts = options; + /* * Check that all zone statements are syntactically correct and * there are no duplicate zones. @@ -2546,20 +2602,30 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, result = ISC_R_FAILURE; } + /* + * Check that the response-policy and catalog-zones options + * refer to zones that exist. + */ + if (opts != NULL) { + obj = NULL; + if (cfg_map_get(opts, "response-policy", &obj) == ISC_R_SUCCESS + && check_rpz_catz("response-policy zone", obj, + viewname, symtab, logctx) != ISC_R_SUCCESS) + result = ISC_R_FAILURE; + obj = NULL; + if (cfg_map_get(opts, "catalog-zones", &obj) == ISC_R_SUCCESS + && check_rpz_catz("catalog zone", obj, + viewname, symtab, logctx) != ISC_R_SUCCESS) + result = ISC_R_FAILURE; + } + isc_symtab_destroy(&symtab); /* * Check that forwarding is reasonable. */ - if (voptions == NULL) { - if (options != NULL) - if (check_forward(options, NULL, - logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } else { - if (check_forward(voptions, NULL, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } + if (opts != NULL && check_forward(opts, NULL, logctx) != ISC_R_SUCCESS) + result = ISC_R_FAILURE; /* * Check non-zero options at the global and view levels. @@ -2572,22 +2638,14 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, /* * Check that dual-stack-servers is reasonable. */ - if (voptions == NULL) { - if (options != NULL) - if (check_dual_stack(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } else { - if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } + if (opts != NULL && check_dual_stack(opts, logctx) != ISC_R_SUCCESS) + result = ISC_R_FAILURE; /* * Check that rrset-order is reasonable. */ - if (voptions != NULL) { - if (check_order(voptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } + if (opts != NULL && check_order(opts, logctx) != ISC_R_SUCCESS) + result = ISC_R_FAILURE; /* * Check that all key statements are syntactically correct and @@ -3024,10 +3082,6 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx, if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS) result = ISC_R_FAILURE; - if (options != NULL && - check_order(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - (void)cfg_map_get(config, "view", &views); if (views != NULL && options != NULL) diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 3c8dcdf014..630e5c8ea7 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -2677,11 +2677,13 @@ cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level, va_start(ap, fmt); vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); - isc_log_write(lctx, CAT, MOD, level, - "%s:%u: %s", - obj->file == NULL ? "" : obj->file, - obj->line, msgbuf); va_end(ap); + if (obj->file != NULL) { + isc_log_write(lctx, CAT, MOD, level, + "%s:%u: %s", obj->file, obj->line, msgbuf); + } else { + isc_log_write(lctx, CAT, MOD, level, "%s", msgbuf); + } } const char *