[SCM] Samba Shared Repository - branch v3-5-test updated

Karolin Seeger kseeger at samba.org
Fri Dec 16 05:59:25 MST 2011


The branch, v3-5-test has been updated
       via  1854e6a s3-winbind: Add an update function for winbind cache.
       via  b5215ca Fix bug #8521 - winbindd cache timeout expiry test was reversed
       via  6a761e8 s3:winbind add timeouts to winbind cache
      from  a8037a5 s3/doc: document the ignore system acls option of vfs_acl_xattr and vfs_acl_tdb

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit 1854e6a766e1a7bf55b175d7975d3b6235149c7d
Author: Andreas Schneider <asn at samba.org>
Date:   Fri Dec 2 16:19:34 2011 -0800

    s3-winbind: Add an update function for winbind cache.
    
    With 57b3d32 we changed the format for the winbind cache database and
    the code deleted the database for the upgrade. As this database holds
    also cached credentials, removing it is not an option. We need to update
    from version 1 to version 2.
    
    Autobuild-User: Jeremy Allison <jra at samba.org>
    Autobuild-Date: Sat Dec  3 03:47:58 CET 2011 on sn-devel-104
    (cherry picked from commit a3f600521122d1a6d74d16668bd1ea4447c5c867)
    
    The last 3 patches address bug #8658 (Negative / positive winbind cache won't
    expire till opposite type of query is made).

commit b5215ca58c7501e093030c527f82078c8b315b88
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 12 09:43:18 2011 -0700

    Fix bug #8521 - winbindd cache timeout expiry test was reversed
    
    Found and fix reported by Micha Lenk <micha at lenk.info>. Thanks !
    (cherry picked from commit 1e4761d05978b7a495d121acc1deaa7049f3911c)

commit 6a761e873c34badd628a5460dd18830465ec484c
Author: Christian Ambach <christian.ambach at de.ibm.com>
Date:   Thu Nov 4 17:10:25 2010 +0100

    s3:winbind add timeouts to winbind cache
    
    This adds a timeout value to cache entries and the NDR records
    in the winbind cache.
    
    The previous approach of just comparing the sequence number has some issues,
    e.g. when retrying a wbinfo -n operation for a user in a not yet trusted
    domain was always failing even after the trusted domain was added.
    
    The new approach compares sequence number and timeout value to
    determine if a cache entry is still valid or not.
    
    I increased the cache version number so an old cache will be wiped
    automatically after upgrade.
    (cherry picked from commit 57b3d32c8d87c4273d30d73fe2bfd3de0178945d)

-----------------------------------------------------------------------

Summary of changes:
 source3/winbindd/winbindd_cache.c |  165 +++++++++++++++++++++++++++++++++----
 1 files changed, 150 insertions(+), 15 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 64a4a1c..ff4eeaa 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -32,7 +32,10 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-#define WINBINDD_CACHE_VERSION 1
+#define WINBINDD_CACHE_VER1 1 /* initial db version */
+#define WINBINDD_CACHE_VER2 2 /* second version with timeouts for NDR entries */
+
+#define WINBINDD_CACHE_VERSION WINBINDD_CACHE_VER2
 #define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
 
 extern struct winbindd_methods reconnect_methods;
@@ -92,6 +95,7 @@ struct winbind_cache {
 struct cache_entry {
 	NTSTATUS status;
 	uint32 sequence_number;
+	uint64 timeout;
 	uint8 *data;
 	uint32 len, ofs;
 };
@@ -223,6 +227,21 @@ static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes)
 }
 
 /*
+  pull a uint64 from a cache entry
+*/
+static uint64 centry_uint64(struct cache_entry *centry)
+{
+	uint64 ret;
+
+	if (!centry_check_bytes(centry, 8)) {
+		smb_panic_fn("centry_uint64");
+	}
+	ret = BVAL(centry->data, centry->ofs);
+	centry->ofs += 8;
+	return ret;
+}
+
+/*
   pull a uint32 from a cache entry 
 */
 static uint32 centry_uint32(struct cache_entry *centry)
