summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/winbindd.c5
-rw-r--r--source3/nsswitch/winbindd_cache.c126
2 files changed, 117 insertions, 14 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 39bd66989c..b17172f4f2 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -1081,6 +1081,11 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ /* Initialize cache (ensure version is correct). */
+ if (!initialize_winbindd_cache()) {
+ exit(1);
+ }
+
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
message_register(MSG_SMB_CONF_UPDATED, msg_reload_services, NULL);
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 355f3e1b16..6b9721a83b 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -29,12 +29,53 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+#define WINBINDD_CACHE_VERSION 1
+#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
+
extern struct winbindd_methods reconnect_methods;
extern BOOL opt_nocache;
#ifdef HAVE_ADS
extern struct winbindd_methods ads_methods;
#endif
+/*
+ * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
+ * Here are the list of entry types that are *not* stored
+ * as form struct cache_entry in the cache.
+ */
+
+static const char *non_centry_keys[] = {
+ "SEQNUM/",
+ "DR/",
+ "DE/",
+ "WINBINDD_OFFLINE",
+ WINBINDD_CACHE_VERSION_KEYSTR,
+ NULL
+};
+
+/************************************************************************
+ Is this key a non-centry type ?
+************************************************************************/
+
+static BOOL is_non_centry_key(TDB_DATA kbuf)
+{
+ int i;
+
+ if (kbuf.dptr == NULL || kbuf.dsize == 0) {
+ return False;
+ }
+ for (i = 0; non_centry_keys[i] != NULL; i++) {
+ size_t namelen = strlen(non_centry_keys[i]);
+ if (kbuf.dsize <= namelen) {
+ continue;
+ }
+ if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) {
+ return True;
+ }
+ }
+ return False;
+}
+
/* Global online/offline state - False when online. winbindd starts up online
and sets this to true if the first query fails and there's an entry in
the cache tdb telling us to stay offline. */
@@ -237,18 +278,11 @@ static NTTIME centry_nttime(struct cache_entry *centry)
}
/*
- pull a time_t from a cache entry
+ pull a time_t from a cache entry. time_t stored portably as a 64-bit time.
*/
static time_t centry_time(struct cache_entry *centry)
{
- time_t ret;
- if (centry_check_bytes(centry, sizeof(time_t))) {
- smb_panic_fn("centry_time");
- return (time_t)-1;
- }
- ret = IVAL(centry->data, centry->ofs); /* FIXME: correct ? */
- centry->ofs += sizeof(time_t);
- return ret;
+ return (time_t)centry_nttime(centry);
}
/* pull a string from a cache entry, using the supplied
@@ -719,13 +753,13 @@ static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
}
/*
- push a time_t into a centry
+ push a time_t into a centry - use a 64 bit size.
+ NTTIME here is being used as a convenient 64-bit size.
*/
static void centry_put_time(struct cache_entry *centry, time_t t)
{
- centry_expand(centry, sizeof(time_t));
- SIVAL(centry->data, centry->ofs, t); /* FIXME: is this correct ?? */
- centry->ofs += sizeof(time_t);
+ NTTIME nt = (NTTIME)t;
+ return centry_put_nttime(centry, nt);
}
/*
@@ -2164,6 +2198,61 @@ static BOOL init_wcache(void)
return True;
}
+/************************************************************************
+ This is called by the parent to initialize the cache file.
+ We don't need sophisticated locking here as we know we're the
+ only opener.
+************************************************************************/
+
+BOOL initialize_winbindd_cache(void)
+{
+ BOOL cache_bad = True;
+ uint32 vers;
+
+ if (!init_wcache()) {
+ DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n"));
+ return False;
+ }
+
+ /* Check version number. */
+ if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) &&
+ vers == WINBINDD_CACHE_VERSION) {
+ cache_bad = False;
+ }
+
+ if (cache_bad) {
+ DEBUG(0,("initialize_winbindd_cache: clearing cache "
+ "and re-creating with version number %d\n",
+ WINBINDD_CACHE_VERSION ));
+
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+
+ if (unlink(lock_path("winbindd_cache.tdb")) == -1) {
+ DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ",
+ lock_path("winbindd_cache.tdb"),
+ strerror(errno) ));
+ return False;
+ }
+ if (!init_wcache()) {
+ DEBUG(0,("initialize_winbindd_cache: re-initialization "
+ "init_wcache failed.\n"));
+ return False;
+ }
+
+ /* Write the version. */
+ if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) {
+ DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n",
+ tdb_errorstr(wcache->tdb) ));
+ return False;
+ }
+ }
+
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+ return True;
+}
+
void cache_store_response(pid_t pid, struct winbindd_response *response)
{
fstring key_str;
@@ -2360,12 +2449,21 @@ void cache_name2sid(struct winbindd_domain *domain,
sid, type);
}
-/* delete all centries that don't have NT_STATUS_OK set */
+/*
+ * The original idea that this cache only contains centries has
+ * been blurred - now other stuff gets put in here. Ensure we
+ * ignore these things on cleanup.
+ */
+
static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
TDB_DATA dbuf, void *state)
{
struct cache_entry *centry;
+ if (is_non_centry_key(kbuf)) {
+ return 0;
+ }
+
centry = wcache_fetch_raw((char *)kbuf.dptr);
if (!centry) {
return 0;