merge of the netsamlogon caching code from APPLIANCE_HEAD
authorGerald Carter <jerry@samba.org>
Sat, 21 Jun 2003 04:05:01 +0000 (04:05 +0000)
committerGerald Carter <jerry@samba.org>
Sat, 21 Jun 2003 04:05:01 +0000 (04:05 +0000)
This replaces the universal group caching code (was originally
based on that code).  Only applies to the the RPC code.

One comment: domain local groups don't show up in 'getent group'
that's easy to fix.

Code has been tested against 2k domain but doesn't change anything
with respect to NT4 domains.

netsamlogon caching works pretty much like the universal group
caching code did but has had much more testing and puts winbind
mostly back in sync between branches.

14 files changed:
source/Makefile.in
source/auth/auth_domain.c
source/lib/username.c
source/libsmb/samlogon_cache.c [new file with mode: 0644]
source/nsswitch/wb_client.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd.h
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_cm.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_pam.c
source/nsswitch/winbindd_rpc.c
source/script/mkproto.awk
source/smbd/server.c

index add45aec7434d474687e924f09ab8d05839e70a2..02b8cd112f2581ab64f304f1921657640997f8d2 100644 (file)
@@ -308,7 +308,7 @@ VFS_NETATALK_OBJ = modules/vfs_netatalk.o
 
 PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
 
-UNIGRP_OBJ = libsmb/netlogon_unigrp.o 
+UNIGRP_OBJ = libsmb/samlogon_cache.o
 
 AUTH_BUILTIN_OBJ = auth/auth_builtin.o
 AUTH_DOMAIN_OBJ = auth/auth_domain.o
@@ -594,7 +594,7 @@ WINBINDD_OBJ1 = \
                nsswitch/winbindd_rpc.o \
                nsswitch/winbindd_ads.o \
                nsswitch/winbindd_dual.o \
-               nsswitch/winbindd_passdb.o
+               nsswitch/winbindd_passdb.o 
 
 WINBINDD_OBJ = \
                $(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
index f1575e43b0a093f3e036f1fa368bb4c7b21a316a..66684cc9404f63dc251941a637953e6ba381aace 100644 (file)
@@ -360,7 +360,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
        } else {
                nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, 
                                                   user_info->smb_name.str, domain, server_info, &info3);
-               uni_group_cache_store_netlogon(mem_ctx, &info3);
+               netsamlogon_cache_store( mem_ctx, &info3 );
        }
 
 #if 0
index d8f4ff80edb7a3b8f035952b9a8c28254ea85c07..8130b93c3f07a07abef9f7d4df4b0a100098e270 100644 (file)
@@ -325,11 +325,12 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
   
 static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered)
 {
-       int num_groups;
        int i;
-       gid_t *groups = NULL;
        gid_t gid, gid_low, gid_high;
        BOOL ret = False;
+       static gid_t *groups = NULL;
+       static int num_groups = 0;
+       static fstring last_user = "";
  
        *winbind_answered = False;
  
@@ -349,27 +350,44 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL
                goto err;
        }
  
-       /*
-        * Get the gid's that this user belongs to.
-        */
-       if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1)
-               return False;
+       /* try to user the last user we looked up */
+       /* otherwise fall back to lookups */
+       
+       if ( !strequal( last_user, user ) || !groups )
+       {
+               /* clear any cached information */
+               
+               SAFE_FREE(groups);
+               fstrcpy( last_user, "" );
+
+               /*
+                * Get the gid's that this user belongs to.
+                */
  
-       if (num_groups == 0) {
-               *winbind_answered = True;
-               return False;
-       }
+               if ((num_groups = winbind_getgroups(user, &groups)) == -1)
+                       return False;
+                       
+               if ( num_groups == -1 )
+                       return False;
  
-       if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) {
-               DEBUG(0,("user_in_winbind_group_list: malloc fail.\n"));
-               goto err;
-       }
+               if ( num_groups == 0 ) {
+                       *winbind_answered = True;
+                       return False;
+               }
+               
+               /* save the last username */
+               
+               fstrcpy( last_user, user );
+               
+       }
+       else 
+               DEBUG(10,("user_in_winbind_group_list: using cached user groups for [%s]\n", user));
  