@@ -614,9 +633,10 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s
 	}
 
 	/* 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) {
+	   current sequence number or it did not timeout then it is OK */
+	if (wcache_server_down(domain)
+	    || (centry->sequence_number == domain->sequence_number
+		&& centry->timeout > time(NULL))) {
 		DEBUG(10,("centry_expired: Key %s for domain %s is good.\n",
 			keystr, domain->name ));
 		return false;
@@ -647,15 +667,17 @@ static struct cache_entry *wcache_fetch_raw(char *kstr)
 	centry->len = data.dsize;
 	centry->ofs = 0;
 
-	if (centry->len < 8) {
+	if (centry->len < 16) {
 		/* huh? corrupt cache? */
-		DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr));
+		DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s "
+			  "(len < 16)?\n", kstr));
 		centry_free(centry);
 		return NULL;
 	}
 
 	centry->status = centry_ntstatus(centry);
 	centry->sequence_number = centry_uint32(centry);
+	centry->timeout = centry_uint64(centry);
 
 	return centry;
 }
@@ -742,6 +764,16 @@ static void centry_expand(struct cache_entry *centry, uint32 len)
 }
 
 /*
+  push a uint64 into a centry
+*/
+static void centry_put_uint64(struct cache_entry *centry, uint64 v)
+{
+	centry_expand(centry, 8);
+	SBVAL(centry->data, centry->ofs, v);
+	centry->ofs += 8;
+}
+
+/*
   push a uint32 into a centry 
 */
 static void centry_put_uint32(struct cache_entry *centry, uint32 v)
@@ -862,8 +894,10 @@ struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status
 	centry->data = SMB_XMALLOC_ARRAY(uint8, centry->len);
 	centry->ofs = 0;
 	centry->sequence_number = domain->sequence_number;
+	centry->timeout = lp_winbind_cache_time() + time(NULL);
 	centry_put_ntstatus(centry, status);
 	centry_put_uint32(centry, centry->sequence_number);
+	centry_put_uint64(centry, centry->timeout);
 	return centry;
 }
 
@@ -3448,9 +3482,10 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat
 	centry->len = data.dsize;
 	centry->ofs = 0;
 
-	if (centry->len < 8) {
+	if (centry->len < 16) {
 		/* huh? corrupt cache? */
-		DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr));
+		DEBUG(0,("create_centry_validate: Corrupt cache for key %s "
+			 "(len < 16) ?\n", kstr));
 		centry_free(centry);
 		state->bad_entry = true;
 		state->success = false;
@@ -3459,6 +3494,7 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat
 
 	centry->status = NT_STATUS(centry_uint32(centry));
 	centry->sequence_number = centry_uint32(centry);
+	centry->timeout = centry_uint64(centry);
 	return centry;
 }
 
@@ -4011,6 +4047,70 @@ static void validate_panic(const char *const why)
 	exit(47);
 }
 
+static int wbcache_update_centry_fn(TDB_CONTEXT *tdb,
+				    TDB_DATA key,
+				    TDB_DATA data,
+				    void *state)
+{
+	uint64_t ctimeout;
+	TDB_DATA blob;
+
+	if (is_non_centry_key(key)) {
+		return 0;
+	}
+
+	if (data.dptr == NULL || data.dsize == 0) {
+		if (tdb_delete(tdb, key) < 0) {
+			DEBUG(0, ("tdb_delete for [%s] failed!\n",
+				  key.dptr));
+			return 1;
+		}
+	}
+
+	/* add timeout to blob (uint64_t) */
+	blob.dsize = data.dsize + 8;
+
+	blob.dptr = SMB_XMALLOC_ARRAY(uint8_t, blob.dsize);
+	if (blob.dptr == NULL) {
+		return 1;
+	}
+	memset(blob.dptr, 0, blob.dsize);
+
+	/* copy status and seqnum */
+	memcpy(blob.dptr, data.dptr, 8);
+
+	/* add timeout */
+	ctimeout = lp_winbind_cache_time() + time(NULL);
+	SBVAL(blob.dptr, 8, ctimeout);
+
+	/* copy the rest */
+	memcpy(blob.dptr + 16, data.dptr + 8, data.dsize - 8);
+
+	if (tdb_store(tdb, key, blob, TDB_REPLACE) < 0) {
+		DEBUG(0, ("tdb_store to update [%s] failed!\n",
+			  key.dptr));
+		SAFE_FREE(blob.dptr);
+		return 1;
+	}
+
+	SAFE_FREE(blob.dptr);
+	return 0;
+}
+
+static bool wbcache_upgrade_v1_to_v2(TDB_CONTEXT *tdb)
+{
+	int rc;
+
+	DEBUG(1, ("Upgrade to version 2 of the winbindd_cache.tdb\n"));
+
+	rc = tdb_traverse(tdb, wbcache_update_centry_fn, NULL);
+	if (rc < 0) {
+		return false;
+	}
+
+	return true;
+}
+
 /***********************************************************************
  Try and validate every entry in the winbindd cache. If we fail here,
  delete the cache tdb and return non-zero.
@@ -4021,11 +4121,12 @@ int winbindd_validate_cache(void)
 	int ret = -1;
 	const char *tdb_path = cache_path("winbindd_cache.tdb");
 	TDB_CONTEXT *tdb = NULL;
+	uint32_t vers_id;
+	bool ok;
 
 	DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
 	smb_panic_fn = validate_panic;
 
-
 	tdb = tdb_open_log(tdb_path, 
 			   WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
 			   ( lp_winbind_offline_logon() 
@@ -4038,6 +4139,30 @@ int winbindd_validate_cache(void)
 			  "error opening/initializing tdb\n"));
 		goto done;
 	}
+
+	/* Version check and upgrade code. */
+	if (!tdb_fetch_uint32(tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers_id)) {
+		DEBUG(10, ("Fresh database\n"));
+		tdb_store_uint32(tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION);
+		vers_id = WINBINDD_CACHE_VERSION;
+	}
+
+	if (vers_id != WINBINDD_CACHE_VERSION) {
+		if (vers_id == WINBINDD_CACHE_VER1) {
+			ok = wbcache_upgrade_v1_to_v2(tdb);
+			if (!ok) {
+				DEBUG(10, ("winbindd_validate_cache: upgrade to version 2 failed.\n"));
+				unlink(tdb_path);
+				goto done;
+			}
+
+			tdb_store_uint32(tdb,
+					 WINBINDD_CACHE_VERSION_KEYSTR,
+					 WINBINDD_CACHE_VERSION);
+			vers_id = WINBINDD_CACHE_VER2;
+		}
+	}
+
 	tdb_close(tdb);
 
 	ret = tdb_validate_and_backup(tdb_path, cache_traverse_validate_fn);
