[SCM] Samba Shared Repository - branch master updated

Andreas Schneider asn at samba.org
Thu Sep 8 08:13:01 UTC 2022


The branch, master has been updated
       via  8132edf1197 s3:libads: let cldap_ping_list() use cldap_multi_netlogon()
       via  ab6b9465eda s3:libads: split out ads_fill_cldap_reply() out of ads_try_connect()
      from  c2e235efd40 s3:modules - fix read of uninitialized memory

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


- Log -----------------------------------------------------------------
commit 8132edf119757ee91070facffef016c93de9c2a6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 24 16:11:06 2022 +0200

    s3:libads: let cldap_ping_list() use cldap_multi_netlogon()
    
    We have a list of ip addresses, so we can request them
    all together under a single timeout, instead of asking
    each ip with it's own timeout.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    
    Autobuild-User(master): Andreas Schneider <asn at cryptomilk.org>
    Autobuild-Date(master): Thu Sep  8 08:12:46 UTC 2022 on sn-devel-184

commit ab6b9465eda9f219bbed3bd65e89668e5e2c93c6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 24 16:36:17 2022 +0200

    s3:libads: split out ads_fill_cldap_reply() out of ads_try_connect()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

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

Summary of changes:
 source3/libads/ldap.c | 246 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 202 insertions(+), 44 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index e7e34998f74..da5a924cde0 100755
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -25,6 +25,7 @@
 #include "ads.h"
 #include "libads/sitename_cache.h"
 #include "libads/cldap.h"
+#include "../lib/tsocket/tsocket.h"
 #include "../lib/addns/dnsquery.h"
 #include "../libds/common/flags.h"
 #include "smbldap.h"
@@ -249,43 +250,23 @@ bool ads_closest_dc(ADS_STRUCT *ads)
 	return False;
 }
 
-
-/*
-  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, bool gc,
-			    struct sockaddr_storage *ss)
+static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
+				 bool gc,
+				 const struct sockaddr_storage *ss,
+				 const struct NETLOGON_SAM_LOGON_RESPONSE_EX *cldap_reply)
 {
-	struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
 	TALLOC_CTX *frame = talloc_stackframe();
 	bool ret = false;
 	char addr[INET6_ADDRSTRLEN];
 	ADS_STATUS status;
 
-	if (ss == NULL) {
-		TALLOC_FREE(frame);
-		return False;
-	}
-
 	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 ) ) {
-		DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr));
-		ret = false;
-		goto out;
-	}
-
 	/* Check the CLDAP reply flags */
 
-	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",
-			addr));
+	if (!(cldap_reply->server_type & NBT_SERVER_LDAP)) {
+		DBG_WARNING("%s's CLDAP reply says it is not an LDAP server!\n",
+			    addr);
 		ret = false;
 		goto out;
 	}
@@ -299,14 +280,14 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 	TALLOC_FREE(ads->config.client_site_name);
 	TALLOC_FREE(ads->server.workgroup);
 
