[SCM] Samba Shared Repository - branch master updated

Günther Deschner gd at samba.org
Fri Sep 26 00:23:04 MDT 2014


The branch, master has been updated
       via  0aacbe7 s3-libnet: Make sure we do not overwrite precreated SPNs.
       via  7e0b8fc s3-libnet: Add libnet_join_get_machine_spns().
       via  5d58b92 s3-libads: Add all machine account principals to the keytab.
       via  e1ee4c8 s3-libads: Add function to search for an element in an array.
       via  4eaa4cc s3-libads: Add a function to retrieve the SPNs of a computer account.
       via  83c62bd s3-libads: Improve service principle guessing.
      from  69a7e3c s4: libcli: ldap message - Ensure all asn1_XX returns are checked.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0aacbe78bb40d76b65087c2a197c92b0101e625e
Author: Günther Deschner <gd at samba.org>
Date:   Fri Sep 26 03:35:43 2014 +0200

    s3-libnet: Make sure we do not overwrite precreated SPNs.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
    
    Signed-off-by: Günther Deschner <gd at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    
    Autobuild-User(master): Günther Deschner <gd at samba.org>
    Autobuild-Date(master): Fri Sep 26 08:22:45 CEST 2014 on sn-devel-104

commit 7e0b8fcce5572c88d50993a1dbd90f65638ba90f
Author: Andreas Schneider <asn at samba.org>
Date:   Fri Sep 26 03:09:08 2014 +0200

    s3-libnet: Add libnet_join_get_machine_spns().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>

commit 5d58b92f8fcbc509f4fe2bd3617bcaeada1806b6
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Sep 24 10:51:33 2014 +0200

    s3-libads: Add all machine account principals to the keytab.
    
    This adds all SPNs defined in the DC for the computer account to the
    keytab using 'net ads keytab create -P'.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9985
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>

commit e1ee4c8bc7018db7787dd9a0be6d3aa40a477ee2
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Sep 24 09:23:58 2014 +0200

    s3-libads: Add function to search for an element in an array.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>

commit 4eaa4ccbdf279f1ff6d8218b36d92aeea0114cd8
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Sep 24 09:22:03 2014 +0200

    s3-libads: Add a function to retrieve the SPNs of a computer account.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>

commit 83c62bd3f5945bbe295cbfbd153736d4c709b3a6
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Sep 23 14:09:41 2014 +0200

    s3-libads: Improve service principle guessing.
    
    If the name passed to the net command with the -S options is the long
    hostname of the domaincontroller and not the 15 char NetBIOS name we
    should construct a FQDN with the realm to get a Kerberos ticket.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10829
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/libads/ads_proto.h       |    8 +++
 source3/libads/kerberos_keytab.c |   74 ++++++++++++++++-------
 source3/libads/ldap.c            |   91 ++++++++++++++++++++++++++++
 source3/libads/sasl.c            |  124 ++++++++++++++++++++------------------
 source3/libnet/libnet_join.c     |   59 +++++++++++++++++-
 5 files changed, 273 insertions(+), 83 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 17a84d1..1e34247 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -87,6 +87,14 @@ ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 				const char *name, const char **vals);
 uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name);
 uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name);
+
+bool ads_element_in_array(const char **el_array, size_t num_el, const char *el);
+
+ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
+					   ADS_STRUCT *ads,
+					   const char *machine_name,
+					   char ***spn_array,
+					   size_t *num_spns);
 ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name);
 ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name,
                                           const char *my_fqdn, const char *spn);
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 6a1ba75..43c755c 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -510,20 +510,57 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 	krb5_kt_cursor cursor;
 	krb5_keytab_entry kt_entry;
 	krb5_kvno kvno;
-	int i, found = 0;
+	size_t found = 0;
 	char *sam_account_name, *upn;
 	char **oldEntries = NULL, *princ_s[26];
-	TALLOC_CTX *tmpctx = NULL;
+	TALLOC_CTX *frame;
 	char *machine_name;
+	char **spn_array;
+	size_t num_spns;
+	size_t i;
+	ADS_STATUS status;
 
