Copyright (C) Volker Lendecke 2005
Copyright (C) Guenther Deschner 2005
Copyright (C) Michael Adam 2007
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
#include "includes.h"
#include "winbindd.h"
+#include "tdb_validate.h"
+#include "../libcli/auth/libcli_auth.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
extern struct winbindd_methods reconnect_methods;
-extern bool opt_nocache;
#ifdef HAVE_ADS
extern struct winbindd_methods ads_methods;
#endif
+extern struct winbindd_methods builtin_passdb_methods;
/*
* JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
int i;
if (kbuf.dptr == NULL || kbuf.dsize == 0) {
- return False;
+ return false;
}
for (i = 0; non_centry_keys[i] != NULL; i++) {
size_t namelen = strlen(non_centry_keys[i]);
continue;
}
if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) {
- return True;
+ return true;
}
}
- return False;
+ return false;
}
/* Global online/offline state - False when online. winbindd starts up online
/* We have to know what type of domain we are dealing with first. */
+ if (domain->internal) {
+ domain->backend = &builtin_passdb_methods;
+ domain->initialized = True;
+ }
if ( !domain->initialized ) {
init_dc_connection( domain );
}
DEBUG(0,("centry corruption? needed %u bytes, have %d\n",
(unsigned int)nbytes,
centry->len - centry->ofs));
- return False;
+ return false;
}
- return True;
+ return true;
}
/*
char *sid_string;
sid_string = centry_string(centry, mem_ctx);
if ((sid_string == NULL) || (!string_to_sid(sid, sid_string))) {
- return False;
+ return false;
}
- return True;
+ return true;
}
bool ret;
if (!wcache->tdb)
- return False;
+ return false;
ret = (domain->sequence_number == DOM_SEQUENCE_NONE);
}
/*
- refresh the domain sequence number. If force is True
+ refresh the domain sequence number. If force is true
then always refresh it, no matter how recently we fetched it
*/
time_diff = t - domain->last_seq_check;
/* see if we have to refetch the domain sequence number */
- if (!force && (time_diff < cache_time)) {
+ if (!force && (time_diff < cache_time) &&
+ (domain->sequence_number != DOM_SEQUENCE_NONE) &&
+ NT_STATUS_IS_OK(domain->last_status)) {
DEBUG(10, ("refresh_sequence_number: %s time ok\n", domain->name));
goto done;
}
/* this will update the timestamp as well */
status = fetch_cache_seqnum( domain, t );
- if ( NT_STATUS_IS_OK(status) )
- goto done;
+ if (NT_STATUS_IS_OK(status) &&
+ (domain->sequence_number != DOM_SEQUENCE_NONE) &&
+ NT_STATUS_IS_OK(domain->last_status)) {
+ goto done;
+ }
/* important! make sure that we know if this is a native
mode domain or not. And that we can contact it. */
domain->last_status = status;
domain->last_seq_check = time(NULL);
- /* save the new sequence number ni the cache */
+ /* save the new sequence number in the cache */
store_cache_seqnum( domain );
done:
if (lp_winbind_offline_logon() && global_winbindd_offline_state) {
DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n",
keystr, domain->name ));
- return False;
+ return false;
}
/* when the domain is offline return the cached entry.
if (!domain->online) {
DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
keystr, domain->name ));
- return False;
+ return false;
}
/* if the server is OK and our cache entry came from when it was down then
(centry->sequence_number == DOM_SEQUENCE_NONE)) {
DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n",
keystr, domain->name ));
- return True;
+ return true;
}
/* if the server is down or the cache entry is not older than the
centry->sequence_number == domain->sequence_number) {
DEBUG(10,("centry_expired: Key %s for domain %s is good.\n",
keystr, domain->name ));
- return False;
+ return false;
}
DEBUG(10,("centry_expired: Key %s for domain %s expired\n",
keystr, domain->name ));
/* it's expired */
- return True;
+ return true;
}
static struct cache_entry *wcache_fetch_raw(char *kstr)
char *kstr;
struct cache_entry *centry;
- if (opt_nocache) {
+ if (!winbindd_use_cache()) {
return NULL;
}
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
va_start(ap, format);
smb_xvasprintf(&kstr, format, ap);
char *kstr;
TDB_DATA key, data;
- if (opt_nocache) {
+ if (!winbindd_use_cache()) {
return;
}
centry_free(centry);
}
-static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy)
+static void wcache_save_lockout_policy(struct winbindd_domain *domain,
+ NTSTATUS status,
+ struct samr_DomInfo12 *lockout_policy)
{
struct cache_entry *centry;
if (!centry)
return;
- centry_put_nttime(centry, lockout_policy->duration);
- centry_put_nttime(centry, lockout_policy->reset_count);
- centry_put_uint16(centry, lockout_policy->bad_attempt_lockout);
+ centry_put_nttime(centry, lockout_policy->lockout_duration);
+ centry_put_nttime(centry, lockout_policy->lockout_window);
+ centry_put_uint16(centry, lockout_policy->lockout_threshold);
centry_end(centry, "LOC_POL/%s", domain->name);
-
+
DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name));
centry_free(centry);
}
-static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *policy)
+
+
+static void wcache_save_password_policy(struct winbindd_domain *domain,
+ NTSTATUS status,
+ struct samr_DomInfo1 *policy)
{
struct cache_entry *centry;
if (!centry)
return;
- centry_put_uint16(centry, policy->min_length_password);
- centry_put_uint16(centry, policy->password_history);
+ centry_put_uint16(centry, policy->min_password_length);
+ centry_put_uint16(centry, policy->password_history_length);
centry_put_uint32(centry, policy->password_properties);
- centry_put_nttime(centry, policy->expire);
- centry_put_nttime(centry, policy->min_passwordage);
+ centry_put_nttime(centry, policy->max_password_age);
+ centry_put_nttime(centry, policy->min_password_age);
centry_end(centry, "PWD_POL/%s", domain->name);
-
+
DEBUG(10,("wcache_save_password_policy: %s\n", domain->name));
centry_free(centry);
}
+/***************************************************************************
+ ***************************************************************************/
+
+static void wcache_save_username_alias(struct winbindd_domain *domain,
+ NTSTATUS status,
+ const char *name, const char *alias)
+{
+ struct cache_entry *centry;
+ fstring uname;
+
+ if ( (centry = centry_start(domain, status)) == NULL )
+ return;
+
+ centry_put_string( centry, alias );
+
+ fstrcpy(uname, name);
+ strupper_m(uname);
+ centry_end(centry, "NSS/NA/%s", uname);
+
+ DEBUG(10,("wcache_save_username_alias: %s -> %s\n", name, alias ));
+
+ centry_free(centry);
+}
+
+static void wcache_save_alias_username(struct winbindd_domain *domain,
+ NTSTATUS status,
+ const char *alias, const char *name)
+{
+ struct cache_entry *centry;
+ fstring uname;
+
+ if ( (centry = centry_start(domain, status)) == NULL )
+ return;
+
+ centry_put_string( centry, name );
+
+ fstrcpy(uname, alias);
+ strupper_m(uname);
+ centry_end(centry, "NSS/AN/%s", uname);
+
+ DEBUG(10,("wcache_save_alias_username: %s -> %s\n", alias, name ));
+
+ centry_free(centry);
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS resolve_username_to_alias( TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
+ const char *name, char **alias )
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ char *upper_name;
+
+ if ( domain->internal )
+ return NT_STATUS_NOT_SUPPORTED;
+
+ if (!cache->tdb)
+ goto do_query;
+
+ if ( (upper_name = SMB_STRDUP(name)) == NULL )
+ return NT_STATUS_NO_MEMORY;
+ strupper_m(upper_name);
+
+ centry = wcache_fetch(cache, domain, "NSS/NA/%s", upper_name);
+
+ SAFE_FREE( upper_name );
+
+ if (!centry)
+ goto do_query;
+
+ status = centry->status;
+
+ if (!NT_STATUS_IS_OK(status)) {
+ centry_free(centry);
+ return status;
+ }
+
+ *alias = centry_string( centry, mem_ctx );
+
+ centry_free(centry);
+
+ DEBUG(10,("resolve_username_to_alias: [Cached] - mapped %s to %s\n",
+ name, *alias ? *alias : "(none)"));
+
+ return (*alias) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+do_query:
+
+ /* If its not in cache and we are offline, then fail */
+
+ if ( get_global_winbindd_state_offline() || !domain->online ) {
+ DEBUG(8,("resolve_username_to_alias: rejecting query "
+ "in offline mode\n"));
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ status = nss_map_to_alias( mem_ctx, domain->name, name, alias );
+
+ if ( NT_STATUS_IS_OK( status ) ) {
+ wcache_save_username_alias(domain, status, name, *alias);
+ }
+
+ if ( NT_STATUS_EQUAL( status, NT_STATUS_NONE_MAPPED ) ) {
+ wcache_save_username_alias(domain, status, name, "(NULL)");
+ }
+
+ DEBUG(5,("resolve_username_to_alias: backend query returned %s\n",
+ nt_errstr(status)));
+
+ if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) {
+ set_domain_offline( domain );
+ }
+
+ return status;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS resolve_alias_to_username( TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
+ const char *alias, char **name )
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ char *upper_name;
+
+ if ( domain->internal )
+ return NT_STATUS_NOT_SUPPORTED;
+
+ if (!cache->tdb)
+ goto do_query;
+
+ if ( (upper_name = SMB_STRDUP(alias)) == NULL )
+ return NT_STATUS_NO_MEMORY;
+ strupper_m(upper_name);
+
+ centry = wcache_fetch(cache, domain, "NSS/AN/%s", upper_name);
+
+ SAFE_FREE( upper_name );
+
+ if (!centry)
+ goto do_query;
+
+ status = centry->status;
+
+ if (!NT_STATUS_IS_OK(status)) {
+ centry_free(centry);
+ return status;
+ }
+
+ *name = centry_string( centry, mem_ctx );
+
+ centry_free(centry);
+
+ DEBUG(10,("resolve_alias_to_username: [Cached] - mapped %s to %s\n",
+ alias, *name ? *name : "(none)"));
+
+ return (*name) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+do_query:
+
+ /* If its not in cache and we are offline, then fail */
+
+ if ( get_global_winbindd_state_offline() || !domain->online ) {
+ DEBUG(8,("resolve_alias_to_username: rejecting query "
+ "in offline mode\n"));
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ /* an alias cannot contain a domain prefix or '@' */
+
+ if (strchr(alias, '\\') || strchr(alias, '@')) {
+ DEBUG(10,("resolve_alias_to_username: skipping fully "
+ "qualified name %s\n", alias));
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+
+ status = nss_map_from_alias( mem_ctx, domain->name, alias, name );
+
+ if ( NT_STATUS_IS_OK( status ) ) {
+ wcache_save_alias_username( domain, status, alias, *name );
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
+ wcache_save_alias_username(domain, status, alias, "(NULL)");
+ }
+
+ DEBUG(5,("resolve_alias_to_username: backend query returned %s\n",
+ nt_errstr(status)));
+
+ if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) {
+ set_domain_offline( domain );
+ }
+
+ return status;
+}
+
NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
{
struct winbind_cache *cache = get_cache(domain);
(retry++ < 5));
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
domain_name, name, sid, type);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
if (domain->online &&
(NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) {
status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
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
goto error;
}
- have_mapped = have_unmapped = False;
+ have_mapped = have_unmapped = false;
for (i=0; i<num_rids; i++) {
DOM_SID sid;
if (NT_STATUS_IS_OK(centry->status)) {
char *dom;
- have_mapped = True;
+ have_mapped = true;
(*types)[i] = (enum lsa_SidType)centry_uint32(centry);
dom = centry_string(centry, mem_ctx);
(*names)[i] = centry_string(centry, *names);
} else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
- have_unmapped = True;
+ have_unmapped = true;
} else {
/* something's definitely wrong */
return result;
}
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
for (i=0; i<num_rids; i++) {
DOM_SID sid;
status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_user(domain, status, info);
return status;
goto skip_save;
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
num_aliases, alias_rids);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
sid_mem, names, name_types);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
/* find the sequence number for a domain */
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
*seq = domain->sequence_number;
for (i=0; i<(*num_domains); i++) {
(*names)[i] = centry_string(centry, mem_ctx);
(*alt_names)[i] = centry_string(centry, mem_ctx);
- centry_sid(centry, mem_ctx, &(*dom_sids)[i]);
+ if (!centry_sid(centry, mem_ctx, &(*dom_sids)[i])) {
+ sid_copy(&(*dom_sids)[i], &global_sid_NULL);
+ }
}
status = centry->status;
the main parent and always to make the query. --jerry */
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
/* get lockout policy */
static NTSTATUS lockout_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- SAM_UNK_INFO_12 *policy){
+ struct samr_DomInfo12 *policy)
+{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
-
+
if (!cache->tdb)
goto do_query;
-
+
centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
-
+
if (!centry)
goto do_query;
-
- policy->duration = centry_nttime(centry);
- policy->reset_count = centry_nttime(centry);
- policy->bad_attempt_lockout = centry_uint16(centry);
-
+
+ policy->lockout_duration = centry_nttime(centry);
+ policy->lockout_window = centry_nttime(centry);
+ policy->lockout_threshold = centry_uint16(centry);
+
status = centry->status;
-
+
DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status: %s\n",
domain->name, nt_errstr(status) ));
-
+
centry_free(centry);
return status;
-
+
do_query:
ZERO_STRUCTP(policy);
-
+
/* Return status value returned by seq number check */
if (!NT_STATUS_IS_OK(domain->last_status))
return domain->last_status;
-
+
DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n",
domain->name ));
-
- status = domain->backend->lockout_policy(domain, mem_ctx, policy);
-
+
+ status = domain->backend->lockout_policy(domain, mem_ctx, policy);
+
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_lockout_policy(domain, status, policy);
-
+
return status;
}
-
+
/* get password policy */
static NTSTATUS password_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- SAM_UNK_INFO_1 *policy)
+ struct samr_DomInfo1 *policy)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
if (!cache->tdb)
goto do_query;
-
+
centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
-
+
if (!centry)
goto do_query;
- policy->min_length_password = centry_uint16(centry);
- policy->password_history = centry_uint16(centry);
+ policy->min_password_length = centry_uint16(centry);
+ policy->password_history_length = centry_uint16(centry);
policy->password_properties = centry_uint32(centry);
- policy->expire = centry_nttime(centry);
- policy->min_passwordage = centry_nttime(centry);
+ policy->max_password_age = centry_nttime(centry);
+ policy->min_password_age = centry_nttime(centry);
status = centry->status;
if (!NT_STATUS_IS_OK(domain->last_status))
return domain->last_status;
-
+
DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n",
domain->name ));
- status = domain->backend->password_policy(domain, mem_ctx, policy);
+ status = domain->backend->password_policy(domain, mem_ctx, policy);
/* and save it */
- refresh_sequence_number(domain, False);
- wcache_save_password_policy(domain, status, policy);
+ refresh_sequence_number(domain, false);
+ if (NT_STATUS_IS_OK(status)) {
+ wcache_save_password_policy(domain, status, policy);
+ }
return status;
}
/* Invalidate the getpwnam and getgroups entries for a winbindd domain */
void wcache_invalidate_samlogon(struct winbindd_domain *domain,
- NET_USER_INFO_3 *info3)
+ struct netr_SamInfo3 *info3)
{
+ DOM_SID sid;
+ fstring key_str, sid_string;
struct winbind_cache *cache;
/* dont clear cached U/SID and UG/SID entries when we want to logon
return;
cache = get_cache(domain);
- netsamlogon_clear_cached_user(cache->tdb, info3);
+
+ if (!cache->tdb) {
+ return;
+ }
+
+ sid_copy(&sid, info3->base.domain_sid);
+ sid_append_rid(&sid, info3->base.rid);
+
+ /* Clear U/SID cache entry */
+ 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));
+ 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);
}
-int wcache_invalidate_cache(void)
+bool wcache_invalidate_cache(void)
{
struct winbindd_domain *domain;
if (cache->tdb) {
tdb_traverse(cache->tdb, traverse_fn, NULL);
} else {
- return -1;
+ return false;
}
}
}
- return 0;
+ return true;
}
bool init_wcache(void)
}
if (wcache->tdb != NULL)
- return True;
+ return true;
/* when working offline we must not clear the cache on restart */
- wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ 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),
O_RDWR|O_CREAT, 0600);
if (wcache->tdb == NULL) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
- return False;
+ return false;
}
- return True;
+ return true;
}
/************************************************************************
bool initialize_winbindd_cache(void)
{
- bool cache_bad = True;
+ bool cache_bad = true;
uint32 vers;
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n"));
- return False;
+ return false;
}
/* Check version number. */
if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) &&
vers == WINBINDD_CACHE_VERSION) {
- cache_bad = False;
+ cache_bad = false;
}
if (cache_bad) {
tdb_close(wcache->tdb);
wcache->tdb = NULL;
- if (unlink(lock_path("winbindd_cache.tdb")) == -1) {
+ if (unlink(cache_path("winbindd_cache.tdb")) == -1) {
DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ",
- lock_path("winbindd_cache.tdb"),
+ cache_path("winbindd_cache.tdb"),
strerror(errno) ));
- return False;
+ return false;
}
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: re-initialization "
"init_wcache failed.\n"));
- return False;
+ return false;
}
/* Write the version. */
if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) {
DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n",
tdb_errorstr(wcache->tdb) ));
- return False;
+ return false;
}
}
tdb_close(wcache->tdb);
wcache->tdb = NULL;
- return True;
+ return true;
}
-void close_winbindd_cache()
+void close_winbindd_cache(void)
{
if (!wcache) {
return;
return;
DEBUG(10, ("Storing response for pid %d, len %d\n",
- pid, response->length));
+ (int)pid, response->length));
- fstr_sprintf(key_str, "DR/%d", pid);
+ fstr_sprintf(key_str, "DR/%d", (int)pid);
if (tdb_store(wcache->tdb, string_tdb_data(key_str),
make_tdb_data((uint8 *)response, sizeof(*response)),
TDB_REPLACE) == -1)
DEBUG(10, ("Storing extra data: len=%d\n",
(int)(response->length - sizeof(*response))));
- fstr_sprintf(key_str, "DE/%d", pid);
+ fstr_sprintf(key_str, "DE/%d", (int)pid);
if (tdb_store(wcache->tdb, string_tdb_data(key_str),
make_tdb_data((uint8 *)response->extra_data.data,
response->length - sizeof(*response)),
/* 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);
+ fstr_sprintf(key_str, "DR/%d", (int)pid);
tdb_delete(wcache->tdb, string_tdb_data(key_str));
return;
fstring key_str;
if (!init_wcache())
- return False;
+ return false;
- DEBUG(10, ("Retrieving response for pid %d\n", pid));
+ DEBUG(10, ("Retrieving response for pid %d\n", (int)pid));
- fstr_sprintf(key_str, "DR/%d", pid);
+ fstr_sprintf(key_str, "DR/%d", (int)pid);
data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
if (data.dptr == NULL)
- return False;
+ return false;
if (data.dsize != sizeof(*response))
- return False;
+ return false;
memcpy(response, data.dptr, data.dsize);
SAFE_FREE(data.dptr);
if (response->length == sizeof(*response)) {
response->extra_data.data = NULL;
- return True;
+ 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);
+ fstr_sprintf(key_str, "DE/%d", (int)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;
+ 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;
+ return false;
}
dump_data(11, (uint8 *)data.dptr, data.dsize);
response->extra_data.data = data.dptr;
- return True;
+ return true;
}
void cache_cleanup_response(pid_t pid)
if (!init_wcache())
return;
- fstr_sprintf(key_str, "DR/%d", pid);
+ fstr_sprintf(key_str, "DR/%d", (int)pid);
tdb_delete(wcache->tdb, string_tdb_data(key_str));
- fstr_sprintf(key_str, "DE/%d", pid);
+ fstr_sprintf(key_str, "DE/%d", (int)pid);
tdb_delete(wcache->tdb, string_tdb_data(key_str));
return;
domain = find_lookup_domain_from_sid(sid);
if (domain == NULL) {
- return False;
+ return false;
}
cache = get_cache(domain);
if (cache->tdb == NULL) {
- return False;
+ return false;
}
centry = wcache_fetch(cache, domain, "SN/%s",
sid_to_fstring(tmp, sid));
if (centry == NULL) {
- return False;
+ return false;
}
if (NT_STATUS_IS_OK(centry->status)) {
domain = find_lookup_domain_from_name(domain_name);
if (domain == NULL) {
- return False;
+ return false;
}
cache = get_cache(domain);
if (cache->tdb == NULL) {
- return False;
+ return false;
}
fstrcpy(uname, name);
offline so the cache won't expire the entry */
original_online_state = domain->online;
- domain->online = False;
+ domain->online = false;
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
domain->online = original_online_state;
if (centry == NULL) {
- return False;
+ return false;
}
if (NT_STATUS_IS_OK(centry->status)) {
const char *domain_name, const char *name,
enum lsa_SidType type, const DOM_SID *sid)
{
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
sid, type);
}
tdb_close(wcache->tdb);
wcache->tdb = NULL;
}
- if (opt_nocache)
+ if (!winbindd_use_cache()) {
return;
+ }
/* when working offline we must not clear the cache on restart */
- wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ 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),
O_RDWR|O_CREAT, 0600);
if (wcache == NULL || wcache->tdb == NULL) {
DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n"));
- return False;
+ return false;
}
if (!lp_winbind_offline_logon()) {
DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n"));
- return False;
+ return false;
}
if (global_winbindd_offline_state) {
/* Already offline. */
- return True;
+ return true;
}
data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
if (!data.dptr || data.dsize != 4) {
DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
SAFE_FREE(data.dptr);
- return False;
+ return false;
} else {
DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
- global_winbindd_offline_state = True;
+ global_winbindd_offline_state = true;
SAFE_FREE(data.dptr);
- return True;
+ return true;
}
}
/* Already online. */
return;
}
- global_winbindd_offline_state = False;
+ global_winbindd_offline_state = false;
if (!wcache->tdb) {
return;
/* huh? corrupt cache? */
DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr));
centry_free(centry);
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return NULL;
}
if (dbuf.dsize != 8) {
DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n",
keystr, (unsigned int)dbuf.dsize ));
- state->bad_entry = True;
+ state->bad_entry = true;
return 1;
}
return 0;
if (dbuf.dsize == 0) {
DEBUG(0,("validate_dr: Corrupt cache for key %s (len == 0) ?\n",
keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
if (dbuf.dsize == 0) {
DEBUG(0,("validate_de: Corrupt cache for key %s (len == 0) ?\n",
keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
return 0;
}
+static int validate_pwinfo(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);
+
+ if (!centry) {
+ return 1;
+ }
+
+ (void)centry_string(centry, mem_ctx);
+ (void)centry_string(centry, mem_ctx);
+ (void)centry_string(centry, mem_ctx);
+ (void)centry_uint32(centry);
+
+ centry_free(centry);
+
+ if (!(state->success)) {
+ return 1;
+ }
+ DEBUG(10,("validate_pwinfo: %s ok\n", keystr));
+ return 0;
+}
+
+static int validate_nss_an(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);
+
+ if (!centry) {
+ return 1;
+ }
+
+ (void)centry_string( centry, mem_ctx );
+
+ centry_free(centry);
+
+ if (!(state->success)) {
+ return 1;
+ }
+ DEBUG(10,("validate_pwinfo: %s ok\n", keystr));
+ return 0;
+}
+
+static int validate_nss_na(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);
+
+ if (!centry) {
+ return 1;
+ }
+
+ (void)centry_string( centry, mem_ctx );
+
+ centry_free(centry);
+
+ if (!(state->success)) {
+ return 1;
+ }
+ DEBUG(10,("validate_pwinfo: %s ok\n", keystr));
+ return 0;
+}
+
static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
struct tdb_validation_status *state)
{
if (dbuf.dsize == 0) {
DEBUG(0, ("validate_trustdomcache: Corrupt cache for "
"key %s (len ==0) ?\n", keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
if (dbuf.dsize != 4) {
DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n",
keystr, (unsigned int)dbuf.dsize ));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
DEBUG(10,("validate_offline: %s ok\n", keystr));
DEBUG(0, ("validate_cache_version: Corrupt cache for "
"key %s (len %u != 4) ?\n",
keystr, (unsigned int)dbuf.dsize));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
{"GM/", validate_gm},
{"DR/", validate_dr},
{"DE/", validate_de},
+ {"NSS/PWINFO/", validate_pwinfo},
{"TRUSTDOMS/", validate_trustdoms},
{"TRUSTDOMCACHE/", validate_trustdomcache},
+ {"NSS/NA/", validate_nss_na},
+ {"NSS/AN/", validate_nss_an},
{"WINBINDD_OFFLINE", validate_offline},
{WINBINDD_CACHE_VERSION_KEYSTR, validate_cache_version},
{NULL, NULL}
static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
int i;
+ unsigned int max_key_len = 1024;
struct tdb_validation_status *v_state = (struct tdb_validation_status *)state;
/* Paranoia check. */
- if (kbuf.dsize > 1024) {
- DEBUG(0,("cache_traverse_validate_fn: key length too large (%u) > 1024\n\n",
- (unsigned int)kbuf.dsize ));
+ if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0) {
+ max_key_len = 1024 * 1024;
+ }
+ if (kbuf.dsize > max_key_len) {
+ DEBUG(0, ("cache_traverse_validate_fn: key length too large: "
+ "(%u) > (%u)\n\n",
+ (unsigned int)kbuf.dsize, (unsigned int)max_key_len));
return 1;
}
dump_data(0, (uint8 *)kbuf.dptr, kbuf.dsize);
DEBUG(0,("data :\n"));
dump_data(0, (uint8 *)dbuf.dptr, dbuf.dsize);
- v_state->unknown_key = True;
- v_state->success = False;
+ v_state->unknown_key = true;
+ v_state->success = false;
return 1; /* terminate. */
}
int winbindd_validate_cache(void)
{
int ret = -1;
- const char *tdb_path = lock_path("winbindd_cache.tdb");
+ const char *tdb_path = cache_path("winbindd_cache.tdb");
TDB_CONTEXT *tdb = NULL;
DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
int winbindd_validate_cache_nobackup(void)
{
int ret = -1;
- const char *tdb_path = lock_path("winbindd_cache.tdb");
+ const char *tdb_path = cache_path("winbindd_cache.tdb");
DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
smb_panic_fn = validate_panic;
return ret;
}
+bool winbindd_cache_validate_and_initialize(void)
+{
+ close_winbindd_cache();
+
+ if (lp_winbind_offline_logon()) {
+ if (winbindd_validate_cache() < 0) {
+ DEBUG(0, ("winbindd cache tdb corrupt and no backup "
+ "could be restored.\n"));
+ }
+ }
+
+ return initialize_winbindd_cache();
+}
+
/*********************************************************************
********************************************************************/
struct winbindd_tdc_domain *list = NULL;
size_t idx;
int i;
- bool set_only = False;
+ bool set_only = false;
/* don't allow duplicates */
DEBUG(10,("add_wbdomain_to_tdc_array: Found existing record for %s\n",
new_dom->name));
idx = i;
- set_only = True;
+ set_only = true;
break;
}
}
if ( !list )
- return False;
+ return false;
list[idx].domain_name = talloc_strdup( list, new_dom->name );
list[idx].dns_name = talloc_strdup( list, new_dom->alt_name );
- if ( !is_null_sid( &new_dom->sid ) )
+ if ( !is_null_sid( &new_dom->sid ) ) {
sid_copy( &list[idx].sid, &new_dom->sid );
+ } else {
+ sid_copy(&list[idx].sid, &global_sid_NULL);
+ }
if ( new_dom->domain_flags != 0x0 )
list[idx].trust_flags = new_dom->domain_flags;
*num_domains = idx + 1;
}
- return True;
+ return true;
}
/*********************************************************************
}
- asprintf( &keystr, "TRUSTDOMCACHE/%s", domain_name );
+ if (asprintf( &keystr, "TRUSTDOMCACHE/%s", domain_name ) == -1) {
+ return key;
+ }
key = string_term_tdb_data(keystr);
return key;
int ret;
if ( !key.dptr )
- return False;
+ return false;
/* See if we were asked to delete the cache entry */
*num_domains = 0;
if ( !key.dptr )
- return False;
+ return false;
data = tdb_fetch( wcache->tdb, key );
SAFE_FREE( key.dptr );
if ( !data.dptr )
- return False;
+ return false;
*num_domains = unpack_tdc_domains( data.dptr, data.dsize, domains );
SAFE_FREE( data.dptr );
if ( !*domains )
- return False;
+ return false;
- return True;
+ return true;
}
/*********************************************************************
{
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
- bool ret = False;
+ bool ret = false;
DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, "
"flags = 0x%x, attributes = 0x%x, type = 0x%x\n",
domain->domain_type));
if ( !init_wcache() ) {
- return False;
+ return false;
}
/* fetch the list */
/* Success */
- ret = True;
+ ret = true;
done:
TALLOC_FREE( dom_list );
DEBUG(10,("wcache_tdc_fetch_domain: Searching for domain %s\n", name));
if ( !init_wcache() ) {
- return False;
+ return false;
}
/* fetch the list */
nt_status = nss_get_info( domain->name, user_sid, ctx, ads, msg,
homedir, shell, gecos, p_gid );
+ DEBUG(10, ("nss_get_info returned %s\n", nt_errstr(nt_status)));
+
if ( NT_STATUS_IS_OK(nt_status) ) {
+ DEBUG(10, ("result:\n\thomedir = '%s'\n", *homedir));
+ DEBUGADD(10, ("\tshell = '%s'\n", *shell));
+ DEBUGADD(10, ("\tgecos = '%s'\n", *gecos));
+ DEBUGADD(10, ("\tgid = '%u'\n", (unsigned int)*p_gid));
+
wcache_save_user_pwinfo( domain, nt_status, user_sid,
*homedir, *shell, *gecos, *p_gid );
}
/* the cache backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
- True,
+ true,
query_user_list,
enum_dom_groups,
enum_local_groups,