From 918ac8f0ed19aeaa4718fa94fcabe87d0419d768 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Mon, 13 Jan 2014 15:59:26 +0100
Subject: [PATCH 1/5] PATCHSET11: s3-kerberos: remove print_kdc_line()
 completely.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Just calling print_canonical_sockaddr() is sufficient, as it already deals with
ipv6 as well. The port handling, which was only done for IPv6 (not IPv4), is
removed as well. It was pointless because it always derived the port number from
the provided address which was either a SMB (usually port 445) or LDAP
connection. No KDC will ever run on port 389 or 445 on a Windows/Samba DC.
Finally, the kerberos libraries that we support and build with, can deal with
ipv6 addresses in krb5.conf, so we no longer put the (unnecessary) burden of
resolving the DC name on the kerberos library anymore.

Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Conflicts:
	source3/libads/kerberos.c
---
 source3/libads/kerberos.c | 86 +++++------------------------------------------
 1 file changed, 9 insertions(+), 77 deletions(-)

diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 1153ccb..064e5f7 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -661,73 +661,6 @@ int kerberos_kinit_password(const char *principal,
 }
 
 /************************************************************************
-************************************************************************/
-
-static char *print_kdc_line(char *mem_ctx,
-			const char *prev_line,
-			const struct sockaddr_storage *pss,
-			const char *kdc_name)
-{
-	char *kdc_str = NULL;
-
-	if (pss->ss_family == AF_INET) {
-		kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-					prev_line,
-                                        print_canonical_sockaddr(mem_ctx, pss));
-	} else {
-		char addr[INET6_ADDRSTRLEN];
-		uint16_t port = get_sockaddr_port(pss);
-
-		DEBUG(10,("print_kdc_line: IPv6 case for kdc_name: %s, port: %d\n",
-			kdc_name, port));
-
-		if (port != 0 && port != DEFAULT_KRB5_PORT) {
-			/* Currently for IPv6 we can't specify a non-default
-			   krb5 port with an address, as this requires a ':'.
-			   Resolve to a name. */
-			char hostname[MAX_DNS_NAME_LENGTH];
-			int ret = sys_getnameinfo((const struct sockaddr *)pss,
-					sizeof(*pss),
-					hostname, sizeof(hostname),
-					NULL, 0,
-					NI_NAMEREQD);
-			if (ret) {
-				DEBUG(0,("print_kdc_line: can't resolve name "
-					"for kdc with non-default port %s. "
-					"Error %s\n.",
-					print_canonical_sockaddr(mem_ctx, pss),
-					gai_strerror(ret)));
-				return NULL;
-			}
-			/* Success, use host:port */
-			kdc_str = talloc_asprintf(mem_ctx,
-					"%s\tkdc = %s:%u\n",
-					prev_line,
-					hostname,
-					(unsigned int)port);
-		} else {
-
-			/* no krb5 lib currently supports "kdc = ipv6 address"
-			 * at all, so just fill in just the kdc_name if we have
-			 * it and let the krb5 lib figure out the appropriate
-			 * ipv6 address - gd */
-
-			if (kdc_name) {
-				kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-						prev_line, kdc_name);
-			} else {
-				kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
-						prev_line,
-						print_sockaddr(addr,
-							sizeof(addr),
-							pss));
-			}
-		}
-	}
-	return kdc_str;
-}
-
-/************************************************************************
  Create a string list of available kdc's, possibly searching by sitename.
  Does DNS queries.
 
@@ -746,7 +679,8 @@ static char *get_kdc_ip_string(char *mem_ctx,
 	struct ip_service *ip_srv_nonsite = NULL;
 	int count_site = 0;
 	int count_nonsite;
-	char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name);
+	char *kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", "",
+					print_canonical_sockaddr(mem_ctx, pss));
 
 	if (kdc_str == NULL) {
 		return NULL;
@@ -768,10 +702,9 @@ static char *get_kdc_ip_string(char *mem_ctx,
 			}
 			/* Append to the string - inefficient
 			 * but not done often. */