-       if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) {
-               DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \
-failed with error %s\n", strerror(errno) ));
-               goto err;
+       if ( DEBUGLEVEL >= 10 ) {
+               DEBUG(10,("user_in_winbind_group_list: using groups -- "));
+               for ( i=0; i<num_groups; i++ )
+                       DEBUGADD(10,("%d ", groups[i]));
+               DEBUGADD(10,("\n"));    
        }
  
        /*
@@ -571,10 +589,15 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr
                                fstrcpy(domain, *list);
                                domain[PTR_DIFF(p, *list)] = 0;
 
-                               /* Check to see if name is a Windows group */
-                               if (winbind_lookup_name(domain, groupname, &g_sid, &name_type) && name_type == SID_NAME_DOM_GRP) {
+                       /* Check to see if name is a Windows group;  Win2k native mode DCs
+                          will return domain local groups; while NT4 or mixed mode 2k DCs
+                          will not */
+                       
+                       if ( winbind_lookup_name(NULL, *list, &g_sid, &name_type) 
+                               && ( name_type==SID_NAME_DOM_GRP || name_type==SID_NAME_ALIAS ) )
+                       {
                                        
-                               /* Check if user name is in the Windows group */
+                                       /* Check if user name is in the Windows group */
                                        ret = user_in_winbind_group_list(user, *list, &winbind_answered);
                                        
                                        if (winbind_answered && ret == True) {
diff --git a/source/libsmb/samlogon_cache.c b/source/libsmb/samlogon_cache.c
new file mode 100644 (file)
index 0000000..7863ad7
--- /dev/null
@@ -0,0 +1,238 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Net_sam_logon info3 helpers
+   Copyright (C) Alexander Bokovoy              2002.
+   Copyright (C) Andrew Bartlett                2002.
+   Copyright (C) Gerald Carter                 2003.
+   Copyright (C) Tim Potter                    2003.
+   
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#define NETSAMLOGON_TDB        "netsamlogon_cache.tdb"
+
+static TDB_CONTEXT *netsamlogon_tdb = NULL;
+
+/***********************************************************************
+ open the tdb
+ ***********************************************************************/
+BOOL netsamlogon_cache_init(void)
+{
+       if (!netsamlogon_tdb) {
+               netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0,
+                                                  TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
+       }
+
+       return (netsamlogon_tdb != NULL);
+}
+
+
+/***********************************************************************
+ Shutdown samlogon_cache database
+***********************************************************************/
+
+BOOL netsamlogon_cache_shutdown(void)
+{
+       if(netsamlogon_tdb)
+               return (tdb_close(netsamlogon_tdb) == 0);
+               
+       return True;
+}
+
+/***********************************************************************
+ Clear cache getpwnam and getgroups entries from the winbindd cache
+***********************************************************************/
+void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
+{
+       fstring domain;
+       TDB_DATA key;
+       BOOL got_tdb = False;
+
+       /* We may need to call this function from smbd which will not have
+           winbindd_cache.tdb open.  Open the tdb if a NULL is passed. */
+
+       if (!tdb) {
+               tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
+                                  TDB_DEFAULT, O_RDWR, 0600);
+               if (!tdb) {
+                       DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
+                       return;
+               }
+               got_tdb = True;
+       }
+
+       unistr2_to_ascii(domain, &user->uni_logon_dom, sizeof(domain) - 1);
+
+       /* Clear U/DOMAIN/RID cache entry */
+
+       asprintf(&key.dptr, "U/%s/%d", domain, user->user_rid);
+       key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */
+
+       DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr));
+
+       tdb_delete(tdb, key);
+
+       SAFE_FREE(key.dptr);
+
+       /* Clear UG/DOMAIN/RID cache entry */
+
+       asprintf(&key.dptr, "UG/%s/%d", domain, user->user_rid);
+       key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */
+
+       DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr));
+
+       tdb_delete(tdb, key);
+
+       SAFE_FREE(key.dptr);
+
+       if (got_tdb)
+               tdb_close(tdb);
+}
+
+/***********************************************************************
+ Store a NET_USER_INFO_3 structure in a tdb for later user 
+***********************************************************************/
+
+BOOL netsamlogon_cache_store(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
+{
+       TDB_DATA        data;
+        fstring        keystr;
+       prs_struct      ps;
+       BOOL            result = False;
+       DOM_SID         user_sid;
+       time_t          t = time(NULL);
+       
+
+       if (!netsamlogon_cache_init()) {
+               DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
+               return False;
+       }
+
+       sid_copy( &user_sid, &user->dom_sid.sid );
+       sid_append_rid( &user_sid, user->user_rid );
+
+       /* Prepare key as DOMAIN-SID/USER-RID string */
+       slprintf(keystr, sizeof(keystr), "%s", sid_string_static(&user_sid));
+
+       DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
+               
+       /* Prepare data */
+       
+       prs_init( &ps,MAX_PDU_FRAG_LEN , mem_ctx, MARSHALL);
+       
+       if ( !prs_uint32( "timestamp", &ps, 0, (uint32*)&t ) )
+               return False;
+       
+       if ( net_io_user_info3("", user, &ps, 0, 3) ) 
+       {
+               data.dsize = prs_offset( &ps );
+               data.dptr = prs_data_p( &ps );
+
+               if (tdb_store_by_string(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1)
+                       result = True;
+               
+               prs_mem_free( &ps );
+       }
+               
+       return result;
+}
+
+/***********************************************************************
+ Retrieves a NET_USER_INFO_3 structure from a tdb.  Caller must 
+ free the user_info struct (malloc()'d memory)
+***********************************************************************/
+
+NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
+{
+       NET_USER_INFO_3 *user = NULL;
+       TDB_DATA        data, key;
+       prs_struct      ps;
+        fstring        keystr;
+       uint32          t;
+       
+       if (!netsamlogon_cache_init()) {
+               DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
+               return False;
+       }
+
+       /* Prepare key as DOMAIN-SID/USER-RID string */
+       slprintf(keystr, sizeof(keystr), "%s", sid_string_static(user_sid));
+       DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
+       key.dptr = keystr;
+       key.dsize = strlen(keystr)+1;
+       data = tdb_fetch( netsamlogon_tdb, key );
+       
+       if ( data.dptr ) {
+               
+               if ( (user = (NET_USER_INFO_3*)malloc(sizeof(NET_USER_INFO_3))) == NULL )
+                       return NULL;
+                       
+               prs_init( &ps, 0, mem_ctx, UNMARSHALL );
+               prs_give_memory( &ps, data.dptr, data.dsize, True );
+               
+               if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) {
+                       prs_mem_free( &ps );
+                       return False;
+               }
+               
+               if ( !net_io_user_info3("", user, &ps, 0, 3) ) {
+                       SAFE_FREE( user );
+               }
+                       
+               prs_mem_free( &ps );
+
+#if 0  /* The netsamlogon cache needs to hang around.  Something about 
+          this feels wrong, but it is the only way we can get all of the
+          groups.  The old universal groups cache didn't expire either.
+          --jerry */
+       {
+               time_t          now = time(NULL);
+               uint32          time_diff;
+          
+               /* is the entry expired? */
+               time_diff = now - t;
+               
+               if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
+                       DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
+                       tdb_delete( netsamlogon_tdb, key );
+                       SAFE_FREE( user );
+               }
+#endif
+       }
+       
+       return user;
+}
+
+BOOL netsamlogon_cache_have(DOM_SID *user_sid)
+{
+       TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
+       NET_USER_INFO_3 *user = NULL;
+       BOOL result;
+
+       if (!mem_ctx)
+               return False;
+
+       user = netsamlogon_cache_get(mem_ctx, user_sid);
+
+       result = (user != NULL);
+
+       talloc_destroy(mem_ctx);
+       SAFE_FREE(user);
+
+       return result;
+}
index 996d15180dc057640897636799b2f72a54e79653..b1765a8bd7d2852c410056aab947af94fa35646a 100644 (file)
@@ -269,11 +269,8 @@ static int wb_getgroups(const char *user, gid_t **groups)
    time consuming.  If size is zero, list is not modified and the total
    number of groups for the user is returned. */
 
-int winbind_getgroups(const char *user, int size, gid_t *list)
+int winbind_getgroups(const char *user, gid_t **list)
 {
-       gid_t *groups = NULL;
-       int result, i;
-
        /*
         * Don't do the lookup if the name has no separator _and_ we are not in
         * 'winbind use default domain' mode.
@@ -284,24 +281,5 @@ int winbind_getgroups(const char *user, int size, gid_t *list)
 
        /* Fetch list of groups */
 
-       result = wb_getgroups(user, &groups);
-
-       if (size == 0)
-               goto done;
-
-       if (result > size) {
-               result = -1;
-               errno = EINVAL; /* This is what getgroups() does */
-               goto done;
-       }
-
-       /* Copy list of groups across */
-
-       for (i = 0; i < result; i++) {
-               list[i] = groups[i];
-       }
-
- done:
-       SAFE_FREE(groups);
-       return result;
+       return wb_getgroups(user, list);
 }
index c7e45e54293dc469521efd8f92aee5d7ac9d3438..d777fe37dd7ee6a110446ea4dca6b510132e7459 100644 (file)
@@ -135,8 +135,17 @@ static void print_winbindd_status(void)
 
 static void flush_caches(void)
 {
+#if 0
        /* Clear cached user and group enumation info */        
-       wcache_flush_cache();
+       if (!opt_dual_daemon) /* Until we have coherent cache flush. */
+               wcache_flush_cache();
+#endif
+
+       /* We need to invalidate cached user list entries on a SIGHUP 
+           otherwise cached access denied errors due to restrict anonymous
+           hang around until the sequence number changes. */
+
+       wcache_invalidate_cache();
 }
 
 /* Handle the signal by unlinking socket and exiting */
@@ -886,12 +895,13 @@ int main(int argc, char **argv)
        }
        poptFreeContext(pc);
 
