Copyright (C) Andrew Tridgell 2001
Copyright (C) Gerald Carter 2003
+ Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify
{
struct winbind_cache *ret = wcache;
+ /* we have to know what type of domain we are dealing with first */
+
+ if ( !domain->initialized )
+ set_dc_type_and_flags( domain );
+
if (!domain->backend) {
- extern struct winbindd_methods msrpc_methods;
+ extern struct winbindd_methods reconnect_methods;
switch (lp_security()) {
#ifdef HAVE_ADS
case SEC_ADS: {
extern struct winbindd_methods ads_methods;
/* always obey the lp_security parameter for our domain */
- if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) {
+ if (domain->primary) {
domain->backend = &ads_methods;
break;
}
+ /* only use ADS for native modes at the momment.
+ The problem is the correct detection of mixed
+ mode domains from NT4 BDC's --jerry */
+
if ( domain->native_mode ) {
+ DEBUG(5,("get_cache: Setting ADS methods for domain %s\n",
+ domain->name));
domain->backend = &ads_methods;
break;
}
}
#endif
default:
- domain->backend = &msrpc_methods;
+ DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n",
+ domain->name));
+ domain->backend = &reconnect_methods;
}
}
if (ret)
return ret;
- ret = smb_xmalloc(sizeof(*ret));
+ ret = SMB_XMALLOC_P(struct winbind_cache);
ZERO_STRUCTP(ret);
wcache = ret;
smb_panic("centry_string");
}
- ret = talloc(mem_ctx, len+1);
+ if (mem_ctx != NULL)
+ ret = TALLOC(mem_ctx, len+1);
+ else
+ ret = SMB_MALLOC(len+1);
if (!ret) {
smb_panic("centry_string out of memory\n");
}
/* pull a string from a cache entry, using the supplied
talloc context
*/
-static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
+static BOOL centry_sid(struct cache_entry *centry, DOM_SID *sid)
{
- DOM_SID *sid;
char *sid_string;
-
- sid = talloc(mem_ctx, sizeof(*sid));
- if (!sid)
- return NULL;
-
- sid_string = centry_string(centry, mem_ctx);
+ sid_string = centry_string(centry, NULL);
if (!string_to_sid(sid, sid_string)) {
- return NULL;
+ return False;
}
- return sid;
+ SAFE_FREE(sid_string);
+ return True;
}
/* the server is considered down if it can't give us a sequence number */
domain->sequence_number = IVAL(data.dptr, 0);
domain->last_seq_check = IVAL(data.dptr, 4);
+ SAFE_FREE(data.dptr);
+
/* have we expired? */
time_diff = now - domain->last_seq_check;
get_cache( domain );
+#if 0 /* JERRY -- disable as the default cache time is now 5 minutes */
/* trying to reconnect is expensive, don't do it too often */
if (domain->sequence_number == DOM_SEQUENCE_NONE) {
cache_time *= 8;
}
+#endif
time_diff = t - domain->last_seq_check;
if ( NT_STATUS_IS_OK(status) )
goto done;
+ /* important! make sure that we know if this is a native
+ mode domain or not */
+
status = domain->backend->sequence_number(domain, &domain->sequence_number);
if (!NT_STATUS_IS_OK(status)) {
return NULL;
}
- centry = smb_xmalloc(sizeof(*centry));
+ centry = SMB_XMALLOC_P(struct cache_entry);
centry->data = (unsigned char *)data.dptr;
centry->len = data.dsize;
centry->ofs = 0;
centry->sequence_number = centry_uint32(centry);
if (centry_expired(domain, kstr, centry)) {
- extern BOOL opt_dual_daemon;
DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
kstr, domain->name ));
- if (opt_dual_daemon) {
- extern BOOL background_process;
- background_process = True;
- DEBUG(10,("wcache_fetch: background processing expired entry %s for domain %s\n",
- kstr, domain->name ));
- } else {
- centry_free(centry);
- free(kstr);
- return NULL;
- }
+ centry_free(centry);
+ free(kstr);
+ return NULL;
}
DEBUG(10,("wcache_fetch: returning entry %s for domain %s\n",
if (centry->len - centry->ofs >= len)
return;
centry->len *= 2;
- p = realloc(centry->data, centry->len);
+ p = SMB_REALLOC(centry->data, centry->len);
if (!p) {
DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len));
smb_panic("out of memory in centry_expand");
if (!wcache->tdb)
return NULL;
- centry = smb_xmalloc(sizeof(*centry));
+ centry = SMB_XMALLOC_P(struct cache_entry);
centry->len = 8192; /* reasonable default */
- centry->data = smb_xmalloc(centry->len);
+ centry->data = SMB_XMALLOC_ARRAY(char, centry->len);
centry->ofs = 0;
centry->sequence_number = domain->sequence_number;
centry_put_uint32(centry, NT_STATUS_V(status));
}
static void wcache_save_name_to_sid(struct winbindd_domain *domain,
- NTSTATUS status,
+ NTSTATUS status, const char *domain_name,
const char *name, const DOM_SID *sid,
enum SID_NAME_USE type)
{
struct cache_entry *centry;
fstring uname;
- fstring sid_string;
centry = centry_start(domain, status);
if (!centry)
return;
+ centry_put_uint32(centry, type);
centry_put_sid(centry, sid);
fstrcpy(uname, name);
strupper_m(uname);
- centry_end(centry, "NS/%s", sid_to_string(sid_string, sid));
- DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
+ centry_end(centry, "NS/%s/%s", domain_name, uname);
+ DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname,
+ sid_string_static(sid)));
centry_free(centry);
}
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status,
- const DOM_SID *sid, const char *name, enum SID_NAME_USE type)
+ const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type)
{
struct cache_entry *centry;
fstring sid_string;
return;
if (NT_STATUS_IS_OK(status)) {
centry_put_uint32(centry, type);
+ centry_put_string(centry, domain_name);
centry_put_string(centry, name);
}
centry_end(centry, "SN/%s", sid_to_string(sid_string, sid));
return;
centry_put_string(centry, info->acct_name);
centry_put_string(centry, info->full_name);
- centry_put_sid(centry, info->user_sid);
- centry_put_sid(centry, info->group_sid);
- centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid));
+ centry_put_string(centry, info->homedir);
+ centry_put_string(centry, info->shell);
+ centry_put_sid(centry, &info->user_sid);
+ centry_put_sid(centry, &info->group_sid);
+ centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid));
DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name));
centry_free(centry);
}
if (*num_entries == 0)
goto do_cached;
- (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ (*info) = TALLOC_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
if (! (*info))
smb_panic("query_user_list out of memory");
for (i=0; i<(*num_entries); i++) {
(*info)[i].acct_name = centry_string(centry, mem_ctx);
(*info)[i].full_name = centry_string(centry, mem_ctx);
- (*info)[i].user_sid = centry_sid(centry, mem_ctx);
- (*info)[i].group_sid = centry_sid(centry, mem_ctx);
+ (*info)[i].homedir = centry_string(centry, mem_ctx);
+ (*info)[i].shell = centry_string(centry, mem_ctx);
+ centry_sid(centry, &(*info)[i].user_sid);
+ centry_sid(centry, &(*info)[i].group_sid);
}
do_cached:
status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info);
if (!NT_STATUS_IS_OK(status))
- DEBUG(3, ("query_user_list: returned 0x%08x, retrying\n", NT_STATUS_V(status)));
- if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL)) {
- DEBUG(3, ("query_user_list: flushing connection cache\n"));
- winbindd_cm_flush();
+ DEBUG(3, ("query_user_list: returned 0x%08x, "
+ "retrying\n", NT_STATUS_V(status)));
+ if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
+ DEBUG(3, ("query_user_list: flushing "
+ "connection cache\n"));
+ invalidate_cm_connection(&domain->conn);
}
} while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) &&
for (i=0; i<(*num_entries); i++) {
centry_put_string(centry, (*info)[i].acct_name);
centry_put_string(centry, (*info)[i].full_name);
- centry_put_sid(centry, (*info)[i].user_sid);
- centry_put_sid(centry, (*info)[i].group_sid);
+ centry_put_string(centry, (*info)[i].homedir);
+ centry_put_string(centry, (*info)[i].shell);
+ centry_put_sid(centry, &(*info)[i].user_sid);
+ centry_put_sid(centry, &(*info)[i].group_sid);
if (domain->backend->consistent) {
/* when the backend is consistent we can pre-prime some mappings */
wcache_save_name_to_sid(domain, NT_STATUS_OK,
+ domain->name,
(*info)[i].acct_name,
- (*info)[i].user_sid,
+ &(*info)[i].user_sid,
SID_NAME_USER);
wcache_save_sid_to_name(domain, NT_STATUS_OK,
- (*info)[i].user_sid,
+ &(*info)[i].user_sid,
+ domain->name,
(*info)[i].acct_name,
SID_NAME_USER);
wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]);
if (*num_entries == 0)
goto do_cached;
- (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
if (! (*info))
smb_panic("enum_dom_groups out of memory");
for (i=0; i<(*num_entries); i++) {
if (*num_entries == 0)
goto do_cached;
- (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
if (! (*info))
smb_panic("enum_dom_groups out of memory");
for (i=0; i<(*num_entries); i++) {
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ const char *domain_name,
const char *name,
DOM_SID *sid,
enum SID_NAME_USE *type)
struct cache_entry *centry = NULL;
NTSTATUS status;
fstring uname;
- DOM_SID *sid2;
if (!cache->tdb)
goto do_query;
fstrcpy(uname, name);
strupper_m(uname);
- centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname);
+ centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
if (!centry)
goto do_query;
*type = (enum SID_NAME_USE)centry_uint32(centry);
- sid2 = centry_sid(centry, mem_ctx);
- if (!sid2) {
- ZERO_STRUCTP(sid);
- } else {
- sid_copy(sid, sid2);
- }
-
+ centry_sid(centry, sid);
status = centry->status;
DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status %s\n",
DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
- status = domain->backend->name_to_sid(domain, mem_ctx, name, sid, type);
+ status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
/* and save it */
- wcache_save_name_to_sid(domain, status, name, sid, *type);
+ wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
/* We can't save the sid to name mapping as we don't know the
correct case of the name without looking it up */
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *sid,
+ char **domain_name,
char **name,
enum SID_NAME_USE *type)
{
goto do_query;
if (NT_STATUS_IS_OK(centry->status)) {
*type = (enum SID_NAME_USE)centry_uint32(centry);
+ *domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx);
}
status = centry->status;
do_query:
*name = NULL;
+ *domain_name = NULL;
/* If the seq number check indicated that there is a problem
* with this DC, then return that status... except for
DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
- status = domain->backend->sid_to_name(domain, mem_ctx, sid, name, type);
+ status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
/* and save it */
refresh_sequence_number(domain, False);
- wcache_save_sid_to_name(domain, status, sid, *name, *type);
- wcache_save_name_to_sid(domain, status, *name, sid, *type);
+ wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type);
+
+ /* We can't save the name to sid mapping here, as with sid history a
+ * later name2sid would give the wrong sid. */
return status;
}
-
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
WINBIND_USERINFO *info)
{
struct winbind_cache *cache = get_cache(domain);
centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid));
- /* If we have an access denied cache entry and a cached info3 in the
- samlogon cache then do a query. This will force the rpc back end
- to return the info3 data. */
-
- if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) &&
- netsamlogon_cache_have(user_sid)) {
- DEBUG(10, ("query_user: cached access denied and have cached info3\n"));
- domain->last_status = NT_STATUS_OK;
- centry_free(centry);
- goto do_query;
- }
-
if (!centry)
goto do_query;
info->acct_name = centry_string(centry, mem_ctx);
info->full_name = centry_string(centry, mem_ctx);
- info->user_sid = centry_sid(centry, mem_ctx);
- info->group_sid = centry_sid(centry, mem_ctx);
+ info->homedir = centry_string(centry, mem_ctx);
+ info->shell = centry_string(centry, mem_ctx);
+ centry_sid(centry, &info->user_sid);
+ centry_sid(centry, &info->group_sid);
status = centry->status;
DEBUG(10,("query_user: [Cached] - cached info for domain %s status %s\n",
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
- uint32 *num_groups, DOM_SID ***user_gids)
+ const DOM_SID *user_sid,
+ uint32 *num_groups, DOM_SID **user_gids)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid));
- /* If we have an access denied cache entry and a cached info3 in the
- samlogon cache then do a query. This will force the rpc back end
- to return the info3 data. */
-
- if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) &&
- netsamlogon_cache_have(user_sid)) {
- DEBUG(10, ("query_user: cached access denied and have cached info3\n"));
- domain->last_status = NT_STATUS_OK;
- centry_free(centry);
- goto do_query;
- }
-
if (!centry)
goto do_query;
if (*num_groups == 0)
goto do_cached;
- (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups));
+ (*user_gids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
if (! (*user_gids))
smb_panic("lookup_usergroups out of memory");
for (i=0; i<(*num_groups); i++) {
- (*user_gids)[i] = centry_sid(centry, mem_ctx);
+ centry_sid(centry, &(*user_gids)[i]);
}
do_cached:
goto skip_save;
centry_put_uint32(centry, *num_groups);
for (i=0; i<(*num_groups); i++) {
- centry_put_sid(centry, (*user_gids)[i]);
+ centry_put_sid(centry, &(*user_gids)[i]);
}
centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid));
centry_free(centry);
return status;
}
+static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 num_sids, const DOM_SID *sids,
+ uint32 *num_aliases, uint32 **alias_rids)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ char *sidlist = talloc_strdup(mem_ctx, "");
+ int i;
+
+ if (!cache->tdb)
+ goto do_query;
+
+ if (num_sids == 0) {
+ *num_aliases = 0;
+ *alias_rids = NULL;
+ return NT_STATUS_OK;
+ }
+
+ /* We need to cache indexed by the whole list of SIDs, the aliases
+ * resulting might come from any of the SIDs. */
+
+ for (i=0; i<num_sids; i++) {
+ sidlist = talloc_asprintf(mem_ctx, "%s/%s", sidlist,
+ sid_string_static(&sids[i]));
+ if (sidlist == NULL)
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ centry = wcache_fetch(cache, domain, "UA%s", sidlist);
+
+ if (!centry)
+ goto do_query;
+
+ *num_aliases = centry_uint32(centry);
+ *alias_rids = NULL;
+
+ (*alias_rids) = TALLOC_ARRAY(mem_ctx, uint32, *num_aliases);
+
+ if ((*num_aliases != 0) && ((*alias_rids) == NULL))
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<(*num_aliases); i++)
+ (*alias_rids)[i] = centry_uint32(centry);
+
+ status = centry->status;
+
+ DEBUG(10,("lookup_useraliases: [Cached] - cached info for domain %s "
+ "status %s\n", domain->name,
+ get_friendly_nt_error_msg(status)));
+
+ centry_free(centry);
+ return status;
+
+ do_query:
+ (*num_aliases) = 0;
+ (*alias_rids) = NULL;
+
+ if (!NT_STATUS_IS_OK(domain->last_status))
+ return domain->last_status;
+
+ DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info "
+ "for domain %s\n", domain->name ));
+
+ status = domain->backend->lookup_useraliases(domain, mem_ctx,
+ num_sids, sids,
+ num_aliases, alias_rids);
+
+ /* and save it */
+ refresh_sequence_number(domain, False);
+ centry = centry_start(domain, status);
+ if (!centry)
+ goto skip_save;
+ centry_put_uint32(centry, *num_aliases);
+ for (i=0; i<(*num_aliases); i++)
+ centry_put_uint32(centry, (*alias_rids)[i]);
+ centry_end(centry, "UA%s", sidlist);
+ centry_free(centry);
+
+ skip_save:
+ return status;
+}
+
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid, uint32 *num_names,
- DOM_SID ***sid_mem, char ***names,
+ const DOM_SID *group_sid, uint32 *num_names,
+ DOM_SID **sid_mem, char ***names,
uint32 **name_types)
{
struct winbind_cache *cache = get_cache(domain);
if (*num_names == 0)
goto do_cached;
- (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names));
- (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names));
- (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names));
+ (*sid_mem) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_names);
+ (*names) = TALLOC_ARRAY(mem_ctx, char *, *num_names);
+ (*name_types) = TALLOC_ARRAY(mem_ctx, uint32, *num_names);
if (! (*sid_mem) || ! (*names) || ! (*name_types)) {
smb_panic("lookup_groupmem out of memory");
}
for (i=0; i<(*num_names); i++) {
- (*sid_mem)[i] = centry_sid(centry, mem_ctx);
+ centry_sid(centry, &(*sid_mem)[i]);
(*names)[i] = centry_string(centry, mem_ctx);
(*name_types)[i] = centry_uint32(centry);
}
goto skip_save;
centry_put_uint32(centry, *num_names);
for (i=0; i<(*num_names); i++) {
- centry_put_sid(centry, (*sid_mem)[i]);
+ centry_put_sid(centry, &(*sid_mem)[i]);
centry_put_string(centry, (*names)[i]);
centry_put_uint32(centry, (*name_types)[i]);
}
names, alt_names, dom_sids);
}
-/* find the domain sid */
-static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
-{
- get_cache(domain);
-
- DEBUG(10,("domain_sid: [Cached] - doing backend query for info for domain %s\n",
- domain->name ));
-
- /* we don't cache this call */
- return domain->backend->domain_sid(domain, sid);
-}
-
/* find the alternate names for the domain, if any */
static NTSTATUS alternate_name(struct winbindd_domain *domain)
{
return 0;
}
-/* Invalidate the getpwnam and getgroups entries for a winbindd domain */
-
-void wcache_invalidate_samlogon(struct winbindd_domain *domain,
- NET_USER_INFO_3 *info3)
-{
- struct winbind_cache *cache;
-
- if (!domain)
- return;
-
- cache = get_cache(domain);
- netsamlogon_clear_cached_user(cache->tdb, info3);
-}
-
void wcache_invalidate_cache(void)
{
struct winbindd_domain *domain;
sid_to_name,
query_user,
lookup_usergroups,
+ lookup_useraliases,
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid,
alternate_name
};
+
+static BOOL init_wcache(void)
+{
+ if (wcache == NULL) {
+ wcache = SMB_XMALLOC_P(struct winbind_cache);
+ ZERO_STRUCTP(wcache);
+ }
+
+ if (wcache->tdb != NULL)
+ return True;
+
+ wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
+ TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
+
+ if (wcache->tdb == NULL) {
+ DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
+ return False;
+ }
+
+ return True;
+}
+
+void cache_store_response(pid_t pid, struct winbindd_response *response)
+{
+ fstring key_str;
+
+ if (!init_wcache())
+ return;
+
+ DEBUG(10, ("Storing response for pid %d, len %d\n",
+ pid, response->length));
+
+ fstr_sprintf(key_str, "DR/%d", pid);
+ if (tdb_store(wcache->tdb, string_tdb_data(key_str),
+ make_tdb_data((void *)response, sizeof(*response)),
+ TDB_REPLACE) == -1)
+ return;
+
+ if (response->length == sizeof(*response))
+ return;
+
+ /* There's extra data */
+
+ DEBUG(10, ("Storing extra data: len=%d\n",
+ (int)(response->length - sizeof(*response))));
+
+ fstr_sprintf(key_str, "DE/%d", pid);
+ if (tdb_store(wcache->tdb, string_tdb_data(key_str),
+ make_tdb_data(response->extra_data,
+ response->length - sizeof(*response)),
+ TDB_REPLACE) == 0)
+ return;
+
+ /* We could not store the extra data, make sure the tdb does not
+ * contain a main record with wrong dangling extra data */
+
+ fstr_sprintf(key_str, "DR/%d", pid);
+ tdb_delete(wcache->tdb, string_tdb_data(key_str));
+
+ return;
+}
+
+BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
+{
+ TDB_DATA data;
+ fstring key_str;
+
+ if (!init_wcache())
+ return False;
+
+ DEBUG(10, ("Retrieving response for pid %d\n", pid));
+
+ fstr_sprintf(key_str, "DR/%d", pid);
+ data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
+
+ if (data.dptr == NULL)
+ return False;
+
+ if (data.dsize != sizeof(*response))
+ return False;
+
+ memcpy(response, data.dptr, data.dsize);
+ SAFE_FREE(data.dptr);
+
+ if (response->length == sizeof(*response)) {
+ response->extra_data = NULL;
+ return True;
+ }
+
+ /* There's extra data */
+
+ DEBUG(10, ("Retrieving extra data length=%d\n",
+ (int)(response->length - sizeof(*response))));
+
+ fstr_sprintf(key_str, "DE/%d", pid);
+ data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
+
+ if (data.dptr == NULL) {
+ DEBUG(0, ("Did not find extra data\n"));
+ return False;
+ }
+
+ if (data.dsize != (response->length - sizeof(*response))) {
+ DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize));
+ SAFE_FREE(data.dptr);
+ return False;
+ }
+
+ dump_data(11, data.dptr, data.dsize);
+
+ response->extra_data = data.dptr;
+ return True;
+}
+
+BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **domain_name, const char **name,
+ enum SID_NAME_USE *type)
+{
+ struct winbindd_domain *domain;
+ struct winbind_cache *cache;
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+
+ domain = find_lookup_domain_from_sid(sid);
+ if (domain == NULL) {
+ return False;
+ }
+
+ cache = get_cache(domain);
+
+ if (cache->tdb == NULL) {
+ return False;
+ }
+
+ centry = wcache_fetch(cache, domain, "SN/%s", sid_string_static(sid));
+ if (centry == NULL) {
+ return False;
+ }
+
+ if (NT_STATUS_IS_OK(centry->status)) {
+ *type = (enum SID_NAME_USE)centry_uint32(centry);
+ *domain_name = centry_string(centry, mem_ctx);
+ *name = centry_string(centry, mem_ctx);
+ }
+
+ status = centry->status;
+ centry_free(centry);
+ return NT_STATUS_IS_OK(status);
+}
+
+void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
+ const char *domain_name, const char *name,
+ enum SID_NAME_USE type)
+{
+ wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name,
+ name, type);
+}