s3: Call sid_check_is_domain instead of dom_sid_equal
[kai/samba.git] / source3 / winbindd / winbindd_cache.c
index b7b5e6d7edab1e1691331a8bc5b2a405977b3e51..c0f44dbb1f6b50a5d6ca794ad66e3d4aed4ca134 100644 (file)
 #include "tdb_validate.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../librpc/gen_ndr/ndr_wbint.h"
+#include "ads.h"
+#include "nss_info.h"
+#include "../libcli/security/security.h"
 
 #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;
@@ -40,6 +43,7 @@ extern struct winbindd_methods reconnect_methods;
 extern struct winbindd_methods ads_methods;
 #endif
 extern struct winbindd_methods builtin_passdb_methods;
+extern struct winbindd_methods sam_passdb_methods;
 
 /*
  * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
@@ -92,6 +96,7 @@ struct winbind_cache {
 struct cache_entry {
        NTSTATUS status;
        uint32 sequence_number;
+       uint64_t timeout;
        uint8 *data;
        uint32 len, ofs;
 };
@@ -102,35 +107,6 @@ void (*smb_panic_fn)(const char *const why) = smb_panic;
 
 static struct winbind_cache *wcache;
 
-void winbindd_check_cache_size(time_t t)
-{
-       static time_t last_check_time;
-       struct stat st;
-
-       if (last_check_time == (time_t)0)
-               last_check_time = t;
-
-       if (t - last_check_time < 60 && t - last_check_time > 0)
-               return;
-
-       if (wcache == NULL || wcache->tdb == NULL) {
-               DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n"));
-               return;
-       }
-
-       if (fstat(tdb_fd(wcache->tdb), &st) == -1) {
-               DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) ));
-               return;
-       }
-
-       if (st.st_size > WINBINDD_MAX_CACHE_SIZE) {
-               DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n",
-                       (unsigned long)st.st_size,
-                       (unsigned long)WINBINDD_MAX_CACHE_SIZE));
-               wcache_flush_cache();
-       }
-}
-
 /* get the winbind_cache structure */
 static struct winbind_cache *get_cache(struct winbindd_domain *domain)
 {
@@ -142,6 +118,13 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
                domain->backend = &builtin_passdb_methods;
                domain->initialized = True;
        }
+
+       if (strequal(domain->name, get_global_sam_name()) &&
+           sid_check_is_domain(&domain->sid)) {
+               domain->backend = &sam_passdb_methods;
+               domain->initialized = True;
+       }
+
        if ( !domain->initialized ) {
                init_dc_connection( domain );
        }
@@ -222,6 +205,21 @@ static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes)
        return true;
 }
 
+/*
+  pull a uint64_t from a cache entry
+*/
+static uint64_t centry_uint64_t(struct cache_entry *centry)
+{
+       uint64_t ret;
+
+       if (!centry_check_bytes(centry, 8)) {
+               smb_panic_fn("centry_uint64_t");
+       }
+       ret = BVAL(centry->data, centry->ofs);
+       centry->ofs += 8;
+       return ret;
+}
+
 /*
   pull a uint32 from a cache entry 
 */
@@ -276,7 +274,7 @@ static NTTIME centry_nttime(struct cache_entry *centry)
        }
        ret = IVAL(centry->data, centry->ofs);
        centry->ofs += 4;
-       ret += (uint64_t)IVAL(centry->data, centry->ofs) << 32;
+       ret += (uint64)IVAL(centry->data, centry->ofs) << 32;
        centry->ofs += 4;
        return ret;
 }
@@ -614,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;
@@ -647,19 +646,41 @@ 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_t(centry);
 
        return centry;
 }
 
