summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-12-09 23:59:42 +0000
committerAndrew Tridgell <tridge@samba.org>2001-12-09 23:59:42 +0000
commitfddb4f4c04473a60a97212c0c8e143d6a4d68380 (patch)
tree47463c89bdb909cbfa96f82a99a3897c92ce485a
parentfa1e7a62acdbcc550e6b29dc69454dcf7472210d (diff)
downloadsamba-fddb4f4c04473a60a97212c0c8e143d6a4d68380.tar.gz
completely new winbindd cache infrastructure
this one looks like just another winbind backend, and has the following properties: - does -ve and +ve cacheing of all queries - can be disabled with -n switch to winbindd - stores all records packed, so even huge domains are not a problem for a complete cache - handles the server being down - uses sequence numbers for all entries This fixes a lot of problems with winbindd. Serving from cache is now *very* fast.
-rw-r--r--source/nsswitch/winbindd.c21
-rw-r--r--source/nsswitch/winbindd.h4
-rw-r--r--source/nsswitch/winbindd_ads.c13
-rw-r--r--source/nsswitch/winbindd_cache.c997
-rw-r--r--source/nsswitch/winbindd_group.c85
-rw-r--r--source/nsswitch/winbindd_proto.h4
-rw-r--r--source/nsswitch/winbindd_rpc.c14
-rw-r--r--source/nsswitch/winbindd_user.c58
-rw-r--r--source/nsswitch/winbindd_util.c151
9 files changed, 591 insertions, 756 deletions
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index c1402dc8fb6..0db16b6874f 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -29,6 +29,7 @@ extern pstring debugf;
struct winbindd_cli_state *client_list;
static int num_clients;
+BOOL opt_nocache;
/* Reload configuration */
@@ -132,7 +133,6 @@ static void print_winbindd_status(void)
{
winbindd_status();
winbindd_idmap_status();
- winbindd_cache_status();
winbindd_cm_status();
}
@@ -140,9 +140,8 @@ static void print_winbindd_status(void)
static void flush_caches(void)
{
- /* Clear cached user and group enumation info */
-
- winbindd_flush_cache();
+ /* Clear cached user and group enumation info */
+ wcache_flush_cache();
}
/* Handle the signal by unlinking socket and exiting */
@@ -748,23 +747,25 @@ int main(int argc, char **argv)
/* Initialise samba/rpc client stuff */
- while ((opt = getopt(argc, argv, "id:s:")) != EOF) {
+ while ((opt = getopt(argc, argv, "id:s:n")) != EOF) {
switch (opt) {
- /* Don't become a daemon */
-
+ /* Don't become a daemon */
case 'i':
interactive = True;
break;
- /* Run with specified debug level */
+ /* disable cacheing */
+ case 'n':
+ opt_nocache = True;
+ break;
+ /* Run with specified debug level */
case 'd':
new_debuglevel = atoi(optarg);
break;
/* Load a different smb.conf file */
-
case 's':
pstrcpy(dyn_CONFIGFILE,optarg);
break;
@@ -823,8 +824,6 @@ int main(int argc, char **argv)
if (!winbindd_idmap_init())
return 1;
- winbindd_cache_init();
-
/* Unblock all signals we are interested in as they may have been
blocked by the parent process. */
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 21dca93af52..a4c0dd970d8 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -136,7 +136,7 @@ struct winbindd_methods {
uint32 **name_types);
/* return the current global sequence number */
- uint32 (*sequence_number)(struct winbindd_domain *domain);
+ NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq);
};
/* Structures to hold per domain information */
@@ -147,6 +147,8 @@ struct winbindd_domain {
this domain (LDAP or
RPC) */
void *private; /* private data for the backends (used for connection cache) */
+ time_t last_seq_check;
+ uint32 sequence_number;
struct winbindd_domain *prev, *next; /* Linked list info */
};
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 2510e4a501b..cabb482f7d4 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -641,17 +641,20 @@ done:
}
/* find the sequence number for a domain */
-static uint32 sequence_number(struct winbindd_domain *domain)
+static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
- uint32 usn;
ADS_STRUCT *ads = NULL;
+ *seq = DOM_SEQUENCE_NONE;
+
ads = ads_cached_connection(domain);
- if (!ads) return DOM_SEQUENCE_NONE;
+ if (!ads) return NT_STATUS_UNSUCCESSFUL;
- if (!ads_USN(ads, &usn)) return DOM_SEQUENCE_NONE;
+ if (!ads_USN(ads, seq)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
- return usn;
+ return NT_STATUS_OK;
}
/* the ADS backend methods are exposed via this structure */
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index 32ef3526faf..da918df4f35 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -1,10 +1,9 @@
/*
Unix SMB/Netbios implementation.
- Version 2.0
- Winbind daemon - caching related functions
+ Winbind cache backend functions
- Copyright (C) Tim Potter 2000
+ Copyright (C) Andrew Tridgell 2001
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
@@ -23,587 +22,687 @@
#include "winbindd.h"
-#define CACHE_TYPE_USER "USR"
-#define CACHE_TYPE_GROUP "GRP"
-#define CACHE_TYPE_NAME "NAM" /* Stores mapping from SID to name. */
-#define CACHE_TYPE_SID "SID" /* Stores mapping from name to SID. */
-
-/* Initialise caching system */
-
-static TDB_CONTEXT *cache_tdb;
-
-struct cache_rec {
- uint32 seq_num;
- time_t mod_time;
+struct winbind_cache {
+ struct winbindd_methods *backend;
+ TDB_CONTEXT *tdb;
};
-void winbindd_cache_init(void)
-{
- /* Open tdb cache */
-
- if (!(cache_tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0,
- TDB_NOLOCK, O_RDWR | O_CREAT | O_TRUNC,
- 0600)))
- DEBUG(0, ("Unable to open tdb cache - user and group caching disabled\n"));
-}
+struct cache_entry {
+ NTSTATUS status;
+ uint32 sequence_number;
+ uint8 *data;
+ uint32 len, ofs;
+};
-/* get the domain sequence number, possibly re-fetching */
+static struct winbind_cache *wcache;
-static uint32 cached_sequence_number(struct winbindd_domain *domain)
+void wcache_flush_cache(void)
{
- fstring keystr;
- TDB_DATA dbuf;
- struct cache_rec rec;
- time_t t = time(NULL);
-
- snprintf(keystr, sizeof(keystr), "CACHESEQ/%s", domain->name);
- dbuf = tdb_fetch_by_string(cache_tdb, keystr);
-
- if (!dbuf.dptr || dbuf.dsize != sizeof(rec))
- goto refetch;
+ extern BOOL opt_nocache;
- memcpy(&rec, dbuf.dptr, sizeof(rec));
- SAFE_FREE(dbuf.dptr);
-
- if (t < (rec.mod_time + lp_winbind_cache_time())) {
- DEBUG(3,("cached sequence number for %s is %u\n",
- domain->name, (unsigned)rec.seq_num));
- return rec.seq_num;
+ if (!wcache) return;
+ if (wcache->tdb) {
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
}
+ if (opt_nocache) return;
- refetch:
- rec.seq_num = domain->methods->sequence_number(domain);
- rec.mod_time = t;
-
- tdb_store_by_string(cache_tdb, keystr, &rec, sizeof(rec));
+ wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0,
+ TDB_NOLOCK, O_RDWR | O_CREAT | O_TRUNC, 0600);
- return rec.seq_num;
+ if (!wcache->tdb) {
+ DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
+ }
}
-/* Check whether a seq_num for a cached item has expired */
-static BOOL cache_domain_expired(struct winbindd_domain *domain,
- uint32 seq_num)
+/* get the winbind_cache structure */
+static struct winbind_cache *get_cache(struct winbindd_domain *domain)
{
- uint32 cache_seq = cached_sequence_number(domain);
- if (cache_seq != seq_num) {
- DEBUG(3,("seq %u for %s has expired (not == %u)\n", (unsigned)seq_num,
- domain->name, (unsigned)cache_seq ));
- return True;
+ extern struct winbindd_methods msrpc_methods;
+ struct winbind_cache *ret = wcache;
+
+ if (ret) return ret;
+
+ ret = smb_xmalloc(sizeof(*ret));
+ ZERO_STRUCTP(ret);
+ switch (lp_security()) {
+#ifdef HAVE_ADS
+ case SEC_ADS: {
+ extern struct winbindd_methods ads_methods;
+ ret->backend = &ads_methods;
+ break;
}
+#endif
+ default:
+ ret->backend = &msrpc_methods;
+ }
+
+ wcache = ret;
+ wcache_flush_cache();
- return False;
+ return ret;
}
-static void set_cache_sequence_number(struct winbindd_domain *domain,
- const char *cache_type, const char *subkey)
+/*
+ free a centry structure
+*/
+static void centry_free(struct cache_entry *centry)
{
- fstring keystr;
+ if (!centry) return;
+ SAFE_FREE(centry->data);
+ free(centry);
+}
- snprintf(keystr, sizeof(keystr),"CACHESEQ %s/%s/%s",
- domain->name, cache_type, subkey?subkey:"");
- tdb_store_int(cache_tdb, keystr, cached_sequence_number(domain));
+/*
+ pull a uint32 from a cache entry
+*/
+static uint32 centry_uint32(struct cache_entry *centry)
+{
+ uint32 ret;
+ if (centry->len - centry->ofs < 4) {
+ DEBUG(0,("centry corruption? needed 4 bytes, have %d\n",
+ centry->len - centry->ofs));
+ smb_panic("centry_uint32");
+ }
+ ret = IVAL(centry->data, centry->ofs);
+ centry->ofs += 4;
+ return ret;
}
-static uint32 get_cache_sequence_number(struct winbindd_domain *domain,
- const char *cache_type, const char *subkey)
+/* pull a string from a cache entry, using the supplied
+ talloc context
+*/
+static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
{
- fstring keystr;
- uint32 seq_num;
-
- snprintf(keystr, sizeof(keystr), "CACHESEQ %s/%s/%s",
- domain->name, cache_type, subkey ? subkey : "");
-
- seq_num = (uint32)tdb_fetch_int(cache_tdb, keystr);
-
- DEBUG(3,("%s is %u\n", keystr, (unsigned)seq_num));
+ uint32 len;
+ char *ret;
+
+ len = centry_uint32(centry);
+ if (centry->len - centry->ofs < len) {
+ DEBUG(0,("centry corruption? needed %d bytes, have %d\n",
+ len, centry->len - centry->ofs));
+ smb_panic("centry_string");
+ }
- return seq_num;
+ ret = talloc(mem_ctx, len+1);
+ if (!ret) {
+ smb_panic("centry_string out of memory\n");
+ }
+ memcpy(ret,centry->data + centry->ofs, len);
+ ret[len] = 0;
+ centry->ofs += len;
+ return ret;
}
-/* Fill the user or group cache with supplied data */
-
-static void store_cache(struct winbindd_domain *domain, const char *cache_type,
- void *sam_entries, int buflen)
+/* the server is considered down if it can't give us a sequence number */
+static BOOL wcache_server_down(struct winbindd_domain *domain)
{
- fstring keystr;
+ if (!wcache->tdb) return False;
+ return (domain->sequence_number == DOM_SEQUENCE_NONE);
+}
- if (lp_winbind_cache_time() == 0)
- return;
- /* Error check */
+/*
+ refresh the domain sequence number. If force is True
+ then always refresh it, no matter how recently we fetched it
+*/
+static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
+{
+ NTSTATUS status;
- if (!sam_entries || buflen == 0)
+ /* see if we have to refetch the domain sequence number */
+ if (!force && (time(NULL) - domain->last_seq_check < lp_winbind_cache_time())) {
return;
+ }
- /* Store data as a mega-huge chunk in the tdb */
-
- snprintf(keystr, sizeof(keystr), "%s CACHE DATA/%s", cache_type,
- domain->name);
+ status = wcache->backend->sequence_number(domain, &domain->sequence_number);
- tdb_store_by_string(cache_tdb, keystr, sam_entries, buflen);
+ if (!NT_STATUS_IS_OK(status)) {
+ domain->sequence_number = DOM_SEQUENCE_NONE;
+ }
- /* Stamp cache with current seq number */
+ domain->last_seq_check = time(NULL);
- set_cache_sequence_number(domain, cache_type, NULL);
+ DEBUG(0,("seq number now %d\n", domain->sequence_number));
}
-/* Fill the user cache with supplied data */
-
-void winbindd_store_user_cache(struct winbindd_domain *domain,
- struct getpwent_user *sam_entries,
- int num_sam_entries)
+/*
+ decide if a cache entry has expired
+*/
+static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *centry)
{
- DEBUG(3, ("storing user cache %s/%d entries\n", domain->name,
- num_sam_entries));
-
- store_cache(domain, CACHE_TYPE_USER, sam_entries,
- num_sam_entries * sizeof(struct getpwent_user));
-}
-
-/* Fill the group cache with supplied data */
+ /* if the server is OK and our cache entry came from when it was down then
+ the entry is invalid */
+ if (domain->sequence_number != DOM_SEQUENCE_NONE &&
+ centry->sequence_number == DOM_SEQUENCE_NONE) {
+ return True;
+ }
-void winbindd_store_group_cache(struct winbindd_domain *domain,
- struct acct_info *sam_entries,
- int num_sam_entries)
-{
- DEBUG(0, ("storing group cache %s/%d entries\n", domain->name,
- num_sam_entries));
+ /* if the server is down or the cache entry is not older than the
+ current sequence number then it is OK */
+ if (wcache_server_down(domain) ||
+ centry->sequence_number >= domain->sequence_number) {
+ return False;
+ }
- store_cache(domain, CACHE_TYPE_GROUP, sam_entries,
- num_sam_entries * sizeof(struct acct_info));
+ /* it's expired */
+ return True;
}
-static void store_cache_entry(struct winbindd_domain *domain, const char *cache_type,
- const char *name, void *buf, int len)
+/*
+ fetch an entry from the cache, with a varargs key. auto-fetch the sequence
+ number and return status
+*/
+static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
+ struct winbindd_domain *domain,
+ const char *format, ...)
{
- fstring keystr;
-
- /* Create key for store */
-
- snprintf(keystr, sizeof(keystr), "%s/%s/%s", cache_type,
- domain->name, name);
+ va_list ap;
+ char *kstr;
+ TDB_DATA data;
+ struct cache_entry *centry;
- /* Store it */
+ refresh_sequence_number(domain, False);
- tdb_store_by_string(cache_tdb, keystr, buf, len);
-}
+ va_start(ap, format);
+ smb_xvasprintf(&kstr, format, ap);
+ va_end(ap);
+
+ data = tdb_fetch_by_string(wcache->tdb, kstr);
+ free(kstr);
+ if (!data.dptr) {
+ /* a cache miss */
+ return NULL;
+ }
-/* Fill a name cache entry */
+ centry = smb_xmalloc(sizeof(*centry));
+ centry->data = data.dptr;
+ centry->len = data.dsize;
+ centry->ofs = 0;
-void winbindd_store_name_cache_entry(struct winbindd_domain *domain,
- char *sid, struct winbindd_name *name)
-{
- if (lp_winbind_cache_time() == 0)
- return;
+ if (centry->len < 8) {
+ /* huh? corrupt cache? */
+ centry_free(centry);
+ return NULL;
+ }
+
+ centry->status = NT_STATUS(centry_uint32(centry));
+ centry->sequence_number = centry_uint32(centry);
- store_cache_entry(domain, CACHE_TYPE_NAME, sid, name,
- sizeof(struct winbindd_name));
+ if (centry_expired(domain, centry)) {
+ centry_free(centry);
+ return NULL;
+ }
- set_cache_sequence_number(domain, CACHE_TYPE_NAME, sid);
+ return centry;
}
-/* Fill a SID cache entry */
-
-void winbindd_store_sid_cache_entry(struct winbindd_domain *domain,
- const char *name, struct winbindd_sid *sid)
+/*
+ make sure we have at least len bytes available in a centry
+*/
+static void centry_expand(struct cache_entry *centry, uint32 len)
{
- if (lp_winbind_cache_time() == 0)
- return;
-
- store_cache_entry(domain, CACHE_TYPE_SID, name, sid,
- sizeof(struct winbindd_sid));
-
- set_cache_sequence_number(domain, CACHE_TYPE_SID, name);
+ uint8 *p;
+ if (centry->len - centry->ofs >= len) return;
+ centry->len *= 2;
+ p = realloc(centry->data, centry->len);
+ if (!p) {
+ DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len));
+ smb_panic("out of memory in centry_expand");
+ }
+ centry->data = p;
}
-/* Fill a user info cache entry */
-
-void winbindd_store_user_cache_entry(struct winbindd_domain *domain,
- char *user_name, struct winbindd_pw *pw)
+/*
+ push a uint32 into a centry
+*/
+static void centry_put_uint32(struct cache_entry *centry, uint32 v)
{
- if (lp_winbind_cache_time() == 0)
- return;
-
- store_cache_entry(domain, CACHE_TYPE_USER, user_name, pw,
- sizeof(struct winbindd_pw));
-
- set_cache_sequence_number(domain, CACHE_TYPE_USER, user_name);
+ centry_expand(centry, 4);
+ SIVAL(centry->data, centry->ofs, v);
+ centry->ofs += 4;
}
-/* Fill a user uid cache entry */
-
-void winbindd_store_uid_cache_entry(struct winbindd_domain *domain, uid_t uid,
- struct winbindd_pw *pw)
+/*
+ push a string into a centry
+ */
+static void centry_put_string(struct cache_entry *centry, const char *s)
{
- fstring uidstr;
-
- if (lp_winbind_cache_time() == 0)
- return;
-
- snprintf(uidstr, sizeof(uidstr), "#%u", (unsigned)uid);
-
- DEBUG(3, ("storing uid cache entry %s/%s\n", domain->name, uidstr));
-
- store_cache_entry(domain, CACHE_TYPE_USER, uidstr, pw,
- sizeof(struct winbindd_pw));
-
- set_cache_sequence_number(domain, CACHE_TYPE_USER, uidstr);
+ int len = strlen(s);
+ centry_put_uint32(centry, len);
+ centry_expand(centry, len);
+ memcpy(centry->data + centry->ofs, s, len);
+ centry->ofs += len;
}
-/* Fill a group info cache entry */
-
-void winbindd_store_group_cache_entry(struct winbindd_domain *domain,
- char *group_name, struct winbindd_gr *gr,
- void *extra_data, int extra_data_len)
+/*
+ start a centry for output. When finished, call centry_end()
+*/
+struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status)
{
- fstring keystr;
-
- if (lp_winbind_cache_time() == 0)
- return;
-
- DEBUG(3, ("storing group cache entry %s/%s\n", domain->name,
- group_name));
-
- /* Fill group data */
+ struct cache_entry *centry;
- store_cache_entry(domain, CACHE_TYPE_GROUP, group_name, gr,
- sizeof(struct winbindd_gr));
+ if (!wcache->tdb) return NULL;
- /* Fill extra data */
+ centry = smb_xmalloc(sizeof(*centry));
- snprintf(keystr, sizeof(keystr), "%s/%s/%s DATA", CACHE_TYPE_GROUP,
- domain->name, group_name);
+ refresh_sequence_number(domain, True);
- tdb_store_by_string(cache_tdb, keystr, extra_data, extra_data_len);
-
- set_cache_sequence_number(domain, CACHE_TYPE_GROUP, group_name);
+ centry->len = 8192; /* reasonable default */
+ centry->data = smb_xmalloc(centry->len);
+ centry->ofs = 0;
+ centry->sequence_number = domain->sequence_number;
+ centry_put_uint32(centry, NT_STATUS_V(status));
+ centry_put_uint32(centry, centry->sequence_number);
+ return centry;
}
-/* Fill a group info cache entry */
-
-void winbindd_store_gid_cache_entry(struct winbindd_domain *domain, gid_t gid,
- struct winbindd_gr *gr, void *extra_data,
- int extra_data_len)
+/*
+ finish a centry and write it to the tdb
+*/
+static void centry_end(struct cache_entry *centry, const char *format, ...)
{
- fstring keystr;
- fstring gidstr;
-
- snprintf(gidstr, sizeof(gidstr), "#%u", (unsigned)gid);
-
- if (lp_winbind_cache_time() == 0)
- return;
+ va_list ap;
+ char *kstr;
- DEBUG(3, ("storing gid cache entry %s/%s\n", domain->name, gidstr));
+ va_start(ap, format);
+ smb_xvasprintf(&kstr, format, ap);
+ va_end(ap);
- /* Fill group data */
-
- store_cache_entry(domain, CACHE_TYPE_GROUP, gidstr, gr,
- sizeof(struct winbindd_gr));
-
- /* Fill extra data */
-
- snprintf(keystr, sizeof(keystr), "%s/%s/%s DATA", CACHE_TYPE_GROUP,
- domain->name, gidstr);
-
- tdb_store_by_string(cache_tdb, keystr, extra_data, extra_data_len);
-
- set_cache_sequence_number(domain, CACHE_TYPE_GROUP, gidstr);
+ tdb_store_by_string(wcache->tdb, kstr, centry->data, centry->ofs);
+ free(kstr);
}
-/* Fetch some cached user or group data */
-
-static BOOL fetch_cache(struct winbindd_domain *domain, char *cache_type,
- void **sam_entries, int *buflen)
+/* Query display info. This is the basic user list fn */
+static NTSTATUS query_user_list(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *start_ndx, uint32 *num_entries,
+ WINBIND_USERINFO **info)
{
- TDB_DATA data;
- fstring keystr;
-
- if (lp_winbind_cache_time() == 0)
- return False;
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
- /* Parameter check */
+ if (!cache->tdb) goto do_query;
- if (!sam_entries || !buflen)
- return False;
-
- /* Check cache data is current */
+ centry = wcache_fetch(cache, domain, "USERLIST/%s/%d", domain->name, *start_ndx);
+ if (!centry) goto do_query;
- if (cache_domain_expired(domain, get_cache_sequence_number(domain, cache_type, NULL)))
- return False;
+ *num_entries = centry_uint32(centry);
- /* Create key */
+ if (*num_entries == 0) goto do_cached;
+
+ (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ if (! (*info)) smb_panic("query_user_list out of memory");
+ for (i=0; i<(*num_entries); i++) {
+ (*info)[i].acct_name = centry_string(centry, mem_ctx);
+ (*info)[i].full_name = centry_string(centry, mem_ctx);
+ (*info)[i].user_rid = centry_uint32(centry);
+ (*info)[i].group_rid = centry_uint32(centry);
+ }
- snprintf(keystr, sizeof(keystr), "%s CACHE DATA/%s", cache_type, domain->name);
-
- /* Fetch cache information */
+do_cached:
+ status = centry->status;
+ centry_free(centry);
+ return status;
- data = tdb_fetch_by_string(cache_tdb, keystr);
-
- if (!data.dptr)
- return False;
+do_query:
+ if (wcache_server_down(domain)) {
+ *num_entries = 0;
+ return NT_STATUS_SERVER_DISABLED;
+ }
- /* Copy across cached data. We can save a memcpy() by directly
- assigning the data.dptr to the sam_entries pointer. It will
- be freed by the end{pw,gr}ent() function. */
-
- *sam_entries = (struct acct_info *)data.dptr;
- *buflen = data.dsize;
-
- return True;
+ status = cache->backend->query_user_list(domain, mem_ctx, start_ndx, num_entries, info);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_uint32(centry, *num_entries);
+ for (i=0; i<(*num_entries); i++) {
+ centry_put_string(centry, (*info)[i].acct_name);
+ centry_put_string(centry, (*info)[i].full_name);
+ centry_put_uint32(centry, (*info)[i].user_rid);
+ centry_put_uint32(centry, (*info)[i].group_rid);
+ }
+ centry_end(centry, "USERLIST/%s/%d", domain->name, *start_ndx);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-/* Return cached entries for a domain. Return false if there are no cached
- entries, or the cached information has expired for the domain. */
-
-BOOL winbindd_fetch_user_cache(struct winbindd_domain *domain,
- struct getpwent_user **sam_entries,
- int *num_entries)
+/* list all domain groups */
+static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *start_ndx, uint32 *num_entries,
+ struct acct_info **info)
{
- BOOL result;
- int buflen;
-
- result = fetch_cache(domain, CACHE_TYPE_USER,
- (void **)sam_entries, &buflen);
-
- *num_entries = buflen / sizeof(struct getpwent_user);
-
- DEBUG(3, ("fetched %d cache entries for %s\n", *num_entries,
- domain->name));
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
- return result;
-}
-
-/* Return cached entries for a domain. Return false if there are no cached
- entries, or the cached information has expired for the domain. */
+ if (!cache->tdb) goto do_query;
-BOOL winbindd_fetch_group_cache(struct winbindd_domain *domain,
- struct acct_info **sam_entries,
- int *num_entries)
-{
- BOOL result;
- int buflen;
+ centry = wcache_fetch(cache, domain, "GROUPLIST/%s/%d", domain->name, *start_ndx);
+ if (!centry) goto do_query;
- result = fetch_cache(domain, CACHE_TYPE_GROUP,
- (void **)sam_entries, &buflen);
+ *num_entries = centry_uint32(centry);
+
+ if (*num_entries == 0) goto do_cached;
+
+ (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ if (! (*info)) smb_panic("enum_dom_groups out of memory");
+ for (i=0; i<(*num_entries); i++) {
+ fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
+ fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+ (*info)[i].rid = centry_uint32(centry);
+ }
- *num_entries = buflen / sizeof(struct acct_info);
+do_cached:
+ status = centry->status;
+ centry_free(centry);
+ return status;
- DEBUG(3, ("fetched %d cache entries for %s\n", *num_entries,
- domain->name));
+do_query:
+ if (wcache_server_down(domain)) {
+ *num_entries = 0;
+ return NT_STATUS_SERVER_DISABLED;
+ }
- return result;
+ status = cache->backend->enum_dom_groups(domain, mem_ctx, start_ndx, num_entries, info);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_uint32(centry, *num_entries);
+ for (i=0; i<(*num_entries); i++) {
+ centry_put_string(centry, (*info)[i].acct_name);
+ centry_put_string(centry, (*info)[i].acct_desc);
+ centry_put_uint32(centry, (*info)[i].rid);
+ }
+ centry_end(centry, "GROUPLIST/%s/%d", domain->name, *start_ndx);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-static BOOL fetch_cache_entry(struct winbindd_domain *domain,
- const char *cache_type,
- const char *name, void *buf, int len)
-{
- TDB_DATA data;
- fstring keystr;
-
- /* Create key for lookup */
-
- snprintf(keystr, sizeof(keystr), "%s/%s/%s", cache_type, domain->name, name);
-
- /* Look up cache entry */
-
- data = tdb_fetch_by_string(cache_tdb, keystr);
-
- if (!data.dptr)
- return False;
-
- /* Copy found entry into buffer */
- memcpy((char *)buf, data.dptr, len < data.dsize ? len : data.dsize);
- SAFE_FREE(data.dptr);
-
- return True;
-}
-
-/* Fetch an individual SID cache entry */
-BOOL winbindd_fetch_sid_cache_entry(struct winbindd_domain *domain,
- const char *name, struct winbindd_sid *sid)
+/* convert a single name to a sid in a domain */
+static NTSTATUS name_to_sid(struct winbindd_domain *domain,
+ const char *name,
+ DOM_SID *sid,
+ enum SID_NAME_USE *type)
{
- uint32 seq_num;
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int len;
- if (lp_winbind_cache_time() == 0)
- return False;
+ if (!cache->tdb) goto do_query;
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_SID, name);
+ centry = wcache_fetch(cache, domain, "NAMETOSID/%s/%s", domain->name, name);
+ if (!centry) goto do_query;
+ *type = centry_uint32(centry);
+ sid_parse(centry->data + centry->ofs, centry->len - centry->ofs, sid);
- if (cache_domain_expired(domain, seq_num))
- return False;
+ status = centry->status;
+ centry_free(centry);
+ return status;
- return fetch_cache_entry(domain, CACHE_TYPE_SID, name, sid,
- sizeof(struct winbindd_sid));
+do_query:
+ if (wcache_server_down(domain)) {
+ return NT_STATUS_SERVER_DISABLED;
+ }
+ status = cache->backend->name_to_sid(domain, name, sid, type);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ len = sid_size(sid);
+ centry_expand(centry, len);
+ centry_put_uint32(centry, *type);
+ sid_linearize(centry->data + centry->ofs, len, sid);
+ centry->ofs += len;
+ centry_end(centry, "NAMETOSID/%s/%s", domain->name, name);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-/* Fetch an individual name cache entry */
-
-BOOL winbindd_fetch_name_cache_entry(struct winbindd_domain *domain,
- char *sid, struct winbindd_name *name)
+/* convert a sid to a user or group name */
+static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ DOM_SID *sid,
+ char **name,
+ enum SID_NAME_USE *type)
{
- uint32 seq_num;
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ char *sidstr = NULL;
- if (lp_winbind_cache_time() == 0)
- return False;
+ if (!cache->tdb) goto do_query;
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_NAME, sid);
+ sidstr = ads_sid_binstring(sid);
- if (cache_domain_expired(domain, seq_num))
- return False;
+ centry = wcache_fetch(cache, domain, "SIDTONAME/%s/%s", domain->name, sidstr);
+ if (!centry) goto do_query;
+ if (NT_STATUS_IS_OK(centry->status)) {
+ *type = centry_uint32(centry);
+ *name = centry_string(centry, mem_ctx);
+ }
+ status = centry->status;
+ centry_free(centry);
+ SAFE_FREE(sidstr);
+ return status;
+
+do_query:
+ if (wcache_server_down(domain)) {
+ return NT_STATUS_SERVER_DISABLED;
+ }
+ status = cache->backend->sid_to_name(domain, mem_ctx, sid, name, type);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ if (NT_STATUS_IS_OK(status)) {
+ centry_put_uint32(centry, *type);
+ centry_put_string(centry, *name);
+ }
+ centry_end(centry, "SIDTONAME/%s/%s", domain->name, sidstr);
+ centry_free(centry);
- return fetch_cache_entry(domain, CACHE_TYPE_NAME, sid, name,
- sizeof(struct winbindd_name));
+skip_save:
+ SAFE_FREE(sidstr);
+ return status;
}
-/* Fetch an individual user cache entry */
-BOOL winbindd_fetch_user_cache_entry(struct winbindd_domain *domain,
- char *user, struct winbindd_pw *pw)
+/* Lookup user information from a rid */
+static NTSTATUS query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 user_rid,
+ WINBIND_USERINFO *info)
{
- uint32 seq_num;
-
- if (lp_winbind_cache_time() == 0)
- return False;
-
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_USER, user);
-
- if (cache_domain_expired(domain, seq_num))
- return False;
-
- return fetch_cache_entry(domain, CACHE_TYPE_USER, user, pw,
- sizeof(struct winbindd_pw));
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+
+ if (!cache->tdb) goto do_query;
+
+ centry = wcache_fetch(cache, domain, "USER/%s/%x", domain->name, user_rid);
+ if (!centry) goto do_query;
+
+ info->acct_name = centry_string(centry, mem_ctx);
+ info->full_name = centry_string(centry, mem_ctx);
+ info->user_rid = centry_uint32(centry);
+ info->group_rid = centry_uint32(centry);
+ status = centry->status;
+ centry_free(centry);
+ return status;
+
+do_query:
+ if (wcache_server_down(domain)) {
+ return NT_STATUS_SERVER_DISABLED;
+ }
+ status = cache->backend->query_user(domain, mem_ctx, user_rid, info);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_string(centry, info->acct_name);
+ centry_put_string(centry, info->full_name);
+ centry_put_uint32(centry, info->user_rid);
+ centry_put_uint32(centry, info->group_rid);
+ centry_end(centry, "USER/%s/%x", domain->name, user_rid);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-/* Fetch an individual uid cache entry */
-BOOL winbindd_fetch_uid_cache_entry(struct winbindd_domain *domain, uid_t uid,
- struct winbindd_pw *pw)
+/* Lookup groups a user is a member of. */
+static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 user_rid,
+ uint32 *num_groups, uint32 **user_gids)
{
- fstring uidstr;
- uint32 seq_num;
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
- if (lp_winbind_cache_time() == 0)
- return False;
+ if (!cache->tdb) goto do_query;
- snprintf(uidstr, sizeof(uidstr), "#%u", (unsigned)uid);
+ centry = wcache_fetch(cache, domain, "USERGROUPS/%s/%x", domain->name, user_rid);
+ if (!centry) goto do_query;
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_USER, uidstr);
+ *num_groups = centry_uint32(centry);
+
+ if (*num_groups == 0) goto do_cached;
- if (cache_domain_expired(domain, seq_num))
- return False;
+ (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups));
+ if (! (*user_gids)) smb_panic("lookup_usergroups out of memory");
+ for (i=0; i<(*num_groups); i++) {
+ (*user_gids)[i] = centry_uint32(centry);
+ }
- return fetch_cache_entry(domain, CACHE_TYPE_USER, uidstr, pw,
- sizeof(struct winbindd_pw));
+do_cached:
+ status = centry->status;
+ centry_free(centry);
+ return status;
+
+do_query:
+ if (wcache_server_down(domain)) {
+ (*num_groups) = 0;
+ return NT_STATUS_SERVER_DISABLED;
+ }
+ status = cache->backend->lookup_usergroups(domain, mem_ctx, user_rid, num_groups, user_gids);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_uint32(centry, *num_groups);
+ for (i=0; i<(*num_groups); i++) {
+ centry_put_uint32(centry, (*user_gids)[i]);
+ }
+ centry_end(centry, "USERGROUPS/%s/%x", domain->name, user_rid);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-/* Fetch an individual group cache entry. This function differs from the
- user cache code as we need to store the group membership data. */
-BOOL winbindd_fetch_group_cache_entry(struct winbindd_domain *domain,
- char *group, struct winbindd_gr *gr,
- void **extra_data, int *extra_data_len)
+static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 *num_names,
+ uint32 **rid_mem, char ***names,
+ uint32 **name_types)
{
- TDB_DATA data;
- fstring keystr;
- uint32 seq_num;
-
- if (lp_winbind_cache_time() == 0)
- return False;
-
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_GROUP, group);
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
- if (cache_domain_expired(domain, seq_num))
- return False;
+ if (!cache->tdb) goto do_query;
- /* Fetch group data */
+ centry = wcache_fetch(cache, domain, "GROUPMEM/%s/%x", domain->name, group_rid);
+ if (!centry) goto do_query;
- if (!fetch_cache_entry(domain, CACHE_TYPE_GROUP, group, gr, sizeof(struct winbindd_gr)))
- return False;
+ *num_names = centry_uint32(centry);
- /* Fetch extra data */
-
- snprintf(keystr, sizeof(keystr), "%s/%s/%s DATA", CACHE_TYPE_GROUP,
- domain->name, group);
+ if (*num_names == 0) goto do_cached;
- data = tdb_fetch_by_string(cache_tdb, keystr);
+ (*rid_mem) = talloc(mem_ctx, sizeof(**rid_mem) * (*num_names));
+ (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names));
+ (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names));
- if (!data.dptr)
- return False;
+ if (! (*rid_mem) || ! (*names) || ! (*name_types)) {
+ smb_panic("lookup_groupmem out of memory");
+ }
- /* Extra data freed when data has been sent */
+ for (i=0; i<(*num_names); i++) {
+ (*rid_mem)[i] = centry_uint32(centry);
+ (*names)[i] = centry_string(centry, mem_ctx);
+ (*name_types)[i] = centry_uint32(centry);
+ }
- if (extra_data)
- *extra_data = data.dptr;
+do_cached:
+ status = centry->status;
+ centry_free(centry);
+ return status;
- if (extra_data_len)
- *extra_data_len = data.dsize;
-
- return True;
+do_query:
+ if (wcache_server_down(domain)) {
+ (*num_names) = 0;
+ return NT_STATUS_SERVER_DISABLED;
+ }
+ status = cache->backend->lookup_groupmem(domain, mem_ctx, group_rid, num_names,
+ rid_mem, names, name_types);
+
+ /* and save it */
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_uint32(centry, *num_names);
+ for (i=0; i<(*num_names); i++) {
+ centry_put_uint32(centry, (*rid_mem)[i]);
+ centry_put_string(centry, (*names)[i]);
+ centry_put_uint32(centry, (*name_types)[i]);
+ }
+ centry_end(centry, "GROUPMEM/%s/%x", domain->name, group_rid);
+ centry_free(centry);
+
+skip_save:
+ return status;
}
-
-/* Fetch an individual gid cache entry. This function differs from the
- user cache code as we need to store the group membership data. */
-
-BOOL winbindd_fetch_gid_cache_entry(struct winbindd_domain *domain, gid_t gid,
- struct winbindd_gr *gr,
- void **extra_data, int *extra_data_len)
+/* find the sequence number for a domain */
+static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
- TDB_DATA data;
- fstring keystr;
- fstring gidstr;
- uint32 seq_num;
+ refresh_sequence_number(domain, False);
- snprintf(gidstr, sizeof(gidstr), "#%u", (unsigned)gid);
-
- if (lp_winbind_cache_time() == 0)
- return False;
-
- seq_num = get_cache_sequence_number(domain, CACHE_TYPE_GROUP, gidstr);
-
- if (cache_domain_expired(domain, seq_num))
- return False;
-
- /* Fetch group data */
+ *seq = domain->sequence_number;
- if (!fetch_cache_entry(domain, CACHE_TYPE_GROUP,
- gidstr, gr, sizeof(struct winbindd_gr)))
- return False;
-
- /* Fetch extra data */
-
- snprintf(keystr, sizeof(keystr), "%s/%s/%s DATA", CACHE_TYPE_GROUP,
- domain->name, gidstr);
-
- data = tdb_fetch_by_string(cache_tdb, keystr);
-
- if (!data.dptr)
- return False;
-
- /* Extra data freed when data has been sent */
-
- if (extra_data)
- *extra_data = data.dptr;
-
- if (extra_data_len)
- *extra_data_len = data.dsize;
-
- return True;
+ return NT_STATUS_OK;
}
-/* Flush cache data - easiest to just reopen the tdb */
-
-void winbindd_flush_cache(void)
-{
- tdb_close(cache_tdb);
- winbindd_cache_init();
-}
+/* the ADS backend methods are exposed via this structure */
+struct winbindd_methods cache_methods = {
+ query_user_list,
+ enum_dom_groups,
+ name_to_sid,
+ sid_to_name,
+ query_user,
+ lookup_usergroups,
+ lookup_groupmem,
+ sequence_number
+};
-/* Print cache status information */
-void winbindd_cache_status(void)
-{
-}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index 7a7abb9a8c9..e7b4541db02 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -28,8 +28,6 @@
Empty static struct for negative caching.
****************************************************************/
-static struct winbindd_gr negative_gr_cache_entry;
-
/* Fill a grent structure from various other information */
static BOOL fill_grent(struct winbindd_gr *gr, char *gr_name,
@@ -200,7 +198,7 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
fstring name_domain, name_group, name;
char *tmp, *gr_mem;
gid_t gid;
- int extra_data_len, gr_mem_len;
+ int gr_mem_len;
DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid,
state->request.data.groupname));
@@ -221,23 +219,6 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
return WINBINDD_ERROR;
}
- /* Check for cached group entry */
-
- if (winbindd_fetch_group_cache_entry(domain, name_group,
- &state->response.data.gr,
- &state->response.extra_data,
- &extra_data_len)) {
-
- /* Check if this is a negative cache entry. */
-
- if (memcmp(&negative_gr_cache_entry, &state->response.data.gr,
- sizeof(state->response.data.gr)) == 0)
- return WINBINDD_ERROR;
-
- state->response.length += extra_data_len;
- return WINBINDD_OK;
- }
-
snprintf(name, sizeof(name), "%s\\%s", name_domain, name_group);
/* Get rid and name type from name */
@@ -245,20 +226,12 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
if (!winbindd_lookup_sid_by_name(domain, name, &group_sid, &name_type)) {
DEBUG(1, ("group %s in domain %s does not exist\n",
name_group, name_domain));
-
- winbindd_store_group_cache_entry(domain, name_group,
- &negative_gr_cache_entry, NULL, 0);
-
return WINBINDD_ERROR;
}
if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) {
DEBUG(1, ("from_group: name '%s' is not a local or domain "
"group: %d\n", name_group, name_type));
-
- winbindd_store_group_cache_entry(domain, name_group,
- &negative_gr_cache_entry, NULL, 0);
-
return WINBINDD_ERROR;
}
@@ -268,10 +241,6 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, &gid)) {
DEBUG(1, ("error sursing unix gid for sid\n"));
-
- winbindd_store_group_cache_entry(domain, name_group,
- &negative_gr_cache_entry, NULL, 0);
-
return WINBINDD_ERROR;
}
@@ -280,10 +249,6 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
!fill_grent_mem(domain, group_rid, name_type,
&state->response.data.gr.num_gr_mem,
&gr_mem, &gr_mem_len)) {
-
- winbindd_store_group_cache_entry(domain, name_group,
- &negative_gr_cache_entry, NULL, 0);
-
return WINBINDD_ERROR;
}
@@ -294,13 +259,6 @@ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *sta
state->response.length += gr_mem_len;
state->response.extra_data = gr_mem;
- /* Update cached group info */
-
- winbindd_store_group_cache_entry(domain, name_group,
- &state->response.data.gr,
- state->response.extra_data,
- gr_mem_len);
-
return WINBINDD_OK;
}
@@ -314,7 +272,7 @@ enum winbindd_result winbindd_getgrnam_from_gid(struct winbindd_cli_state
enum SID_NAME_USE name_type;
fstring group_name;
uint32 group_rid;
- int extra_data_len, gr_mem_len;
+ int gr_mem_len;
char *gr_mem;
DEBUG(3, ("[%5d]: getgrgid %d\n", state->pid,
@@ -335,24 +293,6 @@ enum winbindd_result winbindd_getgrnam_from_gid(struct winbindd_cli_state
return WINBINDD_ERROR;
}
- /* Try a cached entry */
-
- if (winbindd_fetch_gid_cache_entry(domain,
- state->request.data.gid,
- &state->response.data.gr,
- &state->response.extra_data,
- &extra_data_len)) {
-
- /* Check if this is a negative cache entry. */
-
- if (memcmp(&negative_gr_cache_entry, &state->response.data.gr,
- sizeof(state->response.data.gr)) == 0)
- return WINBINDD_ERROR;
-
- state->response.length += extra_data_len;
- return WINBINDD_OK;
- }
-
/* Get sid from gid */
sid_copy(&group_sid, &domain->sid);
@@ -390,13 +330,6 @@ enum winbindd_result winbindd_getgrnam_from_gid(struct winbindd_cli_state
state->response.length += gr_mem_len;
state->response.extra_data = gr_mem;
- /* Update cached group info */
-
- winbindd_store_gid_cache_entry(domain, state->request.data.gid,
- &state->response.data.gr,
- state->response.extra_data,
- gr_mem_len);
-
return WINBINDD_OK;
}
@@ -487,13 +420,6 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
if (ent->got_all_sam_entries)
return False;
-#if 0
- if (winbindd_fetch_group_cache(ent->domain,
- &ent->sam_entries,
- &ent->num_sam_entries))
- return True;
-#endif
-
if (!(mem_ctx = talloc_init()))
return False;
@@ -547,13 +473,6 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
} while (ent->num_sam_entries < MAX_FETCH_SAM_ENTRIES);
-#if 0
- /* Fill cache with received entries */
-
- winbindd_store_group_cache(ent->domain, ent->sam_entries,
- ent->num_sam_entries);
-#endif
-
/* Fill in remaining fields */
ent->sam_entries = name_list;
diff --git a/source/nsswitch/winbindd_proto.h b/source/nsswitch/winbindd_proto.h
index 48ccace476f..fbb5c731d1d 100644
--- a/source/nsswitch/winbindd_proto.h
+++ b/source/nsswitch/winbindd_proto.h
@@ -3,6 +3,10 @@
/* This file is automatically generated with "make proto". DO NOT EDIT */
+/* The following definitions come from nsswitch/wcache.c */
+
+struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status);
+
/* The following definitions come from nsswitch/winbindd.c */
int main(int argc, char **argv);
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 9f1d46b40f0..8a98a2626de 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -403,7 +403,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
}
/* find the sequence number for a domain */
-static uint32 sequence_number(struct winbindd_domain *domain)
+static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
TALLOC_CTX *mem_ctx;
CLI_POLICY_HND *hnd;
@@ -415,8 +415,10 @@ static uint32 sequence_number(struct winbindd_domain *domain)
BOOL got_dom_pol = False;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ *seq = DOM_SEQUENCE_NONE;
+
if (!(mem_ctx = talloc_init()))
- return DOM_SEQUENCE_NONE;
+ return NT_STATUS_NO_MEMORY;
/* Get sam handle */
@@ -426,7 +428,7 @@ static uint32 sequence_number(struct winbindd_domain *domain)
/* Get domain handle */
result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
- des_access, &domain->sid, &dom_pol);
+ des_access, &domain->sid, &dom_pol);
if (!NT_STATUS_IS_OK(result))
goto done;
@@ -436,7 +438,7 @@ static uint32 sequence_number(struct winbindd_domain *domain)
/* Query domain info */
result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol,
- switch_value, &ctr);
+ switch_value, &ctr);
if (NT_STATUS_IS_OK(result)) {
seqnum = ctr.info.inf2.seq_num;
@@ -453,7 +455,9 @@ static uint32 sequence_number(struct winbindd_domain *domain)
talloc_destroy(mem_ctx);
- return seqnum;
+ *seq = seqnum;
+
+ return result;
}
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index d9b2b5a0e6e..9ac7c7faf21 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -91,12 +91,6 @@ static BOOL winbindd_fill_pwent(char *domain_name, char *name,
return True;
}
-/************************************************************************
- Empty static struct for negative caching.
-*************************************************************************/
-
-static struct winbindd_pw negative_pw_cache_entry;
-
/* Return a password structure from a username. Specify whether cached data
can be returned. */
@@ -125,30 +119,18 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat
return WINBINDD_ERROR;
}
- /* Check for cached user entry */
-
- if (winbindd_fetch_user_cache_entry(domain, name_user, &state->response.data.pw)) {
- /* Check if this is a negative cache entry. */
- if (memcmp(&negative_pw_cache_entry, &state->response.data.pw,
- sizeof(state->response.data.pw)) == 0)
- return WINBINDD_ERROR;
- return WINBINDD_OK;
- }
-
slprintf(name, sizeof(name) - 1, "%s\\%s", name_domain, name_user);
/* Get rid and name type from name */
if (!winbindd_lookup_sid_by_name(domain, name, &user_sid, &name_type)) {
DEBUG(1, ("user '%s' does not exist\n", name_user));
- winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
if (name_type != SID_NAME_USER) {
DEBUG(1, ("name '%s' is not a user name: %d\n", name_user,
name_type));
- winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
@@ -167,7 +149,6 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_user(): error getting user info for "
"user '%s'\n", name_user));
- winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
talloc_destroy(mem_ctx);
return WINBINDD_ERROR;
}
@@ -176,15 +157,12 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *stat
if (!winbindd_fill_pwent(name_domain, state->request.data.username,
user_rid, user_info.group_rid, user_info.full_name,
&state->response.data.pw)) {
- winbindd_store_user_cache_entry(domain, name_user, &negative_pw_cache_entry);
talloc_destroy(mem_ctx);
return WINBINDD_ERROR;
}
talloc_destroy(mem_ctx);
- winbindd_store_user_cache_entry(domain, name_user, &state->response.data.pw);
-
return WINBINDD_OK;
}
@@ -220,18 +198,6 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
return WINBINDD_ERROR;
}
- /* Check for cached uid entry */
-
- if (winbindd_fetch_uid_cache_entry(domain,
- state->request.data.uid,
- &state->response.data.pw)) {
- /* Check if this is a negative cache entry. */
- if (memcmp(&negative_pw_cache_entry, &state->response.data.pw,
- sizeof(state->response.data.pw)) == 0)
- return WINBINDD_ERROR;
- return WINBINDD_OK;
- }
-
/* Get name and name type from rid */
sid_copy(&user_sid, &domain->sid);
@@ -242,8 +208,6 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
sid_to_string(temp, &user_sid);
DEBUG(1, ("Could not lookup sid %s\n", temp));
-
- winbindd_store_uid_cache_entry(domain, state->request.data.uid, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
@@ -262,7 +226,6 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("pwnam_from_uid(): error getting user info for "
"user '%s'\n", user_name));
- winbindd_store_uid_cache_entry(domain, state->request.data.uid, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
@@ -277,12 +240,9 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state *state
if (!winbindd_fill_pwent(domain->name, user_name, user_rid, user_info.group_rid,
user_info.full_name, &state->response.data.pw)) {
- winbindd_store_uid_cache_entry(domain, state->request.data.uid, &negative_pw_cache_entry);
return WINBINDD_ERROR;
}
- winbindd_store_uid_cache_entry(domain, state->request.data.uid, &state->response.data.pw);
-
talloc_destroy(mem_ctx);
return WINBINDD_OK;
@@ -383,17 +343,6 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
methods = ent->domain->methods;
-#if 0
- /* Look in cache for entries, else get them direct */
-
- if (winbindd_fetch_user_cache(ent->domain,
- (struct getpwent_user **)
- &ent->sam_entries,
- &ent->num_sam_entries)) {
- return True;
- }
-#endif
-
/* Free any existing user info */
SAFE_FREE(ent->sam_entries);
@@ -453,13 +402,6 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
} while (ent->num_sam_entries < MAX_FETCH_SAM_ENTRIES);
-#if 0
- /* Fill cache with received entries */
-
- winbindd_store_user_cache(ent->domain, ent->sam_entries,
- ent->num_sam_entries);
-#endif
-
/* Fill in remaining fields */
ent->sam_entries = name_list;
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index fb041cc3eab..5add3c9ac74 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -112,6 +112,8 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
fstrcpy(domain->name, domain_name);
sid_copy(&domain->sid, domain_sid);
domain->methods = methods;
+ domain->sequence_number = DOM_SEQUENCE_NONE;
+ domain->last_seq_check = 0;
/* Link to domain list */
@@ -133,22 +135,8 @@ BOOL get_domain_info(void)
fstring level5_dom;
BOOL rv = False;
TALLOC_CTX *mem_ctx;
- extern struct winbindd_methods msrpc_methods;
- struct winbindd_methods *methods;
-
- switch (lp_security()) {
-#ifdef HAVE_ADS
- case SEC_ADS:
- {
- extern struct winbindd_methods ads_methods;
- methods = &ads_methods;
- break;
- }
-#endif
- default:
- methods = &msrpc_methods;
- }
-
+ extern struct winbindd_methods cache_methods;
+
DEBUG(1, ("getting trusted domain list\n"));
if (!(mem_ctx = talloc_init()))
@@ -165,7 +153,7 @@ BOOL get_domain_info(void)
if (!NT_STATUS_IS_OK(result))
goto done;
- add_trusted_domain(lp_workgroup(), &domain_sid, methods);
+ add_trusted_domain(lp_workgroup(), &domain_sid, &cache_methods);
/* Enumerate list of trusted domains */
@@ -181,7 +169,7 @@ BOOL get_domain_info(void)
/* Add each domain to the trusted domain list */
for(i = 0; i < num_doms; i++)
- add_trusted_domain(domains[i], &sids[i], methods);
+ add_trusted_domain(domains[i], &sids[i], &cache_methods);
rv = True;
@@ -260,99 +248,6 @@ BOOL lookup_domain_sid(char *domain_name, struct winbindd_domain *domain)
return rv;
}
-/* Store a SID in a domain indexed by name in the cache. */
-
-static void store_sid_by_name_in_cache(struct winbindd_domain *domain,
- const char *name,
- DOM_SID *sid, enum SID_NAME_USE type)
-{
- struct winbindd_sid sid_val;
-
- sid_to_string(sid_val.sid, sid);
- sid_val.type = (int)type;
-
- DEBUG(10,("store_sid_by_name_in_cache: storing cache entry %s -> SID %s\n",
- name, sid_val.sid ));
-
- winbindd_store_sid_cache_entry(domain, name, &sid_val);
-}
-
-/* Lookup a SID in a domain indexed by name in the cache. */
-
-static BOOL winbindd_lookup_sid_by_name_in_cache(struct winbindd_domain *domain,
- const char *name,
- DOM_SID *sid, enum SID_NAME_USE *type)
-{
- struct winbindd_sid sid_ret;
-
- if (!winbindd_fetch_sid_cache_entry(domain, name, &sid_ret))
- return False;
-
- string_to_sid( sid, sid_ret.sid);
- *type = (enum SID_NAME_USE)sid_ret.type;
-
- DEBUG(10,("winbindd_lookup_sid_by_name_in_cache: Cache hit for name %s. SID = %s\n",
- name, sid_ret.sid ));
-
- return True;
-}
-
-/* Store a name in a domain indexed by SID in the cache. */
-
-static void store_name_by_sid_in_cache(struct winbindd_domain *domain,
- DOM_SID *sid,
- const char *name, enum SID_NAME_USE type)
-{
- fstring sid_str;
- uint32 rid;
- DOM_SID domain_sid;
- struct winbindd_name name_val;
-
- /* Split sid into domain sid and user rid */
- sid_copy(&domain_sid, sid);
- sid_split_rid(&domain_sid, &rid);
-
- sid_to_string(sid_str, sid);
- fstrcpy(name_val.name, name );
- name_val.type = (int)type;
-
- DEBUG(10,("store_name_by_sid_in_cache: storing cache entry SID %s -> %s\n",
- sid_str, name_val.name ));
-
- winbindd_store_name_cache_entry(domain, sid_str, &name_val);
-}
-
-/* Lookup a name in a domain indexed by SID in the cache. */
-
-static BOOL winbindd_lookup_name_by_sid_in_cache(DOM_SID *sid, fstring name, enum SID_NAME_USE *type)
-{
- fstring sid_str;
- uint32 rid;
- DOM_SID domain_sid;
- struct winbindd_name name_ret;
- struct winbindd_domain *domain;
-
- /* Split sid into domain sid and user rid */
- sid_copy(&domain_sid, sid);
- sid_split_rid(&domain_sid, &rid);
-
- if ((domain = find_domain_from_sid(&domain_sid)) == NULL)
- return False;
-
- sid_to_string(sid_str, sid);
-
- if (!winbindd_fetch_name_cache_entry(domain, sid_str, &name_ret))
- return False;
-
- fstrcpy( name, name_ret.name );
- *type = (enum SID_NAME_USE)name_ret.type;
-
- DEBUG(10,("winbindd_lookup_name_by_sid_in_cache: Cache hit for SID = %s, name %s\n",
- sid_str, name ));
-
- return True;
-}
-
/* Lookup a sid in a domain from a name */
BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
@@ -365,26 +260,11 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
if (name[strlen(name) - 1] == '$')
return False;
- /* First check cache. */
- if (winbindd_lookup_sid_by_name_in_cache(domain, name, sid, type)) {
- if (*type == SID_NAME_USE_NONE)
- return False; /* Negative cache hit. */
- return True;
- }
/* Lookup name */
result = domain->methods->name_to_sid(domain, name, sid, type);
/* Return rid and type if lookup successful */
- if (NT_STATUS_IS_OK(result)) {
- store_sid_by_name_in_cache(domain, name, sid, *type);
- store_name_by_sid_in_cache(domain, sid, name, *type);
- } else {
- /* JRA. Here's where we add the -ve cache store with a
- name type of SID_NAME_USE_NONE. */
- DOM_SID nullsid;
-
- ZERO_STRUCT(nullsid);
- store_sid_by_name_in_cache(domain, name, &nullsid, SID_NAME_USE_NONE);
+ if (!NT_STATUS_IS_OK(result)) {
*type = SID_NAME_UNKNOWN;
}
@@ -414,16 +294,6 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
BOOL rv = False;
struct winbindd_domain *domain;
- /* First check cache. */
- if (winbindd_lookup_name_by_sid_in_cache(sid, name, type)) {
- if (*type == SID_NAME_USE_NONE) {
- fstrcpy(name, name_deadbeef);
- *type = SID_NAME_UNKNOWN;
- return False; /* Negative cache hit. */
- } else
- return True;
- }
-
domain = find_domain_from_sid(sid);
if (!domain) {
DEBUG(1,("Can't find domain from sid\n"));
@@ -441,14 +311,7 @@ BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
if ((rv = NT_STATUS_IS_OK(result))) {
fstrcpy(name, names);
-
- store_sid_by_name_in_cache(domain, names, sid, *type);
- store_name_by_sid_in_cache(domain, sid, names, *type);
} else {
- /* OK, so we tried to look up a name in this sid, and
- * didn't find it. Therefore add a negative cache
- * entry. */
- store_name_by_sid_in_cache(domain, sid, "", SID_NAME_USE_NONE);
*type = SID_NAME_UNKNOWN;
fstrcpy(name, name_deadbeef);
}