167d4b
From 3516236ec6eb42f29eda42542b109fa10217e68c Mon Sep 17 00:00:00 2001
167d4b
From: Andreas Schneider <asn@samba.org>
167d4b
Date: Wed, 24 Sep 2014 10:51:33 +0200
167d4b
Subject: [PATCH] s3-libads: Add all machine account principals to the keytab.
167d4b
167d4b
This adds all SPNs defined in the DC for the computer account to the
167d4b
keytab using 'net ads keytab create -P'.
167d4b
167d4b
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9985
167d4b
167d4b
Signed-off-by: Andreas Schneider <asn@samba.org>
167d4b
Reviewed-by: Guenther Deschner <gd@samba.org>
167d4b
(cherry picked from commit 5d58b92f8fcbc509f4fe2bd3617bcaeada1806b6)
167d4b
---
167d4b
 source3/libads/kerberos_keytab.c | 74 ++++++++++++++++++++++++++++------------
167d4b
 1 file changed, 52 insertions(+), 22 deletions(-)
167d4b
167d4b
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
167d4b
index 83df088..d13625b 100644
167d4b
--- a/source3/libads/kerberos_keytab.c
167d4b
+++ b/source3/libads/kerberos_keytab.c
167d4b
@@ -507,20 +507,57 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 	krb5_kt_cursor cursor;
167d4b
 	krb5_keytab_entry kt_entry;
167d4b
 	krb5_kvno kvno;
167d4b
-	int i, found = 0;
167d4b
+	size_t found = 0;
167d4b
 	char *sam_account_name, *upn;
167d4b
 	char **oldEntries = NULL, *princ_s[26];
167d4b
-	TALLOC_CTX *tmpctx = NULL;
167d4b
+	TALLOC_CTX *frame;
167d4b
 	char *machine_name;
167d4b
+	char **spn_array;
167d4b
+	size_t num_spns;
167d4b
+	size_t i;
167d4b
+	ADS_STATUS status;
167d4b
 
167d4b
-	/* these are the main ones we need */
167d4b
-	ret = ads_keytab_add_entry(ads, "host");
167d4b
-	if (ret != 0) {
167d4b
-		DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
167d4b
-			  "adding 'host' principal.\n"));
167d4b
-		return ret;
167d4b
+	frame = talloc_stackframe();
167d4b
+	if (frame == NULL) {
167d4b
+		ret = -1;
167d4b
+		goto done;
167d4b
+	}
167d4b
+
167d4b
+	status = ads_get_service_principal_names(frame,
167d4b
+						 ads,
167d4b
+						 lp_netbios_name(),
167d4b
+						 &spn_array,
167d4b
+						 &num_spns);
167d4b
+	if (!ADS_ERR_OK(status)) {
167d4b
+		ret = -1;
167d4b
+		goto done;
167d4b
 	}
167d4b
 
167d4b
+	for (i = 0; i < num_spns; i++) {
167d4b
+		char *srv_princ;
167d4b
+		char *p;
167d4b
+
167d4b
+		srv_princ = strlower_talloc(frame, spn_array[i]);
167d4b
+		if (srv_princ == NULL) {
167d4b
+			ret = -1;
167d4b
+			goto done;
167d4b
+		}
167d4b
+
167d4b
+		p = strchr_m(srv_princ, '/');
167d4b
+		if (p == NULL) {
167d4b
+			continue;
167d4b
+		}
167d4b
+		p[0] = '\0';
167d4b
+
167d4b
+		/* Add the SPNs found on the DC */
167d4b
+		ret = ads_keytab_add_entry(ads, srv_princ);
167d4b
+		if (ret != 0) {
167d4b
+			DEBUG(1, ("ads_keytab_add_entry failed while "
167d4b
+				  "adding '%s' principal.\n",
167d4b
+				  spn_array[i]));
167d4b
+			goto done;
167d4b
+		}
167d4b
+	}
167d4b
 
167d4b
 #if 0	/* don't create the CIFS/... keytab entries since no one except smbd
167d4b
 	   really needs them and we will fall back to verifying against
167d4b
@@ -543,24 +580,17 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 	if (ret) {
167d4b
 		DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
167d4b
 			  error_message(ret)));
167d4b
-		return ret;
167d4b
-	}
167d4b
-
167d4b
-	tmpctx = talloc_init(__location__);
167d4b
-	if (!tmpctx) {
167d4b
-		DEBUG(0, (__location__ ": talloc_init() failed!\n"));
167d4b
-		ret = -1;
167d4b
 		goto done;
167d4b
 	}
167d4b
 
167d4b
-	machine_name = talloc_strdup(tmpctx, lp_netbios_name());
167d4b
+	machine_name = talloc_strdup(frame, lp_netbios_name());
167d4b
 	if (!machine_name) {
167d4b
 		ret = -1;
167d4b
 		goto done;
167d4b
 	}
167d4b
 
167d4b
 	/* now add the userPrincipalName and sAMAccountName entries */
167d4b
-	sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);
167d4b
+	sam_account_name = ads_get_samaccountname(ads, frame, machine_name);
167d4b
 	if (!sam_account_name) {
167d4b
 		DEBUG(0, (__location__ ": unable to determine machine "
167d4b
 			  "account's name in AD!\n"));
167d4b
@@ -584,7 +614,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 	}
167d4b
 
167d4b
 	/* remember that not every machine account will have a upn */
167d4b
-	upn = ads_get_upn(ads, tmpctx, machine_name);
167d4b
+	upn = ads_get_upn(ads, frame, machine_name);
167d4b
 	if (upn) {
167d4b
 		ret = ads_keytab_add_entry(ads, upn);
167d4b
 		if (ret != 0) {
167d4b
@@ -596,7 +626,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 
167d4b
 	/* Now loop through the keytab and update any other existing entries */
167d4b
 	kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name);
167d4b
-	if (kvno == -1) {
167d4b
+	if (kvno == (krb5_kvno)-1) {
167d4b
 		DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to "
167d4b
 			  "determine the system's kvno.\n"));
167d4b
 		goto done;
167d4b
@@ -629,12 +659,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 	 * have a race condition where someone else could add entries after
167d4b
 	 * we've counted them. Re-open asap to minimise the race. JRA.
167d4b
 	 */
167d4b
-	DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found));
167d4b
+	DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found));
167d4b
 	if (!found) {
167d4b
 		goto done;
167d4b
 	}
167d4b
 
167d4b
-	oldEntries = talloc_array(tmpctx, char *, found);
167d4b
+	oldEntries = talloc_array(frame, char *, found);
167d4b
 	if (!oldEntries) {
167d4b
 		DEBUG(1, (__location__ ": Failed to allocate space to store "
167d4b
 			  "the old keytab entries (talloc failed?).\n"));
167d4b
@@ -708,7 +738,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
167d4b
 
167d4b
 done:
167d4b
 	TALLOC_FREE(oldEntries);
167d4b
-	TALLOC_FREE(tmpctx);
167d4b
+	TALLOC_FREE(frame);
167d4b
 
167d4b
 	{
167d4b
 		krb5_keytab_entry zero_kt_entry;
167d4b
-- 
167d4b
2.1.0
167d4b