+       netsamlogon_cache_init(); /* Non-critical */
+       
        /* Loop waiting for requests */
 
        process_loop();
 
        trustdom_cache_shutdown();
-       uni_group_cache_shutdown();
 
        return 0;
 }
index 8e1c7edc7fb2d3f0ed55cbd343704e016d4cdd27..2acb89b24bb2e18196ec2813b917478f1a50cf83 100644 (file)
@@ -112,6 +112,7 @@ struct winbindd_domain {
 
        time_t last_seq_check;
        uint32 sequence_number;
+       NTSTATUS last_status;
 
        /* Linked list info */
 
index e0860cd695bb76e6add6b2b1a7d7e92c268795e2..5464e765d18d7c159ea4bb0d32f86cbb7812b0cd 100644 (file)
@@ -4,6 +4,8 @@
    Winbind cache backend functions
 
    Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Gerald Carter   2003
+   
    
    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
@@ -342,6 +344,7 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
                domain->sequence_number = DOM_SEQUENCE_NONE;
        }
        
+       domain->last_status = status;
        domain->last_seq_check = time(NULL);
        
        /* save the new sequence number ni the cache */
@@ -671,9 +674,10 @@ do_query:
        *num_entries = 0;
        *info = NULL;
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
 
        /* Put the query_user_list() in a retry loop.  There appears to be
         * some bug either with Windows 2000 or Samba's handling of large
@@ -697,7 +701,8 @@ do_query:
                                winbindd_cm_flush();
                        }
 
-       } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && (retry++ < 5));
+       } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && 
+                (retry++ < 5));
 
        /* and save it */
        refresh_sequence_number(domain, False);
