From d06fb8e02706559e91c6d185427409bb093bb896 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 6 Jan 2010 19:13:59 +0800 Subject: s3: List trusted domains from wcache when domain is offline. Signed-off-by: Bo Yang --- source3/winbindd/winbindd_cache.c | 163 ++++++++++++++++++++++++++++++++------ 1 file changed, 139 insertions(+), 24 deletions(-) (limited to 'source3/winbindd/winbindd_cache.c') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 8e1eb7ac34..68972dd18d 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -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; ionline; 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; -- cgit