-	/* these are the main ones we need */
-	ret = ads_keytab_add_entry(ads, "host");
-	if (ret != 0) {
-		DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
-			  "adding 'host' principal.\n"));
-		return ret;
+	frame = talloc_stackframe();
+	if (frame == NULL) {
+		ret = -1;
+		goto done;
+	}
+
+	status = ads_get_service_principal_names(frame,
+						 ads,
+						 lp_netbios_name(),
+						 &spn_array,
+						 &num_spns);
+	if (!ADS_ERR_OK(status)) {
+		ret = -1;
+		goto done;
 	}
 
+	for (i = 0; i < num_spns; i++) {
+		char *srv_princ;
+		char *p;
+
+		srv_princ = strlower_talloc(frame, spn_array[i]);
+		if (srv_princ == NULL) {
+			ret = -1;
+			goto done;
+		}
+
+		p = strchr_m(srv_princ, '/');
+		if (p == NULL) {
+			continue;
+		}
+		p[0] = '\0';
+
+		/* Add the SPNs found on the DC */
+		ret = ads_keytab_add_entry(ads, srv_princ);
+		if (ret != 0) {
+			DEBUG(1, ("ads_keytab_add_entry failed while "
+				  "adding '%s' principal.\n",
+				  spn_array[i]));
+			goto done;
+		}
+	}
 
 #if 0	/* don't create the CIFS/... keytab entries since no one except smbd
 	   really needs them and we will fall back to verifying against
@@ -546,24 +583,17 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 	if (ret) {
 		DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
 			  error_message(ret)));
-		return ret;
-	}
-
-	tmpctx = talloc_init(__location__);
-	if (!tmpctx) {
-		DEBUG(0, (__location__ ": talloc_init() failed!\n"));
-		ret = -1;
 		goto done;
 	}
 
-	machine_name = talloc_strdup(tmpctx, lp_netbios_name());
+	machine_name = talloc_strdup(frame, lp_netbios_name());
 	if (!machine_name) {
 		ret = -1;
 		goto done;
 	}
 
 	/* now add the userPrincipalName and sAMAccountName entries */
-	sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);
+	sam_account_name = ads_get_samaccountname(ads, frame, machine_name);
 	if (!sam_account_name) {
 		DEBUG(0, (__location__ ": unable to determine machine "
 			  "account's name in AD!\n"));
@@ -587,7 +617,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 	}
 
 	/* remember that not every machine account will have a upn */
-	upn = ads_get_upn(ads, tmpctx, machine_name);
+	upn = ads_get_upn(ads, frame, machine_name);
 	if (upn) {
 		ret = ads_keytab_add_entry(ads, upn);
 		if (ret != 0) {
@@ -599,7 +629,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 
 	/* Now loop through the keytab and update any other existing entries */
 	kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name);
-	if (kvno == -1) {
+	if (kvno == (krb5_kvno)-1) {
 		DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to "
 			  "determine the system's kvno.\n"));
 		goto done;
@@ -632,12 +662,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 	 * have a race condition where someone else could add entries after
 	 * we've counted them. Re-open asap to minimise the race. JRA.
 	 */
-	DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found));
+	DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found));
 	if (!found) {
 		goto done;
 	}
 
