From ea7530366da502e0a116467e4565304603eba5b1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 29 May 2026 12:43:13 +0200
Subject: [PATCH 01/23] CVE-2026-6949: ndr_dns: let ndr_pull_dns_res_rec()
 remember the start offset

In order to verify TSIG signatures we need a reliable way to
truncate the original dns_name_packet buffer before the
last additional dns_res_rec.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16083

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <dbagnall@samba.org>
---
 librpc/idl/dns.idl                                    |  6 ++++++
 librpc/ndr/ndr_dns.c                                  | 11 +++++++++++
 .../librpc/tests/dns-decode_dns_name_packet-hex.txt   |  1 +
 3 files changed, 18 insertions(+)

diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl
index ec8668aa212..7cb316b2b12 100644
--- a/librpc/idl/dns.idl
+++ b/librpc/idl/dns.idl
@@ -251,6 +251,12 @@ interface dns
 	} dns_rdata;
 
 	typedef [flag(LIBNDR_PRINT_ARRAY_HEX|NDR_NOALIGN),nopush,nopull] struct {
+		/*
+		 * This is the start offset of this
+		 * dns_res_rec relative to the start of
+		 * dns_name_packet buffer.
+		 */
+		[ignore] uint32 start_ndr_offset;
 		dns_string name;
 		dns_qtype  rr_type;
 		dns_qclass rr_class;
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
index 9cc54c1a972..f1de40fd7e8 100644
--- a/librpc/ndr/ndr_dns.c
+++ b/librpc/ndr/ndr_dns.c
@@ -276,6 +276,17 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
 	ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX |
 				   LIBNDR_FLAG_NOALIGN);
 	if (ndr_flags & NDR_SCALARS) {
+		/*
+		 * Remember the start offset in order
+		 * to know how to truncate before the
+		 * last dns_res_rec in order to do
+		 * the correct TSIG calculation.
+		 *
+		 * Note that we just set LIBNDR_FLAG_NOALIGN
+		 * above, so ndr_pull_align is a no-op.
+		 */
+		r->start_ndr_offset = ndr->offset;
+
 		NDR_CHECK(ndr_pull_align(ndr, 4));
 		NDR_CHECK(ndr_pull_dns_string(ndr, NDR_SCALARS, &r->name));
 		NDR_CHECK(ndr_pull_dns_qtype(ndr, NDR_SCALARS, &r->rr_type));
diff --git a/source4/librpc/tests/dns-decode_dns_name_packet-hex.txt b/source4/librpc/tests/dns-decode_dns_name_packet-hex.txt
index 84b55f2d362..ccc29c062f2 100644
--- a/source4/librpc/tests/dns-decode_dns_name_packet-hex.txt
+++ b/source4/librpc/tests/dns-decode_dns_name_packet-hex.txt
@@ -21,6 +21,7 @@ pull returned Success
         answers: ARRAY(0)
         nsrecs: ARRAY(1)
             nsrecs: struct dns_res_rec
+                start_ndr_offset         : 0x00000027 (39)
                 name                     : 'cnamedotprefix0.samba2003.example.com'
                 rr_type                  : DNS_QTYPE_CNAME (0x5)
                 rr_class                 : DNS_QCLASS_IN (0x1)
-- 
2.43.0