@@ -4657,12 +4782,13 @@ bool wcache_fetch_ndr(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
 	if (data.dptr == NULL) {
 		return false;
 	}
-	if (data.dsize < 4) {
+	if (data.dsize < 12) {
 		goto fail;
 	}
 
 	if (!is_domain_offline(domain)) {
 		uint32_t entry_seqnum, dom_seqnum, last_check;
+		uint64_t entry_timeout;
 
 		if (!wcache_fetch_seqnum(domain->name, &dom_seqnum,
 					 &last_check)) {
@@ -4674,15 +4800,20 @@ bool wcache_fetch_ndr(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
 				   (int)entry_seqnum));
 			goto fail;
 		}
+		entry_timeout = BVAL(data.dptr, 4);
+		if (time(NULL) > entry_timeout) {
+			DEBUG(10, ("Entry has timed out\n"));
+			goto fail;
+		}
 	}
 
-	resp->data = (uint8_t *)talloc_memdup(mem_ctx, data.dptr + 4,
-					      data.dsize - 4);
+	resp->data = (uint8_t *)talloc_memdup(mem_ctx, data.dptr + 12,
+					      data.dsize - 12);
 	if (resp->data == NULL) {
 		DEBUG(10, ("talloc failed\n"));
 		goto fail;
 	}
-	resp->length = data.dsize - 4;
+	resp->length = data.dsize - 12;
 
 	ret = true;
 fail:
@@ -4695,6 +4826,7 @@ void wcache_store_ndr(struct winbindd_domain *domain, uint32_t opnum,
 {
 	TDB_DATA key, data;
 	uint32_t dom_seqnum, last_check;
+	uint64_t timeout;
 
 	if (!wcache_opnum_cacheable(opnum)) {
 		return;
@@ -4714,14 +4846,17 @@ void wcache_store_ndr(struct winbindd_domain *domain, uint32_t opnum,
 		return;
 	}
 
-	data.dsize = resp->length + 4;
+	timeout = time(NULL) + lp_winbind_cache_time();
+
+	data.dsize = resp->length + 12;
 	data.dptr = talloc_array(key.dptr, uint8_t, data.dsize);
 	if (data.dptr == NULL) {
 		goto done;
 	}
 
 	SIVAL(data.dptr, 0, dom_seqnum);
-	memcpy(data.dptr+4, resp->data, resp->length);
+	SBVAL(data.dptr, 4, timeout);
+	memcpy(data.dptr + 12, resp->data, resp->length);
 
 	tdb_store(wcache->tdb, key, data, 0);
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list