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 <me...@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 <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    
    Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org>
    Autobuild-Date(master): Thu Sep  8 08:12:46 UTC 2022 on sn-devel-184

commit ab6b9465eda9f219bbed3bd65e89668e5e2c93c6
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@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

Reply via email to