@@ -775,9 +780,10 @@ do_query:
        *num_entries = 0;
        *info = NULL;
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
 
        DEBUG(10,("enum_dom_groups: [Cached] - doing backend query for list for domain %s\n",
                domain->name ));
@@ -857,9 +863,10 @@ do_query:
        *num_entries = 0;
        *info = NULL;
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
 
        DEBUG(10,("enum_local_groups: [Cached] - doing backend query for list for domain %s\n",
                domain->name ));
@@ -924,9 +931,16 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 do_query:
        ZERO_STRUCTP(sid);
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* If the seq number check indicated that there is a problem
+        * with this DC, then return that status... except for
+        * access_denied.  This is special because the dc may be in
+        * "restrict anonymous = 1" mode, in which case it will deny
+        * most unauthenticated operations, but *will* allow the LSA
+        * name-to-sid that we try as a fallback. */
+
+       if (!(NT_STATUS_IS_OK(domain->last_status)
+             || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED)))
+               return domain->last_status;
 
        DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n",
                domain->name ));
@@ -980,6 +994,17 @@ do_query:
                return NT_STATUS_SERVER_DISABLED;
        }
 
+       /* If the seq number check indicated that there is a problem
+        * with this DC, then return that status... except for
+        * access_denied.  This is special because the dc may be in
+        * "restrict anonymous = 1" mode, in which case it will deny
+        * most unauthenticated operations, but *will* allow the LSA
+        * sid-to-name that we try as a fallback. */
+
+       if (!(NT_STATUS_IS_OK(domain->last_status)
+             || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED)))
+               return domain->last_status;
+
        DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n",
                domain->name ));
 
@@ -1003,12 +1028,24 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        struct winbind_cache *cache = get_cache(domain);
        struct cache_entry *centry = NULL;
        NTSTATUS status;
-       fstring sid_string;
 
        if (!cache->tdb)
                goto do_query;
 
-       centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid));
+       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;
 
@@ -1027,9 +1064,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 do_query:
        ZERO_STRUCTP(info);
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
        
        DEBUG(10,("sid_to_name: [Cached] - doing backend query for info for domain %s\n",
                domain->name ));
@@ -1060,6 +1098,19 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                goto do_query;
 
        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;
 
@@ -1088,9 +1139,10 @@ do_query:
        (*num_groups) = 0;
        (*user_gids) = NULL;
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       /* Return status value returned by seq number check */
+
+       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 ));
@@ -1167,10 +1219,10 @@ do_query:
        (*names) = NULL;
        (*name_types) = NULL;
        
+       /* Return status value returned by seq number check */
 
-       if (wcache_server_down(domain)) {
-               return NT_STATUS_SERVER_DISABLED;
-       }
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
 
        DEBUG(10,("lookup_groupmem: [Cached] - doing backend query for info for domain %s\n",
                domain->name ));
@@ -1248,6 +1300,46 @@ static NTSTATUS alternate_name(struct winbindd_domain *domain)
        return domain->backend->alternate_name(domain);
 }
 
+/* Invalidate cached user and group lists coherently */
+
+static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
+                      void *state)
+{
+       if (strncmp(kbuf.dptr, "UL/", 3) == 0 ||
+           strncmp(kbuf.dptr, "GL/", 3) == 0)
+               tdb_delete(the_tdb, kbuf);
+
+       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;
+
+       for (domain = domain_list(); domain; domain = domain->next) {
+               struct winbind_cache *cache = get_cache(domain);
+
+               DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
+                          "entries for %s\n", domain->name));
+               if (cache)
+                       tdb_traverse(cache->tdb, traverse_fn, NULL);
+       }
+}
+
 /* the ADS backend methods are exposed via this structure */
 struct winbindd_methods cache_methods = {
        True,
index 0ba9ab8266504b234c9e76fd732a19ebf6261319..d2d99a4203108adbe27c49fdf4c251b119c6a303 100644 (file)
@@ -450,8 +450,14 @@ BOOL cm_check_for_native_mode_win2k( const char *domain )
                ret = True;
 
 done:
+
+#if 0
+       /*
+        * I don't think we need to shutdown here ? JRA.
+        */
        if ( conn.cli )
                cli_shutdown( conn.cli );
+#endif
        
        return ret;
 }
