1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-25 17:57:42 +03:00

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.
This commit is contained in:
Christian Ambach 2010-11-04 17:10:25 +01:00 committed by Volker Lendecke
parent 58cfa5a825
commit 57b3d32c8d

View File

@ -35,7 +35,7 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
#define WINBINDD_CACHE_VERSION 1
#define WINBINDD_CACHE_VERSION 2
#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
extern struct winbindd_methods reconnect_methods;
@ -96,6 +96,7 @@ struct winbind_cache {
struct cache_entry {
NTSTATUS status;
uint32 sequence_number;
uint64 timeout;
uint8 *data;
uint32 len, ofs;
};
@ -204,6 +205,21 @@ static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes)
return true;
}
/*
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
*/
@ -596,9 +612,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;
@ -629,15 +646,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;
}
@ -745,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
*/
@ -866,8 +895,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;
}
@ -3484,9 +3515,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;
@ -3495,6 +3527,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;
}
@ -4699,12 +4732,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)) {
@ -4716,15 +4750,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 (entry_timeout > time(NULL)) {
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:
@ -4737,6 +4776,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) ||
is_my_own_sam_domain(domain) ||
@ -4758,14 +4798,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);