Compare commits

...

No commits in common. "c8-beta" and "imports/c8s/bind9.16-9.16.23-0.9.el8.1" have entirely different histories.

10 changed files with 2 additions and 1896 deletions

View File

@ -1,60 +0,0 @@
From bf2ea6d8525bfd96a84dad221ba9e004adb710a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <michal@isc.org>
Date: Thu, 8 Sep 2022 11:11:30 +0200
Subject: [PATCH] Bound the amount of work performed for delegations
Limit the amount of database lookups that can be triggered in
fctx_getaddresses() (i.e. when determining the name server addresses to
query next) by setting a hard limit on the number of NS RRs processed
for any delegation encountered. Without any limit in place, named can
be forced to perform large amounts of database lookups per each query
received, which severely impacts resolver performance.
The limit used (20) is an arbitrary value that is considered to be big
enough for any sane DNS delegation.
(cherry picked from commit 3a44097fd6c6c260765b628cd1d2c9cb7efb0b2a)
---
lib/dns/resolver.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index d2cf14bbc8..73a0ee9f77 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -195,6 +195,12 @@
*/
#define NS_FAIL_LIMIT 4
#define NS_RR_LIMIT 5
+/*
+ * IP address lookups are performed for at most NS_PROCESSING_LIMIT NS RRs in
+ * any NS RRset encountered, to avoid excessive resource use while processing
+ * large delegations.
+ */
+#define NS_PROCESSING_LIMIT 20
/* Number of hash buckets for zone counters */
#ifndef RES_DOMAIN_BUCKETS
@@ -3711,6 +3717,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
bool need_alternate = false;
bool all_spilled = true;
unsigned int no_addresses = 0;
+ unsigned int ns_processed = 0;
FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
@@ -3902,6 +3909,11 @@ normal_nses:
dns_rdata_reset(&rdata);
dns_rdata_freestruct(&ns);
+
+ if (++ns_processed >= NS_PROCESSING_LIMIT) {
+ result = ISC_R_NOMORE;
+ break;
+ }
}
if (result != ISC_R_NOMORE) {
return (result);
--
2.37.3

View File

@ -1,240 +0,0 @@
From 18036bb3f435eaa20d60093738c61e5da42a6cfe Mon Sep 17 00:00:00 2001
From: Evan Hunt <each@isc.org>
Date: Thu, 1 Sep 2022 16:05:04 -0700
Subject: [PATCH] add an update quota
limit the number of simultaneous DNS UPDATE events that can be
processed by adding a quota for update and update forwarding.
this quota currently, arbitrarily, defaults to 100.
also add a statistics counter to record when the update quota
has been exceeded.
(cherry picked from commit 7c47254a140c3e9cf383cda73c7b6a55c4782826)
---
bin/named/bind9.xsl | 4 +++-
bin/named/bind9.xsl.h | 6 +++++-
bin/named/statschannel.c | 5 +++--
doc/arm/reference.rst | 5 +++++
lib/ns/include/ns/server.h | 1 +
lib/ns/include/ns/stats.h | 4 +++-
lib/ns/server.c | 2 ++
lib/ns/update.c | 37 ++++++++++++++++++++++++++++++++++++-
8 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
index 5078115..194625b 100644
--- a/bin/named/bind9.xsl
+++ b/bin/named/bind9.xsl
@@ -12,7 +12,9 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output method="html" indent="yes" version="4.0"/>
- <xsl:template match="statistics[@version=&quot;3.11&quot;]">
+ <!-- the version number **below** must match version in bin/named/statschannel.c -->
+ <!-- don't forget to update "/xml/v<STATS_XML_VERSION_MAJOR>" in the HTTP endpoints listed below -->
+ <xsl:template match="statistics[@version=&quot;3.11.1&quot;]">
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h
index e30f7f5..b182742 100644
--- a/bin/named/bind9.xsl.h
+++ b/bin/named/bind9.xsl.h
@@ -20,7 +20,11 @@ static char xslmsg[] =
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" "
"xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n"
" <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n"
- " <xsl:template match=\"statistics[@version=&quot;3.11&quot;]\">\n"
+ " <!-- the version number **below** must match version in "
+ "bin/named/statschannel.c -->\n"
+ " <!-- don't forget to update \"/xml/v<STATS_XML_VERSION_MAJOR>\" in "
+ "the HTTP endpoints listed below -->\n"
+ " <xsl:template match=\"statistics[@version=&quot;3.11.1&quot;]\">\n"
" <html>\n"
" <head>\n"
" <script type=\"text/javascript\" "
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
index 832ce93..7361ead 100644
--- a/bin/named/statschannel.c
+++ b/bin/named/statschannel.c
@@ -335,6 +335,7 @@ init_desc(void) {
SET_NSSTATDESC(reclimitdropped,
"queries dropped due to recursive client limit",
"RecLimitDropped");
+ SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota");
INSIST(i == ns_statscounter_max);
@@ -2007,7 +2008,7 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
"href=\"/bind9.xsl\""));
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
- ISC_XMLCHAR "3.11"));
+ ISC_XMLCHAR "3.11.1"));
/* Set common fields for statistics dump */
dumparg.type = isc_statsformat_xml;
@@ -2876,7 +2877,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
/*
* These statistics are included no matter which URL we use.
*/
- obj = json_object_new_string("1.5");
+ obj = json_object_new_string("1.5.1");
CHECKMEM(obj);
json_object_object_add(bindstats, "json-stats-version", obj);
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
index 2d05aec..25c20d7 100644
--- a/doc/arm/reference.rst
+++ b/doc/arm/reference.rst
@@ -6705,6 +6705,11 @@ Name Server Statistics Counters
``UpdateBadPrereq``
This indicates the number of dynamic updates rejected due to a prerequisite failure.
+``UpdateQuota``
+ This indicates the number of times a dynamic update or update
+ forwarding request was rejected because the number of pending
+ requests exceeded the update quota.
+
``RateDropped``
This indicates the number of responses dropped due to rate limits.
diff --git a/lib/ns/include/ns/server.h b/lib/ns/include/ns/server.h
index 6a1f345..0abb579 100644
--- a/lib/ns/include/ns/server.h
+++ b/lib/ns/include/ns/server.h
@@ -84,6 +84,7 @@ struct ns_server {
isc_quota_t recursionquota;
isc_quota_t tcpquota;
isc_quota_t xfroutquota;
+ isc_quota_t updquota;
/*% Test options and other configurables */
uint32_t options;
diff --git a/lib/ns/include/ns/stats.h b/lib/ns/include/ns/stats.h
index 3c08799..95b15d0 100644
--- a/lib/ns/include/ns/stats.h
+++ b/lib/ns/include/ns/stats.h
@@ -106,7 +106,9 @@ enum {
ns_statscounter_reclimitdropped = 66,
- ns_statscounter_max = 67,
+ ns_statscounter_updatequota = 67,
+
+ ns_statscounter_max = 68,
};
void
diff --git a/lib/ns/server.c b/lib/ns/server.c
index a970a28..540bc2e 100644
--- a/lib/ns/server.c
+++ b/lib/ns/server.c
@@ -52,6 +52,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
isc_quota_init(&sctx->xfroutquota, 10);
isc_quota_init(&sctx->tcpquota, 10);
isc_quota_init(&sctx->recursionquota, 100);
+ isc_quota_init(&sctx->updquota, 100);
CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx));
@@ -131,6 +132,7 @@ ns_server_detach(ns_server_t **sctxp) {
isc_mem_put(sctx->mctx, altsecret, sizeof(*altsecret));
}
+ isc_quota_destroy(&sctx->updquota);
isc_quota_destroy(&sctx->recursionquota);
isc_quota_destroy(&sctx->tcpquota);
isc_quota_destroy(&sctx->xfroutquota);
diff --git a/lib/ns/update.c b/lib/ns/update.c
index 546b70a..1871438 100644
--- a/lib/ns/update.c
+++ b/lib/ns/update.c
@@ -1544,6 +1544,19 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
+ result = isc_quota_attach(&client->manager->sctx->updquota,
+ &(isc_quota_t *){ NULL });
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update failed: too many DNS UPDATEs queued (%s)",
+ isc_result_totext(result));
+ ns_stats_increment(client->manager->sctx->nsstats,
+ ns_statscounter_updatequota);
+ ns_client_drop(client, result);
+ isc_nmhandle_detach(&client->reqhandle);
+ return (DNS_R_DROP);
+ }
+
event = (update_event_t *)isc_event_allocate(
client->mctx, client, DNS_EVENT_UPDATE, update_action, NULL,
sizeof(*event));
@@ -1676,12 +1689,18 @@ failure:
dns_zone_gettype(zone) == dns_zone_mirror);
inc_stats(client, zone, ns_statscounter_updaterej);
}
+
/*
* We failed without having sent an update event to the zone.
* We are still in the client task context, so we can
* simply give an error response without switching tasks.
*/
- respond(client, result);
+ if (result == DNS_R_DROP) {
+ ns_client_drop(client, result);
+ } else {
+ respond(client, result);
+ }
+
if (zone != NULL) {
dns_zone_detach(&zone);
}
@@ -3489,6 +3508,7 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
respond(client, uev->result);
+ isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
isc_nmhandle_detach(&client->updatehandle);
}
@@ -3505,6 +3525,8 @@ forward_fail(isc_task_t *task, isc_event_t *event) {
INSIST(client->nupdates > 0);
client->nupdates--;
respond(client, DNS_R_SERVFAIL);
+
+ isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
isc_nmhandle_detach(&client->updatehandle);
}
@@ -3542,6 +3564,8 @@ forward_done(isc_task_t *task, isc_event_t *event) {
client->nupdates--;
ns_client_sendraw(client, uev->answer);
dns_message_detach(&uev->answer);
+
+ isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota });
isc_event_free(&event);
isc_nmhandle_detach(&client->updatehandle);
}
@@ -3576,6 +3600,17 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
+ result = isc_quota_attach(&client->manager->sctx->updquota,
+ &(isc_quota_t *){ NULL });
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update failed: too many DNS UPDATEs queued (%s)",
+ isc_result_totext(result));
+ ns_stats_increment(client->manager->sctx->nsstats,
+ ns_statscounter_updatequota);
+ return (DNS_R_DROP);
+ }
+
event = (update_event_t *)isc_event_allocate(
client->mctx, client, DNS_EVENT_UPDATE, forward_action, NULL,
sizeof(*event));
--
2.39.2