@@ -460,7 +466,7 @@ done:
 
 /* Return a LSA policy handle on a domain */
 
-CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
+NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd)
 {
        struct winbindd_cm_conn *conn;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -470,13 +476,16 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
        /* Look for existing connections */
 
        if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
-               return NULL;
+               return result;
 
        /* This *shitty* code needs scrapping ! JRA */
+       
        if (policy_handle_is_valid(&conn->pol)) {
                hnd.pol = conn->pol;
                hnd.cli = conn->cli;
-               return &hnd;
+               *return_hnd = &hnd;
+
+               return NT_STATUS_OK;
        }
        
        result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 
@@ -486,7 +495,7 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
                /* Hit the cache code again.  This cleans out the old connection and gets a new one */
                if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
                        if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
-                               return NULL;
+                               return result;
 
                        result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 
                                                     des_access, &conn->pol);
@@ -496,19 +505,21 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain)
                        cli_shutdown(conn->cli);
                        DLIST_REMOVE(cm_conns, conn);
                        SAFE_FREE(conn);
-                       return NULL;
+                       return result;
                }
        }       
 
        hnd.pol = conn->pol;
        hnd.cli = conn->cli;
 
-       return &hnd;
+       *return_hnd = &hnd;
+
+       return NT_STATUS_OK;
 }
 
 /* Return a SAM policy handle on a domain */
 
-CLI_POLICY_HND *cm_get_sam_handle(char *domain)
+NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
 { 
        struct winbindd_cm_conn *conn;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -518,39 +529,49 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain)
        /* Look for existing connections */
 
        if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
-               return NULL;
+               return result;
        
        /* This *shitty* code needs scrapping ! JRA */
+       
        if (policy_handle_is_valid(&conn->pol)) {
                hnd.pol = conn->pol;
                hnd.cli = conn->cli;
-               return &hnd;
+               
+               *return_hnd = &hnd;
+
+               return NT_STATUS_OK;
        }
+       
        result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
                                  des_access, &conn->pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                /* Hit the cache code again.  This cleans out the old connection and gets a new one */
                if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
+               
                        if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
-                               return NULL;
+                               return result;
 
                        result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
                                                  des_access, &conn->pol);
                }
 
                if (!NT_STATUS_IS_OK(result)) {
+               
                        cli_shutdown(conn->cli);
                        DLIST_REMOVE(cm_conns, conn);
                        SAFE_FREE(conn);
-                       return NULL;
+                       
+                       return result;
                }
        }       
 
        hnd.pol = conn->pol;
        hnd.cli = conn->cli;
 
-       return &hnd;
+       *return_hnd = &hnd;
+
+       return NT_STATUS_OK;
 }
 
 /* Get a handle on a netlogon pipe.  This is a bit of a hack to re-use the
index e643d933db8ae2325714516ec0e4f00db5c39fdc..bd9a50b3e0cd6ed09efd4c56f8478ca5b13cf754 100644 (file)
@@ -75,7 +75,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
 
        *num_gr_mem = 0;
        
-       if (group_name_type != SID_NAME_DOM_GRP) {
+       if ((group_name_type!=SID_NAME_DOM_GRP) && (group_name_type!=SID_NAME_ALIAS)) {
                DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", 
                          sid_to_string(sid_string, group_sid), domain->name, 
                          group_name_type));
@@ -744,7 +744,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
                ZERO_STRUCT(groups);
 
                /* Get list of sam groups */
-               ZERO_STRUCT(groups);
+               
                fstrcpy(groups.domain_name, domain->name);
 
                get_sam_group_entries(&groups);
@@ -800,21 +800,26 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
 }
 
 /* Get user supplementary groups.  This is much quicker than trying to
-   invert the groups database. */
+   invert the groups database.  We merge the groups from the gids and
+   other_sids info3 fields as trusted domain, universal group
+   memberships, and nested groups (win2k native mode only) are not
+   returned by the getgroups RPC call but are present in the info3. */
 
 enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
 {
        fstring name_domain, name_user;
-       DOM_SID user_sid;
+       DOM_SID user_sid, group_sid;
        enum SID_NAME_USE name_type;
-       uint32 num_groups, num_gids;
+       uint32 num_groups = 0;
+       uint32 num_gids = 0;
        NTSTATUS status;
-       DOM_SID **user_gids;
+       DOM_SID **user_grpsids;
        struct winbindd_domain *domain;
        enum winbindd_result result = WINBINDD_ERROR;
        gid_t *gid_list;
        unsigned int i;
        TALLOC_CTX *mem_ctx;
+       NET_USER_INFO_3 *info3 = NULL;
        
        /* Ensure null termination */
        state->request.data.username[sizeof(state->request.data.username)-1]='\0';
@@ -854,33 +859,109 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                goto done;
        }
 
