Günther Deschner 38eeb01
From e649f9aedfa8a0d5caa241743bb4191927430879 Mon Sep 17 00:00:00 2001
a172510
From: Isaac Boukris <iboukris@gmail.com>
a172510
Date: Fri, 27 Sep 2019 18:25:03 +0300
Günther Deschner 38eeb01
Subject: [PATCH 1/3] mit-kdc: add basic loacl realm S4U support
a172510
a172510
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
a172510
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
a172510
---
Günther Deschner 38eeb01
 source4/kdc/mit-kdb/kdb_samba_policies.c | 124 +++++++++++------------
Günther Deschner 38eeb01
 source4/kdc/mit_samba.c                  |  47 ++-------
Günther Deschner 38eeb01
 source4/kdc/mit_samba.h                  |   6 +-
Günther Deschner 38eeb01
 3 files changed, 71 insertions(+), 106 deletions(-)
a172510
a172510
diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c
Günther Deschner 38eeb01
index 7bc9a7b3347..fc20bfed2f4 100644
a172510
--- a/source4/kdc/mit-kdb/kdb_samba_policies.c
a172510
+++ b/source4/kdc/mit-kdb/kdb_samba_policies.c
a172510
@@ -192,13 +192,17 @@ static krb5_error_code ks_verify_pac(krb5_context context,
a172510
 				     krb5_keyblock *krbtgt_key,
a172510
 				     krb5_timestamp authtime,
a172510
 				     krb5_authdata **tgt_auth_data,
a172510
-				     krb5_pac *pac)
a172510
+				     krb5_pac *out_pac)
a172510
 {
a172510
 	struct mit_samba_context *mit_ctx;
a172510
 	krb5_authdata **authdata = NULL;
a172510
-	krb5_pac ipac = NULL;
a172510
-	DATA_BLOB logon_data = { NULL, 0 };
a172510
+	krb5_keyblock *header_server_key = NULL;
a172510
+	krb5_key_data *impersonator_kd = NULL;
a172510
+	krb5_keyblock impersonator_key = {0};
a172510
 	krb5_error_code code;
a172510
+	krb5_pac pac;
a172510
+
a172510
+	*out_pac = NULL;
a172510
 
a172510
 	mit_ctx = ks_get_context(context);
a172510
 	if (mit_ctx == NULL) {
a172510
@@ -230,41 +234,43 @@ static krb5_error_code ks_verify_pac(krb5_context context,
a172510
 	code = krb5_pac_parse(context,
a172510
 			      authdata[0]->contents,
a172510
 			      authdata[0]->length,
a172510
-			      &ipac);
a172510
+			      &pac;;
a172510
 	if (code != 0) {
a172510
 		goto done;
a172510
 	}
a172510
 
a172510
-	/* TODO: verify this is correct
a172510
-	 *
a172510
-	 * In the constrained delegation case, the PAC is from a service
a172510
-	 * ticket rather than a TGT; we must verify the server and KDC
a172510
-	 * signatures to assert that the server did not forge the PAC.
a172510
+	/*
a172510
+	 * For constrained delegation in MIT version < 1.18 we aren't provided
a172510
+	 * with the 2nd ticket server key to verify the PAC.
a172510
+	 * We can workaround that by fetching the key from the client db entry,
a172510
+	 * which is the impersonator account in that version.
a172510
+	 * TODO: use the provided entry in the new 1.18 version.
a172510
 	 */
a172510
 	if (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
a172510
-		code = krb5_pac_verify(context,
a172510
-				       ipac,
a172510
-				       authtime,
a172510
-				       client_princ,
a172510
-				       server_key,
a172510
-				       krbtgt_key);
a172510
+		/* The impersonator must be local. */
a172510
+		if (client == NULL) {
a172510
+			code = KRB5KDC_ERR_BADOPTION;
a172510
+			goto done;
a172510
+		}
a172510
+		/* Fetch and decrypt 2nd ticket server's current key. */
a172510
+		code = krb5_dbe_find_enctype(context, client, -1, -1, 0,
a172510
+					     &impersonator_kd);
a172510
+		if (code != 0) {
a172510
+			goto done;
a172510
+		}
a172510
+		code = krb5_dbe_decrypt_key_data(context, NULL,
a172510
+						 impersonator_kd,
a172510
+						 &impersonator_key, NULL);
a172510
+		if (code != 0) {
a172510
+			goto done;
a172510
+		}
a172510
+		header_server_key = &impersonator_key;
a172510
 	} else {
a172510
-		code = krb5_pac_verify(context,
a172510
-				       ipac,
a172510
-				       authtime,
a172510
-				       client_princ,
a172510
-				       krbtgt_key,
a172510
-				       NULL);
a172510
-	}
a172510
-	if (code != 0) {
a172510
-		goto done;
a172510
+		header_server_key = krbtgt_key;
a172510
 	}
a172510
 
a172510
-	/* check and update PAC */
a172510
-	code = krb5_pac_parse(context,
a172510
-			      authdata[0]->contents,
a172510
-			      authdata[0]->length,
a172510
-			      pac);
a172510
+	code = krb5_pac_verify(context, pac, authtime, client_princ,
a172510
+			       header_server_key, NULL);
a172510
 	if (code != 0) {
a172510
 		goto done;
a172510
 	}
a172510
@@ -272,17 +278,22 @@ static krb5_error_code ks_verify_pac(krb5_context context,
a172510
 	code = mit_samba_reget_pac(mit_ctx,
a172510
 				   context,
a172510
 				   flags,
a172510
-				   client_princ,
a172510
 				   client,
a172510
 				   server,
a172510
 				   krbtgt,
a172510
 				   krbtgt_key,
a172510
-				   pac);
a172510
+				   &pac;;
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	*out_pac = pac;
a172510
+	pac = NULL;
a172510
 
a172510
 done:
a172510
+	krb5_free_keyblock_contents(context, &impersonator_key);
a172510
 	krb5_free_authdata(context, authdata);
a172510
-	krb5_pac_free(context, ipac);
a172510
-	free(logon_data.data);
a172510
+	krb5_pac_free(context, pac);
a172510
 
a172510
 	return code;
a172510
 }
Günther Deschner 38eeb01
@@ -328,6 +339,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
Günther Deschner 38eeb01
 	krb5_authdata **pac_auth_data = NULL;
a172510
 	krb5_authdata **authdata = NULL;
Günther Deschner 38eeb01
 	krb5_boolean is_as_req;
a172510
+	krb5_const_principal pac_client;
a172510
 	krb5_error_code code;
a172510
 	krb5_pac pac = NULL;
a172510
 	krb5_data pac_data;
Günther Deschner 38eeb01
@@ -341,11 +353,6 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
a172510
 	krbtgt_key = krbtgt_key == NULL ? local_krbtgt_key : krbtgt_key;
a172510
 #endif
a172510
 
a172510
-	/* FIXME: We don't support S4U yet */
a172510
-	if (flags & KRB5_KDB_FLAGS_S4U) {
a172510
-		return KRB5_KDB_DBTYPE_NOSUP;
a172510
-	}
a172510
-
Günther Deschner 38eeb01
 	is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
Günther Deschner 38eeb01
 
Günther Deschner 38eeb01
 	/*
Günther Deschner 38eeb01
@@ -406,6 +413,16 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
Günther Deschner 38eeb01
 		ks_client_princ = client->princ;
Günther Deschner 38eeb01
 	}
Günther Deschner 38eeb01
 
a172510
+	/* In protocol transition, we are currently not provided with the tgt
a172510
+	 * client name to verify the PAC, we could probably skip the name
a172510
+	 * verification and just verify the signatures, but since we don't
a172510
+	 * support cross-realm nor aliases, we can just use server->princ */
a172510
+	if (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) {
a172510
+		pac_client = server->princ;
a172510
+	} else {
Günther Deschner 38eeb01
+		pac_client = ks_client_princ;
a172510
+	}
Günther Deschner 38eeb01
+
Günther Deschner 38eeb01
 	if (client_entry == NULL) {
Günther Deschner 38eeb01
 		client_entry = client;
a172510
 	}
Günther Deschner 38eeb01
@@ -470,7 +487,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
a172510
 
Günther Deschner 38eeb01
 			code = ks_verify_pac(context,
Günther Deschner 38eeb01
 					     flags,
Günther Deschner 38eeb01
-					     ks_client_princ,
Günther Deschner 38eeb01
+					     pac_client,
Günther Deschner 38eeb01
 					     client_entry,
Günther Deschner 38eeb01
 					     server,
Günther Deschner 38eeb01
 					     krbtgt,
Günther Deschner 38eeb01
@@ -510,7 +527,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
Günther Deschner 38eeb01
 		  is_as_req ? "AS-REQ" : "TGS-REQ",
Günther Deschner 38eeb01
 		  client_name);
Günther Deschner 38eeb01
 	code = krb5_pac_sign(context, pac, authtime, ks_client_princ,
a172510
-			server_key, krbtgt_key, &pac_data);
a172510
+			     server_key, krbtgt_key, &pac_data);
a172510
 	if (code != 0) {
a172510
 		DBG_ERR("krb5_pac_sign failed: %d\n", code);
a172510
 		goto done;
Günther Deschner 38eeb01
@@ -536,12 +553,6 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
a172510
 					      KRB5_AUTHDATA_IF_RELEVANT,
a172510
 					      authdata,
a172510
 					      signed_auth_data);
a172510
-	if (code != 0) {
a172510
-		goto done;
a172510
-	}
a172510
-
a172510
-	code = 0;
Günther Deschner 38eeb01
-
a172510
 done:
Günther Deschner 38eeb01
 	if (client_entry != NULL && client_entry != client) {
Günther Deschner 38eeb01
 		ks_free_principal(context, client_entry);
Günther Deschner 38eeb01
@@ -567,32 +578,13 @@ krb5_error_code kdb_samba_db_check_allowed_to_delegate(krb5_context context,
a172510
 	 * server; -> delegating service
a172510
 	 * proxy; -> target principal
a172510
 	 */
a172510
-	krb5_db_entry *delegating_service = discard_const_p(krb5_db_entry, server);
a172510
-
a172510
-	char *target_name = NULL;
a172510
-	bool is_enterprise;
a172510
-	krb5_error_code code;
a172510
 
a172510
 	mit_ctx = ks_get_context(context);
a172510
 	if (mit_ctx == NULL) {
a172510
 		return KRB5_KDB_DBNOTINITED;
a172510
 	}
a172510
 
a172510
-	code = krb5_unparse_name(context, proxy, &target_name);
a172510
-	if (code) {
a172510
-		goto done;
a172510
-	}
a172510
-
a172510
-	is_enterprise = (proxy->type == KRB5_NT_ENTERPRISE_PRINCIPAL);
a172510
-
a172510
-	code = mit_samba_check_s4u2proxy(mit_ctx,
a172510
-					 delegating_service,
a172510
-					 target_name,
a172510
-					 is_enterprise);
a172510
-
a172510
-done:
a172510
-	free(target_name);
a172510
-	return code;
a172510
+	return mit_samba_check_s4u2proxy(mit_ctx, server, proxy);
a172510
 }
a172510
 
a172510
 
a172510
diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
Günther Deschner 38eeb01
index e015c5a52db..2a48d731501 100644
a172510
--- a/source4/kdc/mit_samba.c
a172510
+++ b/source4/kdc/mit_samba.c
Günther Deschner 38eeb01
@@ -475,7 +475,6 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
a172510
 krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
a172510
 				    krb5_context context,
a172510
 				    int flags,
a172510
-				    krb5_const_principal client_principal,
a172510
 				    krb5_db_entry *client,
a172510
 				    krb5_db_entry *server,
a172510
 				    krb5_db_entry *krbtgt,
Günther Deschner 38eeb01
@@ -639,7 +638,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
a172510
 								  context,
a172510
 								  *pac,
a172510
 								  server->princ,
a172510
-								  discard_const(client_principal),
a172510
+								  client->princ,
a172510
 								  deleg_blob);
a172510
 		if (!NT_STATUS_IS_OK(nt_status)) {
a172510
 			DEBUG(0, ("Update delegation info failed: %s\n",
Günther Deschner 38eeb01
@@ -961,41 +960,17 @@ int mit_samba_check_client_access(struct mit_samba_context *ctx,
a172510
 }
a172510
 
a172510
 int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
a172510
-			      krb5_db_entry *kentry,
a172510
-			      const char *target_name,
a172510
-			      bool is_nt_enterprise_name)
a172510
+			      const krb5_db_entry *server,
a172510
+			      krb5_const_principal target_principal)
a172510
 {
a172510
-#if 1
a172510
-	/*
a172510
-	 * This is disabled because mit_samba_update_pac_data() does not handle
a172510
-	 * S4U_DELEGATION_INFO
a172510
-	 */
a172510
-
a172510
-	return KRB5KDC_ERR_BADOPTION;
a172510
-#else
a172510
-	krb5_principal target_principal;
a172510
-	int flags = 0;
a172510
-	int ret;
a172510
-
a172510
-	if (is_nt_enterprise_name) {
a172510
-		flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE;
a172510
-	}
a172510
-
a172510
-	ret = krb5_parse_name_flags(ctx->context, target_name,
a172510
-				    flags, &target_principal);
a172510
-	if (ret) {
a172510
-		return ret;
a172510
-	}
a172510
-
a172510
-	ret = samba_kdc_check_s4u2proxy(ctx->context,
a172510
-					ctx->db_ctx,
a172510
-					skdc_entry,
a172510
-					target_principal);
a172510
-
a172510
-	krb5_free_principal(ctx->context, target_principal);
a172510
-
a172510
-	return ret;
a172510
-#endif
a172510
+	struct samba_kdc_entry *server_skdc_entry =
a172510
+		 talloc_get_type_abort(server->e_data,
a172510
+				       struct samba_kdc_entry);
a172510
+
a172510
+	return samba_kdc_check_s4u2proxy(ctx->context,
a172510
+					 ctx->db_ctx,
a172510
+					 server_skdc_entry,
a172510
+					 target_principal);
a172510
 }
a172510
 
a172510
 static krb5_error_code mit_samba_change_pwd_error(krb5_context context,
a172510
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
Günther Deschner 38eeb01
index 636c77ec97c..9cb00c9610e 100644
a172510
--- a/source4/kdc/mit_samba.h
a172510
+++ b/source4/kdc/mit_samba.h
a172510
@@ -56,7 +56,6 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
a172510
 krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
a172510
 				    krb5_context context,
a172510
 				    int flags,
a172510
-				    krb5_const_principal client_principal,
a172510
 				    krb5_db_entry *client,
a172510
 				    krb5_db_entry *server,
a172510
 				    krb5_db_entry *krbtgt,
a172510
@@ -73,9 +72,8 @@ int mit_samba_check_client_access(struct mit_samba_context *ctx,
a172510
 				  DATA_BLOB *e_data);
a172510
 
a172510
 int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
a172510
-			      krb5_db_entry *kentry,
a172510
-			      const char *target_name,
a172510
-			      bool is_nt_enterprise_name);
a172510
+			      const krb5_db_entry *server,
a172510
+			      krb5_const_principal target_principal);
a172510
 
a172510
 int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
a172510
 				      char *pwd,
a172510
-- 
Günther Deschner 38eeb01
2.33.1
Günther Deschner 38eeb01
a172510
Günther Deschner 38eeb01
From 9eca7b08a3987d6320d6584e146005bbc01720f6 Mon Sep 17 00:00:00 2001
a172510
From: Isaac Boukris <iboukris@gmail.com>
a172510
Date: Fri, 27 Sep 2019 18:35:30 +0300
Günther Deschner 38eeb01
Subject: [PATCH 2/3] krb5-mit: enable S4U client support for MIT build
a172510
a172510
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
a172510
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
a172510
---
a172510
 lib/krb5_wrap/krb5_samba.c            | 185 ++++++++++++++++++++++++++
a172510
 lib/krb5_wrap/krb5_samba.h            |   2 -
a172510
 source4/auth/kerberos/kerberos_util.c |  11 --
Günther Deschner 38eeb01
 3 files changed, 185 insertions(+), 13 deletions(-)
a172510
a172510
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
Günther Deschner 38eeb01
index fff5b4e2a22..791b417d5ba 100644
a172510
--- a/lib/krb5_wrap/krb5_samba.c
a172510
+++ b/lib/krb5_wrap/krb5_samba.c
Günther Deschner 38eeb01
@@ -2694,6 +2694,191 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
a172510
 
a172510
 	return 0;
a172510
 }
a172510
+
a172510
+#else /* MIT */
a172510
+
a172510
+static bool princ_compare_no_dollar(krb5_context ctx,
a172510
+				    krb5_principal a,
a172510
+				    krb5_principal b)
a172510
+{
a172510
+	bool cmp;
a172510
+	krb5_principal mod = NULL;
a172510
+
a172510
+	if (a->length == 1 && b->length == 1 &&
a172510
+	    a->data[0].length != 0 && b->data[0].length != 0 &&
a172510
+	    a->data[0].data[a->data[0].length -1] !=
a172510
+	    b->data[0].data[b->data[0].length -1]) {
a172510
+		if (a->data[0].data[a->data[0].length -1] == '$') {
a172510
+			mod = a;
a172510
+			mod->data[0].length--;
a172510
+		} else if (b->data[0].data[b->data[0].length -1] == '$') {
a172510
+			mod = b;
a172510
+			mod->data[0].length--;
a172510
+		}
a172510
+	}
a172510
+
a172510
+	cmp = krb5_principal_compare_flags(ctx, a, b,
a172510
+					   KRB5_PRINCIPAL_COMPARE_CASEFOLD);
a172510
+
a172510
+	if (mod != NULL) {
a172510
+		mod->data[0].length++;
a172510
+	}
a172510
+
a172510
+	return cmp;
a172510
+}
a172510
+
a172510
+krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
a172510
+					   krb5_ccache store_cc,
a172510
+					   krb5_principal init_principal,
a172510
+					   const char *init_password,
a172510
+					   krb5_principal impersonate_principal,
a172510
+					   const char *self_service,
a172510
+					   const char *target_service,
a172510
+					   krb5_get_init_creds_opt *krb_options,
a172510
+					   time_t *expire_time,
a172510
+					   time_t *kdc_time)
a172510
+{
a172510
+	krb5_error_code code;
a172510
+	krb5_principal self_princ = NULL;
a172510
+	krb5_principal target_princ = NULL;
a172510
+	krb5_creds *store_creds;
a172510
+	krb5_creds *s4u2self_creds = NULL;
a172510
+	krb5_creds *s4u2proxy_creds = NULL;
a172510
+	krb5_creds init_creds = {0};
a172510
+	krb5_creds mcreds = {0};
a172510
+	krb5_flags options = KRB5_GC_NO_STORE;
a172510
+	krb5_ccache tmp_cc;
a172510
+	bool s4u2proxy;
a172510
+
a172510
+	code = krb5_cc_new_unique(ctx, "MEMORY", NULL, &tmp_cc);
a172510
+	if (code != 0) {
a172510
+		return code;
a172510
+	}
a172510
+
a172510
+	code = krb5_get_init_creds_password(ctx, &init_creds,
a172510
+					    init_principal,
a172510
+					    init_password,
a172510
+					    NULL, NULL,
a172510
+					    0,
a172510
+					    NULL,
a172510
+					    krb_options);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	code = krb5_cc_initialize(ctx, tmp_cc, init_creds.client);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	code = krb5_cc_store_cred(ctx, tmp_cc, &init_creds);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	/*
a172510
+	 * Check if we also need S4U2Proxy or if S4U2Self is
a172510
+	 * enough in order to get a ticket for the target.
a172510
+	 */
a172510
+	if (target_service == NULL) {
a172510
+		s4u2proxy = false;
a172510
+	} else if (strcmp(target_service, self_service) == 0) {
a172510
+		s4u2proxy = false;
a172510
+	} else {
a172510
+		s4u2proxy = true;
a172510
+	}
a172510
+
a172510
+	code = krb5_parse_name(ctx, self_service, &self_princ);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	/* MIT lacks aliases support in S4U, for S4U2Self we require the tgt
a172510
+	 * client and the request server to be the same principal name. */
a172510
+	if (!princ_compare_no_dollar(ctx, init_creds.client, self_princ)) {
a172510
+		code = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	mcreds.client = impersonate_principal;
a172510
+	mcreds.server = init_creds.client;
a172510
+
a172510
+	code = krb5_get_credentials_for_user(ctx, options, tmp_cc, &mcreds,
a172510
+					     NULL, &s4u2self_creds);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	if (s4u2proxy) {
a172510
+		code = krb5_parse_name(ctx, target_service, &target_princ);
a172510
+		if (code != 0) {
a172510
+			goto done;
a172510
+		}
a172510
+
a172510
+		mcreds.client = init_creds.client;
a172510
+		mcreds.server = target_princ;
a172510
+		mcreds.second_ticket = s4u2self_creds->ticket;
a172510
+
a172510
+		code = krb5_get_credentials(ctx, options |
a172510
+					    KRB5_GC_CONSTRAINED_DELEGATION,
a172510
+					    tmp_cc, &mcreds, &s4u2proxy_creds);
a172510
+		if (code != 0) {
a172510
+			goto done;
a172510
+		}
a172510
+
a172510
+		/* Check KDC support of S4U2Proxy extension */
a172510
+		if (!krb5_principal_compare(ctx, s4u2self_creds->client,
a172510
+					    s4u2proxy_creds->client)) {
a172510
+			code = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
a172510
+			goto done;
a172510
+		}
a172510
+
a172510
+		store_creds = s4u2proxy_creds;
a172510
+	} else {
a172510
+		store_creds = s4u2self_creds;;
a172510
+
a172510
+		/* We need to save the ticket with the requested server name
a172510
+		 * or the caller won't be able to find it in cache. */
a172510
+		if (!krb5_principal_compare(ctx, self_princ,
a172510
+			store_creds->server)) {
a172510
+			krb5_free_principal(ctx, store_creds->server);
a172510
+			store_creds->server = NULL;
a172510
+			code = krb5_copy_principal(ctx, self_princ,
a172510
+						   &store_creds->server);
a172510
+			if (code != 0) {
a172510
+				goto done;
a172510
+			}
a172510
+		}
a172510
+	}
a172510
+
a172510
+	code = krb5_cc_initialize(ctx, store_cc, store_creds->client);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	code = krb5_cc_store_cred(ctx, store_cc, store_creds);
a172510
+	if (code != 0) {
a172510
+		goto done;
a172510
+	}
a172510
+
a172510
+	if (expire_time) {
a172510
+		*expire_time = (time_t) store_creds->times.endtime;
a172510
+	}
a172510
+
a172510
+	if (kdc_time) {
a172510
+		*kdc_time = (time_t) store_creds->times.starttime;
a172510
+	}
a172510
+
a172510
+done:
a172510
+	krb5_cc_destroy(ctx, tmp_cc);
a172510
+	krb5_free_cred_contents(ctx, &init_creds);
a172510
+	krb5_free_creds(ctx, s4u2self_creds);
a172510
+	krb5_free_creds(ctx, s4u2proxy_creds);
a172510
+	krb5_free_principal(ctx, self_princ);
a172510
+	krb5_free_principal(ctx, target_princ);
a172510
+
a172510
+	return code;
a172510
+}
a172510
 #endif
a172510
 
a172510
 #if !defined(HAVE_KRB5_MAKE_PRINCIPAL) && defined(HAVE_KRB5_BUILD_PRINCIPAL_ALLOC_VA)
a172510
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h
Günther Deschner 38eeb01
index 56a2a975278..5af9c6d73c1 100644
a172510
--- a/lib/krb5_wrap/krb5_samba.h
a172510
+++ b/lib/krb5_wrap/krb5_samba.h
a172510
@@ -252,7 +252,6 @@ krb5_error_code smb_krb5_kinit_password_ccache(krb5_context ctx,
a172510
 					       krb5_get_init_creds_opt *krb_options,
a172510
 					       time_t *expire_time,
a172510
 					       time_t *kdc_time);
a172510
-#ifdef SAMBA4_USES_HEIMDAL
a172510
 krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
a172510
 					   krb5_ccache store_cc,
a172510
 					   krb5_principal init_principal,
a172510
@@ -263,7 +262,6 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx,
a172510
 					   krb5_get_init_creds_opt *krb_options,
a172510
 					   time_t *expire_time,
a172510
 					   time_t *kdc_time);