View File

@ -1,266 +0,0 @@
From 7fe2204a2e8952bf892e4a70fea2ef5167e1f509 Mon Sep 17 00:00:00 2001
From: Evan Hunt <each@isc.org>
Date: Thu, 1 Sep 2022 16:22:46 -0700
Subject: [PATCH] add a configuration option for the update quota
add an "update-quota" option to configure the update quota.
(cherry picked from commit f57758a7303ad0034ff2ff08eaaf2ef899630f19)
---
bin/named/config.c | 1 +
bin/named/named.conf.rst | 9 +++++----
bin/named/server.c | 1 +
bin/tests/system/checkconf/good.conf | 1 +
doc/arm/reference.rst | 7 ++++++-
doc/man/named.conf.5in | 9 +++++----
doc/misc/master.zoneopt.rst | 2 +-
doc/misc/options | 1 +
doc/misc/options.active | 1 +
doc/misc/options.grammar.rst | 3 ++-
doc/misc/slave.zoneopt.rst | 2 +-
lib/isccfg/namedconf.c | 1 +
12 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/bin/named/config.c b/bin/named/config.c
index 5fedee84d9..494147015f 100644
--- a/bin/named/config.c
+++ b/bin/named/config.c
@@ -130,6 +130,7 @@ options {\n\
transfers-out 10;\n\
transfers-per-ns 2;\n\
trust-anchor-telemetry yes;\n\
+ update-quota 100;\n\
\n\
/* view */\n\
allow-new-zones no;\n\
diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst
index 27eed5ca3e..4c9f9a7370 100644
--- a/bin/named/named.conf.rst
+++ b/bin/named/named.conf.rst
@@ -179,7 +179,7 @@ OPTIONS
answer-cookie boolean;
attach-cache string;
auth-nxdomain boolean; // default changed
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off );// deprecated
automatic-interface-scan boolean;
avoid-v4-udp-ports { portrange; ... };
avoid-v6-udp-ports { portrange; ... };
@@ -446,6 +446,7 @@ OPTIONS
trust-anchor-telemetry boolean; // experimental
try-tcp-refresh boolean;
update-check-ksk boolean;
+ update-quota integer;
use-alt-transfer-source boolean;
use-v4-udp-ports { portrange; ... };
use-v6-udp-ports { portrange; ... };
@@ -584,7 +585,7 @@ VIEW
* ) ] [ dscp integer ];
attach-cache string;
auth-nxdomain boolean; // default changed
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off );// deprecated
cache-file quoted_string;// deprecated
catalog-zones { zone string [ default-masters [ port integer ]
[ dscp integer ] { ( remote-servers | ipv4_address [ port
@@ -859,7 +860,7 @@ VIEW
integer | * ) ] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port (
integer | * ) ] [ dscp integer ];
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off );// deprecated
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
@@ -977,7 +978,7 @@ ZONE
] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer |
* ) ] [ dscp integer ];
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off );// deprecated
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
diff --git a/bin/named/server.c b/bin/named/server.c
index 20443ff8a9..78a21d62a2 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -8542,6 +8542,7 @@ load_configuration(const char *filename, named_server_t *server,
configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota);
configure_server_quota(maps, "recursive-clients",
&server->sctx->recursionquota);
+ configure_server_quota(maps, "update-quota", &server->sctx->updquota);
max = isc_quota_getmax(&server->sctx->recursionquota);
if (max > 1000) {
diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf
index b1f7059acf..0ecdb68e95 100644
--- a/bin/tests/system/checkconf/good.conf
+++ b/bin/tests/system/checkconf/good.conf
@@ -75,6 +75,7 @@ options {
recursive-clients 3000;
serial-query-rate 100;
server-id none;
+ update-quota 200;
check-names primary warn;
check-names secondary ignore;
max-cache-size 20000000000000;
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
index 2603d60251..703663d0ba 100644
--- a/doc/arm/reference.rst
+++ b/doc/arm/reference.rst
@@ -3151,6 +3151,11 @@ system.
value as ``tcp-keepalive-timeout``. This value can be updated at
runtime by using ``rndc tcp-timeouts``.
+``update-quota``
+ This is the maximum number of simultaneous DNS UPDATE messages that
+ the server will accept for updating local authoritiative zones or
+ forwarding to a primary server. The default is ``100``.
+
.. _intervals:
Periodic Task Intervals
@@ -6840,7 +6845,7 @@ Name Server Statistics Counters
``UpdateQuota``
This indicates the number of times a dynamic update or update
forwarding request was rejected because the number of pending
- requests exceeded the update quota.
+ requests exceeded ``update-quota``.
``RateDropped``
This indicates the number of responses dropped due to rate limits.
diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in
index 4c46f47592..c87afa2881 100644
--- a/doc/man/named.conf.5in
+++ b/doc/man/named.conf.5in
@@ -231,7 +231,7 @@ options {
answer\-cookie boolean;
attach\-cache string;
auth\-nxdomain boolean; // default changed
- auto\-dnssec ( allow | maintain | off );
+ auto\-dnssec ( allow | maintain | off );// deprecated
automatic\-interface\-scan boolean;
avoid\-v4\-udp\-ports { portrange; ... };
avoid\-v6\-udp\-ports { portrange; ... };
@@ -498,6 +498,7 @@ options {
trust\-anchor\-telemetry boolean; // experimental
try\-tcp\-refresh boolean;
update\-check\-ksk boolean;
+ update\-quota integer;
use\-alt\-transfer\-source boolean;
use\-v4\-udp\-ports { portrange; ... };
use\-v6\-udp\-ports { portrange; ... };
@@ -668,7 +669,7 @@ view string [ class ] {
* ) ] [ dscp integer ];
attach\-cache string;
auth\-nxdomain boolean; // default changed
- auto\-dnssec ( allow | maintain | off );
+ auto\-dnssec ( allow | maintain | off );// deprecated
cache\-file quoted_string;// deprecated
catalog\-zones { zone string [ default\-masters [ port integer ]
[ dscp integer ] { ( remote\-servers | ipv4_address [ port
@@ -943,7 +944,7 @@ view string [ class ] {
integer | * ) ] [ dscp integer ];
alt\-transfer\-source\-v6 ( ipv6_address | * ) [ port (
integer | * ) ] [ dscp integer ];
- auto\-dnssec ( allow | maintain | off );
+ auto\-dnssec ( allow | maintain | off );// deprecated
check\-dup\-records ( fail | warn | ignore );
check\-integrity boolean;
check\-mx ( fail | warn | ignore );
@@ -1065,7 +1066,7 @@ zone string [ class ] {
] [ dscp integer ];
alt\-transfer\-source\-v6 ( ipv6_address | * ) [ port ( integer |
* ) ] [ dscp integer ];
- auto\-dnssec ( allow | maintain | off );
+ auto\-dnssec ( allow | maintain | off );// deprecated
check\-dup\-records ( fail | warn | ignore );
check\-integrity boolean;
check\-mx ( fail | warn | ignore );
diff --git a/doc/misc/master.zoneopt.rst b/doc/misc/master.zoneopt.rst
index 8fc7e1b4f0..346d59813e 100644
--- a/doc/misc/master.zoneopt.rst
+++ b/doc/misc/master.zoneopt.rst
@@ -20,7 +20,7 @@
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];
alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off ); // deprecated
check-dup-records ( fail | warn | ignore );
check-integrity <boolean>;
check-mx ( fail | warn | ignore );
diff --git a/doc/misc/options b/doc/misc/options
index f57399499a..0dbcf101e1 100644
--- a/doc/misc/options
+++ b/doc/misc/options
@@ -404,6 +404,7 @@ options {
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
update-check-ksk <boolean>;
+ update-quota <integer>;
use-alt-transfer-source <boolean>;
use-id-pool <boolean>; // ancient
use-ixfr <boolean>; // obsolete
diff --git a/doc/misc/options.active b/doc/misc/options.active
index 5fc1ab29f4..eb75a86eae 100644
--- a/doc/misc/options.active
+++ b/doc/misc/options.active
@@ -363,6 +363,7 @@ options {
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
update-check-ksk <boolean>;
+ update-quota <integer>;
use-alt-transfer-source <boolean>;
use-v4-udp-ports { <portrange>; ... };
use-v6-udp-ports { <portrange>; ... };
diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst
index 438072c95c..beef35341a 100644
--- a/doc/misc/options.grammar.rst
+++ b/doc/misc/options.grammar.rst
@@ -33,7 +33,7 @@
answer-cookie <boolean>;
attach-cache <string>;
auth-nxdomain <boolean>; // default changed
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off ); // deprecated
automatic-interface-scan <boolean>;
avoid-v4-udp-ports { <portrange>; ... };
avoid-v6-udp-ports { <portrange>; ... };
@@ -300,6 +300,7 @@
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
update-check-ksk <boolean>;
+ update-quota <integer>;
use-alt-transfer-source <boolean>;
use-v4-udp-ports { <portrange>; ... };
use-v6-udp-ports { <portrange>; ... };
diff --git a/doc/misc/slave.zoneopt.rst b/doc/misc/slave.zoneopt.rst
index cc72dcbf67..468a7f4d9a 100644
--- a/doc/misc/slave.zoneopt.rst
+++ b/doc/misc/slave.zoneopt.rst
@@ -21,7 +21,7 @@
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];
alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];
- auto-dnssec ( allow | maintain | off );
+ auto-dnssec ( allow | maintain | off ); // deprecated
check-names ( fail | warn | ignore );
database <string>;
dialup ( notify | notify-passive | passive | refresh | <boolean> );
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index 45de0196bf..6e63d86816 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -1267,6 +1267,7 @@ static cfg_clausedef_t options_clauses[] = {
{ "transfers-out", &cfg_type_uint32, 0 },
{ "transfers-per-ns", &cfg_type_uint32, 0 },
{ "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT },
+ { "update-quota", &cfg_type_uint32, 0 },
{ "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT },
{ "use-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
--
2.39.1

View File

@ -1,470 +0,0 @@
From 93b8bd39145566053ad8b22cef597146e9175ea4 Mon Sep 17 00:00:00 2001
From: Evan Hunt <each@isc.org>
Date: Tue, 8 Nov 2022 17:32:41 -0800
Subject: [PATCH] move update ACL and update-policy checks before quota
check allow-update, update-policy, and allow-update-forwarding before
consuming quota slots, so that unauthorized clients can't fill the
quota.
(this moves the access check before the prerequisite check, which
violates the precise wording of RFC 2136. however, RFC co-author Paul
Vixie has stated that the RFC is mistaken on this point; it should have
said that access checking must happen *no later than* the completion of
prerequisite checks, not that it must happen exactly then.)
(cherry picked from commit 964f559edb5036880b8e463b8f190b9007ee055d)
---
lib/ns/update.c | 335 ++++++++++++++++++++++++++----------------------
1 file changed, 181 insertions(+), 154 deletions(-)
diff --git a/lib/ns/update.c b/lib/ns/update.c
index 9a8c309..036184b 100644
--- a/lib/ns/update.c
+++ b/lib/ns/update.c
@@ -261,6 +261,9 @@ static void
forward_done(isc_task_t *task, isc_event_t *event);
static isc_result_t
add_rr_prepare_action(void *data, rr_t *rr);
+static isc_result_t
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ const dns_rdata_t *rdata, bool *flag);
/**************************************************************************/
@@ -333,25 +336,26 @@ inc_stats(ns_client_t *client, dns_zone_t *zone, isc_statscounter_t counter) {
static isc_result_t
checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
dns_acl_t *updateacl, dns_ssutable_t *ssutable) {
+ isc_result_t result;
char namebuf[DNS_NAME_FORMATSIZE];
char classbuf[DNS_RDATACLASS_FORMATSIZE];
- int level;
- isc_result_t result;
+ bool update_possible =
+ ((updateacl != NULL && !dns_acl_isnone(updateacl)) ||
+ ssutable != NULL);
result = ns_client_checkaclsilent(client, NULL, queryacl, true);
if (result != ISC_R_SUCCESS) {
+ int level = update_possible ? ISC_LOG_ERROR : ISC_LOG_INFO;
+
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
sizeof(classbuf));
- level = (updateacl == NULL && ssutable == NULL) ? ISC_LOG_INFO
- : ISC_LOG_ERROR;
-
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
NS_LOGMODULE_UPDATE, level,
"update '%s/%s' denied due to allow-query",
namebuf, classbuf);
- } else if (updateacl == NULL && ssutable == NULL) {
+ } else if (!update_possible) {
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
sizeof(classbuf));
@@ -1543,6 +1547,156 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
isc_result_t result = ISC_R_SUCCESS;
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
+ dns_ssutable_t *ssutable = NULL;
+ dns_message_t *request = client->message;
+ dns_aclenv_t *env =
+ ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+ dns_rdataclass_t zoneclass;
+ dns_rdatatype_t covers;
+ dns_name_t *zonename = NULL;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+
+ CHECK(dns_zone_getdb(zone, &db));
+ zonename = dns_db_origin(db);
+ zoneclass = dns_db_class(db);
+ dns_zone_getssutable(zone, &ssutable);
+ dns_db_currentversion(db, &ver);
+
+ /*
+ * Update message processing can leak record existence information
+ * so check that we are allowed to query this zone. Additionally,
+ * if we would refuse all updates for this zone, we bail out here.
+ */
+ CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone),
+ dns_zone_getorigin(zone),
+ dns_zone_getupdateacl(zone), ssutable));
+
+ /*
+ * Check requestor's permissions.
+ */
+ if (ssutable == NULL) {
+ CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
+ "update", dns_zone_getorigin(zone), false,
+ false));
+ } else if (client->signer == NULL && !TCPCLIENT(client)) {
+ CHECK(checkupdateacl(client, NULL, "update",
+ dns_zone_getorigin(zone), false, true));
+ }
+
+ if (dns_zone_getupdatedisabled(zone)) {
+ FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled "
+ "because the zone is frozen. Use "
+ "'rndc thaw' to re-enable updates.");
+ }
+
+ /*
+ * Prescan the update section, checking for updates that
+ * are illegal or violate policy.
+ */
+ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_UPDATE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+
+ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
+ &rdata, &covers, &ttl, &update_class);
+
+ if (!dns_name_issubdomain(name, zonename)) {
+ FAILC(DNS_R_NOTZONE, "update RR is outside zone");
+ }
+ if (update_class == zoneclass) {
+ /*
+ * Check for meta-RRs. The RFC2136 pseudocode says
+ * check for ANY|AXFR|MAILA|MAILB, but the text adds
+ * "or any other QUERY metatype"
+ */
+ if (dns_rdatatype_ismeta(rdata.type)) {
+ FAILC(DNS_R_FORMERR, "meta-RR in update");
+ }
+ result = dns_zone_checknames(zone, name, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ FAIL(DNS_R_REFUSED);
+ }
+ } else if (update_class == dns_rdataclass_any) {
+ if (ttl != 0 || rdata.length != 0 ||
+ (dns_rdatatype_ismeta(rdata.type) &&
+ rdata.type != dns_rdatatype_any))
+ {
+ FAILC(DNS_R_FORMERR, "meta-RR in update");
+ }
+ } else if (update_class == dns_rdataclass_none) {
+ if (ttl != 0 || dns_rdatatype_ismeta(rdata.type)) {
+ FAILC(DNS_R_FORMERR, "meta-RR in update");
+ }
+ } else {
+ update_log(client, zone, ISC_LOG_WARNING,
+ "update RR has incorrect class %d",
+ update_class);
+ FAIL(DNS_R_FORMERR);
+ }
+
+ /*
+ * draft-ietf-dnsind-simple-secure-update-01 says
+ * "Unlike traditional dynamic update, the client
+ * is forbidden from updating NSEC records."
+ */
+ if (rdata.type == dns_rdatatype_nsec3) {
+ FAILC(DNS_R_REFUSED, "explicit NSEC3 updates are not "
+ "allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_nsec) {
+ FAILC(DNS_R_REFUSED, "explicit NSEC updates are not "
+ "allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_rrsig &&
+ !dns_name_equal(name, zonename))
+ {
+ FAILC(DNS_R_REFUSED, "explicit RRSIG updates are "
+ "currently "
+ "not supported in secure zones "
+ "except "
+ "at the apex");
+ }
+
+ if (ssutable != NULL) {
+ isc_netaddr_t netaddr;
+ dst_key_t *tsigkey = NULL;
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ if (client->message->tsigkey != NULL) {
+ tsigkey = client->message->tsigkey->key;
+ }
+
+ if (rdata.type != dns_rdatatype_any) {
+ if (!dns_ssutable_checkrules(
+ ssutable, client->signer, name,
+ &netaddr, TCPCLIENT(client), env,
+ rdata.type, tsigkey))
+ {
+ FAILC(DNS_R_REFUSED, "rejected by "
+ "secure update");
+ }
+ } else {
+ if (!ssu_checkall(db, ver, name, ssutable,
+ client->signer, &netaddr, env,
+ TCPCLIENT(client), tsigkey))
+ {
+ FAILC(DNS_R_REFUSED, "rejected by "
+ "secure update");
+ }
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ FAIL(result);
+ }
+
+ update_log(client, zone, LOGLEVEL_DEBUG, "update section prescan OK");
result = isc_quota_attach(&client->manager->sctx->updquota,
&(isc_quota_t *){ NULL });
@@ -1552,9 +1706,7 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
isc_result_totext(result));
ns_stats_increment(client->manager->sctx->nsstats,
ns_statscounter_updatequota);
- ns_client_drop(client, result);
- isc_nmhandle_detach(&client->reqhandle);
- return (DNS_R_DROP);
+ CHECK(DNS_R_DROP);
}
event = (update_event_t *)isc_event_allocate(
@@ -1571,6 +1723,16 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
dns_zone_gettask(zone, &zonetask);
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
+failure:
+ if (db != NULL) {
+ dns_db_closeversion(db, &ver, false);
+ dns_db_detach(&db);
+ }
+
+ if (ssutable != NULL) {
+ dns_ssutable_detach(&ssutable);
+ }
+
return (result);
}
@@ -1671,9 +1833,6 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
break;
case dns_zone_secondary:
case dns_zone_mirror:
- CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone),
- "update forwarding", zonename, true,
- false));
CHECK(send_forward_event(client, zone));
break;
default:
@@ -1685,8 +1844,6 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
failure:
if (result == DNS_R_REFUSED) {
- INSIST(dns_zone_gettype(zone) == dns_zone_secondary ||
- dns_zone_gettype(zone) == dns_zone_mirror);
inc_stats(client, zone, ns_statscounter_updaterej);
}
@@ -2578,7 +2735,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_rdatatype_t covers;
dns_message_t *request = client->message;
dns_rdataclass_t zoneclass;
- dns_name_t *zonename;
+ dns_name_t *zonename = NULL;
dns_ssutable_t *ssutable = NULL;
dns_fixedname_t tmpnamefixed;
dns_name_t *tmpname = NULL;
@@ -2590,8 +2747,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_ttl_t maxttl = 0;
uint32_t maxrecords;
uint64_t records;
- dns_aclenv_t *env =
- ns_interfacemgr_getaclenv(client->manager->interface->mgr);
INSIST(event->ev_type == DNS_EVENT_UPDATE);
@@ -2602,14 +2757,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
zonename = dns_db_origin(db);
zoneclass = dns_db_class(db);
dns_zone_getssutable(zone, &ssutable);
-
- /*
- * Update message processing can leak record existence information
- * so check that we are allowed to query this zone. Additionally
- * if we would refuse all updates for this zone we bail out here.
- */
- CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename,
- dns_zone_getupdateacl(zone), ssutable));
+ options = dns_zone_getoptions(zone);
/*
* Get old and new versions now that queryacl has been checked.
@@ -2745,135 +2893,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
update_log(client, zone, LOGLEVEL_DEBUG, "prerequisites are OK");
- /*
- * Check Requestor's Permissions. It seems a bit silly to do this
- * only after prerequisite testing, but that is what RFC2136 says.
- */
- if (ssutable == NULL) {
- CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
- "update", zonename, false, false));
- } else if (client->signer == NULL && !TCPCLIENT(client)) {
- CHECK(checkupdateacl(client, NULL, "update", zonename, false,
- true));
- }
-
- if (dns_zone_getupdatedisabled(zone)) {
- FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled "
- "because the zone is frozen. Use "
- "'rndc thaw' to re-enable updates.");
- }
-
- /*
- * Perform the Update Section Prescan.
- */
-
- for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
- result == ISC_R_SUCCESS;
- result = dns_message_nextname(request, DNS_SECTION_UPDATE))
- {
- dns_name_t *name = NULL;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_ttl_t ttl;
- dns_rdataclass_t update_class;
- get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
- &rdata, &covers, &ttl, &update_class);
-
- if (!dns_name_issubdomain(name, zonename)) {
- FAILC(DNS_R_NOTZONE, "update RR is outside zone");
- }
- if (update_class == zoneclass) {
- /*
- * Check for meta-RRs. The RFC2136 pseudocode says
- * check for ANY|AXFR|MAILA|MAILB, but the text adds
- * "or any other QUERY metatype"
- */
- if (dns_rdatatype_ismeta(rdata.type)) {
- FAILC(DNS_R_FORMERR, "meta-RR in update");
- }
- result = dns_zone_checknames(zone, name, &rdata);
- if (result != ISC_R_SUCCESS) {
- FAIL(DNS_R_REFUSED);
- }
- } else if (update_class == dns_rdataclass_any) {
- if (ttl != 0 || rdata.length != 0 ||
- (dns_rdatatype_ismeta(rdata.type) &&
- rdata.type != dns_rdatatype_any))
- {
- FAILC(DNS_R_FORMERR, "meta-RR in update");
- }
- } else if (update_class == dns_rdataclass_none) {
- if (ttl != 0 || dns_rdatatype_ismeta(rdata.type)) {
- FAILC(DNS_R_FORMERR, "meta-RR in update");
- }
- } else {
- update_log(client, zone, ISC_LOG_WARNING,
- "update RR has incorrect class %d",
- update_class);
- FAIL(DNS_R_FORMERR);
- }
-
- /*
- * draft-ietf-dnsind-simple-secure-update-01 says
- * "Unlike traditional dynamic update, the client
- * is forbidden from updating NSEC records."
- */
- if (rdata.type == dns_rdatatype_nsec3) {
- FAILC(DNS_R_REFUSED, "explicit NSEC3 updates are not "
- "allowed "
- "in secure zones");
- } else if (rdata.type == dns_rdatatype_nsec) {
- FAILC(DNS_R_REFUSED, "explicit NSEC updates are not "
- "allowed "
- "in secure zones");
- } else if (rdata.type == dns_rdatatype_rrsig &&
- !dns_name_equal(name, zonename)) {
- FAILC(DNS_R_REFUSED, "explicit RRSIG updates are "
- "currently "
- "not supported in secure zones "
- "except "
- "at the apex");
- }
-
- if (ssutable != NULL) {
- isc_netaddr_t netaddr;
- dst_key_t *tsigkey = NULL;
- isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
-
- if (client->message->tsigkey != NULL) {
- tsigkey = client->message->tsigkey->key;
- }
-
- if (rdata.type != dns_rdatatype_any) {
- if (!dns_ssutable_checkrules(
- ssutable, client->signer, name,
- &netaddr, TCPCLIENT(client), env,
- rdata.type, tsigkey))
- {
- FAILC(DNS_R_REFUSED, "rejected by "
- "secure update");
- }
- } else {
- if (!ssu_checkall(db, ver, name, ssutable,
- client->signer, &netaddr, env,
- TCPCLIENT(client), tsigkey))
- {
- FAILC(DNS_R_REFUSED, "rejected by "
- "secure update");
- }
- }
- }
- }
- if (result != ISC_R_NOMORE) {
- FAIL(result);
- }
-
- update_log(client, zone, LOGLEVEL_DEBUG, "update section prescan OK");
-
/*
* Process the Update Section.
*/
- options = dns_zone_getoptions(zone);
for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
result == ISC_R_SUCCESS;
result = dns_message_nextname(request, DNS_SECTION_UPDATE))
@@ -3307,10 +3330,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
if (result == ISC_R_SUCCESS && records > maxrecords) {
update_log(client, zone, ISC_LOG_ERROR,
"records in zone (%" PRIu64 ") "
- "exceeds"
- " max-"
- "records"
- " (%u)",
+ "exceeds max-records (%u)",
records, maxrecords);
result = DNS_R_TOOMANYRECORDS;
goto failure;
@@ -3601,6 +3621,13 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
update_event_t *event = NULL;
isc_task_t *zonetask = NULL;
+ result = checkupdateacl(client, dns_zone_getforwardacl(zone),
+ "update forwarding", dns_zone_getorigin(zone),
+ true, false);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+
result = isc_quota_attach(&client->manager->sctx->updquota,
&(isc_quota_t *){ NULL });
if (result != ISC_R_SUCCESS) {
--
2.39.1

View File

@ -1,272 +0,0 @@
From 54e281c11ee13eabc3c51d6391a58fc90836000c Mon Sep 17 00:00:00 2001
From: Evan Hunt <each@isc.org>
Date: Wed, 9 Nov 2022 21:56:16 -0800
Subject: [PATCH] test failure conditions
verify that updates are refused when the client is disallowed by
allow-query, and update forwarding is refused when the client is
is disallowed by update-forwarding.
verify that "too many DNS UPDATEs" appears in the log file when too
many simultaneous updates are processing.
(cherry picked from commit b91339b80e5b82a56622c93cc1e3cca2d0c11bc0)
---
bin/tests/system/nsupdate/ns1/named.conf.in | 2 +
bin/tests/system/nsupdate/tests.sh | 28 +++++++++++++
bin/tests/system/upforwd/clean.sh | 2 +
.../ns3/{named.conf.in => named1.conf.in} | 13 ++++--
bin/tests/system/upforwd/ns3/named2.conf.in | 41 +++++++++++++++++++
bin/tests/system/upforwd/setup.sh | 2 +-
bin/tests/system/upforwd/tests.sh | 39 ++++++++++++++++++
7 files changed, 123 insertions(+), 4 deletions(-)
rename bin/tests/system/upforwd/ns3/{named.conf.in => named1.conf.in} (78%)
create mode 100644 bin/tests/system/upforwd/ns3/named2.conf.in
diff --git a/bin/tests/system/nsupdate/ns1/named.conf.in b/bin/tests/system/nsupdate/ns1/named.conf.in
index 436c97d..83fe884 100644
--- a/bin/tests/system/nsupdate/ns1/named.conf.in
+++ b/bin/tests/system/nsupdate/ns1/named.conf.in
@@ -21,6 +21,7 @@ options {
recursion no;
notify yes;
minimal-responses no;
+ update-quota 1;
};
acl named-acl {
@@ -81,6 +82,7 @@ zone "other.nil" {
check-integrity no;
check-mx warn;
update-policy local;
+ allow-query { !10.53.0.2; any; };
allow-query-on { 10.53.0.1; 127.0.0.1; };
allow-transfer { any; };
};
diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
index b5f562f..13ba577 100755
--- a/bin/tests/system/nsupdate/tests.sh
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -1268,6 +1268,34 @@ END
grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n >/dev/null || ret=1
[ $ret = 0 ] || { echo_i "failed"; status=1; }
+n=$((n + 1))
+ret=0
+echo_i "check that update is rejected if query is not allowed ($n)"
+{
+ $NSUPDATE -d <<END
+ local 10.53.0.2
+ server 10.53.0.1 ${PORT}
+ update add reject.other.nil 3600 IN TXT Whatever
+ send
+END
+} > nsupdate.out.test$n 2>&1
+grep 'failed: REFUSED' nsupdate.out.test$n > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
+n=$((n + 1))
+ret=0
+echo_i "check that update is rejected if quota is exceeded ($n)"
+for loop in 1 2 3 4 5 6 7 8 9 10; do
+{
+ $NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > /dev/null 2>&1 <<END
+ update add txt-$loop.other.nil 3600 IN TXT Whatever
+ send
+END
+} &
+done
+wait_for_log 10 "too many DNS UPDATEs queued" ns1/named.run || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
if ! $FEATURETEST --gssapi ; then
echo_i "SKIPPED: GSSAPI tests"
else
diff --git a/bin/tests/system/upforwd/clean.sh b/bin/tests/system/upforwd/clean.sh
index 2025252..12311df 100644
--- a/bin/tests/system/upforwd/clean.sh
+++ b/bin/tests/system/upforwd/clean.sh
@@ -29,3 +29,5 @@ rm -f keyname keyname.err
rm -f ns*/named.lock
rm -f ns1/example2.db
rm -f ns*/managed-keys.bind*
+rm -f nsupdate.out.*
+rm -f ns*/named.run.prev
diff --git a/bin/tests/system/upforwd/ns3/named.conf.in b/bin/tests/system/upforwd/ns3/named1.conf.in
similarity index 78%
rename from bin/tests/system/upforwd/ns3/named.conf.in
rename to bin/tests/system/upforwd/ns3/named1.conf.in
index 7bd13d3..2f690ff 100644
--- a/bin/tests/system/upforwd/ns3/named.conf.in
+++ b/bin/tests/system/upforwd/ns3/named1.conf.in
@@ -28,20 +28,27 @@ key rndc_key {
};
controls {
- inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "example" {
type secondary;
file "example.bk";
- allow-update-forwarding { any; };
+ allow-update-forwarding { 10.53.0.1; };
primaries { 10.53.0.1; };
};
zone "example2" {
type secondary;
file "example2.bk";
- allow-update-forwarding { any; };
+ allow-update-forwarding { 10.53.0.1; };
+ primaries { 10.53.0.1; };
+};
+
+zone "example3" {
+ type secondary;
+ file "example3.bk";
+ allow-update-forwarding { 10.53.0.1; };
primaries { 10.53.0.1; };
};
diff --git a/bin/tests/system/upforwd/ns3/named2.conf.in b/bin/tests/system/upforwd/ns3/named2.conf.in
new file mode 100644
index 0000000..e15459a
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/named2.conf.in
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ update-quota 1;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ file "example.bk";
+ allow-update-forwarding { any; };
+ primaries { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/setup.sh b/bin/tests/system/upforwd/setup.sh
index e748078..88ab28d 100644
--- a/bin/tests/system/upforwd/setup.sh
+++ b/bin/tests/system/upforwd/setup.sh
@@ -17,7 +17,7 @@ cp -f ns3/nomaster.db ns3/nomaster1.db
copy_setports ns1/named.conf.in ns1/named.conf
copy_setports ns2/named.conf.in ns2/named.conf
-copy_setports ns3/named.conf.in ns3/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
if $FEATURETEST --enable-dnstap
then
diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh
index 8062d68..20fc46f 100644
--- a/bin/tests/system/upforwd/tests.sh
+++ b/bin/tests/system/upforwd/tests.sh
@@ -80,6 +80,7 @@ if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
echo_i "updating zone (signed) ($n)"
ret=0
$NSUPDATE -y hmac-sha256:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - <<EOF || ret=1
+local 10.53.0.1
server 10.53.0.3 ${PORT}
update add updated.example. 600 A 10.10.10.1
update add updated.example. 600 TXT Foo
@@ -138,6 +139,7 @@ fi
echo_i "updating zone (unsigned) ($n)"
ret=0
$NSUPDATE -- - <<EOF || ret=1
+local 10.53.0.1
server 10.53.0.3 ${PORT}
update add unsigned.example. 600 A 10.10.10.1
update add unsigned.example. 600 TXT Foo
@@ -194,6 +196,7 @@ while [ $count -lt 5 -a $ret -eq 0 ]
do
(
$NSUPDATE -- - <<EOF
+local 10.53.0.1
server 10.53.0.3 ${PORT}
zone nomaster
update add unsigned.nomaster. 600 A 10.10.10.1
@@ -225,6 +228,7 @@ then
ret=0
keyname=`cat keyname`
$NSUPDATE -k $keyname.private -- - <<EOF
+ local 10.53.0.1
server 10.53.0.3 ${PORT}
zone example2
update add unsigned.example2. 600 A 10.10.10.1
@@ -249,5 +253,40 @@ EOF
fi
fi
+echo_i "attempting an update that should be rejected by ACL ($n)"
+ret=0
+{
+ $NSUPDATE -- - << EOF
+ local 10.53.0.2
+ server 10.53.0.3 ${PORT}
+ update add another.unsigned.example. 600 A 10.10.10.2
+ update add another.unsigned.example. 600 TXT Bar
+ send
+EOF
+} > nsupdate.out.$n 2>&1
+grep REFUSED nsupdate.out.$n > /dev/null || ret=1
+if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
+n=`expr $n + 1`
+
+n=$((n + 1))
+ret=0
+echo_i "attempting updates that should exceed quota ($n)"
+# lower the update quota to 1.
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndc_reconfig ns3 10.53.0.3
+nextpart ns3/named.run > /dev/null
+for loop in 1 2 3 4 5 6 7 8 9 10; do
+{
+ $NSUPDATE -- - > /dev/null 2>&1 <<END
+ local 10.53.0.1
+ server 10.53.0.3 ${PORT}
+ update add txt-$loop.unsigned.example 300 IN TXT Whatever
+ send
+END
+} &
+done
+wait_for_log 10 "too many DNS UPDATEs queued" ns3/named.run || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
--
2.39.2

View File

@ -1,53 +0,0 @@
From 1b6590eafce064cbf70f5afc2fe4d6f1bfdc3804 Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Thu, 27 Oct 2022 13:22:11 +1100
Subject: [PATCH] Move the mapping of SIG and RRSIG to ANY
dns_db_findext() asserts if RRSIG is passed to it and
query_lookup_stale() failed to map RRSIG to ANY to prevent this. To
avoid cases like this in the future, move the mapping of SIG and RRSIG
to ANY for qctx->type to qctx_init().
(cherry picked from commit 56eae064183488bcf7ff08c3edf59f2e1742c1b6)
---
lib/ns/query.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/lib/ns/query.c b/lib/ns/query.c
index a450cb7..f66bab4 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -5103,6 +5103,15 @@ qctx_init(ns_client_t *client, dns_fetchevent_t **eventp, dns_rdatatype_t qtype,
qctx->result = ISC_R_SUCCESS;
qctx->findcoveringnsec = qctx->view->synthfromdnssec;
+ /*
+ * If it's an RRSIG or SIG query, we'll iterate the node.
+ */
+ if (qctx->qtype == dns_rdatatype_rrsig ||
+ qctx->qtype == dns_rdatatype_sig)
+ {
+ qctx->type = dns_rdatatype_any;
+ }
+
CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
}
@@ -5243,14 +5252,6 @@ query_setup(ns_client_t *client, dns_rdatatype_t qtype) {
CALL_HOOK(NS_QUERY_SETUP, &qctx);
- /*
- * If it's a SIG query, we'll iterate the node.
- */
- if (qctx.qtype == dns_rdatatype_rrsig ||
- qctx.qtype == dns_rdatatype_sig) {
- qctx.type = dns_rdatatype_any;
- }
-
/*
* Check SERVFAIL cache
*/
--
2.39.1

View File

@ -1,128 +0,0 @@
From 20424b3bfe8d3fae92c11a30e79aeffd26dc2891 Mon Sep 17 00:00:00 2001
From: Aram Sargsyan <aram@isc.org>
Date: Mon, 14 Nov 2022 12:18:06 +0000
Subject: [PATCH] Cancel all fetch events in dns_resolver_cancelfetch()
Although 'dns_fetch_t' fetch can have two associated events, one for
each of 'DNS_EVENT_FETCHDONE' and 'DNS_EVENT_TRYSTALE' types, the
dns_resolver_cancelfetch() function is designed in a way that it
expects only one existing event, which it must cancel, and when it
happens so that 'stale-answer-client-timeout' is enabled and there
are two events, only one of them is canceled, and it results in an
assertion in dns_resolver_destroyfetch(), when it finds a dangling
event.
Change the logic of dns_resolver_cancelfetch() function so that it
cancels both the events (if they exist), and in the right order.
(cherry picked from commit ec2098ca35039e4f81fd0aa7c525eb960b8f47bf)
---
lib/dns/resolver.c | 53 +++++++++++++++++++++++++++++++++++-----------
lib/ns/query.c | 4 +++-
2 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 18585b5..7cbfbb2 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -11254,8 +11254,9 @@ void
dns_resolver_cancelfetch(dns_fetch_t *fetch) {
fetchctx_t *fctx;
dns_resolver_t *res;
- dns_fetchevent_t *event, *next_event;
- isc_task_t *etask;
+ dns_fetchevent_t *event = NULL;
+ dns_fetchevent_t *event_trystale = NULL;
+ dns_fetchevent_t *event_fetchdone = NULL;
REQUIRE(DNS_FETCH_VALID(fetch));
fctx = fetch->private;
@@ -11267,32 +11268,60 @@ dns_resolver_cancelfetch(dns_fetch_t *fetch) {
LOCK(&res->buckets[fctx->bucketnum].lock);
/*
- * Find the completion event for this fetch (as opposed
+ * Find the events for this fetch (as opposed
* to those for other fetches that have joined the same
- * fctx) and send it with result = ISC_R_CANCELED.
+ * fctx) and send them with result = ISC_R_CANCELED.
*/
- event = NULL;
if (fctx->state != fetchstate_done) {
+ dns_fetchevent_t *next_event = NULL;
for (event = ISC_LIST_HEAD(fctx->events); event != NULL;
event = next_event) {
next_event = ISC_LIST_NEXT(event, ev_link);
if (event->fetch == fetch) {
ISC_LIST_UNLINK(fctx->events, event, ev_link);
- break;
+ switch (event->ev_type) {
+ case DNS_EVENT_TRYSTALE:
+ INSIST(event_trystale == NULL);
+ event_trystale = event;
+ break;
+ case DNS_EVENT_FETCHDONE:
+ INSIST(event_fetchdone == NULL);
+ event_fetchdone = event;
+ break;
+ default:
+ ISC_UNREACHABLE();
+ }
+ if (event_trystale != NULL &&
+ event_fetchdone != NULL)
+ {
+ break;
+ }
}
}
}
- if (event != NULL) {
- etask = event->ev_sender;
- event->ev_sender = fctx;
- event->result = ISC_R_CANCELED;
- isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
+
+ /*
+ * The "trystale" event must be sent before the "fetchdone" event,
+ * because the latter clears the "recursing" query attribute, which is
+ * required by both events (handled by the same callback function).
+ */
+ if (event_trystale != NULL) {
+ isc_task_t *etask = event_trystale->ev_sender;
+ event_trystale->ev_sender = fctx;
+ event_trystale->result = ISC_R_CANCELED;
+ isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event_trystale));
}
+ if (event_fetchdone != NULL) {
+ isc_task_t *etask = event_fetchdone->ev_sender;
+ event_fetchdone->ev_sender = fctx;
+ event_fetchdone->result = ISC_R_CANCELED;
+ isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event_fetchdone));
+ }
+
/*
* The fctx continues running even if no fetches remain;
* the answer is still cached.
*/
-
UNLOCK(&res->buckets[fctx->bucketnum].lock);
}
diff --git a/lib/ns/query.c b/lib/ns/query.c
index f66bab4..4f61374 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -6021,7 +6021,9 @@ fetch_callback(isc_task_t *task, isc_event_t *event) {
CTRACE(ISC_LOG_DEBUG(3), "fetch_callback");
if (event->ev_type == DNS_EVENT_TRYSTALE) {
- query_lookup_stale(client);
+ if (devent->result != ISC_R_CANCELED) {
+ query_lookup_stale(client);
+ }
isc_event_free(ISC_EVENT_PTR(&event));
return;
}
--
2.39.1

View File

@ -1,192 +0,0 @@
From ed920ea2ae1cc1214b42b82a5149758dbec941a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
Date: Tue, 30 May 2023 08:46:17 +0200
Subject: [PATCH] Improve RBT overmem cache cleaning
When cache memory usage is over the configured cache size (overmem) and
we are cleaning unused entries, it might not be enough to clean just two
entries if the entries to be expired are smaller than the newly added
rdata. This could be abused by an attacker to cause a remote Denial of
Service by possibly running out of the operating system memory.
Currently, the addrdataset() tries to do a single TTL-based cleaning
considering the serve-stale TTL and then optionally moves to overmem
cleaning if we are in that condition. Then the overmem_purge() tries to
do another single TTL based cleaning from the TTL heap and then continue
with LRU-based cleaning up to 2 entries cleaned.
Squash the TTL-cleaning mechanism into single call from addrdataset(),
but ignore the serve-stale TTL if we are currently overmem.
Then instead of having a fixed number of entries to clean, pass the size
of newly added rdatasetheader to the overmem_purge() function and
cleanup at least the size of the newly added data. This prevents the
cache going over the configured memory limit (`max-cache-size`).
Additionally, refactor the overmem_purge() function to reduce for-loop
nesting for readability.
(cherry picked from commit f1d9e9ee3859976f403914d20ad2a10855343702)
---
lib/dns/rbtdb.c | 105 ++++++++++++++++++++++++++++++------------------
1 file changed, 65 insertions(+), 40 deletions(-)
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 51178cc877..75f97f5550 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -599,7 +599,7 @@ static void
expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, bool tree_locked,
expire_t reason);
static void
-overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
+overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize,
bool tree_locked);
static isc_result_t
resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader);
@@ -6802,6 +6802,16 @@ cleanup:
static dns_dbmethods_t zone_methods;
+static size_t
+rdataset_size(rdatasetheader_t *header) {
+ if (!NONEXISTENT(header)) {
+ return (dns_rdataslab_size((unsigned char *)header,
+ sizeof(*header)));
+ }
+
+ return (sizeof(*header));
+}
+
static isc_result_t
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
@@ -6965,7 +6975,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
if (cache_is_overmem) {
- overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked);
+ overmem_purge(rbtdb, rbtnode->locknum, rdataset_size(newheader),
+ tree_locked);
}
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
@@ -6984,10 +6995,18 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
- if (header != NULL && header->rdh_ttl + rbtdb->serve_stale_ttl <
- now - RBTDB_VIRTUAL)
- {
- expire_header(rbtdb, header, tree_locked, expire_ttl);
+ if (header != NULL) {
+ dns_ttl_t rdh_ttl = header->rdh_ttl;
+
+ /* Only account for stale TTL if cache is not overmem */
+ if (!cache_is_overmem) {
+ rdh_ttl += rbtdb->serve_stale_ttl;
+ }
+
+ if (rdh_ttl < now - RBTDB_VIRTUAL) {
+ expire_header(rbtdb, header, tree_locked,
+ expire_ttl);
+ }
}
/*
@@ -10531,52 +10550,58 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_stdtime_t now) {
ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link);
}
+static size_t
+expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, size_t purgesize,
+ bool tree_locked) {
+ rdatasetheader_t *header, *header_prev;
+ size_t purged = 0;
+
+ for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
+ header != NULL && purged <= purgesize; header = header_prev)
+ {
+ header_prev = ISC_LIST_PREV(header, link);
+ /*
+ * Unlink the entry at this point to avoid checking it
+ * again even if it's currently used someone else and
+ * cannot be purged at this moment. This entry won't be
+ * referenced any more (so unlinking is safe) since the
+ * TTL was reset to 0.
+ */
+ ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, link);
+ size_t header_size = rdataset_size(header);
+ expire_header(rbtdb, header, tree_locked, expire_lru);
+ purged += header_size;
+ }
+
+ return (purged);
+}
+
/*%
- * Purge some expired and/or stale (i.e. unused for some period) cache entries
- * under an overmem condition. To recover from this condition quickly, up to
- * 2 entries will be purged. This process is triggered while adding a new
- * entry, and we specifically avoid purging entries in the same LRU bucket as
- * the one to which the new entry will belong. Otherwise, we might purge
- * entries of the same name of different RR types while adding RRsets from a
- * single response (consider the case where we're adding A and AAAA glue records
- * of the same NS name).
+ * Purge some stale (i.e. unused for some period - LRU based cleaning) cache
+ * entries under the overmem condition. To recover from this condition quickly,
+ * we cleanup entries up to the size of newly added rdata (passed as purgesize).
+ *
+ * This process is triggered while adding a new entry, and we specifically avoid
+ * purging entries in the same LRU bucket as the one to which the new entry will
+ * belong. Otherwise, we might purge entries of the same name of different RR
+ * types while adding RRsets from a single response (consider the case where
+ * we're adding A and AAAA glue records of the same NS name).
*/
static void
-overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
+overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize,
bool tree_locked) {
- rdatasetheader_t *header, *header_prev;
unsigned int locknum;
- int purgecount = 2;
+ size_t purged = 0;
for (locknum = (locknum_start + 1) % rbtdb->node_lock_count;
- locknum != locknum_start && purgecount > 0;
+ locknum != locknum_start && purged <= purgesize;
locknum = (locknum + 1) % rbtdb->node_lock_count)
{
NODE_LOCK(&rbtdb->node_locks[locknum].lock,
isc_rwlocktype_write);
- header = isc_heap_element(rbtdb->heaps[locknum], 1);
- if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) {
- expire_header(rbtdb, header, tree_locked, expire_ttl);
- purgecount--;
- }
-
- for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
- header != NULL && purgecount > 0; header = header_prev)
- {
- header_prev = ISC_LIST_PREV(header, link);
- /*
- * Unlink the entry at this point to avoid checking it
- * again even if it's currently used someone else and
- * cannot be purged at this moment. This entry won't be
- * referenced any more (so unlinking is safe) since the
- * TTL was reset to 0.
- */
- ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
- link);
- expire_header(rbtdb, header, tree_locked, expire_lru);
- purgecount--;
- }
+ purged += expire_lru_headers(rbtdb, locknum, purgesize - purged,
+ tree_locked);
NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
isc_rwlocktype_write);
--
2.40.1