-       status = domain->methods->lookup_usergroups(domain, mem_ctx, 
-                                                   &user_sid, &num_groups, 
-                                                   &user_gids);
-       if (!NT_STATUS_IS_OK(status)) goto done;
+       /* Treat the info3 cache as authoritative as the
+          lookup_usergroups() function may return cached data. */
 
-       /* Copy data back to client */
+       if ((info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) {
 
-       num_gids = 0;
-       gid_list = malloc(sizeof(gid_t) * num_groups);
+               DEBUG(10, ("winbindd_getgroups: info3 has %d groups, %d other sids\n",
+                          info3->num_groups2, info3->num_other_sids));
 
-       if (state->response.extra_data)
-               goto done;
+               num_groups = info3->num_other_sids + info3->num_groups2;
+               gid_list = calloc(sizeof(gid_t), num_groups);
 
-       for (i = 0; i < num_groups; i++) {
-               gid_t gid;
+               /* Go through each other sid and convert it to a gid */
+
+               for (i = 0; i < info3->num_other_sids; i++) {
+                       fstring name;
+                       fstring dom_name;
+                       enum SID_NAME_USE sid_type;
+
+                       /* Is this sid known to us?  It can either be
+                           a trusted domain sid or a foreign sid. */
+
+                       if (!winbindd_lookup_name_by_sid( &info3->other_sids[i].sid, 
+                               dom_name, name, &sid_type))
+                       {
+                               DEBUG(10, ("winbindd_getgroups: could not lookup name for %s\n", 
+                                          sid_string_static(&info3->other_sids[i].sid)));
+                               continue;
+                       }
+
+                       /* Check it is a domain group or an alias (domain local group) 
+                          in a win2k native mode domain. */
+                       
+                       if ( !(sid_type == SID_NAME_DOM_GRP || sid_type == SID_NAME_ALIAS) ) {
+
+                               DEBUG(10, ("winbindd_getgroups: sid type %d "
+                                          "for %s is not a domain group\n",
+                                          sid_type,
+                                          sid_string_static(
+                                                  &info3->other_sids[i].sid)));
+                               continue;
+                       }
+
+                       /* Map to a gid */
+
+                       if ( NT_STATUS_IS_ERR(sid_to_gid(&info3->other_sids[i].sid, 
+                               &gid_list[num_gids])) )
+                       {
+                               DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
+                                          sid_string_static(&info3->other_sids[i].sid)));
+                               continue;
+                       }
+
+                       /* We've jumped through a lot of hoops to get here */
+
+                       DEBUG(10, ("winbindd_getgroups: mapped other sid %s to "
+                                  "gid %d\n", sid_string_static(
+                                          &info3->other_sids[i].sid),
+                                  gid_list[num_gids]));
+
+                       num_gids++;
+               }
+
+               for (i = 0; i < info3->num_groups2; i++) {
                
-               if (NT_STATUS_IS_ERR(sid_to_gid(user_gids[i], &gid))) {
-                       fstring sid_string;
+                       /* create the group SID */
+                       
+                       sid_copy( &group_sid, &domain->sid );
+                       sid_append_rid( &group_sid, info3->gids[i].g_rid );
 
-                       DEBUG(1, ("unable to convert group sid %s to gid\n", 
-                                 sid_to_string(sid_string, user_gids[i])));
-                       continue;
+                       if ( NT_STATUS_IS_ERR(sid_to_gid(&group_sid, &gid_list[num_gids])) ) {
+                               DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
+                                          sid_string_static(&group_sid)));
+                       }
+
+                       num_gids++;
+               }
+
+               SAFE_FREE(info3);
+
+       } else {
+               status = domain->methods->lookup_usergroups(domain, mem_ctx, 
+                                                   &user_sid, &num_groups, 
+                                                   &user_grpsids);
+               if (!NT_STATUS_IS_OK(status)) 
+                       goto done;
+
+               gid_list = malloc(sizeof(gid_t) * num_groups);
+
+               if (state->response.extra_data)
+                       goto done;
+
+               for (i = 0; i < num_groups; i++) {
+                       if (NT_STATUS_IS_ERR(sid_to_gid(user_grpsids[i], &gid_list[num_gids]))) {
+                               DEBUG(1, ("unable to convert group sid %s to gid\n", 
+                                         sid_string_static(user_grpsids[i])));
+                               continue;
+                       }
+                       num_gids++;
                }
-               gid_list[num_gids] = gid;
-               num_gids++;
        }
 
+       /* Send data back to client */
+
        state->response.data.num_entries = num_gids;
        state->response.extra_data = gid_list;
        state->response.length += num_gids * sizeof(gid_t);
