Compare commits
No commits in common. "c8s" and "c8-beta" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
SOURCES/ldns-1.7.0.tar.gz
|
SOURCES/ldns-1.7.0.tar.gz
|
||||||
/ldns-1.7.0.tar.gz
|
|
||||||
|
|||||||
1
.ldns.metadata
Normal file
1
.ldns.metadata
Normal file
@ -0,0 +1 @@
|
|||||||
|
ceeeccf8a27e61a854762737f6ee02f44662c1b8 SOURCES/ldns-1.7.0.tar.gz
|
||||||
@ -39,7 +39,7 @@
|
|||||||
Summary: Low-level DNS(SEC) library with API
|
Summary: Low-level DNS(SEC) library with API
|
||||||
Name: ldns
|
Name: ldns
|
||||||
Version: 1.7.0
|
Version: 1.7.0
|
||||||
Release: 23%{?dist}
|
Release: 22%{?dist}
|
||||||
|
|
||||||
License: BSD
|
License: BSD
|
||||||
Url: http://www.nlnetlabs.nl/%{name}/
|
Url: http://www.nlnetlabs.nl/%{name}/
|
||||||
@ -48,8 +48,6 @@ Patch1: ldns-1.7.0-multilib.patch
|
|||||||
Patch2: ldns-1.7.0-parse-limit.patch
|
Patch2: ldns-1.7.0-parse-limit.patch
|
||||||
Patch3: ldns-1.7.0-realloc.patch
|
Patch3: ldns-1.7.0-realloc.patch
|
||||||
Patch4: ldns-1.7.0-coverity.patch
|
Patch4: ldns-1.7.0-coverity.patch
|
||||||
# https://src.fedoraproject.org/rpms/ldns/raw/rawhide/f/ldns-1.9.0-CVE-2026-10846.patch
|
|
||||||
Patch5: ldns-1.7.0-CVE-2026-10846.patch
|
|
||||||
|
|
||||||
Group: System Environment/Libraries
|
Group: System Environment/Libraries
|
||||||
# Only needed for builds from svn snapshot
|
# Only needed for builds from svn snapshot
|
||||||
@ -162,7 +160,6 @@ pushd %{pkgname}
|
|||||||
%patch2 -p1 -b .limit
|
%patch2 -p1 -b .limit
|
||||||
%patch3 -p1 -b .realloc
|
%patch3 -p1 -b .realloc
|
||||||
%patch4 -p1 -b .covscan
|
%patch4 -p1 -b .covscan
|
||||||
%patch5 -p2 -b .cve-2026-10846
|
|
||||||
# To built svn snapshots
|
# To built svn snapshots
|
||||||
%if 0%{snapshot}
|
%if 0%{snapshot}
|
||||||
rm config.guess config.sub ltmain.sh
|
rm config.guess config.sub ltmain.sh
|
||||||
@ -358,11 +355,6 @@ rm -rf doc/man
|
|||||||
%doc doc
|
%doc doc
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Wed Jul 15 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 1.7.0-23
|
|
||||||
- Fix CVE-2026-10846: validate DNS response source address, transaction
|
|
||||||
ID, and query section matching
|
|
||||||
- Resolves: RHEL-210700
|
|
||||||
|
|
||||||
* Tue Jan 16 2024 Petr Menšík <pemensik@redhat.com> - 1.7.0-22
|
* Tue Jan 16 2024 Petr Menšík <pemensik@redhat.com> - 1.7.0-22
|
||||||
- Export ldns-utils, ldns-doc, perl-ldns and python3-ldns into CRB (RHEL-315)
|
- Export ldns-utils, ldns-doc, perl-ldns and python3-ldns into CRB (RHEL-315)
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
--- !Policy
|
|
||||||
product_versions:
|
|
||||||
- rhel-8
|
|
||||||
decision_context: osci_compose_gate
|
|
||||||
rules:
|
|
||||||
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional}
|
|
||||||
@ -1,202 +0,0 @@
|
|||||||
From cc51382f8bf8bb5675e93ed16e816ccdfb1581ea Mon Sep 17 00:00:00 2001
|
|
||||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2026 09:22:45 +0000
|
|
||||||
Subject: [PATCH] Fix CVE-2026-10846: validate DNS response source address and
|
|
||||||
query matching
|
|
||||||
|
|
||||||
Adapted from upstream patch for ldns 1.9.0. Adds:
|
|
||||||
- ldns_sockaddr_cmp() to verify response comes from queried address
|
|
||||||
- Transaction ID matching check
|
|
||||||
- Query section count validation
|
|
||||||
- Response question matching against original query
|
|
||||||
- New error status codes for ID mismatch, qdcount, and query mismatch
|
|
||||||
---
|
|
||||||
ldns-1.7.0_python3/error.c | 6 +++
|
|
||||||
ldns-1.7.0_python3/ldns/error.h | 5 +-
|
|
||||||
ldns-1.7.0_python3/net.c | 92 ++++++++++++++++++++++++++++++++-
|
|
||||||
3 files changed, 100 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ldns-1.7.0_python3/error.c b/ldns-1.7.0_python3/error.c
|
|
||||||
index 35ee5bd..a3103f8 100644
|
|
||||||
--- a/ldns-1.7.0_python3/error.c
|
|
||||||
+++ b/ldns-1.7.0_python3/error.c
|
|
||||||
@@ -157,6 +157,12 @@ ldns_lookup_table ldns_error_str[] = {
|
|
||||||
"X509_STORE_CTX_set0_dane() functions within OpenSSL >= 1.1.0 "
|
|
||||||
"to be able to verify the DANE-TA usage type." },
|
|
||||||
#endif
|
|
||||||
+ { LDNS_STATUS_ID_DID_NOT_MATCH,
|
|
||||||
+ "Response ID did not match the query ID" },
|
|
||||||
+ { LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
|
|
||||||
+ "The query section MUST contain exactly one question" },
|
|
||||||
+ { LDNS_STATUS_QUERY_DID_NOT_MATCH,
|
|
||||||
+ "The question in the response did not match the query" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
diff --git a/ldns-1.7.0_python3/ldns/error.h b/ldns-1.7.0_python3/ldns/error.h
|
|
||||||
index 15f49a2..936df38 100644
|
|
||||||
--- a/ldns-1.7.0_python3/ldns/error.h
|
|
||||||
+++ b/ldns-1.7.0_python3/ldns/error.h
|
|
||||||
@@ -129,7 +129,10 @@ enum ldns_enum_status {
|
|
||||||
LDNS_STATUS_RDATA_OVERFLOW,
|
|
||||||
LDNS_STATUS_SYNTAX_SUPERFLUOUS_TEXT_ERR,
|
|
||||||
LDNS_STATUS_NSEC3_DOMAINNAME_OVERFLOW,
|
|
||||||
- LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA
|
|
||||||
+ LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA,
|
|
||||||
+ LDNS_STATUS_ID_DID_NOT_MATCH,
|
|
||||||
+ LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
|
|
||||||
+ LDNS_STATUS_QUERY_DID_NOT_MATCH
|
|
||||||
};
|
|
||||||
typedef enum ldns_enum_status ldns_status;
|
|
||||||
|
|
||||||
diff --git a/ldns-1.7.0_python3/net.c b/ldns-1.7.0_python3/net.c
|
|
||||||
index 6e6a12b..53b4df5 100644
|
|
||||||
--- a/ldns-1.7.0_python3/net.c
|
|
||||||
+++ b/ldns-1.7.0_python3/net.c
|
|
||||||
@@ -410,6 +410,50 @@ ldns_udp_bgsend(ldns_buffer *qbin,
|
|
||||||
return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/** helper sockaddr compare function. returns -1, 0 or 1. */
|
|
||||||
+static int
|
|
||||||
+ldns_sockaddr_cmp(const struct sockaddr_storage* addr1, socklen_t len1,
|
|
||||||
+ const struct sockaddr_storage* addr2, socklen_t len2)
|
|
||||||
+{
|
|
||||||
+ struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
|
|
||||||
+ struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
|
|
||||||
+ struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
|
|
||||||
+ struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
|
|
||||||
+ if(len1 < len2)
|
|
||||||
+ return -1;
|
|
||||||
+ if(len1 > len2)
|
|
||||||
+ return 1;
|
|
||||||
+ assert(len1 == len2);
|
|
||||||
+ if( p1_in->sin_family < p2_in->sin_family)
|
|
||||||
+ return -1;
|
|
||||||
+ if( p1_in->sin_family > p2_in->sin_family)
|
|
||||||
+ return 1;
|
|
||||||
+ assert( p1_in->sin_family == p2_in->sin_family );
|
|
||||||
+ /* compare ip4 */
|
|
||||||
+ if( p1_in->sin_family == AF_INET ) {
|
|
||||||
+ /* just order it, ntohs not required */
|
|
||||||
+ if(p1_in->sin_port < p2_in->sin_port)
|
|
||||||
+ return -1;
|
|
||||||
+ if(p1_in->sin_port > p2_in->sin_port)
|
|
||||||
+ return 1;
|
|
||||||
+ assert(p1_in->sin_port == p2_in->sin_port);
|
|
||||||
+ return memcmp(&p1_in->sin_addr, &p2_in->sin_addr,
|
|
||||||
+ sizeof(p1_in->sin_addr));
|
|
||||||
+ } else if (p1_in6->sin6_family == AF_INET6) {
|
|
||||||
+ /* just order it, ntohs not required */
|
|
||||||
+ if(p1_in6->sin6_port < p2_in6->sin6_port)
|
|
||||||
+ return -1;
|
|
||||||
+ if(p1_in6->sin6_port > p2_in6->sin6_port)
|
|
||||||
+ return 1;
|
|
||||||
+ assert(p1_in6->sin6_port == p2_in6->sin6_port);
|
|
||||||
+ return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
|
|
||||||
+ sizeof(p1_in6->sin6_addr));
|
|
||||||
+ } else {
|
|
||||||
+ /* eek unknown type, perform this comparison for sanity. */
|
|
||||||
+ return memcmp(addr1, addr2, len1);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static ldns_status
|
|
||||||
ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
|
|
||||||
const struct sockaddr_storage *to , socklen_t tolen,
|
|
||||||
@@ -418,6 +462,8 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
|
|
||||||
{
|
|
||||||
int sockfd;
|
|
||||||
uint8_t *answer;
|
|
||||||
+ struct sockaddr_storage reply_addr;
|
|
||||||
+ socklen_t reply_addr_len;
|
|
||||||
|
|
||||||
sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
|
|
||||||
|
|
||||||
@@ -436,13 +482,21 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
|
|
||||||
* but returns a 'NETWORK_ERROR' much like a timeout. */
|
|
||||||
ldns_sock_nonblock(sockfd);
|
|
||||||
|
|
||||||
- answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
|
|
||||||
+ reply_addr_len = sizeof(reply_addr);
|
|
||||||
+ memset(&reply_addr, 0, reply_addr_len);
|
|
||||||
+ answer = ldns_udp_read_wire(sockfd, answer_size, &reply_addr,
|
|
||||||
+ &reply_addr_len);
|
|
||||||
close_socket(sockfd);
|
|
||||||
|
|
||||||
if (!answer) {
|
|
||||||
/* oops */
|
|
||||||
return LDNS_STATUS_NETWORK_ERR;
|
|
||||||
}
|
|
||||||
+ /* Check that the reply came from the to addr. */
|
|
||||||
+ if(ldns_sockaddr_cmp(to, tolen, &reply_addr, reply_addr_len) != 0) {
|
|
||||||
+ free(answer);
|
|
||||||
+ return LDNS_STATUS_NETWORK_ERR;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
*result = answer;
|
|
||||||
return LDNS_STATUS_OK;
|
|
||||||
@@ -481,6 +535,10 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
|
|
||||||
|
|
||||||
assert(r != NULL);
|
|
||||||
|
|
||||||
+ /* The query should at least have one question */
|
|
||||||
+ if(ldns_buffer_limit(qb) < 6 || ldns_buffer_read_u16_at(qb, 4) != 1)
|
|
||||||
+ return LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
|
|
||||||
+
|
|
||||||
status = LDNS_STATUS_OK;
|
|
||||||
rtt = ldns_resolver_rtt(r);
|
|
||||||
ns_array = ldns_resolver_nameservers(r);
|
|
||||||
@@ -568,6 +626,16 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
|
|
||||||
ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
|
|
||||||
status = send_status;
|
|
||||||
}
|
|
||||||
+ if(reply_bytes && ldns_buffer_limit(qb) >= 2) {
|
|
||||||
+ uint16_t txid = ldns_buffer_read_u16_at(qb, 0);
|
|
||||||
+ if(reply_size < 2 ||
|
|
||||||
+ ldns_read_uint16(reply_bytes) != txid) {
|
|
||||||
+ status = LDNS_STATUS_ID_DID_NOT_MATCH;
|
|
||||||
+ LDNS_FREE(reply_bytes);
|
|
||||||
+ reply_bytes = NULL;
|
|
||||||
+ reply_size = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* obey the fail directive */
|
|
||||||
if (!reply_bytes) {
|
|
||||||
@@ -577,7 +645,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
|
|
||||||
LDNS_FREE(src);
|
|
||||||
}
|
|
||||||
LDNS_FREE(ns);
|
|
||||||
- return LDNS_STATUS_ERR;
|
|
||||||
+ return status ? status : LDNS_STATUS_ERR;
|
|
||||||
} else {
|
|
||||||
LDNS_FREE(ns);
|
|
||||||
continue;
|
|
||||||
@@ -637,6 +705,26 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
|
|
||||||
#endif /* HAVE_SSL */
|
|
||||||
|
|
||||||
LDNS_FREE(reply_bytes);
|
|
||||||
+ if (reply) {
|
|
||||||
+ ldns_pkt *query = NULL;
|
|
||||||
+
|
|
||||||
+ if(ldns_pkt_qdcount(reply) != 1) {
|
|
||||||
+ status = LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
|
|
||||||
+ ldns_pkt_free(reply);
|
|
||||||
+ reply = NULL;
|
|
||||||
+
|
|
||||||
+ } else if(ldns_wire2pkt(&query
|
|
||||||
+ , ldns_buffer_begin(qb)
|
|
||||||
+ , ldns_buffer_position(qb)) != LDNS_STATUS_OK
|
|
||||||
+ || ldns_pkt_qdcount(query) != 1
|
|
||||||
+ || ldns_rr_compare(ldns_rr_list_rr(ldns_pkt_question(query),0)
|
|
||||||
+ ,ldns_rr_list_rr(ldns_pkt_question(reply),0))){
|
|
||||||
+ status = LDNS_STATUS_QUERY_DID_NOT_MATCH;
|
|
||||||
+ ldns_pkt_free(reply);
|
|
||||||
+ reply = NULL;
|
|
||||||
+ }
|
|
||||||
+ ldns_pkt_free(query);
|
|
||||||
+ }
|
|
||||||
if (result) {
|
|
||||||
*result = reply;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user