summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in4
-rw-r--r--source3/auth/auth_domain.c2
-rw-r--r--source3/lib/username.c69
-rw-r--r--source3/libsmb/samlogon_cache.c238
-rw-r--r--source3/nsswitch/wb_client.c26
-rw-r--r--source3/nsswitch/winbindd.c14
-rw-r--r--source3/nsswitch/winbindd.h1
-rw-r--r--source3/nsswitch/winbindd_cache.c140
-rw-r--r--source3/nsswitch/winbindd_cm.c45
-rw-r--r--source3/nsswitch/winbindd_group.c129
-rw-r--r--source3/nsswitch/winbindd_pam.c10
-rw-r--r--source3/nsswitch/winbindd_rpc.c157
-rw-r--r--source3/script/mkproto.awk2
-rw-r--r--source3/smbd/server.c3
14 files changed, 667 insertions, 173 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index add45aec74..02b8cd112f 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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) \
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index f1575e43b0..66684cc940 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -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
diff --git a/source3/lib/username.c b/source3/lib/username.c
index d8f4ff80ed..8130b93c3f 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -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/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c
new file mode 100644
index 0000000000..7863ad7727
--- /dev/null
+++ b/source3/libsmb/samlogon_cache.c
@@ -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;
+}
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index 996d15180d..b1765a8bd7 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -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);
}
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index c7e45e5429..d777fe37dd 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 8e1c7edc7f..2acb89b24b 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -112,6 +112,7 @@ struct winbindd_domain {
time_t last_seq_check;
uint32 sequence_number;
+ NTSTATUS last_status;
/* Linked list info */
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index e0860cd695..5464e765d1 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -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,
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 0ba9ab8266..d2d99a4203 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -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
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index e643d933db..bd9a50b3e0 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -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);
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 3b306eed3b..7b93015b5d 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 9ec35617f1..5710a323e8 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -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 */
diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk
index 919ae2aa7e..31cbd96474 100644
--- a/source3/script/mkproto.awk
+++ b/source3/script/mkproto.awk
@@ -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;
}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 07723cc20e..24cfed5be9 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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);