winbindd: set routing_domain when enumerating trusts
[metze/samba/wip.git] / source3 / winbindd / winbindd_util.c
index 2f145cdd48afb7567586405996ece47ca022acb3..4d66571703f917db6804480af2a782f25f679464 100644 (file)
@@ -290,6 +290,74 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
        return NT_STATUS_OK;
 }
 
+bool set_routing_domain(struct winbindd_domain *domain,
+                       const struct winbindd_domain *routing_domain)
+{
+       if (domain->routing_domain == NULL) {
+               domain->routing_domain = routing_domain;
+               return true;
+       }
+       if (domain->routing_domain != routing_domain) {
+               return false;
+       }
+       return true;
+}
+
+bool add_trusted_domain_from_auth(uint16_t validation_level,
+                                 struct info3_text *info3,
+                                 struct info6_text *info6)
+{
+       struct winbindd_domain *domain = NULL;
+       struct dom_sid domain_sid;
+       const char *dns_domainname = NULL;
+       NTSTATUS status;
+       bool ok;
+
+       /*
+        * We got a successfull auth from a domain that might not yet be in our
+        * domain list. If we're a member we trust our DC who authenticated the
+        * user from that domain and add the domain to our list on-the-fly. If
+        * we're a DC we rely on configured trusts and don't add on-the-fly.
+        */
+
+       if (IS_DC) {
+               return true;
+       }
+
+       ok = dom_sid_parse(info3->dom_sid, &domain_sid);
+       if (!ok) {
+               DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
+               return false;
+       }
+
+       if (validation_level == 6) {
+               dns_domainname = &info6->dns_domainname[0];
+       }
+
+       status = add_trusted_domain(info3->logon_dom,
+                                   dns_domainname,
+                                   &domain_sid,
+                                   0,
+                                   NETR_TRUST_FLAG_OUTBOUND,
+                                   0,
+                                   SEC_CHAN_NULL,
+                                   &domain);
+       if (!NT_STATUS_IS_OK(status) &&
+           !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
+       {
+               DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
+                         info3->logon_dom, info3->dom_sid);
+               return false;
+       }
+
+       ok = set_routing_domain(domain, find_default_route_domain());
+       if (!ok) {
+               return false;
+       }
+
+       return true;
+}
+
 bool domain_is_forest_root(const struct winbindd_domain *domain)
 {
        const uint32_t fr_flags =
@@ -346,6 +414,7 @@ static void trustdom_list_done(struct tevent_req *req)
        ptrdiff_t extra_len;
        bool within_forest = false;
        NTSTATUS status;
+       bool ok;
 
        /*
         * Only when we enumerate our primary domain
@@ -478,6 +547,12 @@ static void trustdom_list_done(struct tevent_req *req)
                        return;
                }
 
+               ok = set_routing_domain(domain, find_default_route_domain());
+               if (!ok) {
+                       DBG_ERR("set_routing_domain failed\n");
+                       return;
+               }
+
                p = q + strlen(q) + 1;
        }
 
@@ -520,6 +595,7 @@ static void rescan_forest_root_trusts( void )
         size_t num_trusts = 0;
        int i;
        NTSTATUS status;
+       bool ok;
 
        /* The only transitive trusts supported by Windows 2003 AD are
           (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
@@ -561,6 +637,11 @@ static void rescan_forest_root_trusts( void )
                                        nt_errstr(status));
                                return;
                        }
+                       ok = set_routing_domain(d, find_default_route_domain());
+                       if (!ok) {
+                               DBG_ERR("set_routing_domain failed\n");
+                               return;
+                       }
                }
                if (d == NULL) {
                        continue;
@@ -596,6 +677,7 @@ static void rescan_forest_trusts( void )
         size_t num_trusts = 0;
        int i;
        NTSTATUS status;
+       bool ok;
 
        /* The only transitive trusts supported by Windows 2003 AD are
           (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
@@ -643,6 +725,12 @@ static void rescan_forest_trusts( void )
                                                nt_errstr(status));
                                        return;
                                }
+                               ok = set_routing_domain(
+                                       d, find_default_route_domain());
+                               if (!ok) {
+                                       DBG_ERR("set_routing_domain failed\n");
+                                       return;
+                               }
                        }
 
                        if (d == NULL) {
@@ -749,6 +837,7 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
        struct winbindd_domain *d = NULL;
        uint32_t trust_flags = 0;
        NTSTATUS status;
+       bool ok;
 
        DEBUG(5, ("wb_imsg_new_trusted_domain\n"));
 
@@ -799,6 +888,11 @@ static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
                TALLOC_FREE(frame);
                return;
        }
+       ok = set_routing_domain(d, find_default_route_domain());
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return;
+       }
        TALLOC_FREE(frame);
 }
 
@@ -1105,6 +1199,8 @@ bool init_domain_list(void)
                        struct ForestTrustInfo fti;
                        uint32_t fi;
                        enum ndr_err_code ndr_err;
+                       struct winbindd_domain *routing_domain = NULL;
+                       bool ok;
 
                        if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
                                continue;
@@ -1118,6 +1214,14 @@ bool init_domain_list(void)
                                continue;
                        }
 
+                       routing_domain = find_domain_from_name_noinit(
+                               domains[i]->netbios_name);
+                       if (routing_domain == NULL) {
+                               DBG_ERR("Can't find winbindd domain [%s]\n",
+                                       domains[i]->netbios_name);
+                               return false;
+                       }
+
                        ndr_err = ndr_pull_struct_blob_all(
                                        &domains[i]->trust_forest_trust_info,
                                        talloc_tos(), &fti,
@@ -1171,6 +1275,17 @@ bool init_domain_list(void)
                                                   nt_errstr(status));
                                        return false;
                                }
+                               if (domain == NULL) {
+                                       continue;
+                               }
+                               ok = set_routing_domain(domain, routing_domain);
+                               if (!ok) {
+                                       DBG_ERR("set_routing_domain on [%s] to "
+                                               "[%s] failed\n",
+                                               domain->name,
+                                               routing_domain->name);
+                                       return false;
+                               }
                        }
                }
        } else if (IS_DC) {
@@ -1366,6 +1481,15 @@ struct winbindd_domain *find_our_domain(void)
        return NULL;
 }
 
+struct winbindd_domain *find_default_route_domain(void)
+{
+       if (!IS_DC) {
+               return find_our_domain();
+       }
+       DBG_ERR("Routing logic not yet implemented on a DC");
+       return NULL;
+}
+
 /* Find the appropriate domain to lookup a name or SID */
 
 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)