diff options
author | Gerald Carter <jerry@samba.org> | 2005-11-10 20:28:23 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:05:23 -0500 |
commit | ce0a1fa159baab4c4bdaac601d0f56e29a406945 (patch) | |
tree | 964f0900ccb437f2b574dbfacab2d7627ad0425a /source3/nsswitch | |
parent | 438d0ad451678c42614ab800bceaf490e09c120a (diff) | |
download | samba-ce0a1fa159baab4c4bdaac601d0f56e29a406945.tar.gz samba-ce0a1fa159baab4c4bdaac601d0f56e29a406945.tar.xz samba-ce0a1fa159baab4c4bdaac601d0f56e29a406945.zip |
r11652: Reinstate the netsamlogon_cache in order to work
around failed query_user calls. This fixes
logons to a member of a Samba domain as a user from a
trusted AD domain.
As per comments on samba-technical, I still need to add
(a) cache the PAC info as werll as NTLM net_user_info_3
(b) expire the cache when the SMB session goes away
Both Jeremy and Guenther have signed off on the idea.
(This used to be commit 0c2bb5ba7b92d9210e7fa9f7b70aa67dfe9faaf4)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 38 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 52 |
4 files changed, 100 insertions, 0 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 7f2f3d780e1..60a4e2f6c01 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -1063,6 +1063,8 @@ int main(int argc, char **argv) poptFreeContext(pc); + netsamlogon_cache_init(); /* Non-critical */ + init_domain_list(); init_idmap_child(); diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 993e6d96e8e..83ded01d4ea 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -1073,6 +1073,18 @@ static NTSTATUS query_user(struct winbindd_domain *domain, centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid)); + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("query_user: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + if (!centry) goto do_query; @@ -1128,6 +1140,18 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("query_user: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + if (!centry) goto do_query; @@ -1401,6 +1425,20 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, return 0; } +/* Invalidate the getpwnam and getgroups entries for a winbindd domain */ + +void wcache_invalidate_samlogon(struct winbindd_domain *domain, + NET_USER_INFO_3 *info3) +{ + struct winbind_cache *cache; + + if (!domain) + return; + + cache = get_cache(domain); + netsamlogon_clear_cached_user(cache->tdb, info3); +} + void wcache_invalidate_cache(void) { struct winbindd_domain *domain; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 3571142c584..d398e41468c 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -382,6 +382,9 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); if (NT_STATUS_IS_OK(result)) { + netsamlogon_cache_store(state->mem_ctx, name_user, &info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + /* Check if the user is in the right group */ if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, @@ -664,6 +667,11 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); if (NT_STATUS_IS_OK(result)) { + netsamlogon_cache_store(state->mem_ctx, name_user, &info3); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + + /* Check if the user is in the right group */ + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index b3bed2e0bee..63e24877008 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -329,6 +329,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, SAM_USERINFO_CTR *ctr; fstring sid_string; uint32 user_rid; + NET_USER_INFO_3 *user; struct rpc_pipe_client *cli; DEBUG(3,("rpc: query_user rid=%s\n", @@ -337,6 +338,33 @@ static NTSTATUS query_user(struct winbindd_domain *domain, if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) return NT_STATUS_UNSUCCESSFUL; + /* try netsamlogon cache first */ + + if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + { + + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(user_sid))); + + sid_compose(&user_info->user_sid, &domain->sid, user_rid); + sid_compose(&user_info->group_sid, &domain->sid, + user->group_rid); + + user_info->acct_name = unistr2_tdup(mem_ctx, + &user->uni_user_name); + user_info->full_name = unistr2_tdup(mem_ctx, + &user->uni_full_name); + + user_info->homedir = NULL; + user_info->shell = NULL; + + SAFE_FREE(user); + + return NT_STATUS_OK; + } + + /* no cache; hit the wire */ + result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) return result; @@ -384,6 +412,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, unsigned int i; fstring sid_string; uint32 user_rid; + NET_USER_INFO_3 *user; struct rpc_pipe_client *cli; DEBUG(3,("rpc: lookup_usergroups sid=%s\n", @@ -394,6 +423,29 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, *num_groups = 0; *user_grpsids = NULL; + + /* so lets see if we have a cached user_info_3 */ + + if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + { + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(user_sid))); + + *num_groups = user->num_groups; + + (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups); + for (i=0;i<(*num_groups);i++) { + sid_copy(&((*user_grpsids)[i]), &domain->sid); + sid_append_rid(&((*user_grpsids)[i]), + user->gids[i].g_rid); + } + + SAFE_FREE(user); + + return NT_STATUS_OK; + } + + /* no cache; hit the wire */ result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol); if (!NT_STATUS_IS_OK(result)) |