513 lines
18 KiB
Diff
513 lines
18 KiB
Diff
From de237c66c901b451e4957a28e0d953c57648eab9 Mon Sep 17 00:00:00 2001
|
|
From: Evan Hunt <each@isc.org>
|
|
Date: Tue, 3 Mar 2026 14:00:38 -0800
|
|
Subject: [PATCH] Disable recursion for non-IN classes
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Force recursion off, and set allow-recursion/allow-recursion-on ACLs
|
|
to none, for views with a class other than IN. Log a configuration
|
|
warning if recursion is explicitly enabled for a non-IN view.
|
|
|
|
This addresses YWH-PGM40640-74 and YWH-PGM40640-75 by preventing any
|
|
attempt at recursive processing in a class-CHAOS view, ensuring that
|
|
server addresses used for recursive queries and received in recursive
|
|
responses are of the expected format.
|
|
|
|
Fixes: isc-projects/bind9#5780
|
|
Fixes: isc-projects/bind9#5781
|
|
|
|
(cherry picked from commit 70532a37a1aec761e8a12444852866ce9d9d5fcc)
|
|
(cherry picked from commit cf0d5a4e385525e21f2ae39098b1ab90c1137a2a)
|
|
(cherry picked from commit c6b05d8449d94c74e85be70b822b7ad439abca40)
|
|
|
|
Disable UPDATE and NOTIFY for non-IN classes
|
|
|
|
Return NOTIMP for UPDATE and NOTIFY requests received for views with a
|
|
class other than IN. Only QUERY is now supported for non-IN views such
|
|
as CHAOS.
|
|
|
|
When running dns dns_rdata_tostruct() with types that are only defined
|
|
for class IN, ensure that the class is correct before proceeding.
|
|
|
|
Add an assertion that any zone being updated is of class IN. (Note
|
|
that previously, a DLZ zone could have its class value set incorrectly
|
|
to NONE; this has been fixed.)
|
|
|
|
This addresses YWH-PGM40640-70 and YWH-PGM40640-73 (as well as any
|
|
similar problems that might have occurred in the future) by minimizing
|
|
the code paths that can be reached by rdata classes other than IN, so it
|
|
is safe for the implementation to assume that rdatatypes that are only
|
|
defined for class IN, such as SVCB or WKS, have been parsed and
|
|
validated, and not accepted as unknown/opaque data.
|
|
|
|
Fixes: isc-projects/bind9#5777
|
|
Fixes: isc-projects/bind9#5779
|
|
|
|
(cherry picked from commit 9ae24c32bec16c0f64225ef04f34670018bf0765)
|
|
(cherry picked from commit a2ca2408b3ff031c426c5dc785f550c9d30bf4aa)
|
|
(cherry picked from commit f107b702c4ff4a68042d0dad8384544dd99954a8)
|
|
|
|
Validate DNS message CLASS early in request processing
|
|
|
|
Reject requests with unsupported or misused CLASS values before
|
|
further processing. Only IN, CH, HS, RESERVED0 (for DNS Cookies),
|
|
ANY (for TKEY negotiation), and NONE (for DNS UPDATE) are accepted;
|
|
all other classes return NOTIMP. Misuse of NONE or ANY outside
|
|
their allowed contexts returns FORMERR.
|
|
|
|
This adds further protection against bugs of the same general class
|
|
as YWH-PGM40640-70 and YWH-PGM40640-73.
|
|
|
|
(cherry picked from commit d41865a458b9ecd76be4097ac1bea1005cad72db)
|
|
(cherry picked from commit 1c8016c91c3674929f87cbe7ad09f3670e05ad4e)
|
|
(cherry picked from commit 6c50d4812c35fe982614cd53355c4048ab09267a)
|
|
|
|
Reject meta-classes in UPDATE and NOTIFY messages
|
|
|
|
NOTIFY and UPDATE messages must specify a data class in the
|
|
QUESTION/ZONE section. NONE and ANY are meta-classes and not
|
|
appropriate here. Return FORMERR if either is used.
|
|
|
|
Rejecting messages with a query class of NONE addresses YWH-PGM40640-72,
|
|
YWH-PGM40640-82, and YWH-PGM40640-83. Rejecting messages with a query
|
|
class of ANY addresses YWH-PGM40640-87, YWH-PGM40640-88, and
|
|
YWH-PGM40640-117.
|
|
|
|
Fixes: isc-projects/bind9#5778
|
|
Fixes: isc-projects/bind9#5782
|
|
Fixes: isc-projects/bind9#5783
|
|
Fixes: isc-projects/bind9#5797
|
|
Fixes: isc-projects/bind9#5798
|
|
Fixes: isc-projects/bind9#5853
|
|
|
|
(cherry picked from commit 7de5160517ae69196d1c323b8627b267cdd10761)
|
|
(cherry picked from commit 3c44de9e6252ec1c7742ef02ecc0d6cbf1cde5e9)
|
|
(cherry picked from commit f7d5fe628c220245a14397207893424f0b27ff53)
|
|
|
|
Skip "deny-answer-address" for non-IN addresses
|
|
|
|
Ensure that we don't attempt an ACL match for answer addresses
|
|
when handling a class-CHAOS zone. This is an additional line of
|
|
defense for YWH-PGM40640-74.
|
|
|
|
(cherry picked from commit 4cd3d8e6d866143ddc62df821a1007bf3ee7f083)
|
|
(cherry picked from commit fa60101e910346e64fa2a684b903fbcb84d8243b)
|
|
(cherry picked from commit c01d298f53b0ffbf38bf19867f368f60a9ea4ecf)
|
|
|
|
Pass empty string instead of NULL to ns_client_dumpmessage()
|
|
|
|
The two new call sites added by the CLASS-validation work passed NULL
|
|
as the reason, but ns_client_dumpmessage() bails out early on a NULL
|
|
reason — so the message dump never happened. The intent was to dump
|
|
the message and let the follow-up ns_client_log() carry the reason
|
|
text, so pass "" to suppress the prefix without short-circuiting the
|
|
dump.
|
|
|
|
(cherry picked from commit 8af39c360407a92ef31bf233b9df760d1bb9fb5f)
|
|
(cherry picked from commit 4d7e442c9aee72851f2b2d973273ebc92da42cf0)
|
|
|
|
%RH
|
|
Backport fixes.
|
|
---
|
|
bin/named/client.c | 56 +++++++++++++++++++++++++++++--
|
|
bin/named/server.c | 38 ++++++---------------
|
|
bin/named/update.c | 31 +++++++++--------
|
|
bin/tests/system/unknown/tests.sh | 12 +++----
|
|
lib/dns/adb.c | 2 +-
|
|
lib/dns/message.c | 11 ++++++
|
|
lib/dns/resolver.c | 13 +++++--
|
|
7 files changed, 109 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/bin/named/client.c b/bin/named/client.c
|
|
index ea121b301e..6990e02b03 100644
|
|
--- a/bin/named/client.c
|
|
+++ b/bin/named/client.c
|
|
@@ -40,6 +40,7 @@
|
|
#include <dns/dnstap.h>
|
|
#include <dns/cache.h>
|
|
#include <dns/edns.h>
|
|
+#include <dns/enumclass.h>
|
|
#include <dns/events.h>
|
|
#include <dns/message.h>
|
|
#include <dns/peer.h>
|
|
@@ -2829,7 +2830,9 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|
goto cleanup;
|
|
}
|
|
|
|
- if (client->message->rdclass == 0) {
|
|
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
|
|
+ switch (client->message->rdclass) {
|
|
+ case dns_rdataclass_reserved0:
|
|
if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
|
|
client->message->opcode == dns_opcode_query &&
|
|
client->message->counts[DNS_SECTION_QUESTION] == 0U)
|
|
@@ -2851,6 +2854,44 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|
"message class could not be determined");
|
|
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
|
goto cleanup;
|
|
+ case dns_rdataclass_in:
|
|
+ break;
|
|
+ case dns_rdataclass_chaos:
|
|
+ break;
|
|
+ case dns_rdataclass_hs:
|
|
+ break;
|
|
+ case dns_rdataclass_none:
|
|
+ if (client->message->opcode != dns_opcode_update) {
|
|
+ ns_client_dumpmessage(client,
|
|
+ "message class NONE can be only "
|
|
+ "used in DNS updates");
|
|
+ ns_client_error(client, DNS_R_FORMERR);
|
|
+ return;
|
|
+ }
|
|
+ break;
|
|
+ case dns_rdataclass_any:
|
|
+ /*
|
|
+ * Required for TKEY negotiation.
|
|
+ */
|
|
+ if (client->message->tkey == 0) {
|
|
+ ns_client_dumpmessage(client,
|
|
+ "message class ANY can be only "
|
|
+ "used for TKEY negotiation");
|
|
+ ns_client_error(client, DNS_R_FORMERR);
|
|
+ return;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ dns_rdataclass_format(client->message->rdclass, classbuf,
|
|
+ sizeof(classbuf));
|
|
+ ns_client_dumpmessage(client, "");
|
|
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
|
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
|
+ "message class could not be determined");
|
|
+ ns_client_dumpmessage(client, "message class could not be "
|
|
+ "determined");
|
|
+ ns_client_error(client, DNS_R_NOTIMP);
|
|
+ goto cleanup;
|
|
}
|
|
|
|
/*
|
|
@@ -2969,7 +3010,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
|
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
|
"no matching view in class '%s'", classname);
|
|
- ns_client_dumpmessage(client, "no matching view in class");
|
|
+ ns_client_dumpmessage(client, "");
|
|
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
|
|
goto cleanup;
|
|
}
|
|
@@ -3149,11 +3190,19 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
|
break;
|
|
case dns_opcode_update:
|
|
CTRACE("update");
|
|
+ if (client->view->rdclass != dns_rdataclass_in) {
|
|
+ ns_client_error(client, DNS_R_NOTIMP);
|
|
+ break;
|
|
+ }
|
|
ns_client_settimeout(client, 60);
|
|
ns_update_start(client, sigresult);
|
|
break;
|
|
case dns_opcode_notify:
|
|
CTRACE("notify");
|
|
+ if (client->view->rdclass != dns_rdataclass_in) {
|
|
+ ns_client_error(client, DNS_R_NOTIMP);
|
|
+ break;
|
|
+ }
|
|
ns_client_settimeout(client, 60);
|
|
ns_notify_start(client);
|
|
break;
|
|
@@ -4241,8 +4290,9 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
|
|
int len = 1024;
|
|
isc_result_t result;
|
|
|
|
- if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
|
|
+ if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)) || reason == NULL) {
|
|
return;
|
|
+ }
|
|
|
|
/*
|
|
* Note that these are multiline debug messages. We want a newline
|
|
diff --git a/bin/named/server.c b/bin/named/server.c
|
|
index 2086e41ca9..be521f6cf2 100644
|
|
--- a/bin/named/server.c
|
|
+++ b/bin/named/server.c
|
|
@@ -1756,6 +1756,7 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
|
|
dns_rdataclass_t zclass = view->rdclass;
|
|
isc_result_t result;
|
|
|
|
+ dns_zone_setclass(zone, zclass);
|
|
result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
@@ -4170,32 +4171,14 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|
CHECK(configure_alternates(config, view, alternates));
|
|
|
|
/*
|
|
- * We have default hints for class IN if we need them.
|
|
+ * We have default root hints for class IN if we need them.
|
|
+ * Each view gets its own rootdb so a priming response only
|
|
+ * writes into that view's copy. Other classes don't support
|
|
+ * recursion and don't need hints.
|
|
*/
|
|
if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
|
|
dns_view_sethints(view, ns_g_server->in_roothints);
|
|
|
|
- /*
|
|
- * If we still have no hints, this is a non-IN view with no
|
|
- * "hints zone" configured. Issue a warning, except if this
|
|
- * is a root server. Root servers never need to consult
|
|
- * their hints, so it's no point requiring users to configure
|
|
- * them.
|
|
- */
|
|
- if (view->hints == NULL) {
|
|
- dns_zone_t *rootzone = NULL;
|
|
- (void)dns_view_findzone(view, dns_rootname, &rootzone);
|
|
- if (rootzone != NULL) {
|
|
- dns_zone_detach(&rootzone);
|
|
- need_hints = false;
|
|
- }
|
|
- if (need_hints)
|
|
- isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
|
- NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
|
- "no root hints for view '%s'",
|
|
- view->name);
|
|
- }
|
|
-
|
|
/*
|
|
* Configure the view's TSIG keys.
|
|
*/
|
|
@@ -4302,7 +4285,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|
obj = NULL;
|
|
result = ns_config_get(maps, "recursion", &obj);
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
- view->recursion = cfg_obj_asboolean(obj);
|
|
+ view->recursion = (view->rdclass == dns_rdataclass_in &&
|
|
+ cfg_obj_asboolean(obj));
|
|
|
|
obj = NULL;
|
|
result = ns_config_get(maps, "auth-nxdomain", &obj);
|
|
@@ -4409,10 +4393,10 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|
"allow-query-cache", NULL, actx,
|
|
ns_g_mctx, &view->cacheacl));
|
|
|
|
- if (strcmp(view->name, "_bind") != 0 &&
|
|
- view->rdclass != dns_rdataclass_chaos)
|
|
- {
|
|
- /* named.conf only */
|
|
+ if (view->rdclass != dns_rdataclass_in) {
|
|
+ dns_acl_none(ns_g_mctx, &view->recursionacl);
|
|
+ dns_acl_none(ns_g_mctx, &view->recursiononacl);
|
|
+ } else {
|
|
CHECK(configure_view_acl(vconfig, config, NULL,
|
|
"allow-recursion", NULL, actx,
|
|
ns_g_mctx, &view->recursionacl));
|
|
diff --git a/bin/named/update.c b/bin/named/update.c
|
|
index 407ac38272..be469f8e91 100644
|
|
--- a/bin/named/update.c
|
|
+++ b/bin/named/update.c
|
|
@@ -1269,7 +1269,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
|
|
dbsig.algorithm == updatesig.algorithm)
|
|
return (true);
|
|
}
|
|
- if (db_rr->type == dns_rdatatype_wks) {
|
|
+
|
|
+ if (db_rr->rdclass == dns_rdataclass_in &&
|
|
+ db_rr->type == dns_rdatatype_wks)
|
|
+ {
|
|
/*
|
|
* Compare the address and protocol fields only. These
|
|
* form the first five bytes of the RR data. Do a
|
|
@@ -1412,8 +1415,7 @@ add_rr_prepare_action(void *data, rr_t *rr) {
|
|
* 'rdata', and 'ttl', respectively.
|
|
*/
|
|
static void
|
|
-get_current_rr(dns_message_t *msg, dns_section_t section,
|
|
- dns_rdataclass_t zoneclass, dns_name_t **name,
|
|
+get_current_rr(dns_message_t *msg, dns_section_t section, dns_name_t **name,
|
|
dns_rdata_t *rdata, dns_rdatatype_t *covers,
|
|
dns_ttl_t *ttl, dns_rdataclass_t *update_class)
|
|
{
|
|
@@ -1430,7 +1432,7 @@ get_current_rr(dns_message_t *msg, dns_section_t section,
|
|
dns_rdataset_current(rdataset, rdata);
|
|
INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
|
|
*update_class = rdata->rdclass;
|
|
- rdata->rdclass = zoneclass;
|
|
+ rdata->rdclass = dns_rdataclass_in;
|
|
}
|
|
|
|
/*%
|
|
@@ -1580,7 +1582,7 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
dns_ttl_t ttl;
|
|
dns_rdataclass_t update_class;
|
|
- get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
|
|
+ get_current_rr(request, DNS_SECTION_UPDATE,
|
|
&name, &rdata, &covers, &ttl, &update_class);
|
|
|
|
if (! dns_name_issubdomain(name, zonename))
|
|
@@ -1812,6 +1814,9 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
|
CHECK(DNS_R_DROP);
|
|
}
|
|
|
|
+ /* Updates are only supported for class IN. */
|
|
+ INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
|
+
|
|
event = (update_event_t *)
|
|
isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
|
|
update_action, NULL, sizeof(*event));
|
|
@@ -2798,7 +2803,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|
isc_mem_t *mctx = client->mctx;
|
|
dns_rdatatype_t covers;
|
|
dns_message_t *request = client->message;
|
|
- dns_rdataclass_t zoneclass;
|
|
dns_name_t *zonename = NULL;
|
|
dns_ssutable_t *ssutable = NULL;
|
|
dns_fixedname_t tmpnamefixed;
|
|
@@ -2819,10 +2823,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|
|
|
CHECK(dns_zone_getdb(zone, &db));
|
|
zonename = dns_db_origin(db);
|
|
- zoneclass = dns_db_class(db);
|
|
dns_zone_getssutable(zone, &ssutable);
|
|
options = dns_zone_getoptions(zone);
|
|
|
|
+ INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
|
/*
|
|
* Get old and new versions now that queryacl has been checked.
|
|
*/
|
|
@@ -2843,8 +2847,8 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|
dns_rdataclass_t update_class;
|
|
bool flag;
|
|
|
|
- get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
|
|
- &name, &rdata, &covers, &ttl, &update_class);
|
|
+ get_current_rr(request, DNS_SECTION_PREREQUISITE, &name, &rdata,
|
|
+ &covers, &ttl, &update_class);
|
|
|
|
if (ttl != 0)
|
|
PREREQFAILC(DNS_R_FORMERR,
|
|
@@ -2902,7 +2906,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|
"satisfied");
|
|
}
|
|
}
|
|
- } else if (update_class == zoneclass) {
|
|
+ } else if (update_class == dns_rdataclass_in) {
|
|
/* "temp<rr.name, rr.type> += rr;" */
|
|
result = temp_append(&temp, name, &rdata);
|
|
if (result != ISC_R_SUCCESS) {
|
|
@@ -2960,11 +2964,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|
dns_rdataclass_t update_class;
|
|
bool flag;
|
|
|
|
- get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
|
|
- &name, &rdata, &covers, &ttl, &update_class);
|
|
-
|
|
- if (update_class == zoneclass) {
|
|
+ get_current_rr(request, DNS_SECTION_UPDATE, &name,
|
|
+ &rdata, &covers, &ttl, &update_class);
|
|
|
|
+ if (update_class == dns_rdataclass_in) {
|
|
/*
|
|
* RFC1123 doesn't allow MF and MD in master zones.
|
|
*/
|
|
diff --git a/bin/tests/system/unknown/tests.sh b/bin/tests/system/unknown/tests.sh
|
|
index deb9a419ab..a6ceb7c69b 100644
|
|
--- a/bin/tests/system/unknown/tests.sh
|
|
+++ b/bin/tests/system/unknown/tests.sh
|
|
@@ -73,8 +73,8 @@ echo_i "querying for various representations of a CLASS10 TYPE1 record"
|
|
for i in 1 2
|
|
do
|
|
ret=0
|
|
- $DIG +short $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out || ret=1
|
|
- echo '\# 4 0A000001' | $DIFF - dig.out || ret=1
|
|
+ $DIG $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out || ret=1
|
|
+ grep -q "NOTIMP" dig.out || ret=1
|
|
if [ $ret != 0 ]
|
|
then
|
|
echo_i "#$i failed"
|
|
@@ -86,8 +86,8 @@ echo_i "querying for various representations of a CLASS10 TXT record"
|
|
for i in 1 2 3 4
|
|
do
|
|
ret=0
|
|
- $DIG +short $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out || ret=1
|
|
- echo '"hello"' | $DIFF - dig.out || ret=1
|
|
+ $DIG $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out || ret=1
|
|
+ grep -q "NOTIMP" dig.out || ret=1
|
|
if [ $ret != 0 ]
|
|
then
|
|
echo_i "#$i failed"
|
|
@@ -99,8 +99,8 @@ echo_i "querying for various representations of a CLASS10 TYPE123 record"
|
|
for i in 1 2
|
|
do
|
|
ret=0
|
|
- $DIG +short $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out || ret=1
|
|
- echo '\# 1 00' | $DIFF - dig.out || ret=1
|
|
+ $DIG $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out || ret=1
|
|
+ grep -q "NOTIMP" dig.out || ret=1
|
|
if [ $ret != 0 ]
|
|
then
|
|
echo_i "#$i failed"
|
|
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
|
|
index e12c804f2b..25cfa32873 100644
|
|
--- a/lib/dns/adb.c
|
|
+++ b/lib/dns/adb.c
|
|
@@ -892,7 +892,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|
INSIST(DNS_ADB_VALID(adb));
|
|
|
|
rdtype = rdataset->type;
|
|
- INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
|
|
+ REQUIRE(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
|
|
if (rdtype == dns_rdatatype_a)
|
|
findoptions = DNS_ADBFIND_INET;
|
|
else
|
|
diff --git a/lib/dns/message.c b/lib/dns/message.c
|
|
index 5603bcadf9..f9e3163d71 100644
|
|
--- a/lib/dns/message.c
|
|
+++ b/lib/dns/message.c
|
|
@@ -1179,6 +1179,17 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|
rdtype = isc_buffer_getuint16(source);
|
|
rdclass = isc_buffer_getuint16(source);
|
|
|
|
+ /*
|
|
+ * Notify and update messages need to specify the data class.
|
|
+ */
|
|
+ if ((msg->opcode == dns_opcode_update ||
|
|
+ msg->opcode == dns_opcode_notify) &&
|
|
+ (rdclass == dns_rdataclass_none ||
|
|
+ rdclass == dns_rdataclass_any))
|
|
+ {
|
|
+ DO_ERROR(DNS_R_FORMERR);
|
|
+ }
|
|
+
|
|
/*
|
|
* If this class is different than the one we already read,
|
|
* this is an error.
|
|
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
|
|
index 1c704551aa..5331ea9dd2 100644
|
|
--- a/lib/dns/resolver.c
|
|
+++ b/lib/dns/resolver.c
|
|
@@ -6514,9 +6514,16 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
|
|
}
|
|
|
|
/*
|
|
- * Otherwise, search the filter list for a match for each address
|
|
- * record. If a match is found, the address should be filtered,
|
|
- * so should the entire answer.
|
|
+ * deny-answer-address doesn't apply to non-IN classes.
|
|
+ */
|
|
+ if (rdataset->rdclass != dns_rdataclass_in) {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Otherwise, search the filter list for a match for each
|
|
+ * address record. If a match is found, the address should be
|
|
+ * filtered, so should the entire answer.
|
|
*/
|
|
for (result = dns_rdataset_first(rdataset);
|
|
result == ISC_R_SUCCESS;
|
|
--
|
|
2.54.0
|
|
|