-			kdc_str = print_kdc_line(mem_ctx,
-						kdc_str,
-						&ip_srv_site[i].ss,
-						NULL);
+			kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+						  kdc_str,
+						  print_canonical_sockaddr(mem_ctx, &ip_srv_site[i].ss));
 			if (!kdc_str) {
 				SAFE_FREE(ip_srv_site);
 				return NULL;
@@ -806,11 +739,10 @@ static char *get_kdc_ip_string(char *mem_ctx,
 		}
 
 		/* Append to the string - inefficient but not done often. */
-		kdc_str = print_kdc_line(mem_ctx,
-				kdc_str,
-				&ip_srv_nonsite[i].ss,
-				NULL);
-		if (!kdc_str) {
+		kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+					  kdc_str,
+					  print_canonical_sockaddr(mem_ctx, &ip_srv_nonsite[i].ss));
+		if (kdc_str == NULL) {
 			SAFE_FREE(ip_srv_site);
 			SAFE_FREE(ip_srv_nonsite);
 			return NULL;
-- 
1.9.0


From b4eba7d838b60230b9f6c9a08ef0ddc00e3e47f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Fri, 7 Mar 2014 14:47:31 +0100
Subject: [PATCH 2/5] PATCHSET11: s3-kerberos: remove unused kdc_name from
 create_local_private_krb5_conf_for_domain().
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Günther Deschner <gd@samba.org>
Autobuild-Date(master): Fri Mar  7 18:43:57 CET 2014 on sn-devel-104

Conflicts:
	source3/libads/kerberos.c
	source3/libads/kerberos_proto.h
	source3/libnet/libnet_join.c
	source3/winbindd/winbindd_cm.c
---
 source3/libads/kerberos.c       | 10 ++++------
 source3/libads/kerberos_proto.h |  3 +--
 source3/libnet/libnet_join.c    |  2 +-
 source3/libsmb/namequery_dc.c   |  6 ++----
 source3/winbindd/winbindd_cm.c  |  6 ++----
 5 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 064e5f7..b826cb3 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -671,8 +671,7 @@ int kerberos_kinit_password(const char *principal,
 static char *get_kdc_ip_string(char *mem_ctx,
 		const char *realm,
 		const char *sitename,
-		struct sockaddr_storage *pss,
-		const char *kdc_name)
+		struct sockaddr_storage *pss)
 {
 	int i;
 	struct ip_service *ip_srv_site = NULL;
@@ -769,8 +768,7 @@ static char *get_kdc_ip_string(char *mem_ctx,
 bool create_local_private_krb5_conf_for_domain(const char *realm,
 						const char *domain,
 						const char *sitename,
-						struct sockaddr_storage *pss,
-						const char *kdc_name)
+						struct sockaddr_storage *pss)
 {
 	char *dname;
 	char *tmpname = NULL;
@@ -794,7 +792,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
 		return false;
 	}
 
-	if (domain == NULL || pss == NULL || kdc_name == NULL) {
+	if (domain == NULL || pss == NULL) {
 		return false;
 	}
 
@@ -825,7 +823,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
 	realm_upper = talloc_strdup(fname, realm);
 	strupper_m(realm_upper);
 
-	kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss, kdc_name);
+	kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss);
 	if (!kdc_ip_string) {
 		goto done;
 	}
diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h
index 406669cc..90d7cd9 100644
--- a/source3/libads/kerberos_proto.h
+++ b/source3/libads/kerberos_proto.h
@@ -75,8 +75,7 @@ int kerberos_kinit_password(const char *principal,
 bool create_local_private_krb5_conf_for_domain(const char *realm,
 						const char *domain,
 						const char *sitename,
-						struct sockaddr_storage *pss,
-						const char *kdc_name);
+						struct sockaddr_storage *pss);
 
 /* The following definitions come from libads/authdata.c  */
 
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index e84682d..f1736ec 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1985,7 +1985,7 @@ static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
 
 	create_local_private_krb5_conf_for_domain(
 		r->out.dns_domain_name, r->out.netbios_domain_name,
-		NULL, &cli->dest_ss, cli->desthost);
+		NULL, &cli->dest_ss);
 
 	if (r->out.domain_is_ad && r->in.account_ou &&
 	    !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c
index 39b780c..149121a 100644
--- a/source3/libsmb/namequery_dc.c
+++ b/source3/libsmb/namequery_dc.c
@@ -111,14 +111,12 @@ static bool ads_dc_name(const char *domain,
 				create_local_private_krb5_conf_for_domain(realm,
 									domain,
 									sitename,
-									&ads->ldap.ss,
-									ads->config.ldap_server_name);
+									&ads->ldap.ss);
 			} else {
 				create_local_private_krb5_conf_for_domain(realm,
 									domain,
 									NULL,
-									&ads->ldap.ss,
-									ads->config.ldap_server_name);
+									&ads->ldap.ss);
 			}
 		}
 #endif
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 8271279..59f30a5 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1226,8 +1226,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
 					create_local_private_krb5_conf_for_domain(domain->alt_name,
 									domain->name,
 									sitename,
-									pss,
-									name);
+									pss);
 
 					SAFE_FREE(sitename);
 				} else {
@@ -1235,8 +1234,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
 					create_local_private_krb5_conf_for_domain(domain->alt_name,
 									domain->name,
 									NULL,
-									pss,
-									name);
+									pss);
 				}
 				winbindd_set_locator_kdc_envs(domain);
 
