import UBI bind-9.16.23-40.el9_8.2
This commit is contained in:
parent
d71ca201e0
commit
2c0c582c23
376
SOURCES/bind-9.16-CVE-2026-3039.patch
Normal file
376
SOURCES/bind-9.16-CVE-2026-3039.patch
Normal file
@ -0,0 +1,376 @@
|
||||
From c824f5e341094edc653f64e730a7471d31f9cc14 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
|
||||
Date: Wed, 18 Mar 2026 00:10:35 +0100
|
||||
Subject: [PATCH] Fix GSS-API context leak in TKEY negotiation
|
||||
|
||||
Reject multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) in
|
||||
dst_gssapi_acceptctx(). Each call to gss_accept_sec_context()
|
||||
allocates a context inside the GSS library; without this fix, the
|
||||
context handle was passed back to process_gsstkey() which did not
|
||||
store it persistently, leaking it on every incomplete negotiation.
|
||||
|
||||
An unauthenticated attacker could exhaust server memory by sending
|
||||
repeated TKEY queries with GSSAPI tokens, each leaking one GSS
|
||||
context. The leaked memory is allocated by the GSS library via
|
||||
malloc(), bypassing BIND's memory accounting.
|
||||
|
||||
In practice, Kerberos/SPNEGO (the only mechanism used with BIND)
|
||||
completes in a single round, so rejecting continuation does not
|
||||
affect real-world deployments. See RFC 3645 Section 4.1.3.
|
||||
|
||||
(cherry picked from commit 3883058bf284de2889e4e3676767e58ad91a0ae3)
|
||||
(cherry picked from commit 58c646c4b95efcda759cf194a534290eef38135e)
|
||||
|
||||
Fix output token and GSS context leaks in TKEY/GSS-API error paths
|
||||
|
||||
In dst_gssapi_acceptctx(), rename outtoken to outtokenp (matching BIND
|
||||
convention for output pointer parameters) and free the allocated output
|
||||
token buffer on error in the cleanup path.
|
||||
|
||||
In process_gsstkey(), route the empty-principal error path through
|
||||
cleanup via CLEANUP() instead of returning early, so that the output
|
||||
token, GSS context, and TSIG key are all freed consistently by the
|
||||
existing cleanup block.
|
||||
|
||||
(cherry picked from commit f2240d2d06a1a68b622bd6b00a52c6fe4274426d)
|
||||
(cherry picked from commit 7eef47ce676672f65b4988b1b5c086c4f30a9b70)
|
||||
---
|
||||
lib/dns/gssapictx.c | 124 +++++++++++++++++++----------------
|
||||
lib/dns/include/dst/gssapi.h | 17 ++---
|
||||
lib/dns/tkey.c | 52 +++++++--------
|
||||
3 files changed, 98 insertions(+), 95 deletions(-)
|
||||
|
||||
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
|
||||
index b0c62497a5..2a78169869 100644
|
||||
--- a/lib/dns/gssapictx.c
|
||||
+++ b/lib/dns/gssapictx.c
|
||||
@@ -606,7 +606,14 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
||||
GSS_SPNEGO_MECHANISM, flags, 0, NULL, gintokenp, NULL,
|
||||
&gouttoken, &ret_flags, NULL);
|
||||
|
||||
- if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
|
||||
+ switch (gret) {
|
||||
+ case GSS_S_COMPLETE:
|
||||
+ result = ISC_R_SUCCESS;
|
||||
+ break;
|
||||
+ case GSS_S_CONTINUE_NEEDED:
|
||||
+ result = DNS_R_CONTINUE;
|
||||
+ break;
|
||||
+ default:
|
||||
gss_err_message(mctx, gret, minor, err_message);
|
||||
if (err_message != NULL && *err_message != NULL) {
|
||||
gss_log(3, "Failure initiating security context: %s",
|
||||
@@ -632,12 +639,6 @@ dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken,
|
||||
RETERR(isc_buffer_copyregion(outtoken, &r));
|
||||
}
|
||||
|
||||
- if (gret == GSS_S_COMPLETE) {
|
||||
- result = ISC_R_SUCCESS;
|
||||
- } else {
|
||||
- result = DNS_R_CONTINUE;
|
||||
- }
|
||||
-
|
||||
out:
|
||||
if (gouttoken.length != 0U) {
|
||||
(void)gss_release_buffer(&minor, &gouttoken);
|
||||
@@ -648,7 +649,7 @@ out:
|
||||
|
||||
isc_result_t
|
||||
dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
- isc_region_t *intoken, isc_buffer_t **outtoken,
|
||||
+ isc_region_t *intoken, isc_buffer_t **outtokenp,
|
||||
dns_gss_ctx_id_t *ctxout, dns_name_t *principal,
|
||||
isc_mem_t *mctx) {
|
||||
isc_region_t r;
|
||||
@@ -661,16 +662,11 @@ dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
isc_result_t result;
|
||||
char buf[1024];
|
||||
|
||||
- REQUIRE(outtoken != NULL && *outtoken == NULL);
|
||||
+ REQUIRE(outtokenp != NULL && *outtokenp == NULL);
|
||||
+ REQUIRE(*ctxout == NULL);
|
||||
|
||||
REGION_TO_GBUFFER(*intoken, gintoken);
|
||||
|
||||
- if (*ctxout == NULL) {
|
||||
- context = GSS_C_NO_CONTEXT;
|
||||
- } else {
|
||||
- context = *ctxout;
|
||||
- }
|
||||
-
|
||||
if (gssapi_keytab != NULL) {
|
||||
#if defined(ISC_PLATFORM_GSSAPI_KRB5_HEADER) || defined(WIN32)
|
||||
gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
|
||||
@@ -715,8 +711,15 @@ dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
|
||||
switch (gret) {
|
||||
case GSS_S_COMPLETE:
|
||||
- case GSS_S_CONTINUE_NEEDED:
|
||||
break;
|
||||
+ /*
|
||||
+ * RFC 3645 4.1.3: we don't handle GSS_S_CONTINUE_NEEDED
|
||||
+ * Multi-round GSS-API negotiation is not supported.
|
||||
+ */
|
||||
+ case GSS_S_CONTINUE_NEEDED:
|
||||
+ gss_log(3, "multi-round GSS-API negotiation not supported");
|
||||
+ (void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
+ /* FALLTHROUGH */
|
||||
case GSS_S_DEFECTIVE_TOKEN:
|
||||
case GSS_S_DEFECTIVE_CREDENTIAL:
|
||||
case GSS_S_BAD_SIG:
|
||||
@@ -729,7 +732,7 @@ dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
case GSS_S_BAD_MECH:
|
||||
case GSS_S_FAILURE:
|
||||
result = DNS_R_INVALIDTKEY;
|
||||
- /* fall through */
|
||||
+ /* FALLTHROUGH */
|
||||
default:
|
||||
gss_log(3, "failed gss_accept_sec_context: %s",
|
||||
gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
@@ -740,59 +743,70 @@ dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
}
|
||||
|
||||
if (gouttoken.length > 0U) {
|
||||
- isc_buffer_allocate(mctx, outtoken,
|
||||
+ isc_buffer_allocate(mctx, outtokenp,
|
||||
(unsigned int)gouttoken.length);
|
||||
GBUFFER_TO_REGION(gouttoken, r);
|
||||
- RETERR(isc_buffer_copyregion(*outtoken, &r));
|
||||
+ result = isc_buffer_copyregion(*outtokenp, &r);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ goto out;
|
||||
+ }
|
||||
(void)gss_release_buffer(&minor, &gouttoken);
|
||||
}
|
||||
|
||||
- if (gret == GSS_S_COMPLETE) {
|
||||
- gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
- if (gret != GSS_S_COMPLETE) {
|
||||
- gss_log(3, "failed gss_display_name: %s",
|
||||
- gss_error_tostring(gret, minor, buf,
|
||||
- sizeof(buf)));
|
||||
- RETERR(ISC_R_FAILURE);
|
||||
- }
|
||||
+ INSIST(gret == GSS_S_COMPLETE);
|
||||
|
||||
- /*
|
||||
- * Compensate for a bug in Solaris8's implementation
|
||||
- * of gss_display_name(). Should be harmless in any
|
||||
- * case, since principal names really should not
|
||||
- * contain null characters.
|
||||
- */
|
||||
- if (gnamebuf.length > 0U &&
|
||||
- ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
- {
|
||||
- gnamebuf.length--;
|
||||
- }
|
||||
+ gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
|
||||
+ if (gret != GSS_S_COMPLETE) {
|
||||
+ gss_log(3, "failed gss_display_name: %s",
|
||||
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
|
||||
+ result = ISC_R_FAILURE;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- gss_log(3, "gss-api source name (accept) is %.*s",
|
||||
- (int)gnamebuf.length, (char *)gnamebuf.value);
|
||||
+ /*
|
||||
+ * Compensate for a bug in Solaris8's implementation
|
||||
+ * of gss_display_name(). Should be harmless in any
|
||||
+ * case, since principal names really should not
|
||||
+ * contain null characters.
|
||||
+ */
|
||||
+ if (gnamebuf.length > 0U &&
|
||||
+ ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
|
||||
+ {
|
||||
+ gnamebuf.length--;
|
||||
+ }
|
||||
|
||||
- GBUFFER_TO_REGION(gnamebuf, r);
|
||||
- isc_buffer_init(&namebuf, r.base, r.length);
|
||||
- isc_buffer_add(&namebuf, r.length);
|
||||
+ gss_log(3, "gss-api source name (accept) is %.*s", (int)gnamebuf.length,
|
||||
+ (char *)gnamebuf.value);
|
||||
|
||||
- RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname, 0,
|
||||
- NULL));
|
||||
+ GBUFFER_TO_REGION(gnamebuf, r);
|
||||
+ isc_buffer_init(&namebuf, r.base, r.length);
|
||||
+ isc_buffer_add(&namebuf, r.length);
|
||||
|
||||
- if (gnamebuf.length != 0U) {
|
||||
- gret = gss_release_buffer(&minor, &gnamebuf);
|
||||
- if (gret != GSS_S_COMPLETE) {
|
||||
- gss_log(3, "failed gss_release_buffer: %s",
|
||||
- gss_error_tostring(gret, minor, buf,
|
||||
- sizeof(buf)));
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
- result = DNS_R_CONTINUE;
|
||||
+ result = dns_name_fromtext(principal, &namebuf, dns_rootname, 0, NULL);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
*ctxout = context;
|
||||
|
||||
out:
|
||||
+ if (result != ISC_R_SUCCESS && *outtokenp != NULL) {
|
||||
+ isc_buffer_free(outtokenp);
|
||||
+ }
|
||||
+
|
||||
+ if (result != ISC_R_SUCCESS && context != GSS_C_NO_CONTEXT) {
|
||||
+ (void)gss_delete_sec_context(&minor, &context, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (gnamebuf.length != 0U) {
|
||||
+ gret = gss_release_buffer(&minor, &gnamebuf);
|
||||
+ if (gret != GSS_S_COMPLETE) {
|
||||
+ gss_log(3, "failed gss_release_buffer: %s",
|
||||
+ gss_error_tostring(gret, minor, buf,
|
||||
+ sizeof(buf)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (gname != NULL) {
|
||||
gret = gss_release_name(&minor, &gname);
|
||||
if (gret != GSS_S_COMPLETE) {
|
||||
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
|
||||
index 10f8467aef..92dad43440 100644
|
||||
--- a/lib/dns/include/dst/gssapi.h
|
||||
+++ b/lib/dns/include/dst/gssapi.h
|
||||
@@ -113,20 +113,17 @@ dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab,
|
||||
* generated by gss_accept_sec_context() to be sent to the
|
||||
* initiator
|
||||
* 'context' is a valid pointer to receive the generated context handle.
|
||||
- * On the initial call, it should be a pointer to NULL, which
|
||||
- * will be allocated as a dns_gss_ctx_id_t. Subsequent calls
|
||||
- * should pass in the handle generated on the first call.
|
||||
- * Call dst_gssapi_releasecred to delete the context and free
|
||||
- * the memory.
|
||||
*
|
||||
* Requires:
|
||||
- * 'outtoken' to != NULL && *outtoken == NULL.
|
||||
+ * 'outtoken' != NULL && *outtoken == NULL.
|
||||
+ * 'context' != NULL && *context == NULL.
|
||||
*
|
||||
* Returns:
|
||||
- * ISC_R_SUCCESS msg was successfully updated to include the
|
||||
- * query to be sent
|
||||
- * DNS_R_CONTINUE transaction still in progress
|
||||
- * other an error occurred while building the message
|
||||
+ * ISC_R_SUCCESS msg was successfully updated to include
|
||||
+ * the query to be sent
|
||||
+ * DNS_R_INVALIDTKEY an error occurred while accepting the
|
||||
+ * context
|
||||
+ * ISC_R_FAILURE other error occurred
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
|
||||
index b4f12a0831..e7800113d9 100644
|
||||
--- a/lib/dns/tkey.c
|
||||
+++ b/lib/dns/tkey.c
|
||||
@@ -529,19 +529,9 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
- /*
|
||||
- * XXXDCL need to check for key expiry per 4.1.1
|
||||
- * XXXDCL need a way to check fully established, perhaps w/key_flags
|
||||
- */
|
||||
-
|
||||
intoken.base = tkeyin->key;
|
||||
intoken.length = tkeyin->keylen;
|
||||
|
||||
- result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
|
||||
- if (result == ISC_R_SUCCESS) {
|
||||
- gss_ctx = dst_key_getgssctx(tsigkey->key);
|
||||
- }
|
||||
-
|
||||
principal = dns_fixedname_initname(&fixed);
|
||||
|
||||
/*
|
||||
@@ -550,28 +540,27 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
||||
result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
|
||||
&intoken, &outtoken, &gss_ctx, principal,
|
||||
tctx->mctx);
|
||||
- if (result == DNS_R_INVALIDTKEY) {
|
||||
- if (tsigkey != NULL) {
|
||||
- dns_tsigkey_detach(&tsigkey);
|
||||
- }
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
tkeyout->error = dns_tsigerror_badkey;
|
||||
- tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA
|
||||
- */
|
||||
- return (ISC_R_SUCCESS);
|
||||
- }
|
||||
- if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) {
|
||||
+ tkey_log("process_gsstkey(): dns_tsigerror_badkey");
|
||||
+ result = ISC_R_SUCCESS;
|
||||
goto failure;
|
||||
}
|
||||
+
|
||||
/*
|
||||
- * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
|
||||
+ * Multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) is
|
||||
+ * rejected in dst_gssapi_acceptctx(), so if we reach here the
|
||||
+ * negotiation is complete and the principal must be set.
|
||||
*/
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
if (dns_name_countlabels(principal) == 0U) {
|
||||
- if (tsigkey != NULL) {
|
||||
- dns_tsigkey_detach(&tsigkey);
|
||||
- }
|
||||
+ tkeyout->error = dns_tsigerror_badkey;
|
||||
+ tkey_log("process_gsstkey(): "
|
||||
+ "completed context with empty principal");
|
||||
+ result = ISC_R_SUCCESS;
|
||||
+ goto failure;
|
||||
} else if (tsigkey == NULL) {
|
||||
#ifdef GSSAPI
|
||||
OM_uint32 gret, minor, lifetime;
|
||||
@@ -634,6 +623,10 @@ process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
failure:
|
||||
+ if (dstkey == NULL && gss_ctx != NULL) {
|
||||
+ dst_gssapi_deletectx(tctx->mctx, &gss_ctx);
|
||||
+ }
|
||||
+
|
||||
if (tsigkey != NULL) {
|
||||
dns_tsigkey_detach(&tsigkey);
|
||||
}
|
||||
@@ -646,10 +639,10 @@ failure:
|
||||
isc_buffer_free(&outtoken);
|
||||
}
|
||||
|
||||
- tkey_log("process_gsstkey(): %s", isc_result_totext(result)); /* XXXSRA
|
||||
- */
|
||||
-
|
||||
- return (result);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ tkey_log("process_gsstkey(): %s", isc_result_totext(result));
|
||||
+ }
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@@ -1558,9 +1551,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
|
||||
NULL));
|
||||
|
||||
/*
|
||||
- * XXXSRA This seems confused. If we got CONTINUE from initctx,
|
||||
- * the GSS negotiation hasn't completed yet, so we can't sign
|
||||
- * anything yet.
|
||||
+ * GSS negotiation is complete (CONTINUE returned earlier).
|
||||
+ * Create the TSIG key from the established context.
|
||||
*/
|
||||
|
||||
RETERR(dns_tsigkey_createfromkey(
|
||||
--
|
||||
2.54.0
|
||||
|
||||
729
SOURCES/bind-9.16-CVE-2026-5946.patch
Normal file
729
SOURCES/bind-9.16-CVE-2026-5946.patch
Normal file
@ -0,0 +1,729 @@
|
||||
From f215b6bb4a2a2bbed98195be7aa25e81d6e13b5c 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 e577560f65dbc6109fca8a597d16568a1cd8987c)
|
||||
|
||||
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 bec30ad70d17e36241df9da259bb2ac85b3c3435)
|
||||
|
||||
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 986533b5ae8e855e23430bd7f6af7552d82e0ece)
|
||||
|
||||
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 e7468f6be6dc98f86508627f4f333b6d09d2ac31)
|
||||
|
||||
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 e60ee54f7d650783d3b6dd7fdd749c64c6593353)
|
||||
|
||||
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 cd3a72e414d35c2ae573f4faea1148a95db7d5ff)
|
||||
|
||||
%RH
|
||||
fixed resolver, checkconf test
|
||||
---
|
||||
bin/named/server.c | 41 ++++--------
|
||||
bin/tests/system/checkconf/tests.sh | 14 +++-
|
||||
.../checkconf/warn-chaos-recursion.conf | 25 ++++++++
|
||||
bin/tests/system/resolver/tests.sh | 12 +++-
|
||||
bin/tests/system/unknown/tests.sh | 12 ++--
|
||||
lib/bind9/check.c | 22 ++++++-
|
||||
lib/dns/adb.c | 3 +-
|
||||
lib/dns/message.c | 11 ++++
|
||||
lib/dns/resolver.c | 13 +++-
|
||||
lib/ns/client.c | 64 ++++++++++++++++---
|
||||
lib/ns/update.c | 38 +++++------
|
||||
11 files changed, 181 insertions(+), 74 deletions(-)
|
||||
create mode 100644 bin/tests/system/checkconf/warn-chaos-recursion.conf
|
||||
|
||||
diff --git a/bin/named/server.c b/bin/named/server.c
|
||||
index 4cc69b5..c61de53 100644
|
||||
--- a/bin/named/server.c
|
||||
+++ b/bin/named/server.c
|
||||
@@ -1925,10 +1925,12 @@ 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(named_g_server->zonemgr, zone);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
+
|
||||
dns_zone_setstats(zone, named_g_server->zonestats);
|
||||
|
||||
return (named_zone_configure_writeable_dlz(dlzdb, zone, zclass,
|
||||
@@ -4180,6 +4182,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "max-cache-size", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
+
|
||||
/*
|
||||
* If "-T maxcachesize=..." is in effect, it overrides any other
|
||||
* "max-cache-size" setting found in configuration, either implicit or
|
||||
@@ -4930,34 +4933,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||||
}
|
||||
|
||||
/*
|
||||
- * 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, named_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(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
- NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
- "no root hints for view '%s'",
|
||||
- view->name);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Configure the view's TSIG keys.
|
||||
*/
|
||||
@@ -5067,7 +5051,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||||
obj = NULL;
|
||||
result = named_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 = named_config_get(maps, "qname-minimization", &obj);
|
||||
@@ -5168,13 +5153,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||||
CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on",
|
||||
NULL, actx, named_g_mctx, &view->cacheonacl));
|
||||
|
||||
- if (strcmp(view->name, "_bind") != 0 &&
|
||||
- view->rdclass != dns_rdataclass_chaos) {
|
||||
- /* named.conf only */
|
||||
+ if (view->rdclass != dns_rdataclass_in) {
|
||||
+ dns_acl_none(named_g_mctx, &view->recursionacl);
|
||||
+ dns_acl_none(named_g_mctx, &view->recursiononacl);
|
||||
+ } else {
|
||||
CHECK(configure_view_acl(vconfig, config, NULL,
|
||||
"allow-recursion", NULL, actx,
|
||||
named_g_mctx, &view->recursionacl));
|
||||
- /* named.conf only */
|
||||
CHECK(configure_view_acl(vconfig, config, NULL,
|
||||
"allow-recursion-on", NULL, actx,
|
||||
named_g_mctx, &view->recursiononacl));
|
||||
diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh
|
||||
index c1feed1..921707e 100644
|
||||
--- a/bin/tests/system/checkconf/tests.sh
|
||||
+++ b/bin/tests/system/checkconf/tests.sh
|
||||
@@ -402,7 +402,8 @@ $CHECKCONF -l good.conf |
|
||||
grep -v "is not implemented" |
|
||||
grep -v "is not recommended" |
|
||||
grep -v "no longer exists" |
|
||||
-grep -v "is obsolete" > checkconf.out$n || ret=1
|
||||
+grep -v "is obsolete" |
|
||||
+grep -v "recursion will be disabled" > checkconf.out$n || ret=1
|
||||
diff good.zonelist checkconf.out$n > diff.out$n || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
|
||||
status=`expr $status + $ret`
|
||||
@@ -603,5 +604,16 @@ status=$((status+ret))
|
||||
|
||||
rmdir keys
|
||||
|
||||
+n=$((n + 1))
|
||||
+echo_i "check 'recursion yes;' is warned and disabled in a non-IN view ($n)"
|
||||
+ret=0
|
||||
+$CHECKCONF warn-chaos-recursion.conf >checkconf.out$n 2>&1 || ret=1
|
||||
+grep -F "recursion will be disabled" checkconf.out$n >/dev/null || ret=1
|
||||
+if [ $ret != 0 ]; then
|
||||
+ echo_i "failed"
|
||||
+ ret=1
|
||||
+fi
|
||||
+status=$((status + ret))
|
||||
+
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
diff --git a/bin/tests/system/checkconf/warn-chaos-recursion.conf b/bin/tests/system/checkconf/warn-chaos-recursion.conf
|
||||
new file mode 100644
|
||||
index 0000000..e384533
|
||||
--- /dev/null
|
||||
+++ b/bin/tests/system/checkconf/warn-chaos-recursion.conf
|
||||
@@ -0,0 +1,25 @@
|
||||
+/*
|
||||
+ * 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 {
|
||||
+ directory ".";
|
||||
+};
|
||||
+
|
||||
+view chaos ch {
|
||||
+ match-clients { any; };
|
||||
+ recursion yes;
|
||||
+ zone "." {
|
||||
+ type hint;
|
||||
+ file "chaos.hints";
|
||||
+ };
|
||||
+};
|
||||
diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh
|
||||
index 2eae16f..30e86bc 100755
|
||||
--- a/bin/tests/system/resolver/tests.sh
|
||||
+++ b/bin/tests/system/resolver/tests.sh
|
||||
@@ -16,6 +16,10 @@ DIGOPTS="-p ${PORT}"
|
||||
RESOLVOPTS="-p ${PORT}"
|
||||
RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
|
||||
|
||||
+dig_with_opts() {
|
||||
+ "$DIG" $DIGOPTS "$@"
|
||||
+}
|
||||
+
|
||||
status=0
|
||||
n=0
|
||||
|
||||
@@ -853,10 +857,12 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
-echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
|
||||
+echo_i "checking REFUSED is returned when querying non existing domain in CH class ($n)"
|
||||
ret=0
|
||||
-$DIG $DIGOPTS @10.53.0.1 id.hostname txt ch > dig.ns1.out.${n} || ret=1
|
||||
-grep "status: NXDOMAIN" dig.ns1.out.${n} > /dev/null || ret=1
|
||||
+dig_with_opts @10.53.0.1 hostname.chaostest txt ch >dig.ns1.out.1.${n} || ret=1
|
||||
+grep "status: NOERROR" dig.ns1.out.1.${n} >/dev/null || ret=1
|
||||
+dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.2.${n} || ret=1
|
||||
+grep "status: REFUSED" dig.ns1.out.2.${n} >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
diff --git a/bin/tests/system/unknown/tests.sh b/bin/tests/system/unknown/tests.sh
|
||||
index e480f66..5576216 100644
|
||||
--- a/bin/tests/system/unknown/tests.sh
|
||||
+++ b/bin/tests/system/unknown/tests.sh
|
||||
@@ -80,8 +80,8 @@ echo_i "querying for various representations of a CLASS10 TYPE1 record ($n)"
|
||||
for i in 1 2
|
||||
do
|
||||
ret=0
|
||||
- $DIG +short $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out.$i.test$n || ret=1
|
||||
- echo '\# 4 0A000001' | $DIFF - dig.out.$i.test$n || ret=1
|
||||
+ $DIG $DIGOPTS @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n || ret=1
|
||||
+ grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]
|
||||
then
|
||||
echo_i "#$i failed"
|
||||
@@ -94,8 +94,8 @@ echo_i "querying for various representations of a CLASS10 TXT record ($n)"
|
||||
for i in 1 2 3 4
|
||||
do
|
||||
ret=0
|
||||
- $DIG +short $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out.$i.test$n || ret=1
|
||||
- echo '"hello"' | $DIFF - dig.out.$i.test$n || ret=1
|
||||
+ $DIG $DIGOPTS @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n || ret=1
|
||||
+ grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]
|
||||
then
|
||||
echo_i "#$i failed"
|
||||
@@ -108,8 +108,8 @@ echo_i "querying for various representations of a CLASS10 TYPE123 record ($n)"
|
||||
for i in 1 2
|
||||
do
|
||||
ret=0
|
||||
- $DIG +short $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out.$i.test$n || ret=1
|
||||
- echo '\# 1 00' | $DIFF - dig.out.$i.test$n || ret=1
|
||||
+ $DIG $DIGOPTS @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n || ret=1
|
||||
+ grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]
|
||||
then
|
||||
echo_i "#$i failed"
|
||||
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
|
||||
index 2225bee..e55c4fc 100644
|
||||
--- a/lib/bind9/check.c
|
||||
+++ b/lib/bind9/check.c
|
||||
@@ -2271,13 +2271,17 @@ check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr,
|
||||
*/
|
||||
static bool
|
||||
check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
- const cfg_obj_t *goptions, isc_log_t *logctx,
|
||||
- cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
|
||||
+ dns_rdataclass_t vclass, const cfg_obj_t *goptions,
|
||||
+ isc_log_t *logctx, cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
|
||||
dns_acl_t *acl = NULL;
|
||||
const cfg_obj_t *obj;
|
||||
isc_result_t result;
|
||||
bool retval = true;
|
||||
|
||||
+ if (vclass != dns_rdataclass_in) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Check the "recursion" option first.
|
||||
*/
|
||||
@@ -2831,7 +2835,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* contradicts the purpose of the former.
|
||||
*/
|
||||
if (ztype == CFG_ZONE_MIRROR &&
|
||||
- !check_recursion(config, voptions, goptions, logctx, actx, mctx))
|
||||
+ !check_recursion(config, voptions, zclass, goptions, logctx, actx,
|
||||
+ mctx))
|
||||
{
|
||||
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
||||
"zone '%s': mirror zones cannot be used if "
|
||||
@@ -4553,6 +4558,17 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
|
||||
cfg_aclconfctx_create(mctx, &actx);
|
||||
|
||||
+ if (vclass != dns_rdataclass_in) {
|
||||
+ if (check_recursion(config, voptions, dns_rdataclass_in,
|
||||
+ options, logctx, actx, mctx))
|
||||
+ {
|
||||
+ cfg_obj_log(opts, logctx, ISC_LOG_WARNING,
|
||||
+ "recursion will be disabled for "
|
||||
+ "non-IN view '%s'",
|
||||
+ viewname);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "zone", &zones);
|
||||
} else {
|
||||
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
|
||||
index 74fdc72..cc00798 100644
|
||||
--- a/lib/dns/adb.c
|
||||
+++ b/lib/dns/adb.c
|
||||
@@ -941,7 +941,8 @@ 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 aa434a7..a81943d 100644
|
||||
--- a/lib/dns/message.c
|
||||
+++ b/lib/dns/message.c
|
||||
@@ -1085,6 +1085,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 5973bc1..460a15e 100644
|
||||
--- a/lib/dns/resolver.c
|
||||
+++ b/lib/dns/resolver.c
|
||||
@@ -7369,9 +7369,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;
|
||||
result = dns_rdataset_next(rdataset))
|
||||
diff --git a/lib/ns/client.c b/lib/ns/client.c
|
||||
index 87b8a18..554934f 100644
|
||||
--- a/lib/ns/client.c
|
||||
+++ b/lib/ns/client.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/dnstap.h>
|
||||
#include <dns/edns.h>
|
||||
+#include <dns/enumclass.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/peer.h>
|
||||
@@ -1937,7 +1938,9 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
}
|
||||
}
|
||||
|
||||
- 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)
|
||||
@@ -1958,12 +1961,49 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
return;
|
||||
}
|
||||
|
||||
+ ns_client_dumpmessage(client,
|
||||
+ "message class could not be determined");
|
||||
+ ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
+ isc_task_unpause(client->task);
|
||||
+ return;
|
||||
+ 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);
|
||||
+ isc_task_unpause(client->task);
|
||||
+ 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);
|
||||
+ isc_task_unpause(client->task);
|
||||
+ 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, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
+ "invalid message class: %s", classbuf);
|
||||
+
|
||||
+ ns_client_error(client, DNS_R_NOTIMP);
|
||||
isc_task_unpause(client->task);
|
||||
return;
|
||||
}
|
||||
@@ -2017,7 +2057,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
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);
|
||||
isc_task_unpause(client->task);
|
||||
return;
|
||||
@@ -2201,6 +2241,10 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
break;
|
||||
case dns_opcode_update:
|
||||
CTRACE("update");
|
||||
+ if (client->view->rdclass != dns_rdataclass_in) {
|
||||
+ ns_client_error(client, DNS_R_NOTIMP);
|
||||
+ break;
|
||||
+ }
|
||||
#ifdef HAVE_DNSTAP
|
||||
dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
|
||||
&client->destsockaddr, TCP_CLIENT(client), NULL,
|
||||
@@ -2211,6 +2255,10 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
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, handle);
|
||||
break;
|
||||
@@ -2302,7 +2350,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
* The caller is responsible for that.
|
||||
*/
|
||||
|
||||
- REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL));
|
||||
+ REQUIRE(NS_CLIENT_VALID(client) || (new && client != NULL));
|
||||
REQUIRE(VALID_MANAGER(mgr) || !new);
|
||||
|
||||
if (new) {
|
||||
@@ -2748,7 +2796,7 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
|
||||
int len = 1024;
|
||||
isc_result_t result;
|
||||
|
||||
- if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
|
||||
+ if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1)) || reason == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/lib/ns/update.c b/lib/ns/update.c
|
||||
index 0e0bdc9..dc6ebdf 100644
|
||||
--- a/lib/ns/update.c
|
||||
+++ b/lib/ns/update.c
|
||||
@@ -1288,7 +1288,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
|
||||
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
|
||||
@@ -1432,8 +1435,7 @@ failure:
|
||||
* '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) {
|
||||
dns_rdataset_t *rdataset;
|
||||
@@ -1449,7 +1451,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;
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1551,7 +1553,6 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
||||
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;
|
||||
@@ -1559,10 +1560,12 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
||||
|
||||
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);
|
||||
|
||||
+ /* Updates are only supported for class IN. */
|
||||
+ INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
||||
+
|
||||
/*
|
||||
* Update message processing can leak record existence information
|
||||
* so check that we are allowed to query this zone. Additionally,
|
||||
@@ -1603,13 +1606,13 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
||||
dns_ttl_t ttl;
|
||||
dns_rdataclass_t update_class;
|
||||
|
||||
- get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
+ get_current_rr(request, DNS_SECTION_UPDATE, &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) {
|
||||
+ if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* Check for meta-RRs. The RFC2136 pseudocode says
|
||||
* check for ANY|AXFR|MAILA|MAILB, but the text adds
|
||||
@@ -2733,9 +2736,7 @@ 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;
|
||||
dns_name_t *tmpname = NULL;
|
||||
dns_zoneopt_t options;
|
||||
@@ -2754,10 +2755,9 @@ 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.
|
||||
*/
|
||||
@@ -2778,8 +2778,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, "prerequisite TTL is not "
|
||||
@@ -2846,7 +2846,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) {
|
||||
@@ -2906,10 +2906,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,
|
||||
+ get_current_rr(request, DNS_SECTION_UPDATE, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
|
||||
- if (update_class == zoneclass) {
|
||||
+ if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* RFC1123 doesn't allow MF and MD in master zones.
|
||||
*/
|
||||
@@ -3488,10 +3488,6 @@ common:
|
||||
dns_db_detach(&db);
|
||||
}
|
||||
|
||||
- if (ssutable != NULL) {
|
||||
- dns_ssutable_detach(&ssutable);
|
||||
- }
|
||||
-
|
||||
isc_task_detach(&task);
|
||||
uev->result = result;
|
||||
if (zone != NULL) {
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -54,7 +54,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
|
||||
Name: bind
|
||||
License: MPLv2.0
|
||||
Version: 9.16.23
|
||||
Release: 40%{?dist}.1
|
||||
Release: 40%{?dist}.2
|
||||
Epoch: 32
|
||||
Url: https://www.isc.org/downloads/bind/
|
||||
#
|
||||
@ -203,6 +203,11 @@ Patch225: bind-9.16-CVE-2025-40778.patch
|
||||
Patch226: bind-9.16-properly-process-extra-nameserver-lines.patch
|
||||
# https://gitlab.isc.org/isc-projects/bind9/-/commit/a5e8d2354385d4f42a58113b16960d85ec306b09
|
||||
Patch227: bind-9.16-CVE-2026-1519.patch
|
||||
# https://gitlab.isc.org/isc-projects/bind9/-/commit/7f04d7104304fdc6b858c41bb44ad151b2c3e1b7
|
||||
Patch230: bind-9.16-CVE-2026-3039.patch
|
||||
# https://gitlab.isc.org/isc-projects/bind9/-/commit/ec2c98181115bd5f6c7087fcc74d816490d4312e
|
||||
# https://gitlab.isc.org/isc-projects/bind9/-/commit/e5abd37cb2330af1fbfeba68eb32f2873390226d
|
||||
Patch231: bind-9.16-CVE-2026-5946.patch
|
||||
|
||||
%{?systemd_ordering}
|
||||
# https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers
|
||||
@ -1262,6 +1267,10 @@ fi;
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon May 25 2026 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-40.2
|
||||
- Fix GSS-API resource leak (CVE-2026-3039)
|
||||
- Invalid handling of CLASS != IN (CVE-2026-5946)
|
||||
|
||||
* Fri Mar 27 2026 Petr Menšík <pemensik@redhat.com> - 32:9.16.23-40.1
|
||||
- Prevent Denial of Service via maliciously crafted DNSSEC-validated zone
|
||||
(CVE-2026-1519)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user