s3: List trusted domains from wcache when domain is offline.
authorBo Yang <boyang@samba.org>
Wed, 6 Jan 2010 11:13:59 +0000 (19:13 +0800)
committerBo Yang <boyang@samba.org>
Wed, 6 Jan 2010 11:19:52 +0000 (19:19 +0800)
Signed-off-by: Bo Yang <boyang@samba.org>
source3/winbindd/winbindd_cache.c

index 8e1eb7ac3436a4944384b2fc10329d74fc5aee07..68972dd18d4ae5790e849f50fb61702f472dba7c 100644 (file)
@@ -1380,6 +1380,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i, retry;
+       bool old_status = domain->online;
 
        if (!cache->tdb)
                goto do_query;
@@ -1451,7 +1452,7 @@ do_query:
                }
                if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                    NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-                       if (!domain->internal) {
+                       if (!domain->internal && old_status) {
                                set_domain_offline(domain);
                        }
                        /* store partial response. */
@@ -1466,7 +1467,7 @@ do_query:
                         * domain is offline now, and there is no user entries,
                         * try to fetch from cache again.
                         */
-                       if (cache->tdb && !domain->online && !domain->internal) {
+                       if (cache->tdb && !domain->online && !domain->internal && old_status) {
                                centry = wcache_fetch(cache, domain, "UL/%s", domain->name);
                                /* partial response... */
                                if (!centry) {
@@ -1530,7 +1531,9 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -1579,12 +1582,13 @@ do_query:
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
            NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (cache->tdb &&
                        !domain->online &&
-                       !domain->internal) {
+                       !domain->internal &&
+                       old_status) {
                        centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name);
                        if (centry) {
                                goto do_fetch_cache;
@@ -1622,7 +1626,9 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
        struct cache_entry *centry = NULL;
        NTSTATUS status;
        unsigned int i;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -1681,12 +1687,13 @@ do_query:
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (cache->tdb &&
                        !domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name);
                        if (centry) {
                                goto do_fetch_cache;
@@ -1763,6 +1770,9 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
                            enum lsa_SidType *type)
 {
        NTSTATUS status;
+       bool old_status;
+
+       old_status = domain->online;
 
        status = wcache_name_to_sid(domain, domain_name, name, sid, type);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -1790,11 +1800,12 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_name_to_sid(domain, domain_name, name, sid, type);
                        return cache_status;
@@ -1870,7 +1881,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
                            enum lsa_SidType *type)
 {
        NTSTATUS status;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_sid_to_name(domain, sid, mem_ctx, domain_name, name,
                                    type);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -1898,11 +1911,12 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_sid_to_name(domain, sid, mem_ctx,
                                                        domain_name, name, type);
@@ -1936,7 +1950,9 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        bool have_mapped;
        bool have_unmapped;
+       bool old_status;
 
+       old_status = domain->online;
        *domain_name = NULL;
        *names = NULL;
        *types = NULL;
@@ -2023,12 +2039,13 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (cache->tdb &&
                        !domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        have_mapped = have_unmapped = false;
 
                        for (i=0; i<num_rids; i++) {
@@ -2209,7 +2226,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
                           struct wbint_userinfo *info)
 {
        NTSTATUS status;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_query_user(domain, mem_ctx, user_sid, info);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
                return status;
@@ -2229,11 +2248,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_query_user(domain, mem_ctx, user_sid, info);
                        return cache_status;
@@ -2318,7 +2338,9 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        NTSTATUS status;
        unsigned int i;
        fstring sid_string;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
                                          num_groups, user_gids);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -2340,11 +2362,12 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
                                                          num_groups, user_gids);
@@ -2466,7 +2489,9 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
        NTSTATUS status;
        char *sidlist;
        int i;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_lookup_useraliases(domain, mem_ctx, num_sids, sids,
                                           num_aliases, alias_rids);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -2493,11 +2518,12 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_lookup_useraliases(domain, mem_ctx, num_sids,
                                                                 sids, num_aliases, alias_rids);
@@ -2599,7 +2625,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        NTSTATUS status;
        unsigned int i;
        fstring sid_string;
+       bool old_status;
 
+       old_status = domain->online;
        status = wcache_lookup_groupmem(domain, mem_ctx, group_sid, num_names,
                                        sid_mem, names, name_types);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
@@ -2625,11 +2653,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (!domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        NTSTATUS cache_status;
                        cache_status = wcache_lookup_groupmem(domain, mem_ctx, group_sid,
                                                              num_names, sid_mem, names,
@@ -2676,7 +2705,71 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                struct netr_DomainTrustList *trusts)
 {
        NTSTATUS status;
+       struct winbind_cache *cache;
+       struct winbindd_tdc_domain *dom_list = NULL;
+       size_t num_domains = 0;
+       bool retval = false;
+       int i;
+       bool old_status;
+
+       old_status = domain->online;
+       trusts->count = 0;
+       trusts->array = NULL;
+       if (domain->online) {
+               goto do_query;
+       }
 
+       cache = get_cache(domain);
+       if (!cache || !cache->tdb) {
+               goto do_query;
+       }
+
+       retval = wcache_tdc_fetch_list(&dom_list, &num_domains);
+       if (!retval || !num_domains || !dom_list) {
+               TALLOC_FREE(dom_list);
+               goto do_query;
+       }
+
+do_fetch_cache:
+       trusts->array = TALLOC_ZERO_ARRAY(mem_ctx, struct netr_DomainTrust, num_domains);
+       if (!trusts->array) {
+               TALLOC_FREE(dom_list);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i = 0; i < num_domains; i++) {
+               struct netr_DomainTrust *trust;
+               struct dom_sid *sid;
+               struct winbindd_domain *dom;
+
+               dom = find_domain_from_name_noinit(dom_list[i].domain_name);
+               if (dom && dom->internal) {
+                       continue;
+               }
+
+               trust = &trusts->array[trusts->count];
+               trust->netbios_name = talloc_strdup(trusts->array, dom_list[i].domain_name);
+               trust->dns_name = talloc_strdup(trusts->array, dom_list[i].dns_name);
+               sid = talloc(trusts->array, struct dom_sid);
+               if (!trust->netbios_name || !trust->dns_name ||
+                       !sid) {
+                       TALLOC_FREE(dom_list);
+                       TALLOC_FREE(trusts->array);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               trust->trust_flags = dom_list[i].trust_flags;
+               trust->trust_attributes = dom_list[i].trust_attribs;
+               trust->trust_type = dom_list[i].trust_type;
+               sid_copy(sid, &dom_list[i].sid);
+               trust->sid = sid;
+               trusts->count++;
+       }
+
+       TALLOC_FREE(dom_list);
+       return NT_STATUS_OK;
+
+do_query:
        /* Return status value returned by seq number check */
 
        if (!NT_STATUS_IS_OK(domain->last_status))
@@ -2687,6 +2780,22 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 
        status = domain->backend->trusted_domains(domain, mem_ctx, trusts);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+               NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+               if (!domain->internal && old_status) {
+                       set_domain_offline(domain);
+               }
+               if (!domain->internal &&
+                       !domain->online &&
+                       old_status) {
+                       retval = wcache_tdc_fetch_list(&dom_list, &num_domains);
+                       if (retval && num_domains && dom_list) {
+                               TALLOC_FREE(trusts->array);
+                               trusts->count = 0;
+                               goto do_fetch_cache;
+                       }
+               }
+       }
        /* no trusts gives NT_STATUS_NO_MORE_ENTRIES resetting to NT_STATUS_OK
         * so that the generic centry handling still applies correctly -
         * Guenther*/
@@ -2705,7 +2814,9 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
        struct winbind_cache *cache = get_cache(domain);
        struct cache_entry *centry = NULL;
        NTSTATUS status;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -2742,12 +2853,13 @@ do_query:
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (cache->tdb &&
                        !domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
                        if (centry) {
                                goto do_fetch_cache;
@@ -2772,7 +2884,9 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
        struct winbind_cache *cache = get_cache(domain);
        struct cache_entry *centry = NULL;
        NTSTATUS status;
+       bool old_status;
 
+       old_status = domain->online;
        if (!cache->tdb)
                goto do_query;
 
@@ -2811,12 +2925,13 @@ do_query:
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
                NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
-               if (!domain->internal) {
+               if (!domain->internal && old_status) {
                        set_domain_offline(domain);
                }
                if (cache->tdb &&
                        !domain->internal &&
-                       !domain->online) {
+                       !domain->online &&
+                       old_status) {
                        centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
                        if (centry) {
                                goto do_fetch_cache;