View File

@ -1,168 +0,0 @@
From b137e12dc8118cddee20e372e480a495585e72b6 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Tue, 19 Sep 2023 12:44:31 +0200
Subject: [PATCH] Fix CVE-2023-3341
6245. [security] Limit the amount of recursion that can be performed
by isccc_cc_fromwire. (CVE-2023-3341) [GL #4152]
---
lib/isccc/cc.c | 39 ++++++++++++++++++++++++--------
lib/isccc/include/isccc/result.h | 4 +++-
lib/isccc/result.c | 4 +++-
3 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c
index 0be28b9057..3744d0f037 100644
--- a/lib/isccc/cc.c
+++ b/lib/isccc/cc.c
@@ -50,6 +50,10 @@
#define MAX_TAGS 256
#define DUP_LIFETIME 900
+#ifndef ISCCC_MAXDEPTH
+#define ISCCC_MAXDEPTH \
+ 10 /* Big enough for rndc which just sends a string each way. */
+#endif
typedef isccc_sexpr_t *sexpr_ptr;
@@ -480,19 +484,25 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length,
static isc_result_t
table_fromwire(isccc_region_t *source, isccc_region_t *secret,
- uint32_t algorithm, isccc_sexpr_t **alistp);
+ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp);
static isc_result_t
-list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp);
+list_fromwire(isccc_region_t *source, unsigned int depth,
+ isccc_sexpr_t **listp);
static isc_result_t
-value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
+value_fromwire(isccc_region_t *source, unsigned int depth,
+ isccc_sexpr_t **valuep) {
unsigned int msgtype;
uint32_t len;
isccc_sexpr_t *value;
isccc_region_t active;
isc_result_t result;
+ if (depth > ISCCC_MAXDEPTH) {
+ return (ISCCC_R_MAXDEPTH);
+ }
+
if (REGION_SIZE(*source) < 1 + 4) {
return (ISC_R_UNEXPECTEDEND);
}
@@ -513,9 +523,9 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
result = ISC_R_NOMEMORY;
}
} else if (msgtype == ISCCC_CCMSGTYPE_TABLE) {
- result = table_fromwire(&active, NULL, 0, valuep);
+ result = table_fromwire(&active, NULL, 0, depth + 1, valuep);
} else if (msgtype == ISCCC_CCMSGTYPE_LIST) {
- result = list_fromwire(&active, valuep);
+ result = list_fromwire(&active, depth + 1, valuep);
} else {
result = ISCCC_R_SYNTAX;
}
@@ -525,7 +535,7 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
static isc_result_t
table_fromwire(isccc_region_t *source, isccc_region_t *secret,
- uint32_t algorithm, isccc_sexpr_t **alistp) {
+ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp) {
char key[256];
uint32_t len;
isc_result_t result;
@@ -535,6 +545,10 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret,
REQUIRE(alistp != NULL && *alistp == NULL);
+ if (depth > ISCCC_MAXDEPTH) {
+ return (ISCCC_R_MAXDEPTH);
+ }
+
checksum_rstart = NULL;
first_tag = true;
alist = isccc_alist_create();
@@ -551,7 +565,7 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret,
GET_MEM(key, len, source->rstart);
key[len] = '\0'; /* Ensure NUL termination. */
value = NULL;
- result = value_fromwire(source, &value);
+ result = value_fromwire(source, depth + 1, &value);
if (result != ISC_R_SUCCESS) {
goto bad;
}
@@ -589,14 +603,19 @@ bad:
}
static isc_result_t
-list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp) {
+list_fromwire(isccc_region_t *source, unsigned int depth,
+ isccc_sexpr_t **listp) {
isccc_sexpr_t *list, *value;
isc_result_t result;
+ if (depth > ISCCC_MAXDEPTH) {
+ return (ISCCC_R_MAXDEPTH);
+ }
+
list = NULL;
while (!REGION_EMPTY(*source)) {
value = NULL;
- result = value_fromwire(source, &value);
+ result = value_fromwire(source, depth + 1, &value);
if (result != ISC_R_SUCCESS) {
isccc_sexpr_free(&list);
return (result);
@@ -628,7 +647,7 @@ isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp,
return (ISCCC_R_UNKNOWNVERSION);
}
- return (table_fromwire(source, secret, algorithm, alistp));
+ return (table_fromwire(source, secret, algorithm, 0, alistp));
}
static isc_result_t
diff --git a/lib/isccc/include/isccc/result.h b/lib/isccc/include/isccc/result.h
index 5346babefc..5b6a876d1c 100644
--- a/lib/isccc/include/isccc/result.h
+++ b/lib/isccc/include/isccc/result.h
@@ -46,8 +46,10 @@
#define ISCCC_R_CLOCKSKEW (ISC_RESULTCLASS_ISCCC + 4)
/*% Duplicate */
#define ISCCC_R_DUPLICATE (ISC_RESULTCLASS_ISCCC + 5)
+/*% Maximum recursion depth */
+#define ISCCC_R_MAXDEPTH (ISC_RESULTCLASS_ISCCC + 6)
-#define ISCCC_R_NRESULTS 6 /*%< Number of results */
+#define ISCCC_R_NRESULTS 7 /*%< Number of results */
ISC_LANG_BEGINDECLS
diff --git a/lib/isccc/result.c b/lib/isccc/result.c
index 9285435209..1956cb1655 100644
--- a/lib/isccc/result.c
+++ b/lib/isccc/result.c
@@ -36,12 +36,14 @@ static const char *text[ISCCC_R_NRESULTS] = {
"bad auth", /* 3 */
"expired", /* 4 */
"clock skew", /* 5 */
- "duplicate" /* 6 */
+ "duplicate", /* 6 */
+ "max depth" /* 7 */
};
static const char *ids[ISCCC_R_NRESULTS] = {
"ISCCC_R_UNKNOWNVERSION", "ISCCC_R_SYNTAX", "ISCCC_R_BADAUTH",
"ISCCC_R_EXPIRED", "ISCCC_R_CLOCKSKEW", "ISCCC_R_DUPLICATE",
+ "ISCCC_R_MAXDEPTH"
};
#define ISCCC_RESULT_RESULTSET 2
--
2.41.0

View File

@ -57,7 +57,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
Name: bind9.16 Name: bind9.16
License: MPLv2.0 License: MPLv2.0
Version: 9.16.23 Version: 9.16.23
Release: 0.16%{?dist} Release: 0.9%{?dist}.1
Epoch: 32 Epoch: 32
Url: https://www.isc.org/downloads/bind/ Url: https://www.isc.org/downloads/bind/
# #
@ -114,21 +114,6 @@ Patch174:bind-9.16-CVE-2021-25220-test.patch
Patch175:bind-9.16-CVE-2022-3080.patch Patch175:bind-9.16-CVE-2022-3080.patch
Patch176:bind-9.16-CVE-2022-38177.patch Patch176:bind-9.16-CVE-2022-38177.patch
Patch177:bind-9.16-CVE-2022-38178.patch Patch177:bind-9.16-CVE-2022-38178.patch
# https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/6793
# https://gitlab.isc.org/isc-projects/bind9/commit/bf2ea6d8525bfd96a84dad221ba9e004adb710a8
Patch178:bind-9.16-CVE-2022-2795.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/82185f4f80d2fa39a4569f6740cb360ffff8f5c4
Patch182: bind-9.16-CVE-2022-3094-1.patch
Patch183: bind-9.16-CVE-2022-3094-2.patch
Patch184: bind-9.16-CVE-2022-3094-3.patch
Patch185: bind-9.16-CVE-2022-3094-test.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/ea79385990c564eb478c286c089ea7ed15520690
Patch186: bind-9.16-CVE-2022-3736.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/b4a65aaea19762a3712932aa2270e8a833fbde22
Patch187: bind-9.16-CVE-2022-3924.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/f1d9e9ee3859976f403914d20ad2a10855343702
Patch188: bind-9.16-CVE-2023-2828.patch
Patch189: bind-9.16-CVE-2023-3341.patch
%{?systemd_ordering} %{?systemd_ordering}
Requires: coreutils Requires: coreutils
@ -433,15 +418,6 @@ in HTML and PDF format.
%patch175 -p1 -b .CVE-2022-3080 %patch175 -p1 -b .CVE-2022-3080
%patch176 -p1 -b .CVE-2022-38177 %patch176 -p1 -b .CVE-2022-38177
%patch177 -p1 -b .CVE-2022-38178 %patch177 -p1 -b .CVE-2022-38178
%patch178 -p1 -b .CVE-2022-2795
%patch182 -p1 -b .CVE-2022-3094
%patch183 -p1 -b .CVE-2022-3094
%patch184 -p1 -b .CVE-2022-3094
%patch185 -p1 -b .CVE-2022-3094-test
%patch186 -p1 -b .CVE-2022-3736
%patch187 -p1 -b .CVE-2022-3924
%patch188 -p1 -b .CVE-2023-2828
%patch189 -p1 -b .CVE-2023-3341
%if %{with PKCS11} %if %{with PKCS11}
%patch135 -p1 -b .config-pkcs11 %patch135 -p1 -b .config-pkcs11
@ -1161,28 +1137,7 @@ fi;
%endif %endif
%changelog %changelog
* Wed Sep 20 2023 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.16 * Thu Sep 22 2022 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.9.1
- Limit the amount of recursion possible in control channel (CVE-2023-3341)
* Tue Jun 20 2023 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.15
- Strengten cache cleaning to prevent overflowing configured limit
(CVE-2023-2828)
* Sat Feb 25 2023 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.14
- Handle subtle difference between upstream and rhel (CVE-2022-3094)
* Wed Feb 08 2023 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.13
- Prevent flooding with UPDATE requests (CVE-2022-3094)
- Handle RRSIG queries when server-stale is active (CVE-2022-3736)
- Fix crash when soft-quota is reached and serve-stale is active (CVE-2022-3924)
* Tue Dec 20 2022 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.12
- Include bind9.16-dnssec-utils in public repository (#2115322)
* Tue Oct 04 2022 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.11
- Bound the amount of work performed for delegations (CVE-2022-2795)
* Thu Sep 22 2022 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-0.10
- Fix possible serve-stale related crash (CVE-2022-3080) - Fix possible serve-stale related crash (CVE-2022-3080)
- Fix memory leak in ECDSA verify processing (CVE-2022-38177) - Fix memory leak in ECDSA verify processing (CVE-2022-38177)
- Fix memory leak in EdDSA verify processing (CVE-2022-38178) - Fix memory leak in EdDSA verify processing (CVE-2022-38178)