[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