*/
#include "includes.h"
+#include "system/filesys.h"
#include "winbindd.h"
#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/dom_sid.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;
struct cache_entry {
NTSTATUS status;
uint32 sequence_number;
+ uint64_t timeout;
uint8 *data;
uint32 len, ofs;
};
}
if (strequal(domain->name, get_global_sam_name()) &&
- dom_sid_equal(&domain->sid, get_global_sam_sid())) {
+ sid_check_is_domain(&domain->sid)) {
domain->backend = &sam_passdb_methods;
domain->initialized = True;
}
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
*/
}
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;
}
}
/* 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;
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())) {
+ sid_check_is_domain(&domain->sid)) {
return true;
}
static bool is_builtin_domain(struct winbindd_domain *domain)
{
if (strequal(domain->name, "BUILTIN") &&
- dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
+ sid_check_is_builtin(&domain->sid)) {
return true;
}
}
}
+/*
+ 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
*/
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;
}
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
- struct acct_info **info)
+ struct wb_acct_info **info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
if (*num_entries == 0)
goto do_cached;
- (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
+ (*info) = TALLOC_ARRAY(mem_ctx, struct wb_acct_info, *num_entries);
if (! (*info)) {
smb_panic_fn("enum_dom_groups out of memory");
}
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
- struct acct_info **info)
+ struct wb_acct_info **info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
if (*num_entries == 0)
goto do_cached;
- (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
+ (*info) = TALLOC_ARRAY(mem_ctx, struct wb_acct_info, *num_entries);
if (! (*info)) {
smb_panic_fn("enum_dom_groups out of memory");
}
(*names)[i] = centry_string(centry, *names);
- } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
+ } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)
+ || NT_STATUS_EQUAL(centry->status, STATUS_SOME_UNMAPPED)) {
have_unmapped = true;
} else {
/* Invalidate the getpwnam and getgroups entries for a winbindd domain */
void wcache_invalidate_samlogon(struct winbindd_domain *domain,
- struct netr_SamInfo3 *info3)
+ const struct dom_sid *sid)
{
- struct dom_sid sid;
fstring key_str, sid_string;
struct winbind_cache *cache;
return;
}
- sid_compose(&sid, info3->base.domain_sid, info3->base.rid);
-
/* Clear U/SID cache entry */
- fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid));
+ fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, sid));
DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
tdb_delete(cache->tdb, string_tdb_data(key_str));
/* Clear UG/SID cache entry */
- fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid));
+ fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, sid));
DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
tdb_delete(cache->tdb, string_tdb_data(key_str));
/* Samba/winbindd never needs this. */
- netsamlogon_clear_cached_user(info3);
+ netsamlogon_clear_cached_user(sid);
}
bool wcache_invalidate_cache(void)
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;
centry->status = NT_STATUS(centry_uint32(centry));
centry->sequence_number = centry_uint32(centry);
+ centry->timeout = centry_uint64_t(centry);
return centry;
}
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;
+}
+
/*********************************************************************
********************************************************************/
NTSTATUS nss_get_info_cached( struct winbindd_domain *domain,
const struct dom_sid *user_sid,
TALLOC_CTX *ctx,
- ADS_STRUCT *ads, LDAPMessage *msg,
const char **homedir, const char **shell,
const char **gecos, gid_t *p_gid)
{
do_query:
- nt_status = nss_get_info( domain->name, user_sid, ctx, ads, msg,
+ nt_status = nss_get_info( domain->name, user_sid, ctx,
homedir, shell, gecos, p_gid );
DEBUG(10, ("nss_get_info returned %s\n", nt_errstr(nt_status)));
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)) {
(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:
{
TDB_DATA key, data;
uint32_t dom_seqnum, last_check;
+ uint64_t timeout;
if (!wcache_opnum_cacheable(opnum) ||
is_my_own_sam_domain(domain) ||
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);