Backport of:

From d8752af75899caa621f71e6149024a2ed5d552b4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Wed, 17 Jun 2026 08:58:40 +0200
Subject: [PATCH 20/23] CVE-2026-58218: dns_server: Only add a tkey after successful
 authentication

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

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Douglas Bagnall <dbagnall@samba.org>
---
 source4/dns_server/dns_query.c | 41 ++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 14 deletions(-)

--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -654,7 +654,8 @@ static WERROR handle_authoritative_recv(
 	return WERR_OK;
 }
 
-static NTSTATUS create_tkey(struct dns_server *dns,
+static NTSTATUS create_tkey(TALLOC_CTX *mem_ctx,
+			    struct dns_server *dns,
 			    const char* name,
 			    const char* algorithm,
 			    const struct tsocket_address *remote_address,
@@ -662,9 +663,9 @@ static NTSTATUS create_tkey(struct dns_s
 			    struct dns_server_tkey **tkey)
 {
 	NTSTATUS status;
-	struct dns_server_tkey_store *store = dns->tkeys;
-	struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey);
+	struct dns_server_tkey *k = NULL;
 
+	k = talloc_zero(mem_ctx, struct dns_server_tkey);
 	if (k == NULL) {
 		goto nomem;
 	}
@@ -724,12 +725,6 @@ static NTSTATUS create_tkey(struct dns_s
 		goto fail;
 	}
 
-	TALLOC_FREE(store->tkeys[store->next_idx]);
-
-	store->tkeys[store->next_idx] = k;
-	(store->next_idx)++;
-	store->next_idx %= store->size;
-
 	*tkey = k;
 	return NT_STATUS_OK;
 
@@ -741,6 +736,17 @@ fail:
 	return status;
 }
 
+static void add_tkey(struct dns_server_tkey_store *store,
+		     struct dns_server_tkey **tkey)
+{
+	TALLOC_FREE(store->tkeys[store->next_idx]);
+
+	store->tkeys[store->next_idx] = talloc_move(store->tkeys, tkey);
+
+	(store->next_idx)++;
+	store->next_idx %= store->size;
+}
+
 static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
 				  struct dns_server *dns,
 				  struct dns_server_tkey *tkey,
@@ -844,6 +850,7 @@ static WERROR handle_tkey(struct dns_ser
 		struct dns_server_tkey *tkey;
 		DATA_BLOB key;
 		DATA_BLOB reply;
+		bool created = false;
 
 		tkey = dns_find_tkey(dns->tkeys, in->questions[0].name);
 		if (tkey != NULL && tkey->complete) {
@@ -854,15 +861,19 @@ static WERROR handle_tkey(struct dns_ser
 		}
 
 		if (tkey == NULL) {
-			status  = create_tkey(dns, in->questions[0].name,
-					      in_tkey->rdata.tkey_record.algorithm,
-					      state->remote_address,
-					      state->local_address,
-					      &tkey);
+			status = create_tkey(
+				mem_ctx,
+				dns,
+				in->questions[0].name,
+				in_tkey->rdata.tkey_record.algorithm,
+				state->remote_address,
+				state->local_address,
+				&tkey);
 			if (!NT_STATUS_IS_OK(status)) {
 				ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
 				return ntstatus_to_werror(status);
 			}
+			created = true;
 		}
 
 		key.data = in_tkey->rdata.tkey_record.key_data;
@@ -887,6 +898,9 @@ static WERROR handle_tkey(struct dns_ser
 			if (state->key_name == NULL) {
 				return WERR_NOT_ENOUGH_MEMORY;
 			}
+			if (created) {
+				add_tkey(dns->tkeys, &tkey);
+			}
 		} else {
 			DEBUG(1, ("GSS key negotiation returned %s\n", nt_errstr(status)));
 			ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