-	oldEntries = talloc_array(tmpctx, char *, found);
+	oldEntries = talloc_array(frame, char *, found);
 	if (!oldEntries) {
 		DEBUG(1, (__location__ ": Failed to allocate space to store "
 			  "the old keytab entries (talloc failed?).\n"));
@@ -711,7 +741,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
 
 done:
 	TALLOC_FREE(oldEntries);
-	TALLOC_FREE(tmpctx);
+	TALLOC_FREE(frame);
 
 	{
 		krb5_keytab_entry zero_kt_entry;
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 8fed8fd..06b4895 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1915,6 +1915,97 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin
 }
 
 /**
+ * @brief Search for an element in a string array.
+ *
+ * @param[in]  el_array  The string array to search.
+ *
+ * @param[in]  num_el    The number of elements in the string array.
+ *
+ * @param[in]  el        The string to search.
+ *
+ * @return               True if found, false if not.
+ */
+bool ads_element_in_array(const char **el_array, size_t num_el, const char *el)
+{
+	size_t i;
+
+	if (el_array == NULL || num_el == 0 || el == NULL) {
+		return false;
+	}
+
+	for (i = 0; i < num_el && el_array[i] != NULL; i++) {
+		int cmp;
+
+		cmp = strcasecmp_m(el_array[i], el);
+		if (cmp == 0) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * @brief This gets the service principal names of an existing computer account.
+ *
+ * @param[in]  mem_ctx      The memory context to use to allocate the spn array.
+ *
+ * @param[in]  ads          The ADS context to use.
+ *
+ * @param[in]  machine_name The NetBIOS name of the computer, which is used to
+ *                          identify the computer account.
+ *
+ * @param[in]  spn_array    A pointer to store the array for SPNs.
+ *
+ * @param[in]  num_spns     The number of principals stored in the array.
+ *
+ * @return                  0 on success, or a ADS error if a failure occured.
+ */
+ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
+					   ADS_STRUCT *ads,
+					   const char *machine_name,
+					   char ***spn_array,
+					   size_t *num_spns)
+{
+	ADS_STATUS status;
+	LDAPMessage *res = NULL;
+	char *dn;
+	int count;
+
+	status = ads_find_machine_acct(ads,
+				       &res,
+				       machine_name);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("Host Account for %s not found... skipping operation.\n",
+			 machine_name));
+		return status;
+	}
+
+	count = ads_count_replies(ads, res);
+	if (count != 1) {
+		status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+		goto done;
+	}
+
+	dn = ads_get_dn(ads, mem_ctx, res);
+	if (dn == NULL) {
+		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+		goto done;
+	}
+
+	*spn_array = ads_pull_strings(ads,
+				      mem_ctx,
+				      res,
+				      "servicePrincipalName",
+				      num_spns);
+
+done:
+	ads_msgfree(ads, res);
+
+	return status;
+}
+
+/**
  * This adds a service principal name to an existing computer account
  * (found by hostname) in AD.
  * @param ads An initialized ADS_STRUCT
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 6890fb2..8a9e157 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -714,88 +714,96 @@ static void ads_free_service_principal(struct ads_service_principal *p)
 static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
 					      char **returned_principal)
 {
+	ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
 	char *princ = NULL;
+	TALLOC_CTX *frame;
+	char *server = NULL;
+	char *realm = NULL;
+	int rc;
 
-	if (ads->server.realm && ads->server.ldap_server) {
-		char *server, *server_realm;
-
-		server = SMB_STRDUP(ads->server.ldap_server);
-		server_realm = SMB_STRDUP(ads->server.realm);
-
-		if (!server || !server_realm) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
-		}
+	frame = talloc_stackframe();
+	if (frame == NULL) {
+		return ADS_ERROR(LDAP_NO_MEMORY);
+	}
 
-		if (!strlower_m(server)) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
+	if (ads->server.realm && ads->server.ldap_server) {
+		server = strlower_talloc(frame, ads->server.ldap_server);
+		if (server == NULL) {
+			goto out;
 		}
 
-		if (!strupper_m(server_realm)) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
+		realm = strupper_talloc(frame, ads->server.realm);
+		if (realm == NULL) {
+			goto out;
 		}
 
-		if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
-		}
+		/*
+		 * If we got a name which is bigger than a NetBIOS name,
+		 * but isn't a FQDN, create one.
+		 */
+		if (strlen(server) > 15 && strstr(server, ".") == NULL) {
+			char *dnsdomain;
 
-		SAFE_FREE(server);
-		SAFE_FREE(server_realm);
+			dnsdomain = strlower_talloc(frame, ads->server.realm);
+			if (dnsdomain == NULL) {
+				goto out;
+			}
 
-		if (!princ) {
-			return ADS_ERROR(LDAP_NO_MEMORY);
+			server = talloc_asprintf(frame,
+						 "%s.%s",
+						 server, dnsdomain);
+			if (server == NULL) {
+				goto out;
+			}
 		}
 	} else if (ads->config.realm && ads->config.ldap_server_name) {
-		char *server, *server_realm;
-
-		server = SMB_STRDUP(ads->config.ldap_server_name);
-		server_realm = SMB_STRDUP(ads->config.realm);
-
-		if (!server || !server_realm) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
+		server = strlower_talloc(frame, ads->config.ldap_server_name);
+		if (server == NULL) {
+			goto out;
 		}
 
-		if (!strlower_m(server)) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
+		realm = strupper_talloc(frame, ads->config.realm);
+		if (realm == NULL) {
+			goto out;
 		}
 
-		if (!strupper_m(server_realm)) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
-		}
-		if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
-			SAFE_FREE(server);
-			SAFE_FREE(server_realm);
-			return ADS_ERROR(LDAP_NO_MEMORY);
-		}
+		/*
+		 * If we got a name which is bigger than a NetBIOS name,
+		 * but isn't a FQDN, create one.
+		 */
+		if (strlen(server) > 15 && strstr(server, ".") == NULL) {
+			char *dnsdomain;
 
-		SAFE_FREE(server);
-		SAFE_FREE(server_realm);
+			dnsdomain = strlower_talloc(frame, ads->server.realm);
+			if (dnsdomain == NULL) {
+				goto out;
+			}
 
-		if (!princ) {
-			return ADS_ERROR(LDAP_NO_MEMORY);
+			server = talloc_asprintf(frame,
+						 "%s.%s",
+						 server, dnsdomain);
+			if (server == NULL) {
+				goto out;
+			}
 		}
 	}
 
