libads: Check cldap flags in libads/ldap
authorGarming Sam <garming@catalyst.net.nz>
Mon, 20 Mar 2017 02:37:12 +0000 (15:37 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 30 May 2017 06:06:06 +0000 (08:06 +0200)
Pass down request flags and check they are respected with the response
flags. Otherwise, error out and pretend the connection never happened.

Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/libads/cldap.c
source3/libads/cldap.h
source3/libads/ldap.c
source3/libsmb/dsgetdcname.c

index 586a04a0e42b3d944aab1319d46789421f388510..f4022a19905f89d3a818f4aa4416d5985661ff0c 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "../libcli/cldap/cldap.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "libads/cldap.h"
@@ -47,6 +48,43 @@ struct cldap_multi_netlogon_state {
 static void cldap_multi_netlogon_done(struct tevent_req *subreq);
 static void cldap_multi_netlogon_next(struct tevent_req *subreq);
 
+/****************************************************************
+****************************************************************/
+
+#define RETURN_ON_FALSE(x) if (!(x)) return false;
+
+bool check_cldap_reply_required_flags(uint32_t ret_flags,
+                                     uint32_t req_flags)
+{
+       if (req_flags == 0) {
+               return true;
+       }
+
+       if (req_flags & DS_PDC_REQUIRED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_PDC);
+
+       if (req_flags & DS_GC_SERVER_REQUIRED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_GC);
+
+       if (req_flags & DS_ONLY_LDAP_NEEDED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_LDAP);
+
+       if ((req_flags & DS_DIRECTORY_SERVICE_REQUIRED) ||
+           (req_flags & DS_DIRECTORY_SERVICE_PREFERRED))
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_DS);
+
+       if (req_flags & DS_KDC_REQUIRED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_KDC);
+
+       if (req_flags & DS_TIMESERV_REQUIRED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_TIMESERV);
+
+       if (req_flags & DS_WRITABLE_REQUIRED)
+               RETURN_ON_FALSE(ret_flags & NBT_SERVER_WRITABLE);
+
+       return true;
+}
+
 /*
  * Do a parallel cldap ping to the servers. The first "min_servers"
  * are fired directly, the remaining ones in 100msec intervals. If
index 9e42782052a560a0cd1e2703196769711c3a7822..7fa1bdf8d60dad5288eb287bfdefee1c3d2a5006 100644 (file)
@@ -27,6 +27,9 @@
 
 /* The following definitions come from libads/cldap.c  */
 
+bool check_cldap_reply_required_flags(uint32_t ret_flags,
+                                     uint32_t req_flags);
+
 struct tevent_req *cldap_multi_netlogon_send(
        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
        const struct tsocket_address * const *servers,
index fdb729e90daf7ec740b3a9ae52588966f49b2aba..b2c57480f1e231366987b5a7204968289deaa6a8 100644 (file)
@@ -279,7 +279,12 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
        SAFE_FREE(ads->config.client_site_name);
        SAFE_FREE(ads->server.workgroup);
 
-       ads->config.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   = SMB_STRDUP(cldap_reply.pdc_dns_name);
        ads->config.realm              = SMB_STRDUP(cldap_reply.dns_domain);
        if (!strupper_m(ads->config.realm)) {
@@ -305,6 +310,9 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
        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;
+
        ret = true;
 
  out:
@@ -334,7 +342,9 @@ static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,const char *domain,
                        check_negative_conn_cache(domain, server)))
                        continue;
 
+               /* Returns ok only if it matches the correct server type */
                ok = ads_try_connect(ads, false, &ip_list[i].ss);
+
                if (ok) {
                        return NT_STATUS_OK;
                }
index b5bc51dffaeb65ee11865b525a746b350eb44644..92fc312c6a493e9a6f18fa9233987d5680b2a44b 100644 (file)
@@ -279,43 +279,6 @@ static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response *
 /****************************************************************
 ****************************************************************/
 
-#define RETURN_ON_FALSE(x) if (!(x)) return false;
-
-static bool check_cldap_reply_required_flags(uint32_t ret_flags,
-                                            uint32_t req_flags)
-{
-       if (req_flags == 0) {
-               return true;
-       }
-
-       if (req_flags & DS_PDC_REQUIRED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_PDC);
-
-       if (req_flags & DS_GC_SERVER_REQUIRED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_GC);
-
-       if (req_flags & DS_ONLY_LDAP_NEEDED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_LDAP);
-
-       if ((req_flags & DS_DIRECTORY_SERVICE_REQUIRED) ||
-           (req_flags & DS_DIRECTORY_SERVICE_PREFERRED))
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_DS);
-
-       if (req_flags & DS_KDC_REQUIRED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_KDC);
-
-       if (req_flags & DS_TIMESERV_REQUIRED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_TIMESERV);
-
-       if (req_flags & DS_WRITABLE_REQUIRED)
-               RETURN_ON_FALSE(ret_flags & NBT_SERVER_WRITABLE);
-
-       return true;
-}
-
-/****************************************************************
-****************************************************************/
-
 static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
                                        const char *domain_name,
                                        const struct GUID *domain_guid,