From 9902f1b0bf30b663a457230d3b3dcd92fd279879 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 14 Jul 2021 14:51:34 +0200
Subject: [PATCH 201/266] CVE-2020-25719 mit-samba: Add ks_free_principal()
 
Conflict: NA 
Reference: https://git.samba.org/samba.git/?p=samba.git;a=patch;h=9902f1b0bf30b663a457230d3b3dcd92fd279879


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

[abartlet@samba.org As submitted in patch to Samba bugzilla
 to address this issue as https://attachments.samba.org/attachment.cgi?id=16724
 on overall bug https://bugzilla.samba.org/show_bug.cgi?id=14725]

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
---
 source4/kdc/mit-kdb/kdb_samba.h            |  2 +
 source4/kdc/mit-kdb/kdb_samba_principals.c | 52 ++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/source4/kdc/mit-kdb/kdb_samba.h b/source4/kdc/mit-kdb/kdb_samba.h
index 132dcfed363..2ff8642cc50 100644
--- a/source4/kdc/mit-kdb/kdb_samba.h
+++ b/source4/kdc/mit-kdb/kdb_samba.h
@@ -46,6 +46,8 @@ krb5_error_code ks_get_principal(krb5_context context,
 				 unsigned int kflags,
 				 krb5_db_entry **kentry);
 
+void ks_free_principal(krb5_context context, krb5_db_entry *entry);
+
 bool ks_data_eq_string(krb5_data d, const char *s);
 
 krb5_data ks_make_data(void *data, unsigned int len);
diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c
index 79219e5a274..cc67c2392be 100644
--- a/source4/kdc/mit-kdb/kdb_samba_principals.c
+++ b/source4/kdc/mit-kdb/kdb_samba_principals.c
@@ -59,6 +59,58 @@ cleanup:
 	return code;
 }
 
+static void ks_free_principal_e_data(krb5_context context, krb5_octet *e_data)
+{
+	struct samba_kdc_entry *skdc_entry;
+
+	skdc_entry = talloc_get_type_abort(e_data,
+					   struct samba_kdc_entry);
+	talloc_set_destructor(skdc_entry, NULL);
+	TALLOC_FREE(skdc_entry);
+}
+
+void ks_free_principal(krb5_context context, krb5_db_entry *entry)
+{
+	krb5_tl_data *tl_data_next = NULL;
+	krb5_tl_data *tl_data = NULL;
+	size_t i, j;
+
+	if (entry != NULL) {
+		krb5_free_principal(context, entry->princ);
+
+		for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
+			tl_data_next = tl_data->tl_data_next;
+			if (tl_data->tl_data_contents != NULL) {
+				free(tl_data->tl_data_contents);
+			}
+			free(tl_data);
+		}
+
+		if (entry->key_data != NULL) {
+			for (i = 0; i < entry->n_key_data; i++) {
+				for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+					if (entry->key_data[i].key_data_length[j] != 0) {
+						if (entry->key_data[i].key_data_contents[j] != NULL) {
+							memset(entry->key_data[i].key_data_contents[j], 0, entry->key_data[i].key_data_length[j]);
+							free(entry->key_data[i].key_data_contents[j]);
+						}
+					}
+					entry->key_data[i].key_data_contents[j] = NULL;
+					 entry->key_data[i].key_data_length[j] = 0;
+					 entry->key_data[i].key_data_type[j] = 0;
+				}
+			}
+			free(entry->key_data);
+		}
+
+		if (entry->e_data) {
+			ks_free_principal_e_data(context, entry->e_data);
+		}
+
+		free(entry);
+	}
+}
+
 static krb5_boolean ks_is_master_key_principal(krb5_context context,
 					       krb5_const_principal princ)
 {
-- 
2.23.0

