DEFER!!! netlogon: Resolve calls to GetDCNameEx2 within the same NETLOGON domain
authorGarming Sam <garming@catalyst.net.nz>
Sun, 25 Mar 2018 23:10:58 +0000 (12:10 +1300)
committerStefan Metzmacher <metze@samba.org>
Fri, 13 Apr 2018 22:22:17 +0000 (00:22 +0200)
The return will have the DNS domain, which is not quite as nice, but it
does not seem to violate any assumptions

The reason we do this is because DNS based querying seems to be much
more reliable than the NETBIOS based queries.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13365

Signed-off-by: Garming Sam <garming@catalyst.net.nz>
source4/rpc_server/netlogon/dcerpc_netlogon.c

index fa34251a0fa33b3231079dd674c38342efc062b5..f450e8f1b340b386c4a714563f9b141803a1ca68 100644 (file)
@@ -2785,6 +2785,7 @@ 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 forward_with_dns_name = false;
 
        ZERO_STRUCTP(r->out.info);
 
@@ -2859,6 +2860,7 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
                        if (strcasecmp_m(r->in.domain_name,
                                         lpcfg_sam_name(lp_ctx)) == 0) {
                                different_domain = false;
+                               forward_with_dns_name = true;
                        }
                } else if (r->in.flags & DS_IS_DNS_NAME) {
                        if (strcasecmp_m(r->in.domain_name,
@@ -2871,6 +2873,7 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
                            strcasecmp_m(r->in.domain_name,
                                         lpcfg_dnsdomain(lp_ctx)) == 0) {
                                different_domain = false;
+                               forward_with_dns_name = true;
                        }
                }
        } else {
@@ -2879,6 +2882,7 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
                 * revert to our domain by default.
                 */
                different_domain = false;
+               forward_with_dns_name = true;
        }
 
        /* Proof server site parameter "site_name" if it was specified */
@@ -2890,6 +2894,7 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
 
                struct dcerpc_binding_handle *irpc_handle = NULL;
                struct tevent_req *subreq = NULL;
+               uint32_t forward_flags = r->in.flags;
 
                /*
                 * Retrieve the client site to override the winbind response.
@@ -2922,13 +2927,22 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
 
                dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
 
+               domain_name = r->in.domain_name;
+
+               /* This only fixes the single domain case with NETBIOS names. */
+               if (forward_with_dns_name) {
+                       forward_flags &= ~DS_IS_FLAT_NAME;
+                       forward_flags |= DS_IS_DNS_NAME;
+                       domain_name = lpcfg_dnsdomain(lp_ctx);
+               }
+
                subreq = dcerpc_wbint_DsGetDcName_send(state,
                                                       dce_call->event_ctx,
                                                       irpc_handle,
-                                                      r->in.domain_name,
+                                                      domain_name,
                                                       r->in.domain_guid,
                                                       r->in.site_name,
-                                                      r->in.flags,
+                                                      forward_flags,
                                                       r->out.info);
                if (subreq == NULL) {
                        return WERR_NOT_ENOUGH_MEMORY;
@@ -3029,6 +3043,12 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
        return WERR_OK;
 }
 
+/*
+ * TODO: We can still erroneously return ourselves across winbind when a
+ * (NETBIOS) domain sometimes does not exist. We may wish to pass down a flag
+ * to prevent that. This is partly mitigated by the site name check in this
+ * function, and because it preferably sends the DNS domain.
+ */
 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
 {
        struct dcesrv_netr_DsRGetDCName_base_state *state =
@@ -3077,6 +3097,11 @@ static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
         *
         * TODO: Currently this means that requests with NETBIOS domain
         * names can fail because they do not return the site name.
+        * In the standard single domain case, the caller will pass
+        * down the DNS domain instead (which perhaps should be
+        * reverted to the NETBIOS name here).
+        *
+        * For trusted domains, changes to winbind will need to be made.
         */
        if (state->r.in.site_name == NULL ||
            strcasecmp_m("", state->r.in.site_name) == 0 ||