From 4b61092459b403b2945daa9082052366f3508b69 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Fri, 10 Jun 2022 19:18:07 +1200
Subject: [PATCH 94/99] CVE-2022-2031 auth: Add ticket type field to
 auth_user_info_dc and auth_session_info

This field may be used to convey whether we were provided with a TGT or
a non-TGT. We ensure both structures are zeroed out to avoid incorrect
results being produced by an uninitialised field.

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

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 auth/auth_sam_reply.c              |  2 +-
 auth/auth_util.c                   |  2 +-
 librpc/idl/auth.idl                | 23 +++++++++++++++++++++++
 source4/auth/ntlm/auth_developer.c |  2 +-
 source4/auth/sam.c                 |  2 +-
 source4/auth/session.c             |  2 ++
 source4/auth/system_session.c      |  6 +++---
 7 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/auth/auth_sam_reply.c b/auth/auth_sam_reply.c
index b5b6362dc93..2e27e5715d1 100644
--- a/auth/auth_sam_reply.c
+++ b/auth/auth_sam_reply.c
@@ -416,7 +416,7 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_INVALID_LEVEL;
 	}
 
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	/*
diff --git a/auth/auth_util.c b/auth/auth_util.c
index fe01babd107..ec9094d0f15 100644
--- a/auth/auth_util.c
+++ b/auth/auth_util.c
@@ -44,7 +44,7 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	dst = talloc(mem_ctx, struct auth_session_info);
+	dst = talloc_zero(mem_ctx, struct auth_session_info);
 	if (dst == NULL) {
 		DBG_ERR("talloc failed\n");
 		TALLOC_FREE(frame);
diff --git a/librpc/idl/auth.idl b/librpc/idl/auth.idl
index 1092935b971..f7658cdde28 100644
--- a/librpc/idl/auth.idl
+++ b/librpc/idl/auth.idl
@@ -75,6 +75,26 @@ interface auth
 		[unique,charset(UTF8),string] char *sanitized_username;
 	} auth_user_info_unix;
 
+	/*
+	 * If the user was authenticated with a Kerberos ticket, this indicates
+	 * the type of the ticket; TGT, or non-TGT (i.e. service ticket). If
+	 * unset, the type is unknown. This indicator is useful for the KDC and
+	 * the kpasswd service, which share the same account and keys. By
+	 * ensuring it is provided with the appopriate ticket type, each service
+	 * avoids accepting a ticket meant for the other.
+	 *
+	 * The heuristic used to determine the type is the presence or absence
+	 * of a REQUESTER_SID buffer in the PAC; we use its presence to assume
+	 * we have a TGT. This heuristic will fail for older Samba versions and
+	 * Windows prior to Nov. 2021 updates, which lack support for this
+	 * buffer.
+	 */
+	typedef enum {
+		TICKET_TYPE_UNKNOWN = 0,
+		TICKET_TYPE_TGT = 1,
+		TICKET_TYPE_NON_TGT = 2
+	} ticket_type;
+
 	/* This is the interim product of the auth subsystem, before
 	 * privileges and local groups are handled */
 	typedef [public] struct {
@@ -83,6 +103,7 @@ interface auth
 		auth_user_info *info;
 		[noprint] DATA_BLOB user_session_key;
 		[noprint] DATA_BLOB lm_session_key;
+		ticket_type ticket_type;
 	} auth_user_info_dc;
 
 	typedef [public] struct {
@@ -112,6 +133,8 @@ interface auth
 		 * We generate this in auth_generate_session_info()
 		 */
 	        GUID unique_session_token;
+
+		ticket_type ticket_type;
 	} auth_session_info;
 
 	typedef [public] struct {
diff --git a/source4/auth/ntlm/auth_developer.c b/source4/auth/ntlm/auth_developer.c
index 1823989c68d..6e92252d5c5 100644
--- a/source4/auth/ntlm/auth_developer.c
+++ b/source4/auth/ntlm/auth_developer.c
@@ -76,7 +76,7 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx,
 	}
 	NT_STATUS_NOT_OK_RETURN(nt_status);
 
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	/* This returns a pointer to a struct dom_sid, which is the
diff --git a/source4/auth/sam.c b/source4/auth/sam.c
index 8b233bab3ad..7c609655fcb 100644
--- a/source4/auth/sam.c
+++ b/source4/auth/sam.c
@@ -363,7 +363,7 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx,
 	TALLOC_CTX *tmp_ctx;
 	struct ldb_message_element *el;
 
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	tmp_ctx = talloc_new(user_info_dc);
diff --git a/source4/auth/session.c b/source4/auth/session.c
index 8e44dcd24f1..d6e936dd1f1 100644
--- a/source4/auth/session.c
+++ b/source4/auth/session.c
@@ -222,6 +222,8 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
 
 	session_info->credentials = NULL;
 
+	session_info->ticket_type = user_info_dc->ticket_type;
+
 	talloc_steal(mem_ctx, session_info);
 	*_session_info = session_info;
 	talloc_free(tmp_ctx);
diff --git a/source4/auth/system_session.c b/source4/auth/system_session.c
index 85b8f1c4edb..2518d654e8b 100644
--- a/source4/auth/system_session.c
+++ b/source4/auth/system_session.c
@@ -115,7 +115,7 @@ NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name,
 	struct auth_user_info_dc *user_info_dc;
 	struct auth_user_info *info;
 
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	/* This returns a pointer to a struct dom_sid, which is the
@@ -191,7 +191,7 @@ static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx,
 	struct auth_user_info_dc *user_info_dc;
 	struct auth_user_info *info;
 
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	user_info_dc->num_sids = 7;
@@ -356,7 +356,7 @@ _PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx,
 {
 	struct auth_user_info_dc *user_info_dc;
 	struct auth_user_info *info;
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
 
 	/* This returns a pointer to a struct dom_sid, which is the
-- 
2.25.1
