diff options
author | Andrew Tridgell <tridge@samba.org> | 2001-12-09 23:59:42 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2001-12-09 23:59:42 +0000 |
commit | 31842f5d017f01922cec306f7bfa2fa0fe748ca2 (patch) | |
tree | 3a17ecc634f1079f60fcb81d05d3672d65b84aa0 | |
parent | e3d171ff55c7afec6687616a3808637f2d4cf456 (diff) | |
download | samba-31842f5d017f01922cec306f7bfa2fa0fe748ca2.tar.gz samba-31842f5d017f01922cec306f7bfa2fa0fe748ca2.tar.bz2 samba-31842f5d017f01922cec306f7bfa2fa0fe748ca2.zip |
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.
(This used to be commit fddb4f4c04473a60a97212c0c8e143d6a4d68380)
-rw-r--r-- | source3/nsswitch/winbindd.c | 21 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 997 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 85 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_proto.h | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 14 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 58 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 151 |
9 files changed, 591 insertions, 756 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index c1402dc8fb..0db16b6874 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/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/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 21dca93af5..a4c0dd970d 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/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/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 2510e4a501..cabb482f7d 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/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/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 32ef3526fa..da918df4f3 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/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/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 7a7abb9a8c..e7b4541db0 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/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/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index 48ccace476..fbb5c731d1 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/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/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 9f1d46b40f..8a98a2626d 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/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/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index d9b2b5a0e6..9ac7c7faf2 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/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/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index fb041cc3ea..5add3c9ac7 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/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); } |