-- 
1.9.0


From db840b57e81922cea984530e2dc1b42cc99e75de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Wed, 2 Apr 2014 19:37:34 +0200
Subject: [PATCH 3/5] PATCHSET11: s3-kerberos: make ipv6 support for generated
 krb5 config files more robust.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Older MIT Kerberos libraries will add any secondary ipv6 address as
ipv4 address, defining the (default) krb5 port 88 circumvents that.

Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Günther Deschner <gd@samba.org>
Autobuild-Date(master): Fri Apr  4 16:33:12 CEST 2014 on sn-devel-104

Conflicts:
	source3/libads/kerberos.c
---
 source3/libads/kerberos.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index b826cb3..5e34aa3 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -668,6 +668,31 @@ int kerberos_kinit_password(const char *principal,
 
 ************************************************************************/
 
+/* print_canonical_sockaddr prints an ipv6 addr in the form of
+* [ipv6.addr]. This string, when put in a generated krb5.conf file is not
+* always properly dealt with by some older krb5 libraries. Adding the hard-coded
+* portnumber workarounds the issue. - gd */
+
+static char *print_canonical_sockaddr_with_port(TALLOC_CTX *mem_ctx,
+						const struct sockaddr_storage *pss)
+{
+	char *str = NULL;
+
+	str = print_canonical_sockaddr(mem_ctx, pss);
+	if (str == NULL) {
+		return NULL;
+	}
+
+	if (pss->ss_family != AF_INET6) {
+		return str;
+	}
+
+#if defined(HAVE_IPV6)
+	str = talloc_asprintf_append(str, ":88");
+#endif
+	return str;
+}
+
 static char *get_kdc_ip_string(char *mem_ctx,
 		const char *realm,
 		const char *sitename,
@@ -679,7 +704,7 @@ static char *get_kdc_ip_string(char *mem_ctx,
 	int count_site = 0;
 	int count_nonsite;
 	char *kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n", "",
-					print_canonical_sockaddr(mem_ctx, pss));
+					print_canonical_sockaddr_with_port(mem_ctx, pss));
 
 	if (kdc_str == NULL) {
 		return NULL;
@@ -740,7 +765,7 @@ static char *get_kdc_ip_string(char *mem_ctx,
 		/* Append to the string - inefficient but not done often. */
 		kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
 					  kdc_str,
-					  print_canonical_sockaddr(mem_ctx, &ip_srv_nonsite[i].ss));
+					  print_canonical_sockaddr_with_port(mem_ctx, &ip_srv_nonsite[i].ss));
 		if (kdc_str == NULL) {
 			SAFE_FREE(ip_srv_site);
 			SAFE_FREE(ip_srv_nonsite);
-- 
1.9.0


From 208f1d7b5ae557bf34a39c847aeb1925ce4cb171 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
Date: Tue, 26 Apr 2011 17:03:32 +1000
Subject: [PATCH 4/5] PATCHSET11: s3-libads Pass a struct sockaddr_storage to
 cldap routines

This avoids these routines doing a DNS lookup that has already been
done, and ensures that the emulated DNS lookup isn't thrown away.

Andrew Bartlett
---
 source3/libads/cldap.c                | 14 ++++--------
 source3/libads/cldap.h                |  4 ++--
 source3/libads/ldap.c                 | 41 ++++++++++-------------------------
 source3/libsmb/dsgetdcname.c          |  3 ++-
 source3/utils/net_ads.c               |  7 +++---
 source3/winbindd/idmap_adex/gc_util.c | 12 +++++++++-
 6 files changed, 33 insertions(+), 48 deletions(-)

diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c
index 5d2e900..03fa17c 100644
--- a/source3/libads/cldap.c
+++ b/source3/libads/cldap.c
@@ -30,7 +30,7 @@
 *******************************************************************/
 
 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
-			const char *server,
+			struct sockaddr_storage *ss,
 			const char *realm,
 			uint32_t nt_version,
 			struct netlogon_samlogon_response **_reply)
@@ -39,18 +39,12 @@ bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
 	struct cldap_netlogon io;
 	struct netlogon_samlogon_response *reply;
 	NTSTATUS status;
-	struct sockaddr_storage ss;
 	char addrstr[INET6_ADDRSTRLEN];
 	const char *dest_str;
 	int ret;
 	struct tsocket_address *dest_addr;
 
-	if (!interpret_string_addr_prefer_ipv4(&ss, server, 0)) {
-		DEBUG(2,("Failed to resolve[%s] into an address for cldap\n",
-			server));
-		return false;
-	}
-	dest_str = print_sockaddr(addrstr, sizeof(addrstr), &ss);
+	dest_str = print_sockaddr(addrstr, sizeof(addrstr), ss);
 
 	ret = tsocket_address_inet_from_strings(mem_ctx, "ip",
 						dest_str, LDAP_PORT,
@@ -113,7 +107,7 @@ failed:
 *******************************************************************/
 
 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
-			  const char *server,
+			  struct sockaddr_storage *ss,
 			  const char *realm,
 			  struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
 {
@@ -121,7 +115,7 @@ bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
 	struct netlogon_samlogon_response *reply = NULL;
 	bool ret;
 
-	ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
+	ret = ads_cldap_netlogon(mem_ctx, ss, realm, nt_version, &reply);
 	if (!ret) {
 		return false;
 	}
diff --git a/source3/libads/cldap.h b/source3/libads/cldap.h
index d2ad4b0..60e1c56 100644
--- a/source3/libads/cldap.h
+++ b/source3/libads/cldap.h
@@ -27,12 +27,12 @@
 
 /* The following definitions come from libads/cldap.c  */
 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
-			const char *server,
+			struct sockaddr_storage *ss,
 			const char *realm,
 			uint32_t nt_version,
 			struct netlogon_samlogon_response **reply);
 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
-			  const char *server,
+			  struct sockaddr_storage *ss,
 			  const char *realm,
 			  struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5);
 
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index b841c84..0db0bcd 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -196,45 +196,32 @@ bool ads_closest_dc(ADS_STRUCT *ads)
  */
 static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
 {
-	char *srv;
 	struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
 	TALLOC_CTX *frame = talloc_stackframe();
 	bool ret = false;
+	struct sockaddr_storage ss;
+	char addr[INET6_ADDRSTRLEN];
 
 	if (!server || !*server) {
 		TALLOC_FREE(frame);
 		return False;
 	}
 
-	if (!is_ipaddress(server)) {
-		struct sockaddr_storage ss;
-		char addr[INET6_ADDRSTRLEN];
-
-		if (!resolve_name(server, &ss, 0x20, true)) {
-			DEBUG(5,("ads_try_connect: unable to resolve name %s\n",
-				server ));
-			TALLOC_FREE(frame);
-			return false;
-		}
-		print_sockaddr(addr, sizeof(addr), &ss);
-		srv = talloc_strdup(frame, addr);
-	} else {
-		/* this copes with inet_ntoa brokenness */
-		srv = talloc_strdup(frame, server);
-	}
-
-	if (!srv) {
+	if (!resolve_name(server, &ss, 0x20, true)) {
+		DEBUG(5,("ads_try_connect: unable to resolve name %s\n",
+			 server ));
 		TALLOC_FREE(frame);
 		return false;
 	}
+	print_sockaddr(addr, sizeof(addr), &ss);
 
 	DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", 
-		srv, ads->server.realm));
+		addr, ads->server.realm));
 
 	ZERO_STRUCT( cldap_reply );
 