a172510
-#endif
a172510
 
a172510
 #if defined(HAVE_KRB5_MAKE_PRINCIPAL)
a172510
 #define smb_krb5_make_principal krb5_make_principal
a172510
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
a172510
index 544d9d853cc..c14d8c72d8c 100644
a172510
--- a/source4/auth/kerberos/kerberos_util.c
a172510
+++ b/source4/auth/kerberos/kerberos_util.c
a172510
@@ -234,9 +234,7 @@ done:
a172510
 {
a172510
 	krb5_error_code ret;
a172510
 	const char *password;
a172510
-#ifdef SAMBA4_USES_HEIMDAL
a172510
 	const char *self_service;
a172510
-#endif
a172510
 	const char *target_service;
a172510
 	time_t kdc_time = 0;
a172510
 	krb5_principal princ;
a172510
@@ -268,9 +266,7 @@ done:
a172510
 		return ret;
a172510
 	}
a172510
 
a172510
-#ifdef SAMBA4_USES_HEIMDAL
a172510
 	self_service = cli_credentials_get_self_service(credentials);
a172510
-#endif
a172510
 	target_service = cli_credentials_get_target_service(credentials);
a172510
 
a172510
 	password = cli_credentials_get_password(credentials);
a172510
@@ -331,7 +327,6 @@ done:
a172510
 #endif
