s4-rpc_server: Filter via dsdb_dc_functional_level() before we are returning a lookup...
authorAndrew Bartlett <abartlet@samba.org>
Tue, 30 May 2023 06:03:13 +0000 (18:03 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 31 May 2023 04:59:01 +0000 (04:59 +0000)
Otherwise, punt to winbindd to see if another DC has this capability.

This allows a FL2008-emulating DC to forward a request to a
2012R2-emlating DC, particularly in another domain.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed May 31 04:59:01 UTC 2023 on atb-devel-224

selftest/knownfail.d/getdcname [deleted file]
source4/rpc_server/netlogon/dcerpc_netlogon.c

diff --git a/selftest/knownfail.d/getdcname b/selftest/knownfail.d/getdcname
deleted file mode 100644 (file)
index 30d5fc7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-^samba.tests.getdcname.samba.tests.getdcname.GetDCNameEx.test_get_dc_direct_need_2012r2_but_not_found\(fl2008r2dc\)
-^samba.tests.getdcname.samba.tests.getdcname.GetDCNameEx.test_get_dc_direct_need_2012r2_but_not_found_fallback
-^samba.tests.getdcname.samba.tests.getdcname.GetDCNameEx.test_get_dc_direct_need_web_but_not_found
index b06b542791d0759ec757cb1b903d064b5b2733f9..9d9b6c792abebe7ae5065456d0bd612d944def6c 100644 (file)
@@ -3192,7 +3192,9 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
        const char *domain_name = NULL;
        const char *pdc_ip;
        bool different_domain = true;
+       bool force_remote_lookup = false;
        uint32_t valid_flags;
+       uint32_t this_dc_valid_flags;
        int dc_level;
 
        ZERO_STRUCTP(r->out.info);
@@ -3257,17 +3259,8 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
         * ...
         */
 
-       dc_level = dsdb_dc_functional_level(sam_ctx);
        valid_flags = DSGETDC_VALID_FLAGS;
-       if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
-               valid_flags |= DS_DIRECTORY_SERVICE_8_REQUIRED;
-       }
-       if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
-               valid_flags |= DS_DIRECTORY_SERVICE_9_REQUIRED;
-       }
-       if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
-               valid_flags |= DS_DIRECTORY_SERVICE_10_REQUIRED;
-       }
+
        if (r->in.flags & ~valid_flags) {
                /*
                 * TODO: add tests to prove this (maybe based on the
@@ -3362,12 +3355,44 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
                different_domain = false;
        }
 
+       if (!different_domain) {
+               dc_level = dsdb_dc_functional_level(sam_ctx);
+
+               /*
+                * Do not return a local response if we do not support the
+                * functional level or feature (eg web services)
+                */
+               this_dc_valid_flags = valid_flags;
+
+               /* Samba does not implement this */
+               this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
+
+               if (dc_level < DS_DOMAIN_FUNCTION_2012) {
+                       this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
+               }
+               if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
+                       this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
+               }
+               if (dc_level < DS_DOMAIN_FUNCTION_2016) {
+                       this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
+               }
+               if (r->in.flags & ~this_dc_valid_flags) {
+                       DBG_INFO("Forcing remote lookup to find another DC "
+                                "in this domain %s with more features, "
+                                "as this Samba DC is Functional level %d but flags are 0x08%x\n",
+                                r->in.domain_name, dc_level, (unsigned int)r->in.flags);
+                       force_remote_lookup = true;
+               }
+       }
+
        /* Proof server site parameter "site_name" if it was specified */
        server_site_name = samdb_server_site_name(sam_ctx, state);
        W_ERROR_HAVE_NO_MEMORY(server_site_name);
-       if (different_domain || (r->in.site_name != NULL &&
-                                (strcasecmp_m(r->in.site_name,
-                                            server_site_name) != 0))) {
+       if (force_remote_lookup
+           || different_domain
+           || (r->in.site_name != NULL &&
+               (strcasecmp_m(r->in.site_name,
+                             server_site_name) != 0))) {
 
                struct dcerpc_binding_handle *irpc_handle = NULL;
                struct tevent_req *subreq = NULL;