#include "includes.h"
#include "winbindd.h"
-extern BOOL opt_nocache;
-extern struct winbindd_methods msrpc_methods;
-extern struct winbindd_methods ads_methods;
-extern BOOL opt_dual_daemon;
-extern BOOL background_process;
-
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
/* flush the cache */
void wcache_flush_cache(void)
{
+ extern BOOL opt_nocache;
+
if (!wcache)
return;
if (wcache->tdb) {
{
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 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 (domain->primary) {
domain->backend = &ads_methods;
default:
DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n",
domain->name));
- domain->backend = &msrpc_methods;
+ domain->backend = &reconnect_methods;
}
}
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_P(mem_ctx, DOM_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 */
/* important! make sure that we know if this is a native
mode domain or not */
- if ( !domain->initialized )
- set_dc_type_and_flags( domain );
-
status = domain->backend->sequence_number(domain, &domain->sequence_number);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
kstr, domain->name ));
- if (opt_dual_daemon) {
- 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",
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);
}
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);
struct cache_entry *centry = NULL;
NTSTATUS status;
fstring uname;
- DOM_SID *sid2;
if (!cache->tdb)
goto do_query;
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",
return status;
}
-
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
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",
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *user_sid,
- uint32 *num_groups, DOM_SID ***user_gids)
+ 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_ARRAY(mem_ctx, DOM_SID *, *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);
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 num_sids, DOM_SID **sids,
+ uint32 num_sids, const DOM_SID *sids,
uint32 *num_aliases, uint32 **alias_rids)
{
struct winbind_cache *cache = get_cache(domain);
for (i=0; i<num_sids; i++) {
sidlist = talloc_asprintf(mem_ctx, "%s/%s", sidlist,
- sid_string_static(sids[i]));
+ sid_string_static(&sids[i]));
if (sidlist == NULL)
return NT_STATUS_NO_MEMORY;
}
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *group_sid, uint32 *num_names,
- DOM_SID ***sid_mem, char ***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_ARRAY(mem_ctx, DOM_SID *, *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);
}
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;
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);
+}