diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/nsswitch/winbindd.h | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 86 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 41 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_passdb.c | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 62 |
6 files changed, 206 insertions, 0 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 22deaf82c6..cd1d16e344 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -183,6 +183,14 @@ struct winbindd_methods { const DOM_SID *user_sid, uint32 *num_groups, DOM_SID ***user_gids); + /* Lookup all aliases that the sids delivered are member of. This is + * to implement 'domain local groups' correctly */ + NTSTATUS (*lookup_useraliases)(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, DOM_SID **sids, + uint32 *num_aliases, + uint32 **alias_rids); + /* find all members of the group with the specified group_rid */ NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index f77b76cd9a..335e21adcb 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -966,6 +966,7 @@ struct winbindd_methods ads_methods = { msrpc_sid_to_name, query_user, lookup_usergroups, + msrpc_lookup_useraliases, lookup_groupmem, sequence_number, trusted_domains, diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index ba274ec8e7..460ce934cb 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Gerald Carter 2003 + Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify @@ -1202,6 +1203,90 @@ skip_save: return status; } +static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, DOM_SID **sids, + uint32 *num_aliases, uint32 **alias_rids) +{ + struct winbind_cache *cache = get_cache(domain); + struct cache_entry *centry = NULL; + NTSTATUS status; + char *sidlist = talloc_strdup(mem_ctx, ""); + int i; + + if (!cache->tdb) + goto do_query; + + if (num_sids == 0) { + *num_aliases = 0; + *alias_rids = NULL; + return NT_STATUS_OK; + } + + /* We need to cache indexed by the whole list of SIDs, the aliases + * resulting might come from any of the SIDs. */ + + for (i=0; i<num_sids; i++) { + sidlist = talloc_asprintf(mem_ctx, "%s/%s", sidlist, + sid_string_static(sids[i])); + if (sidlist == NULL) + return NT_STATUS_NO_MEMORY; + } + + centry = wcache_fetch(cache, domain, "UA%s", sidlist); + + if (!centry) + goto do_query; + + *num_aliases = centry_uint32(centry); + *alias_rids = NULL; + + (*alias_rids) = TALLOC_ARRAY(mem_ctx, uint32, *num_aliases); + + if (!(*alias_rids)) + return NT_STATUS_NO_MEMORY; + + for (i=0; i<(*num_aliases); i++) + (*alias_rids)[i] = centry_uint32(centry); + + status = centry->status; + + DEBUG(10,("lookup_useraliases: [Cached] - cached info for domain %s " + "status %s\n", domain->name, + get_friendly_nt_error_msg(status))); + + centry_free(centry); + return status; + + do_query: + (*num_aliases) = 0; + (*alias_rids) = NULL; + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info " + "for domain %s\n", domain->name )); + + status = domain->backend->lookup_useraliases(domain, mem_ctx, + num_sids, sids, + num_aliases, alias_rids); + + /* and save it */ + refresh_sequence_number(domain, False); + centry = centry_start(domain, status); + if (!centry) + goto skip_save; + centry_put_uint32(centry, *num_aliases); + for (i=0; i<(*num_aliases); i++) + centry_put_uint32(centry, (*alias_rids)[i]); + centry_end(centry, "UA%s", sidlist); + centry_free(centry); + + skip_save: + return status; +} + static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -1387,6 +1472,7 @@ struct winbindd_methods cache_methods = { sid_to_name, query_user, lookup_usergroups, + lookup_useraliases, lookup_groupmem, sequence_number, trusted_domains, diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index d64c2e4a19..502a4b8584 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -6,6 +6,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jeremy Allison 2001. Copyright (C) Gerald (Jerry) Carter 2003. + Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1234,6 +1235,46 @@ enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state) goto no_groups; } + domain = find_our_domain(); + + if (domain == NULL) { + DEBUG(0, ("Could not find our domain\n")); + goto done; + } + + /* Note that I do not check for AD or its mode. XP in a real NT4 + * domain also asks for this info. -- vl */ + + if (!IS_DC) { + uint32_t *alias_rids = NULL; + int num_aliases; + + /* We need to include the user SID to expand */ + user_grpsids = TALLOC_REALLOC_ARRAY(mem_ctx, user_grpsids, + DOM_SID *, num_groups+1); + user_grpsids[num_groups] = &user_sid; + + status = domain->methods->lookup_useraliases(domain, mem_ctx, + num_groups, + user_grpsids+1, + &num_aliases, + &alias_rids); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not expand alias sids: %s\n", + nt_errstr(status))); + goto done; + } + + for (i=0; i<num_aliases; i++) { + DOM_SID sid; + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, alias_rids[i]); + add_sid_to_parray_unique(mem_ctx, &sid, &user_grpsids, + &num_groups); + } + } + if (lp_winbind_nested_groups()) { int k; /* num_groups is changed during the loop, that's why we have diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c index a208186b5f..4dcc018c64 100644 --- a/source3/nsswitch/winbindd_passdb.c +++ b/source3/nsswitch/winbindd_passdb.c @@ -292,6 +292,13 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_NO_SUCH_USER; } +static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, const DOM_SID **sids, + uint32 *num_aliases, DOM_SID ***aliases) +{ + return NT_STATUS_NO_SUCH_USER; +} /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, @@ -384,6 +391,7 @@ struct winbindd_methods passdb_methods = { sid_to_name, query_user, lookup_usergroups, + lookup_useraliases, lookup_groupmem, sequence_number, trusted_domains, diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index e6edb70f07..10d6e4f4fa 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -5,6 +5,7 @@ Copyright (C) Tim Potter 2000-2001,2003 Copyright (C) Andrew Tridgell 2001 + Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -561,6 +562,66 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return result; } +NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32 num_sids, DOM_SID **sids, + uint32 *num_aliases, uint32 **alias_rids) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + CLI_POLICY_HND *hnd; + BOOL got_dom_pol = False; + POLICY_HND dom_pol; + DOM_SID2 *sid2; + int i, retry; + + *num_aliases = 0; + *alias_rids = NULL; + + retry = 0; + do { + /* Get sam handle; if we fail here there is no hope */ + + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, + &hnd))) + goto done; + + /* Get domain handle */ + + result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &domain->sid, &dom_pol); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && + hnd && hnd->cli && hnd->cli->fd == -1); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + got_dom_pol = True; + + sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids); + + if (sid2 == NULL) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0; i<num_sids; i++) { + sid_copy(&sid2[i].sid, sids[i]); + sid2[i].num_auths = sid2[i].sid.num_auths; + } + + result = cli_samr_query_useraliases(hnd->cli, mem_ctx, &dom_pol, + num_sids, sid2, + num_aliases, alias_rids); + + done: + + if (got_dom_pol) + cli_samr_close(hnd->cli, mem_ctx, &dom_pol); + + return result; +} + /* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, @@ -980,6 +1041,7 @@ struct winbindd_methods msrpc_methods = { msrpc_sid_to_name, query_user, lookup_usergroups, + msrpc_lookup_useraliases, lookup_groupmem, sequence_number, trusted_domains, |