a172510
 		if (password) {
a172510
 			if (impersonate_principal) {
a172510
-#ifdef SAMBA4_USES_HEIMDAL
a172510
 				ret = smb_krb5_kinit_s4u2_ccache(smb_krb5_context->krb5_context,
a172510
 								 ccache,
a172510
 								 princ,
a172510
@@ -342,12 +337,6 @@ done:
a172510
 								 krb_options,
a172510
 								 NULL,
a172510
 								 &kdc_time);
a172510
-#else
a172510
-				talloc_free(mem_ctx);
a172510
-				(*error_string) = "INTERNAL error: s4u2 ops "
a172510
-					"are not supported with MIT build yet";
a172510
-				return EINVAL;
a172510
-#endif
a172510
 			} else {
a172510
 				ret = smb_krb5_kinit_password_ccache(smb_krb5_context->krb5_context,
a172510
 								     ccache,
a172510
-- 
Günther Deschner 38eeb01
2.33.1
a172510
a172510
Günther Deschner 38eeb01
From 80289eca2bb614aacd0df86bcf7ad7027c080671 Mon Sep 17 00:00:00 2001
a172510
From: Isaac Boukris <iboukris@gmail.com>
a172510
Date: Sat, 19 Sep 2020 14:16:20 +0200
Günther Deschner 38eeb01
Subject: [PATCH 3/3] wip: for canonicalization with new MIT kdc code
a172510
a172510
---
a172510
 source4/heimdal/lib/hdb/hdb.h | 1 +
a172510
 source4/kdc/db-glue.c         | 8 ++++++--
a172510
 source4/kdc/mit_samba.c       | 3 +++
a172510
 source4/kdc/sdb.h             | 1 +
a172510
 4 files changed, 11 insertions(+), 2 deletions(-)
a172510
a172510
diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h
Günther Deschner 38eeb01
index 5ef9d9565f3..dafaffc6c2d 100644
a172510
--- a/source4/heimdal/lib/hdb/hdb.h
a172510
+++ b/source4/heimdal/lib/hdb/hdb.h
a172510
@@ -63,6 +63,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
a172510
 #define HDB_F_ALL_KVNOS		2048	/* we want all the keys, live or not */
a172510
 #define HDB_F_FOR_AS_REQ	4096	/* fetch is for a AS REQ */
a172510
 #define HDB_F_FOR_TGS_REQ	8192	/* fetch is for a TGS REQ */
a172510
+#define HDB_F_FORCE_CANON	16384	/* force canonicalition */
a172510
 
a172510
 /* hdb_capability_flags */
a172510
 #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
a172510
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
Günther Deschner 38eeb01
index aff74f2ee71..d16b4c3329a 100644
a172510
--- a/source4/kdc/db-glue.c
a172510
+++ b/source4/kdc/db-glue.c
a172510
@@ -916,17 +916,21 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
a172510
 			}
a172510
 		}
a172510
 
a172510
-	} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) {
a172510
+	} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { // was this supposed to be || ?
a172510
 		ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
a172510
 		if (ret) {
a172510
 			krb5_clear_error_message(context);
a172510
 			goto out;
a172510
 		}
a172510
-	} else if ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) {
a172510
+	} else if (((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) || (flags & SDB_F_FORCE_CANON)){
a172510
 		/*
a172510
 		 * SDB_F_CANON maps from the canonicalize flag in the
a172510
 		 * packet, and has a different meaning between AS-REQ
a172510
 		 * and TGS-REQ.  We only change the principal in the AS-REQ case
a172510
+		 *
a172510
+		 * The SDB_F_FORCE_CANON if for the new MIT kdc code that wants
a172510
+		 * the canonical name in all lookups, and takes care to canonicalize
a172510
+		 * only when appropriate.
a172510
 		 */
a172510
 		ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
a172510
 		if (ret) {
a172510
diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
Günther Deschner 38eeb01
index 2a48d731501..a8d3e7ed493 100644
a172510
--- a/source4/kdc/mit_samba.c
a172510
+++ b/source4/kdc/mit_samba.c
a172510
@@ -198,6 +198,9 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
a172510
 	if (kflags & KRB5_KDB_FLAG_CANONICALIZE) {
a172510
 		sflags |= SDB_F_CANON;
a172510
 	}
a172510
+#if KRB5_KDB_API_VERSION >= 10
a172510
+	sflags |= SDB_F_FORCE_CANON;
a172510
+#endif
a172510
 	if (kflags & (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY |
a172510
 		      KRB5_KDB_FLAG_INCLUDE_PAC)) {
a172510
 		/*
a172510
diff --git a/source4/kdc/sdb.h b/source4/kdc/sdb.h
a172510
index c929acccce6..a9115ec23d7 100644
a172510
--- a/source4/kdc/sdb.h
a172510
+++ b/source4/kdc/sdb.h
a172510
@@ -116,6 +116,7 @@ struct sdb_entry_ex {
a172510
 #define SDB_F_KVNO_SPECIFIED	128	/* we want a particular KVNO */
a172510
 #define SDB_F_FOR_AS_REQ	4096	/* fetch is for a AS REQ */
a172510
 #define SDB_F_FOR_TGS_REQ	8192	/* fetch is for a TGS REQ */
a172510
+#define SDB_F_FORCE_CANON	16384	/* force canonicalition */
a172510
 
a172510
 void sdb_free_entry(struct sdb_entry_ex *e);
a172510
 void free_sdb_entry(struct sdb_entry *s);
a172510
-- 
Günther Deschner 38eeb01
2.33.1
a172510