index 3b306eed3b2eb2b9e9bcdbdd6cae96083a4b3ffc..7b93015b5d6b758eeaff25f5693f55d5ce1ea023 100644 (file)
@@ -151,7 +151,6 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
         
        clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
         
-       uni_group_cache_store_netlogon(mem_ctx, &info3);
 done:
        
        /* give us a more useful (more correct?) error code */
@@ -313,11 +312,13 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
        clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
         
        if (NT_STATUS_IS_OK(result)) {
-               uni_group_cache_store_netlogon(mem_ctx, &info3);
+               netsamlogon_cache_store( cli->mem_ctx, &info3 );
+               wcache_invalidate_samlogon(find_domain_from_name(domain), &info3);
+               
                if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) {
                        result = append_info3_as_ndr(mem_ctx, state, &info3);
                }
-
+               
                if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
                        memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
                }
@@ -382,9 +383,8 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
 
        /* Get sam handle */
 
-       if (!(hnd = cm_get_sam_handle(domain))) {
+       if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(domain, &hnd)) ) {
                DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
-               result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
                goto done;
        }
 
index 9ec35617f111cdd7030f7d6abc1caca78c0dd881..5710a323e8f74608d62d194eba0050b2136fa40f 100644 (file)
@@ -51,8 +51,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
        do {
                /* Get sam handle */
 
-               if (!(hnd = cm_get_sam_handle(domain->name)))
-                       goto done;
+               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
+                       return result;
 
                /* Get domain handle */
 
@@ -136,6 +136,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
        NTSTATUS status;
        uint32 start = 0;
        int retry;
+       NTSTATUS result;
 
        *num_entries = 0;
        *info = NULL;
@@ -144,8 +145,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!(hnd = cm_get_sam_handle(domain->name)))
-                       return NT_STATUS_UNSUCCESSFUL;
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
+                       return result;
 
                status = cli_samr_open_domain(hnd->cli, mem_ctx,
                                              &hnd->pol, des_access, &domain->sid, &dom_pol);
@@ -209,8 +210,8 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if ( !(hnd = cm_get_sam_handle(domain->name)) )
-                       return NT_STATUS_UNSUCCESSFUL;
+               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
+                       return result;
 
                result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, 
                                                des_access, &domain->sid, &dom_pol);
@@ -262,7 +263,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
                            enum SID_NAME_USE *type)
 {
        CLI_POLICY_HND *hnd;
-       NTSTATUS status;
+       NTSTATUS result;
        DOM_SID *sids = NULL;
        uint32 *types = NULL;
        const char *full_name;
@@ -277,24 +278,27 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
                return NT_STATUS_NO_MEMORY;
        }
 
+       DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name ));
+
        retry = 0;
        do {
-               if (!(hnd = cm_get_lsa_handle(domain->name))) {
-                       return NT_STATUS_UNSUCCESSFUL;
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) {
+                       return result;
                }
         
-               status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, 
+               result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, 
                                              &full_name, &sids, &types);
-       } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
+       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
+                       hnd && hnd->cli && hnd->cli->fd == -1);
         
        /* Return rid and type if lookup successful */
 
-       if (NT_STATUS_IS_OK(status)) {
+       if (NT_STATUS_IS_OK(result)) {
                sid_copy(sid, &sids[0]);
                *type = types[0];
        }
 
-       return status;
+       return result;
 }
 
 /*
@@ -310,21 +314,23 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
        char **domains;
        char **names;
        uint32 *types;
-       NTSTATUS status;
+       NTSTATUS result;
        int retry;
 
-       DEBUG(3,("rpc: sid_to_name\n"));
+       DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
+                       domain->name ));
 
        retry = 0;
        do {
-               if (!(hnd = cm_get_lsa_handle(domain->name)))
-                       return NT_STATUS_UNSUCCESSFUL;
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
+                       return result;
         
-               status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
+               result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
                                             1, sid, &domains, &names, &types);
-       } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
+       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
+                       hnd && hnd->cli && hnd->cli->fd == -1);
 
-       if (NT_STATUS_IS_OK(status)) {
+       if (NT_STATUS_IS_OK(result)) {
                *type = types[0];
                *name = names[0];
                DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
@@ -335,7 +341,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
                        return NT_STATUS_UNSUCCESSFUL;
                }
        }
-       return status;
+
+       return result;
 }
 
 /* Lookup user information from a rid or username. */
@@ -352,24 +359,48 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        int retry;
        fstring sid_string;
        uint32 user_rid;
+       NET_USER_INFO_3 *user;
 
        DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
        if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
                goto done;
        }
