diff options
author | Volker Lendecke <vl@samba.org> | 2008-07-11 17:42:58 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2008-07-11 17:53:24 +0200 |
commit | b6dcc24987c5c8790502c70687cb0c302333d12c (patch) | |
tree | 48b2541962a0affe250090180e73b169d48a19e9 /source3 | |
parent | ebb2d70a607cf33f3d2084d715c2d9d4329f2e7b (diff) | |
download | samba-b6dcc24987c5c8790502c70687cb0c302333d12c.tar.gz samba-b6dcc24987c5c8790502c70687cb0c302333d12c.tar.bz2 samba-b6dcc24987c5c8790502c70687cb0c302333d12c.zip |
Revert "Convert idmap_cache to gencache"
This reverts commit 0bf0434f22b0ea46fda3ccc4dd612adbc88dd4f2.
(This used to be commit cc536677735ecc318cbd2176ce53b124f44d85a0)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/proto.h | 13 | ||||
-rw-r--r-- | source3/winbindd/idmap.c | 54 | ||||
-rw-r--r-- | source3/winbindd/idmap_cache.c | 463 | ||||
-rw-r--r-- | source3/winbindd/winbindd.h | 1 |
4 files changed, 399 insertions, 132 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 43420985a3..278a42a974 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -10494,13 +10494,12 @@ char *idmap_fetch_secret(const char *backend, bool alloc, /* The following definitions come from winbindd/idmap_cache.c */ -NTSTATUS idmap_cache_set(const struct id_map *id); -NTSTATUS idmap_cache_set_negative_sid(const struct id_map *id); -NTSTATUS idmap_cache_set_negative_id(const struct id_map *id); -bool idmap_cache_map_sid(const struct dom_sid *sid, struct unixid *xid, - bool *mapped, bool *expired); -bool idmap_cache_map_id(const struct unixid *xid, struct dom_sid *psid, - bool *mapped, bool *expired); +struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx); +NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id); +NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id); +NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id); +NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id); +NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id); /* The following definitions come from winbindd/idmap_nss.c */ diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index db17245b92..32fc3dc975 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -40,6 +40,8 @@ struct idmap_alloc_backend { struct idmap_alloc_backend *prev, *next; }; +struct idmap_cache_ctx; + struct idmap_alloc_context { const char *params; struct idmap_alloc_methods *methods; @@ -47,6 +49,7 @@ struct idmap_alloc_context { }; static TALLOC_CTX *idmap_ctx = NULL; +static struct idmap_cache_ctx *idmap_cache; static struct idmap_backend *backends = NULL; static struct idmap_domain **idmap_domains = NULL; @@ -243,6 +246,7 @@ NTSTATUS idmap_close(void) /* this talloc_free call will fire the talloc destructors * that will free all active backends resources */ TALLOC_FREE(idmap_ctx); + idmap_cache = NULL; idmap_domains = NULL; backends = NULL; @@ -265,6 +269,10 @@ NTSTATUS idmap_init_cache(void) return NT_STATUS_NO_MEMORY; } + if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) { + return NT_STATUS_UNSUCCESSFUL; + } + return NT_STATUS_OK; } @@ -1308,28 +1316,15 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) for (i = 0; ids[i]; i++) { - bool found, mapped, expired; - if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ids[i]->status = ID_UNKNOWN; - - found = idmap_cache_map_id(&ids[i]->xid, ids[i]->sid, - &mapped, &expired); - - if (found) { - ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; - } - - if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + ret = idmap_cache_map_id(idmap_cache, ids[i]); - /* - * Need to ask the backend - */ + if ( ! NT_STATUS_IS_OK(ret)) { if ( ! bids) { /* alloc space for ids to be resolved by @@ -1381,7 +1376,7 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) /* update the cache */ for (i = 0; i < bi; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(bids[i]); + ret = idmap_cache_set(idmap_cache, bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1396,7 +1391,8 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_id(bids[i]); + ret = idmap_cache_set_negative_id(idmap_cache, + bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1438,28 +1434,15 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) for (i = 0; ids[i]; i++) { - bool found, mapped, expired; - if ( ! ids[i]->sid) { DEBUG(1, ("invalid null SID in id_map array\n")); talloc_free(ctx); return NT_STATUS_INVALID_PARAMETER; } - ids[i]->status = ID_UNKNOWN; - - found = idmap_cache_map_sid(ids[i]->sid, &ids[i]->xid, - &mapped, &expired); - - if (found) { - ids[i]->status = mapped ? ID_MAPPED : ID_UNMAPPED; - } - - if (!found || (expired && IS_DOMAIN_ONLINE(our_domain))) { + ret = idmap_cache_map_sid(idmap_cache, ids[i]); - /* - * Need to ask the backends - */ + if ( ! NT_STATUS_IS_OK(ret)) { if ( ! bids) { /* alloc space for ids to be resolved @@ -1511,7 +1494,7 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) /* update the cache */ for (i = 0; bids[i]; i++) { if (bids[i]->status == ID_MAPPED) { - ret = idmap_cache_set(bids[i]); + ret = idmap_cache_set(idmap_cache, bids[i]); } else if (bids[i]->status == ID_EXPIRED) { /* the cache returned an expired entry and the * backend was not able to clear the situation @@ -1526,7 +1509,8 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids) * settle down. */ bids[i]->status = ID_UNMAPPED; } else { /* unmapped */ - ret = idmap_cache_set_negative_sid(bids[i]); + ret = idmap_cache_set_negative_sid(idmap_cache, + bids[i]); } IDMAP_CHECK_RET(ret); } @@ -1566,7 +1550,7 @@ NTSTATUS idmap_set_mapping(const struct id_map *id) IDMAP_CHECK_RET(ret); /* set the mapping in the cache */ - ret = idmap_cache_set(id); + ret = idmap_cache_set(idmap_cache, id); IDMAP_CHECK_RET(ret); done: diff --git a/source3/winbindd/idmap_cache.c b/source3/winbindd/idmap_cache.c index 191cadb536..8bf797f952 100644 --- a/source3/winbindd/idmap_cache.c +++ b/source3/winbindd/idmap_cache.c @@ -1,8 +1,9 @@ -/* +/* Unix SMB/CIFS implementation. ID Mapping Cache - Copyright (C) Volker Lendecke 2008 + based on gencache + Copyright (C) Simo Sorce 2006 Copyright (C) Rafal Szczesniak 2002 @@ -22,6 +23,52 @@ #include "includes.h" #include "winbindd.h" +#define TIMEOUT_LEN 12 +#define IDMAP_CACHE_DATA_FMT "%12u/%s" + +struct idmap_cache_ctx { + TDB_CONTEXT *tdb; +}; + +static int idmap_cache_destructor(struct idmap_cache_ctx *cache) +{ + int ret = 0; + + if (cache && cache->tdb) { + ret = tdb_close(cache->tdb); + cache->tdb = NULL; + } + + return ret; +} + +struct idmap_cache_ctx *idmap_cache_init(TALLOC_CTX *memctx) +{ + struct idmap_cache_ctx *cache; + char* cache_fname = NULL; + + cache = talloc(memctx, struct idmap_cache_ctx); + if ( ! cache) { + DEBUG(0, ("Out of memory!\n")); + return NULL; + } + + cache_fname = lock_path("idmap_cache.tdb"); + + DEBUG(10, ("Opening cache file at %s\n", cache_fname)); + + cache->tdb = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + + if (!cache->tdb) { + DEBUG(5, ("Attempt to open %s has failed.\n", cache_fname)); + return NULL; + } + + talloc_set_destructor(cache, idmap_cache_destructor); + + return cache; +} + static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) { fstring sidstr; @@ -30,19 +77,21 @@ static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid) sid_to_fstring(sidstr, sid)); } -static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct unixid *xid) +static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct id_map *id) { return talloc_asprintf(ctx, "IDMAP/%s/%lu", - (xid->type==ID_TYPE_UID)?"UID":"GID", - (unsigned long)xid->id); + (id->xid.type==ID_TYPE_UID)?"UID":"GID", + (unsigned long)id->xid.id); } -NTSTATUS idmap_cache_set(const struct id_map *id) +NTSTATUS idmap_cache_set(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret; time_t timeout = time(NULL) + lp_idmap_cache_time(); + TDB_DATA databuf; char *sidkey; char *idkey; + char *valstr; /* Don't cache lookups in the S-1-22-{1,2} domain */ @@ -51,179 +100,415 @@ NTSTATUS idmap_cache_set(const struct id_map *id) return NT_STATUS_OK; } - sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } /* use sidkey as the local memory ctx */ - idkey = idmap_cache_idkey(sidkey, &id->xid); + idkey = idmap_cache_idkey(sidkey, id); if (idkey == NULL) { ret = NT_STATUS_NO_MEMORY; goto done; } - if (!gencache_set(idkey, sidkey, timeout) - || !gencache_set(sidkey, idkey, timeout)) { + /* save SID -> ID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, idkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr , ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { + DEBUG(3, ("Failed to store cache entry!\n")); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* save ID -> SID */ + + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, sidkey); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } ret = NT_STATUS_OK; done: - TALLOC_FREE(sidkey); + talloc_free(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_sid(const struct id_map *id) +NTSTATUS idmap_cache_set_negative_sid(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; char *sidkey; + char *valstr; - sidkey = idmap_cache_sidkey(talloc_tos(), id->sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { return NT_STATUS_NO_MEMORY; } - if (!gencache_set(sidkey, "IDMAP/NEGATIVE", - time(NULL) + lp_idmap_negative_cache_time())) { + /* use sidkey as the local memory ctx */ + valstr = talloc_asprintf(sidkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", sidkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, sidkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } done: - TALLOC_FREE(sidkey); + talloc_free(sidkey); return ret; } -NTSTATUS idmap_cache_set_negative_id(const struct id_map *id) +NTSTATUS idmap_cache_set_negative_id(struct idmap_cache_ctx *cache, const struct id_map *id) { NTSTATUS ret = NT_STATUS_OK; + time_t timeout = time(NULL) + lp_idmap_negative_cache_time(); + TDB_DATA databuf; char *idkey; + char *valstr; - idkey = idmap_cache_idkey(talloc_tos(), &id->xid); + idkey = idmap_cache_idkey(cache, id); if (idkey == NULL) { return NT_STATUS_NO_MEMORY; } - if (!gencache_set(idkey, "IDMAP/NEGATIVE", - time(NULL) + lp_idmap_negative_cache_time())) { + /* use idkey as the local memory ctx */ + valstr = talloc_asprintf(idkey, IDMAP_CACHE_DATA_FMT, (int)timeout, "IDMAP/NEGATIVE"); + if (!valstr) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + databuf = string_term_tdb_data(valstr); + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", idkey, valstr, ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + + if (tdb_store_bystring(cache->tdb, idkey, databuf, TDB_REPLACE) != 0) { DEBUG(3, ("Failed to store cache entry!\n")); - ret = NT_STATUS_ACCESS_DENIED; + ret = NT_STATUS_UNSUCCESSFUL; goto done; } done: - TALLOC_FREE(idkey); + talloc_free(idkey); return ret; } -/* - * search the cache for the SID an return a mapping if found +static NTSTATUS idmap_cache_fill_map(struct id_map *id, const char *value) +{ + char *rem; + + /* see if it is a sid */ + if ( ! strncmp("IDMAP/SID/", value, 10)) { + + if ( ! string_to_sid(id->sid, &value[10])) { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + } + + /* not a SID see if it is an UID or a GID */ + if ( ! strncmp("IDMAP/UID/", value, 10)) { + + /* a uid */ + id->xid.type = ID_TYPE_UID; + + } else if ( ! strncmp("IDMAP/GID/", value, 10)) { + + /* a gid */ + id->xid.type = ID_TYPE_GID; + + } else { + + /* a completely bogus value bail out */ + goto failed; + } + + id->xid.id = strtol(&value[10], &rem, 0); + if (*rem != '\0') { + goto failed; + } + + id->status = ID_MAPPED; + + return NT_STATUS_OK; + +failed: + DEBUG(1, ("invalid value: %s\n", value)); + id->status = ID_UNKNOWN; + return NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +/* search the cache for the SID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. */ -bool idmap_cache_map_sid(const struct dom_sid *sid, struct unixid *xid, - bool *mapped, bool *expired) +NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id) { - bool ret = false; - time_t timeout; + NTSTATUS ret = NT_STATUS_OK; + TDB_DATA databuf; + time_t t; char *sidkey; - char *value; - char *rem; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); + + /* make sure it is marked as not mapped by default */ + id->status = ID_UNKNOWN; - sidkey = idmap_cache_sidkey(talloc_tos(), sid); + sidkey = idmap_cache_sidkey(cache, id->sid); if (sidkey == NULL) { - DEBUG(0, ("idmap_cache_sidkey failed\n")); - return false; + return NT_STATUS_NO_MEMORY; } - if (!gencache_get(sidkey, &value, &timeout)) { - TALLOC_FREE(sidkey); - return false; + databuf = tdb_fetch_bystring(cache->tdb, sidkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", sidkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - if (strcmp(value, "IDMAP/NEGATIVE") == 0) { - *mapped = false; + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - else if (strncmp(value, "IDMAP/UID/", 10) == 0) { - *mapped = true; - xid->type = ID_TYPE_UID; - xid->id = strtol(&value[10], &rem, 10); - if (*rem != '\0') { - goto fail; + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", sidkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, sidkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - } - else if (strncmp(value, "IDMAP/GID/", 10) == 0) { - *mapped = true; - xid->type = ID_TYPE_GID; - xid->id = strtol(&value[10], &rem, 10); - if (*rem != '\0') { - goto fail; + + /* here ret == NT_STATUS_OK and id->status = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; } + + goto done; } - else { - goto fail; - } - *expired = (timeout <= time(NULL)); + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } - ret = true; - fail: - if (!ret) { - DEBUG(1, ("Invalid entry %s in cache\n", value)); + /* Check for valid or expired cache hits */ + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped as it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; } - SAFE_FREE(value); - TALLOC_FREE(sidkey); + +done: + SAFE_FREE(databuf.dptr); + talloc_free(sidkey); return ret; } -/* - * search the cache for the ID an return a mapping if found +/* search the cache for the ID an return a mapping if found * + * + * 4 cases are possible + * + * 1 map found + * in this case id->status = ID_MAPPED and NT_STATUS_OK is returned + * 2 map not found + * in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned + * 3 negative cache found + * in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned + * 4 map found but timer expired + * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED + * is returned. In this case revalidation of the cache is needed. */ -bool idmap_cache_map_id(const struct unixid *xid, struct dom_sid *psid, - bool *mapped, bool *expired) +NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id) { - bool ret = false; - time_t timeout; + NTSTATUS ret; + TDB_DATA databuf; + time_t t; char *idkey; - char *value; + char *endptr; + struct winbindd_domain *our_domain = find_our_domain(); + time_t now = time(NULL); - idkey = idmap_cache_idkey(talloc_tos(), xid); + /* make sure it is marked as unknown by default */ + id->status = ID_UNKNOWN; + + idkey = idmap_cache_idkey(cache, id); if (idkey == NULL) { - return false; + return NT_STATUS_NO_MEMORY; } - if (!gencache_get(idkey, &value, &timeout)) { - TALLOC_FREE(idkey); - return false; + databuf = tdb_fetch_bystring(cache->tdb, idkey); + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found\n", idkey)); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - if (strcmp(value, "IDMAP/NEGATIVE") == 0) { - *mapped = false; + t = strtol((const char *)databuf.dptr, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid idmap cache data format: %s\n", + (const char *)databuf.dptr)); + /* remove the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - else if (strncmp(value, "IDMAP/SID/", 10) == 0) { - *mapped = true; - if (!string_to_sid(psid, value+10)) { - goto fail; + + /* check it is not negative */ + if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) { + + DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " + "timeout = %s", t > now ? "valid" : + "expired", idkey, endptr+1, ctime(&t))); + + /* this call if successful will also mark the entry as mapped */ + ret = idmap_cache_fill_map(id, endptr+1); + if ( ! NT_STATUS_IS_OK(ret)) { + /* if not valid form delete the entry */ + tdb_delete_bystring(cache->tdb, idkey); + ret = NT_STATUS_NONE_MAPPED; + goto done; } + + /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */ + + if (t <= now) { + /* If we've been told to be offline - stay in + that state... */ + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + goto done; + } + + /* We're expired, set an error code + for upper layer */ + ret = NT_STATUS_SYNCHRONIZATION_REQUIRED; + } + + goto done; } - else { - goto fail; + + /* Was a negative cache hit */ + + /* Ignore the negative cache when offline */ + + if ( IS_DOMAIN_OFFLINE(our_domain) ) { + DEBUG(10,("idmap_cache_map_sid: idmap is offline\n")); + ret = NT_STATUS_NONE_MAPPED; + goto done; } - ret = true; + /* Process the negative cache hit */ - fail: - if (!ret) { - DEBUG(1, ("Invalid entry %s in cache\n", value)); + if (t <= now) { + /* We're expired. Return not mapped */ + ret = NT_STATUS_NONE_MAPPED; + } else { + /* this is not mapped is it was a negative cache hit */ + id->status = ID_UNMAPPED; + ret = NT_STATUS_OK; } - SAFE_FREE(value); - TALLOC_FREE(idkey); + +done: + SAFE_FREE(databuf.dptr); + talloc_free(idkey); return ret; } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 8a35fd9e37..b2fe8b67e7 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -379,5 +379,4 @@ enum ent_type { #define IS_DOMAIN_OFFLINE(x) ( lp_winbind_offline_logon() && \ ( get_global_winbindd_state_offline() \ || !(x)->online ) ) -#define IS_DOMAIN_ONLINE(x) (!(IS_DOMAIN_OFFLINE(x))) #endif /* _WINBINDD_H */ |