+static bool is_my_own_sam_domain(struct winbindd_domain *domain)
+{
+       if (strequal(domain->name, get_global_sam_name()) &&
+            dom_sid_equal(&domain->sid, get_global_sam_sid())) {
+               return true;
+       }
+
+       return false;
+}
+
+static bool is_builtin_domain(struct winbindd_domain *domain)
+{
+       if (strequal(domain->name, "BUILTIN") &&
+           dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
+               return true;
+       }
+
+       return false;
+}
+
 /*
   fetch an entry from the cache, with a varargs key. auto-fetch the sequence
   number and return status
@@ -675,7 +696,9 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
        char *kstr;
        struct cache_entry *centry;
 
-       if (!winbindd_use_cache()) {
+       if (!winbindd_use_cache() ||
+           is_my_own_sam_domain(domain) ||
+           is_builtin_domain(domain)) {
                return NULL;
        }
 
@@ -741,6 +764,16 @@ static void centry_expand(struct cache_entry *centry, uint32 len)
        }
 }
 
+/*
+  push a uint64_t into a centry
+*/
+static void centry_put_uint64_t(struct cache_entry *centry, uint64_t v)
+{
+       centry_expand(centry, 8);
+       SBVAL(centry->data, centry->ofs, v);
+       centry->ofs += 8;
+}
+
 /*
   push a uint32 into a centry 
 */
@@ -807,7 +840,7 @@ static void centry_put_hash16(struct cache_entry *centry, const uint8 val[16])
        centry->ofs += 16;
 }
 
-static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) 
+static void centry_put_sid(struct cache_entry *centry, const struct dom_sid *sid)
 {
        fstring sid_string;
        centry_put_string(centry, sid_to_fstring(sid_string, sid));
@@ -862,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_t(centry, centry->timeout);
        return centry;
 }
 
@@ -895,7 +930,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...)
 
 static void wcache_save_name_to_sid(struct winbindd_domain *domain, 
                                    NTSTATUS status, const char *domain_name,
-                                   const char *name, const DOM_SID *sid, 
+                                   const char *name, const struct dom_sid *sid,
                                    enum lsa_SidType type)
 {
        struct cache_entry *centry;
@@ -915,7 +950,7 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
 }
 
 static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, 
-                                   const DOM_SID *sid, const char *domain_name, const char *name, enum lsa_SidType type)
+                                   const struct dom_sid *sid, const char *domain_name, const char *name, enum lsa_SidType type)
 {
        struct cache_entry *centry;
        fstring sid_string;
@@ -1212,7 +1247,7 @@ do_query:
        return status;
 }
 
-NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
+NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const struct dom_sid *sid)
 {
        struct winbind_cache *cache = get_cache(domain);
        TDB_DATA data;
@@ -1247,7 +1282,7 @@ NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID
 
 NTSTATUS wcache_get_creds(struct winbindd_domain *domain, 
                          TALLOC_CTX *mem_ctx, 
-                         const DOM_SID *sid,
+                         const struct dom_sid *sid,
                          const uint8 **cached_nt_pass,
                          const uint8 **cached_salt)
 {
@@ -1327,8 +1362,7 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
 /* Store creds for a SID - only writes out new salted ones. */
 
 NTSTATUS wcache_save_creds(struct winbindd_domain *domain, 
-                          TALLOC_CTX *mem_ctx, 
-                          const DOM_SID *sid, 
+                          const struct dom_sid *sid,
                           const uint8 nt_pass[NT_HASH_LEN])
 {
        struct cache_entry *centry;
@@ -1766,7 +1800,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
                            const char *domain_name,
                            const char *name,
                            uint32_t flags,
-                           DOM_SID *sid,
+                           struct dom_sid *sid,
                            enum lsa_SidType *type)
 {
        NTSTATUS status;
@@ -1875,7 +1909,7 @@ NTSTATUS wcache_sid_to_name(struct winbindd_domain *domain,
    given */
 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
                            TALLOC_CTX *mem_ctx,
-                           const DOM_SID *sid,
+                           const struct dom_sid *sid,
                            char **domain_name,
                            char **name,
                            enum lsa_SidType *type)
@@ -1938,7 +1972,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 
 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
                              TALLOC_CTX *mem_ctx,
-                             const DOM_SID *domain_sid,
+                             const struct dom_sid *domain_sid,
                              uint32 *rids,
                              size_t num_rids,
                              char **domain_name,
@@ -1976,7 +2010,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
        have_mapped = have_unmapped = false;
 
        for (i=0; i<num_rids; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                struct cache_entry *centry;
                fstring tmp;
 
@@ -2049,7 +2083,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
                        have_mapped = have_unmapped = false;
 
                        for (i=0; i<num_rids; i++) {
-                               DOM_SID sid;
+                               struct dom_sid sid;
                                struct cache_entry *centry;
                                fstring tmp;
 
@@ -2109,7 +2143,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
        */
        if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED)) {
                for (i = 0; i < num_rids; i++) {
-                       DOM_SID sid;
+                       struct dom_sid sid;
                        const char *name = "";
                        const enum lsa_SidType type = SID_NAME_UNKNOWN;
                        NTSTATUS status = NT_STATUS_NONE_MAPPED;
@@ -2136,7 +2170,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
        refresh_sequence_number(domain, false);
 
        for (i=0; i<num_rids; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                NTSTATUS status;
 
                if (!sid_compose(&sid, domain_sid, rids[i])) {
@@ -2222,7 +2256,7 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain,
 /* Lookup user information from a rid */
 static NTSTATUS query_user(struct winbindd_domain *domain,
                           TALLOC_CTX *mem_ctx,
-                          const DOM_SID *user_sid,
+                          const struct dom_sid *user_sid,
                           struct wbint_userinfo *info)
 {
        NTSTATUS status;
@@ -2331,8 +2365,8 @@ NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
 /* Lookup groups a user is a member of. */
 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                                  TALLOC_CTX *mem_ctx,
-                                 const DOM_SID *user_sid,
-                                 uint32 *num_groups, DOM_SID **user_gids)
+                                 const struct dom_sid *user_sid,
+                                 uint32 *num_groups, struct dom_sid **user_gids)
 {
        struct cache_entry *centry = NULL;
        NTSTATUS status;
@@ -2482,7 +2516,7 @@ NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
 
 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
                                   TALLOC_CTX *mem_ctx,
-                                  uint32 num_sids, const DOM_SID *sids,
+                                  uint32 num_sids, const struct dom_sid *sids,
                                   uint32 *num_aliases, uint32 **alias_rids)
 {
        struct cache_entry *centry = NULL;
@@ -2586,7 +2620,7 @@ NTSTATUS wcache_lookup_groupmem(struct winbindd_domain *domain,
                return NT_STATUS_OK;
        }
 
-       *sid_mem = talloc_array(mem_ctx, DOM_SID, *num_names);
+       *sid_mem = talloc_array(mem_ctx, struct dom_sid, *num_names);
        *names = talloc_array(mem_ctx, char *, *num_names);
        *name_types = talloc_array(mem_ctx, uint32, *num_names);
 
@@ -2615,10 +2649,10 @@ NTSTATUS wcache_lookup_groupmem(struct winbindd_domain *domain,
 
 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
-                               const DOM_SID *group_sid,
+                               const struct dom_sid *group_sid,
                                enum lsa_SidType type,
                                uint32 *num_names,
-                               DOM_SID **sid_mem, char ***names,
+                               struct dom_sid **sid_mem, char ***names,
                                uint32 **name_types)
 {
        struct cache_entry *centry = NULL;
@@ -2715,15 +2749,16 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        old_status = domain->online;
        trusts->count = 0;
        trusts->array = NULL;
-       if (domain->online) {
-               goto do_query;
-       }
 
        cache = get_cache(domain);
        if (!cache || !cache->tdb) {
                goto do_query;
        }
 
+       if (domain->online) {
+               goto do_query;
+       }
+
        retval = wcache_tdc_fetch_list(&dom_list, &num_domains);
        if (!retval || !num_domains || !dom_list) {
                TALLOC_FREE(dom_list);
@@ -2966,7 +3001,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 void wcache_invalidate_samlogon(struct winbindd_domain *domain, 
                                struct netr_SamInfo3 *info3)
 {
-        DOM_SID sid;
+        struct dom_sid sid;
         fstring key_str, sid_string;
        struct winbind_cache *cache;
 
@@ -3022,6 +3057,39 @@ bool wcache_invalidate_cache(void)
        return true;
 }
 
+bool wcache_invalidate_cache_noinit(void)
+{
+       struct winbindd_domain *domain;
+
+       for (domain = domain_list(); domain; domain = domain->next) {
+               struct winbind_cache *cache;
+
+               /* Skip uninitialized domains. */
+               if (!domain->initialized && !domain->internal) {
+                       continue;
+               }
+
+               cache = get_cache(domain);
+
+               DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
+                          "entries for %s\n", domain->name));
+               if (cache) {
+                       if (cache->tdb) {
+                               tdb_traverse(cache->tdb, traverse_fn, NULL);
+                               /*
+                                * Flushing cache has nothing to with domains.
+                                * return here if we successfully flushed once.
+                                * To avoid unnecessary traversing the cache.
+                                */
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+       }
+       return true;
+}
+
 bool init_wcache(void)
 {
        if (wcache == NULL) {
@@ -3035,7 +3103,8 @@ bool init_wcache(void)
        /* when working offline we must not clear the cache on restart */
        wcache->tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
                                WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
-                               lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), 
+                               TDB_INCOMPATIBLE_HASH |
+                                       (lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
                                O_RDWR|O_CREAT, 0600);
 
        if (wcache->tdb == NULL) {
@@ -3112,7 +3181,7 @@ void close_winbindd_cache(void)
        }
 }
 
-bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
                       char **domain_name, char **name,
                       enum lsa_SidType *type)
 {
@@ -3128,10 +3197,9 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        return NT_STATUS_IS_OK(status);
 }
 
-bool lookup_cached_name(TALLOC_CTX *mem_ctx,
-                       const char *domain_name,
+bool lookup_cached_name(const char *domain_name,
                        const char *name,
-                       DOM_SID *sid,
+                       struct dom_sid *sid,
                        enum lsa_SidType *type)
 {
        struct winbindd_domain *domain;
@@ -3156,7 +3224,7 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx,
 
 void cache_name2sid(struct winbindd_domain *domain, 
                    const char *domain_name, const char *name,
-                   enum lsa_SidType type, const DOM_SID *sid)
+                   enum lsa_SidType type, const struct dom_sid *sid)
 {
        refresh_sequence_number(domain, false);
        wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
@@ -3208,7 +3276,8 @@ void wcache_flush_cache(void)
        /* when working offline we must not clear the cache on restart */
        wcache->tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
                                WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
-                               lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), 
+                               TDB_INCOMPATIBLE_HASH |
+                               (lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
                                O_RDWR|O_CREAT, 0600);
 
        if (!wcache->tdb) {
@@ -3281,7 +3350,7 @@ static int traverse_fn_get_credlist(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DAT
        return 0;
 }
 
-NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) 
+NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const struct dom_sid *sid)
 {
        struct winbind_cache *cache = get_cache(domain);
        NTSTATUS status;
@@ -3446,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;
@@ -3457,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_t(centry);
        return centry;
 }
 
@@ -3482,7 +3553,7 @@ static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
 
        (void)centry_uint32(centry);
        if (NT_STATUS_IS_OK(centry->status)) {
-               DOM_SID sid;
+               struct dom_sid sid;
                (void)centry_sid(centry, &sid);
        }
 
@@ -3522,7 +3593,7 @@ static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
                      struct tdb_validation_status *state)
 {
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
-       DOM_SID sid;
+       struct dom_sid sid;
 
        if (!centry) {
                return 1;
@@ -3630,7 +3701,7 @@ static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
        num_entries = (int32)centry_uint32(centry);
 
        for (i=0; i< num_entries; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                (void)centry_string(centry, mem_ctx);
                (void)centry_string(centry, mem_ctx);
                (void)centry_string(centry, mem_ctx);
@@ -3688,7 +3759,7 @@ static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
        num_groups = centry_uint32(centry);
 
        for (i=0; i< num_groups; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                centry_sid(centry, &sid);
        }
 
@@ -3739,7 +3810,7 @@ static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
        num_names = centry_uint32(centry);
 
        for (i=0; i< num_names; i++) {
-               DOM_SID sid;
+               struct dom_sid sid;
                centry_sid(centry, &sid);
                (void)centry_string(centry, mem_ctx);
                (void)centry_uint32(centry);
@@ -4026,6 +4097,7 @@ int winbindd_validate_cache(void)
 
        tdb = tdb_open_log(tdb_path, 
                           WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+                          TDB_INCOMPATIBLE_HASH |
                           ( lp_winbind_offline_logon() 
                             ? TDB_DEFAULT 
                             : TDB_DEFAULT | TDB_CLEAR_IF_FIRST ),
@@ -4470,6 +4542,58 @@ struct winbindd_tdc_domain * wcache_tdc_fetch_domain( TALLOC_CTX *ctx, const cha
        return d;       
 }
 
+/*********************************************************************
+ ********************************************************************/
+
+struct winbindd_tdc_domain*
+       wcache_tdc_fetch_domainbysid(TALLOC_CTX *ctx,
+                                    const struct dom_sid *sid)
+{
+       struct winbindd_tdc_domain *dom_list = NULL;
+       size_t num_domains = 0;
+       int i;
+       struct winbindd_tdc_domain *d = NULL;
+
+       DEBUG(10,("wcache_tdc_fetch_domainbysid: Searching for domain %s\n",
+                 sid_string_dbg(sid)));
+
+       if (!init_wcache()) {
+               return false;
+       }
+
+       /* fetch the list */
+
+       wcache_tdc_fetch_list(&dom_list, &num_domains);
+
+       for (i = 0; i<num_domains; i++) {
+               if (sid_equal(sid, &(dom_list[i].sid))) {
+                       DEBUG(10, ("wcache_tdc_fetch_domainbysid: "
+                                  "Found domain %s for SID %s\n",
+                                  dom_list[i].domain_name,
+                                  sid_string_dbg(sid)));
+
+                       d = TALLOC_P(ctx, struct winbindd_tdc_domain);
+                       if (!d)
+                               break;
+
+                       d->domain_name = talloc_strdup(d,
+                                                      dom_list[i].domain_name);
+
+                       d->dns_name = talloc_strdup(d, dom_list[i].dns_name);
+                       sid_copy(&d->sid, &dom_list[i].sid);
+                       d->trust_flags = dom_list[i].trust_flags;
+                       d->trust_type = dom_list[i].trust_type;
+                       d->trust_attribs = dom_list[i].trust_attribs;
+
+                       break;
+               }
+       }
+
+        TALLOC_FREE(dom_list);
+
+       return d;
+}
+
 
 /*********************************************************************
  ********************************************************************/
@@ -4490,7 +4614,7 @@ void wcache_tdc_clear( void )
 
 static void wcache_save_user_pwinfo(struct winbindd_domain *domain, 
                                    NTSTATUS status,
-                                   const DOM_SID *user_sid,
+                                   const struct dom_sid *user_sid,
                                    const char *homedir,
                                    const char *shell,
                                    const char *gecos,
@@ -4514,8 +4638,10 @@ static void wcache_save_user_pwinfo(struct winbindd_domain *domain,
        centry_free(centry);
 }
 
+#ifdef HAVE_ADS
+
 NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, 
-                             const DOM_SID *user_sid,
+                             const struct dom_sid *user_sid,
                              TALLOC_CTX *ctx,
                              ADS_STRUCT *ads, LDAPMessage *msg,
                              const char **homedir, const char **shell,
@@ -4573,6 +4699,7 @@ do_query:
        return nt_status;       
 }
 
+#endif
 
 /* the cache backend methods are exposed via this structure */
 struct winbindd_methods cache_methods = {
@@ -4638,7 +4765,9 @@ bool wcache_fetch_ndr(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
        TDB_DATA key, data;
        bool ret = false;
 
-       if (!wcache_opnum_cacheable(opnum)) {
+       if (!wcache_opnum_cacheable(opnum) ||
+           is_my_own_sam_domain(domain) ||
+           is_builtin_domain(domain)) {
                return false;
        }
 
@@ -4655,12 +4784,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)) {
@@ -4672,15 +4802,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:
@@ -4693,8 +4828,11 @@ 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)) {
+       if (!wcache_opnum_cacheable(opnum) ||
+           is_my_own_sam_domain(domain) ||
+           is_builtin_domain(domain)) {
                return;
        }
 
@@ -4712,14 +4850,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);