-	if (!check_cldap_reply_required_flags(cldap_reply.server_type,
+	if (!check_cldap_reply_required_flags(cldap_reply->server_type,
 					      ads->config.flags)) {
 		ret = false;
 		goto out;
 	}
 
 	ads->config.ldap_server_name = talloc_strdup(ads,
-						     cldap_reply.pdc_dns_name);
+						     cldap_reply->pdc_dns_name);
 	if (ads->config.ldap_server_name == NULL) {
 		DBG_WARNING("Out of memory\n");
 		ret = false;
@@ -315,7 +296,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 
 	ads->config.realm = talloc_asprintf_strupper_m(ads,
 						       "%s",
-						       cldap_reply.dns_domain);
+						       cldap_reply->dns_domain);
 	if (ads->config.realm == NULL) {
 		DBG_WARNING("Out of memory\n");
 		ret = false;
@@ -330,9 +311,9 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 		goto out;
 	}
 
-	if (*cldap_reply.server_site) {
+	if (*cldap_reply->server_site) {
 		ads->config.server_site_name =
-			talloc_strdup(ads, cldap_reply.server_site);
+			talloc_strdup(ads, cldap_reply->server_site);
 		if (ads->config.server_site_name == NULL) {
 			DBG_WARNING("Out of memory\n");
 			ret = false;
@@ -340,9 +321,9 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 		}
 	}
 
-	if (*cldap_reply.client_site) {
+	if (*cldap_reply->client_site) {
 		ads->config.client_site_name =
-			talloc_strdup(ads, cldap_reply.client_site);
+			talloc_strdup(ads, cldap_reply->client_site);
 		if (ads->config.client_site_name == NULL) {
 			DBG_WARNING("Out of memory\n");
 			ret = false;
@@ -350,7 +331,7 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 		}
 	}
 
-	ads->server.workgroup = talloc_strdup(ads, cldap_reply.domain_name);
+	ads->server.workgroup = talloc_strdup(ads, cldap_reply->domain_name);
 	if (ads->server.workgroup == NULL) {
 		DBG_WARNING("Out of memory\n");
 		ret = false;
@@ -361,11 +342,11 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 	ads->ldap.ss = *ss;
 
 	/* Store our site name. */
-	sitename_store( cldap_reply.domain_name, cldap_reply.client_site);
-	sitename_store( cldap_reply.dns_domain, cldap_reply.client_site);
+	sitename_store(cldap_reply->domain_name, cldap_reply->client_site);
+	sitename_store(cldap_reply->dns_domain, cldap_reply->client_site);
 
 	/* Leave this until last so that the flags are not clobbered */
-	ads->config.flags	       = cldap_reply.server_type;
+	ads->config.flags = cldap_reply->server_type;
 
 	ret = true;
 
@@ -375,6 +356,48 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 	return ret;
 }
 
+/*
+  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, bool gc,
+			    struct sockaddr_storage *ss)
+{
+	struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply = {};
+	TALLOC_CTX *frame = talloc_stackframe();
+	bool ok;
+	char addr[INET6_ADDRSTRLEN] = { 0, };
+
+	if (ss == NULL) {
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	print_sockaddr(addr, sizeof(addr), ss);
+
+	DBG_INFO("ads_try_connect: sending CLDAP request to %s (realm: %s)\n",
+		 addr, ads->server.realm);
+
+	ok = ads_cldap_netlogon_5(frame, ss, ads->server.realm, &cldap_reply);
+	if (!ok) {
+		DBG_NOTICE("ads_cldap_netlogon_5(%s, %s) failed.\n",
+			   addr, ads->server.realm);
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	ok = ads_fill_cldap_reply(ads, gc, ss, &cldap_reply);
+	if (!ok) {
+		DBG_NOTICE("ads_fill_cldap_reply(%s, %s) failed.\n",
+			   addr, ads->server.realm);
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	TALLOC_FREE(frame);
+	return true;
+}
+
 /**********************************************************************
  send a cldap ping to list of servers, one at a time, until one of
  them answers it's an ldap server. Record success in the ADS_STRUCT.
@@ -386,11 +409,44 @@ static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,
 			struct samba_sockaddr *sa_list,
 			size_t count)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct timeval endtime = timeval_current_ofs(MAX(3,lp_ldap_timeout()/2), 0);
+	uint32_t nt_version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+	struct tsocket_address **ts_list = NULL;
+	const struct tsocket_address * const *ts_list_const = NULL;
+	struct samba_sockaddr **req_sa_list = NULL;
+	struct netlogon_samlogon_response **responses = NULL;
+	size_t num_requests = 0;
+	NTSTATUS status;
 	size_t i;
-	bool ok;
+	bool ok = false;
+	bool retry;
+
+	ts_list = talloc_zero_array(frame,
+				    struct tsocket_address *,
+				    count);
+	if (ts_list == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	req_sa_list = talloc_zero_array(frame,
+					struct samba_sockaddr *,
+					count);
+	if (req_sa_list == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+again:
+	/*
+	 * The retry loop is bound by the timeout
+	 */
+	retry = false;
 
 	for (i = 0; i < count; i++) {
 		char server[INET6_ADDRSTRLEN];
+		int ret;
 
 		if (is_zero_addr(&sa_list[i].u.ss)) {
 			continue;
@@ -398,22 +454,124 @@ static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,
 
 		print_sockaddr(server, sizeof(server), &sa_list[i].u.ss);
 
-		if (!NT_STATUS_IS_OK(
-			check_negative_conn_cache(domain, server)))
+		status = check_negative_conn_cache(domain, server);
+		if (!NT_STATUS_IS_OK(status)) {
 			continue;
+		}
 
-		/* Returns ok only if it matches the correct server type */
-		ok = ads_try_connect(ads, false, &sa_list[i].u.ss);
+		ret = tsocket_address_inet_from_strings(ts_list, "ip",
+							server, LDAP_PORT,
+							&ts_list[num_requests]);
+		if (ret != 0) {
+			status = map_nt_error_from_unix(errno);
+			DBG_WARNING("Failed to create tsocket_address for %s - %s\n",
+				    server, nt_errstr(status));
+			TALLOC_FREE(frame);
+			return status;
+		}
+
+		req_sa_list[num_requests] = &sa_list[i];
+		num_requests += 1;
+	}
 
+	if (num_requests == 0) {
+		status = NT_STATUS_NO_LOGON_SERVERS;
+		DBG_WARNING("domain[%s] num_requests[%zu] for count[%zu] - %s\n",
+			    domain, num_requests, count, nt_errstr(status));
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	ts_list_const = (const struct tsocket_address * const *)ts_list;
+
+	status = cldap_multi_netlogon(frame,
+				      ts_list_const, num_requests,
+				      ads->server.realm, NULL,
+				      nt_version,
+				      1, endtime, &responses);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_WARNING("cldap_multi_netlogon(realm=%s, num_requests=%zu) "
+			    "for count[%zu] - %s\n",
+			    ads->server.realm,
+			    num_requests, count,
+			    nt_errstr(status));
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_LOGON_SERVERS;
+	}
+
+	for (i = 0; i < num_requests; i++) {
+		struct NETLOGON_SAM_LOGON_RESPONSE_EX *cldap_reply = NULL;
+		char server[INET6_ADDRSTRLEN];
+
+		if (responses[i] == NULL) {
+			continue;
+		}
+
+		print_sockaddr(server, sizeof(server), &req_sa_list[i]->u.ss);
+
+		if (responses[i]->ntver != NETLOGON_NT_VERSION_5EX) {
+			DBG_NOTICE("realm=[%s] nt_version mismatch: 0x%08x for %s\n",
+				   ads->server.realm,
+				   responses[i]->ntver, server);
+			continue;
+		}
+
+		cldap_reply = &responses[i]->data.nt5_ex;
+
+		/* Returns ok only if it matches the correct server type */
+		ok = ads_fill_cldap_reply(ads,
+					  false,
+					  &req_sa_list[i]->u.ss,
+					  cldap_reply);
 		if (ok) {
+			DBG_DEBUG("realm[%s]: selected %s => %s\n",
+				  ads->server.realm,
+				  server, cldap_reply->pdc_dns_name);
+			if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
+				NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
+						cldap_reply);
+			}
+			TALLOC_FREE(frame);
 			return NT_STATUS_OK;
 		}
 
-		/* keep track of failures */
+		DBG_NOTICE("realm[%s] server %s %s - not usable\n",
+			   ads->server.realm,
+			   server, cldap_reply->pdc_dns_name);
+		if (CHECK_DEBUGLVL(DBGLVL_NOTICE)) {
+			NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
+					cldap_reply);
+		}
+		add_failed_connection_entry(domain, server,
+				NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID);
+		retry = true;
+	}
+
+	if (retry) {
+		bool expired;
+
+		expired = timeval_expired(&endtime);
+		if (!expired) {
+			goto again;
+		}
+	}
+
+	/* keep track of failures as all were not suitable */
+	for (i = 0; i < num_requests; i++) {
+		char server[INET6_ADDRSTRLEN];
+
+		print_sockaddr(server, sizeof(server), &req_sa_list[i]->u.ss);
+
 		add_failed_connection_entry(domain, server,
 					    NT_STATUS_UNSUCCESSFUL);
 	}
 
+	status = NT_STATUS_NO_LOGON_SERVERS;
+	DBG_WARNING("realm[%s] no valid response "
+		    "num_requests[%zu] for count[%zu] - %s\n",
+		    ads->server.realm,
+		    num_requests, count, nt_errstr(status));
+	TALLOC_FREE(frame);
 	return NT_STATUS_NO_LOGON_SERVERS;
 }
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list