-	if ( !ads_cldap_netlogon_5(frame, srv, ads->server.realm, &cldap_reply ) ) {
-		DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));
+	if ( !ads_cldap_netlogon_5(frame, &ss, ads->server.realm, &cldap_reply ) ) {
+		DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr));
 		ret = false;
 		goto out;
 	}
@@ -243,7 +230,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
 
 	if ( !(cldap_reply.server_type & NBT_SERVER_LDAP) ) {
 		DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n",
-			srv));
+			addr));
 		ret = false;
 		goto out;
 	}
@@ -273,13 +260,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
 	ads->server.workgroup          = SMB_STRDUP(cldap_reply.domain_name);
 
 	ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
-	if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
-		DEBUG(1,("ads_try_connect: unable to convert %s "
-			"to an address\n",
-			srv));
-		ret = false;
-		goto out;
-	}
+	ads->ldap.ss = ss;
 
 	/* Store our site name. */
 	sitename_store( cldap_reply.domain_name, cldap_reply.client_site);
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 841a179..2f8b8dc 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -863,9 +863,10 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
 
 	for (i=0; i<num_dcs; i++) {
 
+
 		DEBUG(10,("LDAP ping to %s\n", dclist[i].hostname));
 
-		if (ads_cldap_netlogon(mem_ctx, dclist[i].hostname,
+		if (ads_cldap_netlogon(mem_ctx, &dclist[i].ss,
 					domain_name,
 					nt_version,
 					&r))
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 8f8b7b4..816349d 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -62,7 +62,8 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
 	struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
 
 	print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
-	if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
+
+	if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
 		d_fprintf(stderr, _("CLDAP query failed!\n"));
 		return -1;
 	}
@@ -385,7 +386,6 @@ int net_ads_check(struct net_context *c)
 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
 {
 	ADS_STRUCT *ads;
-	char addr[INET6_ADDRSTRLEN];
 	struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
 
 	if (c->display_usage) {
@@ -407,8 +407,7 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
 		ads->ldap.port = 389;
 	}
 
-	print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
-	if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
+	if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
 		d_fprintf(stderr, _("CLDAP query failed!\n"));
 		ads_destroy(&ads);
 		return -1;
diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c
index 77b318c..e625265 100644
--- a/source3/winbindd/idmap_adex/gc_util.c
+++ b/source3/winbindd/idmap_adex/gc_util.c
@@ -107,6 +107,7 @@ done:
 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 	struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
 	TALLOC_CTX *frame = talloc_stackframe();
+	struct sockaddr_storage ss;
 
 	if (!gc || !domain) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -126,8 +127,17 @@ done:
 	nt_status = ads_ntstatus(ads_status);
 	BAIL_ON_NTSTATUS_ERROR(nt_status);
 
+	if (!resolve_name(ads->config.ldap_server_name, &ss, 0x20, true)) {
+		DEBUG(5,("gc_find_forest_root: unable to resolve name %s\n",
+			 ads->config.ldap_server_name));
+		nt_status = NT_STATUS_IO_TIMEOUT;
+		/* This matches the old code which did the resolve in
+		 * ads_cldap_netlogon_5 */
+		BAIL_ON_NTSTATUS_ERROR(nt_status);
+	}
+
 	if (!ads_cldap_netlogon_5(frame,
-				  ads->config.ldap_server_name,
+				  &ss,
 				  ads->config.realm,
 				  &cldap_reply))
 	{
-- 
1.9.0


From 4eb02e7caa83b725988dd9f659b3568873522a30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Wed, 16 Apr 2014 16:07:14 +0200
Subject: [PATCH 5/5] PATCHSET11: s3-libads: allow ads_try_connect() to re-use
 a resolved ip address.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Pass down a struct sockaddr_storage to ads_try_connect.

Guenther

Signed-off-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Günther Deschner <gd@samba.org>
Autobuild-Date(master): Thu Apr 17 19:56:16 CEST 2014 on sn-devel-104
---
 source3/libads/ldap.c | 44 ++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 0db0bcd..f8349cf 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -194,33 +194,27 @@ bool ads_closest_dc(ADS_STRUCT *ads)
   try a connection to a given ldap server, returning True and setting the servers IP
   in the ads struct if successful
  */
-static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
+static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
+			    struct sockaddr_storage *ss)
 {
 	struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
 	TALLOC_CTX *frame = talloc_stackframe();
 	bool ret = false;
-	struct sockaddr_storage ss;
 	char addr[INET6_ADDRSTRLEN];
 
-	if (!server || !*server) {
+	if (ss == NULL) {
 		TALLOC_FREE(frame);
 		return False;
 	}
 
-	if (!resolve_name(server, &ss, 0x20, true)) {
-		DEBUG(5,("ads_try_connect: unable to resolve name %s\n",
-			 server ));
-		TALLOC_FREE(frame);
-		return false;
-	}
-	print_sockaddr(addr, sizeof(addr), &ss);
+	print_sockaddr(addr, sizeof(addr), ss);
 
 	DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", 
 		addr, ads->server.realm));
 
 	ZERO_STRUCT( cldap_reply );
 
-	if ( !ads_cldap_netlogon_5(frame, &ss, ads->server.realm, &cldap_reply ) ) {
+	if ( !ads_cldap_netlogon_5(frame, ss, ads->server.realm, &cldap_reply ) ) {
 		DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr));
 		ret = false;
 		goto out;
@@ -260,7 +254,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
 	ads->server.workgroup          = SMB_STRDUP(cldap_reply.domain_name);
 
 	ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
-	ads->ldap.ss = ss;
+	ads->ldap.ss = *ss;
 
 	/* Store our site name. */
 	sitename_store( cldap_reply.domain_name, cldap_reply.client_site);
@@ -292,6 +286,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 	bool use_own_domain = False;
 	char *sitename;
 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	bool ok = false;
 
 	/* if the realm and workgroup are both empty, assume they are ours */
 
@@ -345,12 +340,14 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 		DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n",
 			(got_realm ? "realm" : "domain"), realm));
 
-		if (get_dc_name(domain, realm, srv_name, &ip_out)) {
+		ok = get_dc_name(domain, realm, srv_name, &ip_out);
+		if (ok) {
 			/*
 			 * we call ads_try_connect() to fill in the
 			 * ads->config details
 			 */
-			if (ads_try_connect(ads, srv_name, false)) {
+			ok = ads_try_connect(ads, false, &ip_out);
+			if (ok) {
 				return NT_STATUS_OK;
 			}
 		}
@@ -406,7 +403,8 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 			}
 		}
 
-		if ( ads_try_connect(ads, server, false) ) {
+		ok = ads_try_connect(ads, false, &ip_list[i].ss);
+		if (ok) {
 			SAFE_FREE(ip_list);
 			SAFE_FREE(sitename);
 			return NT_STATUS_OK;
@@ -591,9 +589,19 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
 		TALLOC_FREE(s);
 	}
 
-	if (ads->server.ldap_server)
-	{
-		if (ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) {
+	if (ads->server.ldap_server) {
+		bool ok = false;
+		struct sockaddr_storage ss;
+
+		ok = resolve_name(ads->server.ldap_server, &ss, 0x20, true);
+		if (!ok) {
+			DEBUG(5,("ads_connect: unable to resolve name %s\n",
+				 ads->server.ldap_server));
+			status = ADS_ERROR_NT(NT_STATUS_NOT_FOUND);
+			goto out;
+		}
+		ok = ads_try_connect(ads, ads->server.gc, &ss);
+		if (ok) {
 			goto got_connection;
 		}
 
-- 
1.9.0

diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index b826cb3..5e34aa3 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -827,10 +827,6 @@
 		return false;
 	}
 
-	if (domain == NULL || pss == NULL || kdc_name == NULL) {
-		return false;
-	}
-
 	dname = lock_path("smb_krb5");
 	if (!dname) {
 		return false;
