167d4b
From 579901faf787d8d787c978324bdec87c349e3d9b Mon Sep 17 00:00:00 2001
167d4b
From: Andreas Schneider <asn@samba.org>
167d4b
Date: Tue, 23 Sep 2014 14:09:41 +0200
167d4b
Subject: [PATCH] s3-libads: Improve service principle guessing.
167d4b
167d4b
If the name passed to the net command with the -S options is the long
167d4b
hostname of the domaincontroller and not the 15 char NetBIOS name we
167d4b
should construct a FQDN with the realm to get a Kerberos ticket.
167d4b
167d4b
BUG: https://bugzilla.samba.org/show_bug.cgi?id=10829
167d4b
167d4b
Signed-off-by: Andreas Schneider <asn@samba.org>
167d4b
Reviewed-by: Guenther Deschner <gd@samba.org>
167d4b
(cherry picked from commit 83c62bd3f5945bbe295cbfbd153736d4c709b3a6)
167d4b
---
167d4b
 source3/libads/sasl.c | 124 +++++++++++++++++++++++++++-----------------------
167d4b
 1 file changed, 66 insertions(+), 58 deletions(-)
167d4b
167d4b
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
167d4b
index 33f4e24..1450ff1 100644
167d4b
--- a/source3/libads/sasl.c
167d4b
+++ b/source3/libads/sasl.c
167d4b
@@ -714,88 +714,96 @@ static void ads_free_service_principal(struct ads_service_principal *p)
167d4b
 static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
167d4b
 					      char **returned_principal)
167d4b
 {
167d4b
+	ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
167d4b
 	char *princ = NULL;
167d4b
+	TALLOC_CTX *frame;
167d4b
+	char *server = NULL;
167d4b
+	char *realm = NULL;
167d4b
+	int rc;
167d4b
 
167d4b
-	if (ads->server.realm && ads->server.ldap_server) {
167d4b
-		char *server, *server_realm;
167d4b
-
167d4b
-		server = SMB_STRDUP(ads->server.ldap_server);
167d4b
-		server_realm = SMB_STRDUP(ads->server.realm);
167d4b
-
167d4b
-		if (!server || !server_realm) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
-		}
167d4b
+	frame = talloc_stackframe();
167d4b
+	if (frame == NULL) {
167d4b
+		return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+	}
167d4b
 
167d4b
-		if (!strlower_m(server)) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+	if (ads->server.realm && ads->server.ldap_server) {
167d4b
+		server = strlower_talloc(frame, ads->server.ldap_server);
167d4b
+		if (server == NULL) {
167d4b
+			goto out;
167d4b
 		}
167d4b
 
167d4b
-		if (!strupper_m(server_realm)) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+		realm = strupper_talloc(frame, ads->server.realm);
167d4b
+		if (realm == NULL) {
167d4b
+			goto out;
167d4b
 		}
167d4b
 
167d4b
-		if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
-		}
167d4b
+		/*
167d4b
+		 * If we got a name which is bigger than a NetBIOS name,
167d4b
+		 * but isn't a FQDN, create one.
167d4b
+		 */
167d4b
+		if (strlen(server) > 15 && strstr(server, ".") == NULL) {
167d4b
+			char *dnsdomain;
167d4b
 
167d4b
-		SAFE_FREE(server);
167d4b
-		SAFE_FREE(server_realm);
167d4b
+			dnsdomain = strlower_talloc(frame, ads->server.realm);
167d4b
+			if (dnsdomain == NULL) {
167d4b
+				goto out;
167d4b
+			}
167d4b
 
167d4b
-		if (!princ) {
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+			server = talloc_asprintf(frame,
167d4b
+						 "%s.%s",
167d4b
+						 server, dnsdomain);
167d4b
+			if (server == NULL) {
167d4b
+				goto out;
167d4b
+			}
167d4b
 		}
167d4b
 	} else if (ads->config.realm && ads->config.ldap_server_name) {
167d4b
-		char *server, *server_realm;
167d4b
-
167d4b
-		server = SMB_STRDUP(ads->config.ldap_server_name);
167d4b
-		server_realm = SMB_STRDUP(ads->config.realm);
167d4b
-
167d4b
-		if (!server || !server_realm) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+		server = strlower_talloc(frame, ads->config.ldap_server_name);
167d4b
+		if (server == NULL) {
167d4b
+			goto out;
167d4b
 		}
167d4b
 
167d4b
-		if (!strlower_m(server)) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+		realm = strupper_talloc(frame, ads->config.realm);
167d4b
+		if (realm == NULL) {
167d4b
+			goto out;
167d4b
 		}
167d4b
 
167d4b
-		if (!strupper_m(server_realm)) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
-		}
167d4b
-		if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
167d4b
-			SAFE_FREE(server);
167d4b
-			SAFE_FREE(server_realm);
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
-		}
167d4b
+		/*
167d4b
+		 * If we got a name which is bigger than a NetBIOS name,
167d4b
+		 * but isn't a FQDN, create one.
167d4b
+		 */
167d4b
+		if (strlen(server) > 15 && strstr(server, ".") == NULL) {
167d4b
+			char *dnsdomain;
167d4b
 
167d4b
-		SAFE_FREE(server);
167d4b
-		SAFE_FREE(server_realm);
167d4b
+			dnsdomain = strlower_talloc(frame, ads->server.realm);
167d4b
+			if (dnsdomain == NULL) {
167d4b
+				goto out;
167d4b
+			}
167d4b
 
167d4b
-		if (!princ) {
167d4b
-			return ADS_ERROR(LDAP_NO_MEMORY);
167d4b
+			server = talloc_asprintf(frame,
167d4b
+						 "%s.%s",
167d4b
+						 server, dnsdomain);
167d4b
+			if (server == NULL) {
167d4b
+				goto out;
167d4b
+			}
167d4b
 		}
167d4b
 	}
167d4b
 
167d4b
-	if (!princ) {
167d4b
-		return ADS_ERROR(LDAP_PARAM_ERROR);
167d4b
+	if (server == NULL || realm == NULL) {
167d4b
+		goto out;
167d4b
+	}
167d4b
+
167d4b
+	rc = asprintf(&princ, "ldap/%s@%s", server, realm);
167d4b
+	if (rc == -1 || princ == NULL) {
167d4b
+		status = ADS_ERROR(LDAP_PARAM_ERROR);
167d4b
+		goto out;
167d4b
 	}
167d4b
 
167d4b
 	*returned_principal = princ;
167d4b
 
167d4b
-	return ADS_SUCCESS;
167d4b
+	status = ADS_SUCCESS;
167d4b
+out:
167d4b
+	TALLOC_FREE(frame);
167d4b
+	return status;
167d4b
 }
167d4b
 
167d4b
 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
167d4b
-- 
167d4b
2.1.0
167d4b