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:
parent
58cfa5a825
commit
57b3d32c8d
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user