-	if (!princ) {
-		return ADS_ERROR(LDAP_PARAM_ERROR);
+	if (server == NULL || realm == NULL) {
+		goto out;
+	}
+
+	rc = asprintf(&princ, "ldap/%s@%s", server, realm);
+	if (rc == -1 || princ == NULL) {
+		status = ADS_ERROR(LDAP_PARAM_ERROR);
+		goto out;
 	}
 
 	*returned_principal = princ;
 
-	return ADS_SUCCESS;
+	status = ADS_SUCCESS;
+out:
+	TALLOC_FREE(frame);
+	return status;
 }
 
 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index fe348d1..381a59c 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -360,6 +360,26 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx,
 	return status;
 }
 
+static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx,
+					       struct libnet_JoinCtx *r,
+					       char ***spn_array,
+					       size_t *num_spns)
+{
+	ADS_STATUS status;
+
+	if (r->in.machine_name == NULL) {
+		return ADS_ERROR_SYSTEM(EINVAL);
+	}
+
+	status = ads_get_service_principal_names(mem_ctx,
+						 r->in.ads,
+						 r->in.machine_name,
+						 spn_array,
+						 num_spns);
+
+	return status;
+}
+
 /****************************************************************
  Set a machines dNSHostName and servicePrincipalName attributes
 ****************************************************************/
@@ -370,8 +390,10 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 	ADS_STATUS status;
 	ADS_MODLIST mods;
 	fstring my_fqdn;
-	const char *spn_array[3] = {NULL, NULL, NULL};
+	const char **spn_array = NULL;
+	size_t num_spns = 0;
 	char *spn = NULL;
+	bool ok;
 
 	/* Find our DN */
 
@@ -380,6 +402,14 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		return status;
 	}
 
+	status = libnet_join_get_machine_spns(mem_ctx,
+					      r,
+					      discard_const_p(char **, &spn_array),
+					      &num_spns);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(5, ("Retrieving the servicePrincipalNames failed.\n"));
+	}
+
 	/* Windows only creates HOST/shortname & HOST/fqdn. */
 
 	spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name);
@@ -389,7 +419,15 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 	if (!strupper_m(spn)) {
 		return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
 	}
-	spn_array[0] = spn;
+
+	ok = ads_element_in_array(spn_array, num_spns, spn);
+	if (!ok) {
+		ok = add_string_to_array(spn_array, spn,
+					 &spn_array, (int *)&num_spns);
+		if (!ok) {
+			return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+		}
+	}
 
 	if (!name_to_fqdn(my_fqdn, r->in.machine_name)
 	    || (strchr(my_fqdn, '.') == NULL)) {
@@ -406,8 +444,23 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		if (!spn) {
 			return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
 		}
-		spn_array[1] = spn;
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list