-
+       
+       /* 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)));
+                       
+               user_info->user_sid  = rid_to_talloced_sid( domain, mem_ctx, user_rid );
+               user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, 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);
+                                                               
+               SAFE_FREE(user);
+                               
+               return NT_STATUS_OK;
+       }
+       
+       /* no cache; hit the wire */
+               
        retry = 0;
        do {
-               /* Get sam handle */
-               if (!(hnd = cm_get_sam_handle(domain->name)))
+               /* Get sam handle; if we fail here there is no hope */
+               
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &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);
+       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
+                       hnd && hnd->cli && hnd->cli->fd == -1);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -417,7 +448,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                                  TALLOC_CTX *mem_ctx,
                                  DOM_SID *user_sid,
-                                 uint32 *num_groups, DOM_SID ***user_gids)
+                                 uint32 *num_groups, DOM_SID ***user_grpsids)
 {
        CLI_POLICY_HND *hnd;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -429,30 +460,47 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        unsigned int retry;
        fstring sid_string;
        uint32 user_rid;
+       NET_USER_INFO_3 *user;
 
        DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));
 
        *num_groups = 0;
+       *user_grpsids = NULL;
 
-       /* First try cached universal groups from logon */
-       *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups);
-       if((*num_groups > 0) && *user_gids) {
+       /* 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(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
+               for (i=0;i<(*num_groups);i++) {
+                       (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
+               }
+                               
+               SAFE_FREE(user);
+                               
                return NT_STATUS_OK;
-       } else {
-           *user_gids = NULL;
-           *num_groups = 0;
        }
 
+       /* no cache; hit the wire */
+       
        retry = 0;
        do {
-               /* Get sam handle */
-               if (!(hnd = cm_get_sam_handle(domain->name)))
+               /* Get sam handle; if we fail here there is no hope */
+               
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))           
                        goto done;
 
                /* Get domain handle */
+               
                result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
                                              des_access, &domain->sid, &dom_pol);
-       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
+       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && 
+                       hnd && hnd->cli && hnd->cli->fd == -1);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -480,14 +528,14 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
                goto done;
 
-       (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups));
-       if (!(*user_gids)) {
+       (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
+       if (!(*user_grpsids)) {
                result = NT_STATUS_NO_MEMORY;
                goto done;
        }
 
        for (i=0;i<(*num_groups);i++) {
-               (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
+               (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
        }
        
  done:
@@ -532,7 +580,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        retry = 0;
        do {
                /* Get sam handle */
-               if (!(hnd = cm_get_sam_handle(domain->name)))
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
                        goto done;
 
                /* Get domain handle */
@@ -601,9 +649,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                               &tmp_num_names,
                                               &tmp_names, &tmp_types);
 
-                if (!NT_STATUS_IS_OK(result))
+               /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is
+                  the one returned from 2k) */
+               
+                if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED))
                         goto done;
-
+                       
                 /* Copy result into array.  The talloc system will take
                    care of freeing the temporary arrays later on. */
 
@@ -618,7 +669,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 
         *num_names = total_names;
 
- done:
+       result = NT_STATUS_OK;
+       
+done:
         if (got_group_pol)
                 cli_samr_close(hnd->cli, mem_ctx, &group_pol);
 
@@ -651,8 +704,8 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
 
        retry = 0;
        do {
-               /* Get sam handle */
-               if (!(hnd = cm_get_sam_handle(domain->name)))
+               /* Get sam handle */
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
                        goto done;
 
                /* Get domain handle */
@@ -710,7 +763,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(lp_workgroup(), &hnd)))
                        goto done;
 
                result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
@@ -725,7 +778,7 @@ done:
 /* find the domain sid for a domain */
 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
 {
-       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        TALLOC_CTX *mem_ctx;
        CLI_POLICY_HND *hnd;
        fstring level5_dom;
@@ -738,17 +791,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
 
        retry = 0;
        do {
-               /* Get sam handle */
-               if (!(hnd = cm_get_lsa_handle(domain->name)))
+               /* Get lsa handle */
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
                        goto done;
 
-               status = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
+               result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
                                           &hnd->pol, 0x05, level5_dom, sid);
-       } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
+       } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
 
 done:
        talloc_destroy(mem_ctx);
-       return status;
+       return result;
 }
 
 /* find alternate names list for the domain - none for rpc */
index 919ae2aa7e6ec0c037c0d0152a2d39bb882371af..31cbd96474c9b92ecb4fcc1130ba8a3eaa208428 100644 (file)
@@ -142,7 +142,7 @@ END {
     gotstart = 1;
   }
 
-  if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA/ ) {
+  if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3/ ) {
     gotstart = 1;
   }
 
index 07723cc20e7e7284189c4d936b460cb058bacf9a..24cfed5be937697ff1d399eace6380cbabff6389 100644 (file)
@@ -855,8 +855,6 @@ void build_options(BOOL screen);
 
        init_modules();
 
-       uni_group_cache_init(); /* Non-critical */
-       
        /* possibly reload the services file. */
        reload_services(True);
 
@@ -891,7 +889,6 @@ void build_options(BOOL screen);
 
        smbd_process();
        
-       uni_group_cache_shutdown();
        namecache_shutdown();
        exit_server("normal exit");
        return(0);