#include "winbindd.h"
#include "tdb_validate.h"
#include "../libcli/auth/libcli_auth.h"
-#include "../librpc/gen_ndr/ndr_wbint.h"
+#include "../librpc/gen_ndr/ndr_winbind.h"
#include "ads.h"
#include "nss_info.h"
#include "../libcli/security/security.h"
#include "passdb/machine_sid.h"
#include "util_tdb.h"
+#include "libsmb/samlogon_cache.h"
+#include "lib/namemap_cache.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
extern struct winbindd_methods reconnect_methods;
#ifdef HAVE_ADS
-extern struct winbindd_methods ads_methods;
+extern struct winbindd_methods reconnect_ads_methods;
#endif
extern struct winbindd_methods builtin_passdb_methods;
extern struct winbindd_methods sam_passdb_methods;
+static void wcache_flush_cache(void);
+
/*
* JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
* Here are the list of entry types that are *not* stored
struct cache_entry {
NTSTATUS status;
- uint32 sequence_number;
+ uint32_t sequence_number;
uint64_t timeout;
- uint8 *data;
- uint32 len, ofs;
+ uint8_t *data;
+ uint32_t len, ofs;
};
void (*smb_panic_fn)(const char *const why) = smb_panic;
-#define WINBINDD_MAX_CACHE_SIZE (50*1024*1024)
-
static struct winbind_cache *wcache;
-/* get the winbind_cache structure */
-static struct winbind_cache *get_cache(struct winbindd_domain *domain)
+static char *wcache_path(void)
{
- struct winbind_cache *ret = wcache;
+ /*
+ * Data needs to be kept persistent in state directory for
+ * running with "winbindd offline logon".
+ */
+ return state_path(talloc_tos(), "winbindd_cache.tdb");
+}
- /* We have to know what type of domain we are dealing with first. */
+static void winbindd_domain_init_backend(struct winbindd_domain *domain)
+{
+ if (domain->backend != NULL) {
+ return;
+ }
if (domain->internal) {
domain->backend = &builtin_passdb_methods;
- domain->initialized = True;
+ }
+
+ if (dom_sid_equal(&domain->sid, &global_sid_Builtin)) {
+ domain->initialized = true;
}
if (strequal(domain->name, get_global_sam_name()) &&
- sid_check_is_our_sam(&domain->sid)) {
+ sid_check_is_our_sam(&domain->sid))
+ {
domain->backend = &sam_passdb_methods;
- domain->initialized = True;
}
- if ( !domain->initialized ) {
- init_dc_connection( domain );
+ if (!domain->initialized) {
+ /* We do not need a connection to an RW DC for cache operation */
+ init_dc_connection(domain, false);
}
- /*
- OK. listen up becasue I'm only going to say this once.
- We have the following scenarios to consider
- (a) trusted AD domains on a Samba DC,
- (b) trusted AD domains and we are joined to a non-kerberos domain
- (c) trusted AD domains and we are joined to a kerberos (AD) domain
-
- For (a) we can always contact the trusted domain using krb5
- since we have the domain trust account password
-
- For (b) we can only use RPC since we have no way of
- getting a krb5 ticket in our own domain
-
- For (c) we can always use krb5 since we have a kerberos trust
-
- --jerry
- */
-
- if (!domain->backend) {
#ifdef HAVE_ADS
+ if (domain->backend == NULL) {
struct winbindd_domain *our_domain = domain;
- /* find our domain first so we can figure out if we
+ /* find our domain first so we can figure out if we
are joined to a kerberized domain */
- if ( !domain->primary )
+ if (!domain->primary) {
our_domain = find_our_domain();
+ }
if ((our_domain->active_directory || IS_DC)
&& domain->active_directory
- && !lp_winbind_rpc_only()) {
- DEBUG(5,("get_cache: Setting ADS methods for domain %s\n", domain->name));
- domain->backend = &ads_methods;
- } else {
-#endif /* HAVE_ADS */
- DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n", domain->name));
- domain->backend = &reconnect_methods;
-#ifdef HAVE_ADS
+ && !lp_winbind_rpc_only())
+ {
+ DBG_INFO("Setting ADS methods for domain %s\n",
+ domain->name);
+ domain->backend = &reconnect_ads_methods;
}
+ }
#endif /* HAVE_ADS */
+
+ if (domain->backend == NULL) {
+ DBG_INFO("Setting MS-RPC methods for domain %s\n", domain->name);
+ domain->backend = &reconnect_methods;
}
+}
- if (ret)
+/* get the winbind_cache structure */
+static struct winbind_cache *get_cache(struct winbindd_domain *domain)
+{
+ struct winbind_cache *ret = wcache;
+
+ winbindd_domain_init_backend(domain);
+
+ if (ret != NULL) {
return ret;
+ }
ret = SMB_XMALLOC_P(struct winbind_cache);
ZERO_STRUCTP(ret);
}
/*
- pull a uint32 from a cache entry
+ pull a uint32_t from a cache entry
*/
-static uint32 centry_uint32(struct cache_entry *centry)
+static uint32_t centry_uint32(struct cache_entry *centry)
{
- uint32 ret;
+ uint32_t ret;
if (!centry_check_bytes(centry, 4)) {
smb_panic_fn("centry_uint32");
}
/*
- pull a uint16 from a cache entry
+ pull a uint16_t from a cache entry
*/
-static uint16 centry_uint16(struct cache_entry *centry)
+static uint16_t centry_uint16(struct cache_entry *centry)
{
- uint16 ret;
+ uint16_t ret;
if (!centry_check_bytes(centry, 2)) {
smb_panic_fn("centry_uint16");
}
}
/*
- pull a uint8 from a cache entry
+ pull a uint8_t from a cache entry
*/
-static uint8 centry_uint8(struct cache_entry *centry)
+static uint8_t centry_uint8(struct cache_entry *centry)
{
- uint8 ret;
+ uint8_t ret;
if (!centry_check_bytes(centry, 1)) {
smb_panic_fn("centry_uint8");
}
}
ret = IVAL(centry->data, centry->ofs);
centry->ofs += 4;
- ret += (uint64)IVAL(centry->data, centry->ofs) << 32;
+ ret += (uint64_t)IVAL(centry->data, centry->ofs) << 32;
centry->ofs += 4;
return ret;
}
*/
static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
{
- uint32 len;
+ uint32_t len;
char *ret;
len = centry_uint8(centry);
*/
static char *centry_hash16(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
{
- uint32 len;
+ uint32_t len;
char *ret;
len = centry_uint8(centry);
return ret;
}
-static bool wcache_fetch_seqnum(const char *domain_name, uint32_t *seqnum,
- uint32_t *last_seq_check)
+struct wcache_seqnum_state {
+ uint32_t *seqnum;
+ uint32_t *last_seq_check;
+};
+
+static int wcache_seqnum_parser(TDB_DATA key, TDB_DATA data,
+ void *private_data)
{
- char *key;
- TDB_DATA data;
+ struct wcache_seqnum_state *state = private_data;
- if (wcache->tdb == NULL) {
- DEBUG(10,("wcache_fetch_seqnum: tdb == NULL\n"));
- return false;
+ if (data.dsize != 8) {
+ DEBUG(10, ("wcache_fetch_seqnum: invalid data size %d\n",
+ (int)data.dsize));
+ return -1;
}
- key = talloc_asprintf(talloc_tos(), "SEQNUM/%s", domain_name);
- if (key == NULL) {
- DEBUG(10, ("talloc failed\n"));
- return false;
- }
+ *state->seqnum = IVAL(data.dptr, 0);
+ *state->last_seq_check = IVAL(data.dptr, 4);
+ return 0;
+}
- data = tdb_fetch_bystring(wcache->tdb, key);
- TALLOC_FREE(key);
+static bool wcache_fetch_seqnum(const char *domain_name, uint32_t *seqnum,
+ uint32_t *last_seq_check)
+{
+ struct wcache_seqnum_state state = {
+ .seqnum = seqnum, .last_seq_check = last_seq_check
+ };
+ size_t len = strlen(domain_name);
+ char keystr[len+8];
+ TDB_DATA key = { .dptr = (uint8_t *)keystr, .dsize = sizeof(keystr) };
+ int ret;
- if (data.dptr == NULL) {
- DEBUG(10, ("wcache_fetch_seqnum: %s not found\n",
- domain_name));
- return false;
- }
- if (data.dsize != 8) {
- DEBUG(10, ("wcache_fetch_seqnum: invalid data size %d\n",
- (int)data.dsize));
- SAFE_FREE(data.dptr);
+ if (wcache->tdb == NULL) {
+ DEBUG(10,("wcache_fetch_seqnum: tdb == NULL\n"));
return false;
}
- *seqnum = IVAL(data.dptr, 0);
- *last_seq_check = IVAL(data.dptr, 4);
- SAFE_FREE(data.dptr);
+ snprintf(keystr, sizeof(keystr), "SEQNUM/%s", domain_name);
- return true;
+ ret = tdb_parse_record(wcache->tdb, key, wcache_seqnum_parser,
+ &state);
+ return (ret == 0);
}
static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now )
{
- uint32 last_check, time_diff;
+ uint32_t last_check, time_diff;
if (!wcache_fetch_seqnum(domain->name, &domain->sequence_number,
&last_check)) {
/* have we expired? */
time_diff = now - domain->last_seq_check;
- if ( time_diff > lp_winbind_cache_time() ) {
+ if ((int)time_diff > lp_winbind_cache_time()) {
DEBUG(10,("fetch_cache_seqnum: timeout [%s][%u @ %u]\n",
domain->name, domain->sequence_number,
- (uint32)domain->last_seq_check));
+ (uint32_t)domain->last_seq_check));
return NT_STATUS_UNSUCCESSFUL;
}
DEBUG(10,("fetch_cache_seqnum: success [%s][%u @ %u]\n",
domain->name, domain->sequence_number,
- (uint32)domain->last_seq_check));
+ (uint32_t)domain->last_seq_check));
return NT_STATUS_OK;
}
bool wcache_store_seqnum(const char *domain_name, uint32_t seqnum,
time_t last_seq_check)
{
- char *key_str;
+ size_t len = strlen(domain_name);
+ char keystr[len+8];
+ TDB_DATA key = { .dptr = (uint8_t *)keystr, .dsize = sizeof(keystr) };
uint8_t buf[8];
int ret;
return false;
}
- key_str = talloc_asprintf(talloc_tos(), "SEQNUM/%s", domain_name);
- if (key_str == NULL) {
- DEBUG(10, ("talloc_asprintf failed\n"));
- return false;
- }
+ snprintf(keystr, sizeof(keystr), "SEQNUM/%s", domain_name);
SIVAL(buf, 0, seqnum);
SIVAL(buf, 4, last_seq_check);
- ret = tdb_store_bystring(wcache->tdb, key_str,
- make_tdb_data(buf, sizeof(buf)), TDB_REPLACE);
- TALLOC_FREE(key_str);
+ ret = tdb_store(wcache->tdb, key, make_tdb_data(buf, sizeof(buf)),
+ TDB_REPLACE);
if (ret != 0) {
DEBUG(10, ("tdb_store_bystring failed: %s\n",
- tdb_errorstr_compat(wcache->tdb)));
- TALLOC_FREE(key_str);
+ tdb_errorstr(wcache->tdb)));
return false;
}
}
/*
- refresh the domain sequence number. If force is true
- then always refresh it, no matter how recently we fetched it
+ refresh the domain sequence number on timeout.
*/
-static void refresh_sequence_number(struct winbindd_domain *domain, bool force)
+static void refresh_sequence_number(struct winbindd_domain *domain)
{
NTSTATUS status;
unsigned time_diff;
time_diff = t - domain->last_seq_check;
/* see if we have to refetch the domain sequence number */
- if (!force && (time_diff < cache_time) &&
+ if ((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));
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)))) {
+ && ((time_t)centry->timeout > time(NULL)))) {
DEBUG(10,("centry_expired: Key %s for domain %s is good.\n",
keystr, domain->name ));
return false;
TDB_DATA key;
key = string_tdb_data(kstr);
- data = tdb_fetch_compat(wcache->tdb, key);
+ data = tdb_fetch(wcache->tdb, key);
if (!data.dptr) {
/* a cache miss */
return NULL;
return NULL;
}
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
va_start(ap, format);
smb_xvasprintf(&kstr, format, ap);
/*
make sure we have at least len bytes available in a centry
*/
-static void centry_expand(struct cache_entry *centry, uint32 len)
+static void centry_expand(struct cache_entry *centry, uint32_t len)
{
if (centry->len - centry->ofs >= len)
return;
}
/*
- push a uint32 into a centry
+ push a uint32_t into a centry
*/
-static void centry_put_uint32(struct cache_entry *centry, uint32 v)
+static void centry_put_uint32(struct cache_entry *centry, uint32_t v)
{
centry_expand(centry, 4);
SIVAL(centry->data, centry->ofs, v);
}
/*
- push a uint16 into a centry
+ push a uint16_t into a centry
*/
-static void centry_put_uint16(struct cache_entry *centry, uint16 v)
+static void centry_put_uint16(struct cache_entry *centry, uint16_t v)
{
centry_expand(centry, 2);
SSVAL(centry->data, centry->ofs, v);
}
/*
- push a uint8 into a centry
+ push a uint8_t into a centry
*/
-static void centry_put_uint8(struct cache_entry *centry, uint8 v)
+static void centry_put_uint8(struct cache_entry *centry, uint8_t v)
{
centry_expand(centry, 1);
SCVAL(centry->data, centry->ofs, v);
/*
push a 16 byte hash into a centry - treat as 16 byte string.
*/
-static void centry_put_hash16(struct cache_entry *centry, const uint8 val[16])
+static void centry_put_hash16(struct cache_entry *centry, const uint8_t val[16])
{
centry_put_uint8(centry, 16);
centry_expand(centry, 16);
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));
+ struct dom_sid_buf sid_string;
+ centry_put_string(centry, dom_sid_str_buf(sid, &sid_string));
}
*/
static void centry_put_ntstatus(struct cache_entry *centry, NTSTATUS status)
{
- uint32 status_value = NT_STATUS_V(status);
+ uint32_t status_value = NT_STATUS_V(status);
centry_put_uint32(centry, status_value);
}
/*
start a centry for output. When finished, call centry_end()
*/
-struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status)
+static struct cache_entry *centry_start(struct winbindd_domain *domain,
+ NTSTATUS status)
{
struct cache_entry *centry;
centry = SMB_XMALLOC_P(struct cache_entry);
centry->len = 8192; /* reasonable default */
- centry->data = SMB_XMALLOC_ARRAY(uint8, centry->len);
+ centry->data = SMB_XMALLOC_ARRAY(uint8_t, centry->len);
centry->ofs = 0;
centry->sequence_number = domain->sequence_number;
centry->timeout = lp_winbind_cache_time() + time(NULL);
const char *name, const struct dom_sid *sid,
enum lsa_SidType type)
{
- struct cache_entry *centry;
- fstring uname;
+ bool ok;
- centry = centry_start(domain, status);
- if (!centry)
- return;
- centry_put_uint32(centry, type);
- centry_put_sid(centry, sid);
- fstrcpy(uname, name);
- (void)strupper_m(uname);
- centry_end(centry, "NS/%s/%s", domain_name, uname);
- DEBUG(10,("wcache_save_name_to_sid: %s\\%s -> %s (%s)\n", domain_name,
- uname, sid_string_dbg(sid), nt_errstr(status)));
- centry_free(centry);
+ ok = namemap_cache_set_name2sid(domain_name, name, sid, type,
+ time(NULL) + lp_winbind_cache_time());
+ if (!ok) {
+ DBG_DEBUG("namemap_cache_set_name2sid failed\n");
+ }
+
+ /*
+ * Don't store the reverse mapping. The name came from user
+ * input, and we might not have the correct capitalization,
+ * which is important for nsswitch.
+ */
}
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status,
const struct dom_sid *sid, const char *domain_name, const char *name, enum lsa_SidType type)
{
- struct cache_entry *centry;
- fstring sid_string;
-
- centry = centry_start(domain, status);
- if (!centry)
- return;
+ bool ok;
- if (NT_STATUS_IS_OK(status)) {
- centry_put_uint32(centry, type);
- centry_put_string(centry, domain_name);
- centry_put_string(centry, name);
+ ok = namemap_cache_set_sid2name(sid, domain_name, name, type,
+ time(NULL) + lp_winbind_cache_time());
+ if (!ok) {
+ DBG_DEBUG("namemap_cache_set_sid2name failed\n");
}
- centry_end(centry, "SN/%s", sid_to_fstring(sid_string, sid));
- DEBUG(10,("wcache_save_sid_to_name: %s -> %s\\%s (%s)\n", sid_string,
- domain_name, name, nt_errstr(status)));
- centry_free(centry);
-}
-
-
-static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status,
- struct wbint_userinfo *info)
-{
- struct cache_entry *centry;
- fstring sid_string;
-
- if (is_null_sid(&info->user_sid)) {
- return;
+ if (type != SID_NAME_UNKNOWN) {
+ ok = namemap_cache_set_name2sid(
+ domain_name, name, sid, type,
+ time(NULL) + lp_winbind_cache_time());
+ if (!ok) {
+ DBG_DEBUG("namemap_cache_set_name2sid failed\n");
+ }
}
-
- centry = centry_start(domain, status);
- if (!centry)
- return;
- centry_put_string(centry, info->acct_name);
- centry_put_string(centry, info->full_name);
- centry_put_string(centry, info->homedir);
- centry_put_string(centry, info->shell);
- centry_put_uint32(centry, info->primary_gid);
- centry_put_sid(centry, &info->user_sid);
- centry_put_sid(centry, &info->group_sid);
- centry_end(centry, "U/%s", sid_to_fstring(sid_string,
- &info->user_sid));
- DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name));
- centry_free(centry);
}
static void wcache_save_lockout_policy(struct winbindd_domain *domain,
if (!cache->tdb)
goto do_query;
- if ( (upper_name = SMB_STRDUP(name)) == NULL )
+ upper_name = talloc_strdup_upper(mem_ctx, name);
+ if (upper_name == NULL) {
return NT_STATUS_NO_MEMORY;
- if (!strupper_m(upper_name)) {
- SAFE_FREE(upper_name);
- return NT_STATUS_INVALID_PARAMETER;
}
centry = wcache_fetch(cache, domain, "NSS/NA/%s", upper_name);
- SAFE_FREE( upper_name );
+ talloc_free(upper_name);
if (!centry)
goto do_query;
/* If its not in cache and we are offline, then fail */
- if ( get_global_winbindd_state_offline() || !domain->online ) {
+ if (is_domain_offline(domain)) {
DEBUG(8,("resolve_username_to_alias: rejecting query "
"in offline mode\n"));
return NT_STATUS_NOT_FOUND;
if (!cache->tdb)
goto do_query;
- if ( (upper_name = SMB_STRDUP(alias)) == NULL )
+ upper_name = talloc_strdup(mem_ctx, alias);
+ if (upper_name == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
if (!strupper_m(upper_name)) {
- SAFE_FREE(alias);
+ talloc_free(upper_name);
return NT_STATUS_INVALID_PARAMETER;
}
centry = wcache_fetch(cache, domain, "NSS/AN/%s", upper_name);
- SAFE_FREE( upper_name );
+ talloc_free(upper_name);
if (!centry)
goto do_query;
/* If its not in cache and we are offline, then fail */
- if ( get_global_winbindd_state_offline() || !domain->online ) {
+ if (is_domain_offline(domain)) {
DEBUG(8,("resolve_alias_to_username: rejecting query "
"in offline mode\n"));
return NT_STATUS_NOT_FOUND;
NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const struct dom_sid *sid)
{
struct winbind_cache *cache = get_cache(domain);
- TDB_DATA data;
- fstring key_str, tmp;
- uint32 rid;
+ int ret;
+ struct dom_sid_buf tmp;
+ fstring key_str;
+ uint32_t rid;
if (!cache->tdb) {
return NT_STATUS_INTERNAL_DB_ERROR;
return NT_STATUS_INVALID_SID;
}
- fstr_sprintf(key_str, "CRED/%s", sid_to_fstring(tmp, sid));
+ fstr_sprintf(key_str, "CRED/%s", dom_sid_str_buf(sid, &tmp));
- data = tdb_fetch_compat(cache->tdb, string_tdb_data(key_str));
- if (!data.dptr) {
+ ret = tdb_exists(cache->tdb, string_tdb_data(key_str));
+ if (ret != 1) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- SAFE_FREE(data.dptr);
return NT_STATUS_OK;
}
NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *sid,
- const uint8 **cached_nt_pass,
- const uint8 **cached_salt)
+ const uint8_t **cached_nt_pass,
+ const uint8_t **cached_salt)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
- uint32 rid;
- fstring tmp;
+ uint32_t rid;
+ struct dom_sid_buf sidstr;
if (!cache->tdb) {
return NT_STATUS_INTERNAL_DB_ERROR;
fall back to an unsalted cred. */
centry = wcache_fetch(cache, domain, "CRED/%s",
- sid_to_fstring(tmp, sid));
+ dom_sid_str_buf(sid, &sidstr));
if (!centry) {
DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n",
- sid_string_dbg(sid)));
+ dom_sid_str_buf(sid, &sidstr)));
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
sort this out. It can tell as we only return the cached_salt
if we are returning a salted cred. */
- *cached_nt_pass = (const uint8 *)centry_hash16(centry, mem_ctx);
+ *cached_nt_pass = (const uint8_t *)centry_hash16(centry, mem_ctx);
if (*cached_nt_pass == NULL) {
- fstring sidstr;
- sid_to_fstring(sidstr, sid);
+ dom_sid_str_buf(sid, &sidstr);
/* Bad (old) cred cache. Delete and pretend we
don't have it. */
DEBUG(0,("wcache_get_creds: bad entry for [CRED/%s] - deleting\n",
- sidstr));
- wcache_delete("CRED/%s", sidstr);
+ sidstr.buf));
+ wcache_delete("CRED/%s", sidstr.buf);
centry_free(centry);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
/* We only have 17 bytes more data in the salted cred case. */
if (centry->len - centry->ofs == 17) {
- *cached_salt = (const uint8 *)centry_hash16(centry, mem_ctx);
+ *cached_salt = (const uint8_t *)centry_hash16(centry, mem_ctx);
} else {
*cached_salt = NULL;
}
status = centry->status;
DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status: %s\n",
- sid_string_dbg(sid), nt_errstr(status) ));
+ dom_sid_str_buf(sid, &sidstr),
+ nt_errstr(status) ));
centry_free(centry);
return status;
NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
const struct dom_sid *sid,
- const uint8 nt_pass[NT_HASH_LEN])
+ const uint8_t nt_pass[NT_HASH_LEN])
{
struct cache_entry *centry;
- fstring sid_string;
- uint32 rid;
- uint8 cred_salt[NT_HASH_LEN];
- uint8 salted_hash[NT_HASH_LEN];
+ struct dom_sid_buf sid_str;
+ uint32_t rid;
+ uint8_t cred_salt[NT_HASH_LEN];
+ uint8_t salted_hash[NT_HASH_LEN];
if (is_null_sid(sid)) {
return NT_STATUS_INVALID_SID;
centry_put_hash16(centry, salted_hash);
centry_put_hash16(centry, cred_salt);
- centry_end(centry, "CRED/%s", sid_to_fstring(sid_string, sid));
+ centry_end(centry, "CRED/%s", dom_sid_str_buf(sid, &sid_str));
- DEBUG(10,("wcache_save_creds: %s\n", sid_string));
+ DEBUG(10,("wcache_save_creds: %s\n", sid_str.buf));
centry_free(centry);
/* Query display info. This is the basic user list fn */
-static NTSTATUS query_user_list(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- struct wbint_userinfo **info)
+NTSTATUS wb_cache_query_user_list(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32_t **prids)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
+ uint32_t num_rids = 0;
+ uint32_t *rids = NULL;
NTSTATUS status;
unsigned int i, retry;
bool old_status = domain->online;
+ *prids = NULL;
+
if (!cache->tdb)
goto do_query;
goto do_query;
do_fetch_cache:
- *num_entries = centry_uint32(centry);
+ num_rids = centry_uint32(centry);
- if (*num_entries == 0)
+ if (num_rids == 0) {
goto do_cached;
+ }
- (*info) = talloc_array(mem_ctx, struct wbint_userinfo, *num_entries);
- if (! (*info)) {
- smb_panic_fn("query_user_list out of memory");
+ rids = talloc_array(mem_ctx, uint32_t, num_rids);
+ if (rids == NULL) {
+ centry_free(centry);
+ return NT_STATUS_NO_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].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);
+
+ for (i=0; i<num_rids; i++) {
+ rids[i] = centry_uint32(centry);
}
do_cached:
return status;
do_query:
- *num_entries = 0;
- *info = NULL;
/* Return status value returned by seq number check */
DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n",
domain->name ));
- status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info);
+ rids = NULL;
+ status = domain->backend->query_user_list(domain, mem_ctx,
+ &rids);
+ num_rids = talloc_array_length(rids);
+
if (!NT_STATUS_IS_OK(status)) {
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);
+ invalidate_cm_connection(domain);
}
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
set_domain_offline(domain);
}
/* store partial response. */
- if (*num_entries > 0) {
+ if (num_rids > 0) {
/*
* humm, what about the status used for cache?
* Should it be NT_STATUS_OK?
(retry++ < 5));
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
- centry_put_uint32(centry, *num_entries);
- 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_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 && 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,
- SID_NAME_USER);
- wcache_save_sid_to_name(domain, NT_STATUS_OK,
- &(*info)[i].user_sid,
- domain->name,
- (*info)[i].acct_name,
- SID_NAME_USER);
- wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]);
- }
+ centry_put_uint32(centry, num_rids);
+ for (i=0; i<num_rids; i++) {
+ centry_put_uint32(centry, rids[i]);
}
centry_end(centry, "UL/%s", domain->name);
centry_free(centry);
+ *prids = rids;
+
skip_save:
return status;
}
/* list all domain groups */
-static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- struct wb_acct_info **info)
+NTSTATUS wb_cache_enum_dom_groups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32_t *num_entries,
+ struct wb_acct_info **info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
smb_panic_fn("enum_dom_groups out of memory");
}
for (i=0; i<(*num_entries); i++) {
- fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
- fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+ (*info)[i].acct_name = centry_string(centry, (*info));
+ (*info)[i].acct_desc = centry_string(centry, (*info));
(*info)[i].rid = centry_uint32(centry);
}
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
}
/* list all domain groups */
-static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 *num_entries,
- struct wb_acct_info **info)
+NTSTATUS wb_cache_enum_local_groups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32_t *num_entries,
+ struct wb_acct_info **info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
smb_panic_fn("enum_dom_groups out of memory");
}
for (i=0; i<(*num_entries); i++) {
- fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
- fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+ (*info)[i].acct_name = centry_string(centry, (*info));
+ (*info)[i].acct_desc = centry_string(centry, (*info));
(*info)[i].rid = centry_uint32(centry);
}
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return status;
}
-NTSTATUS wcache_name_to_sid(struct winbindd_domain *domain,
- const char *domain_name,
- const char *name,
- struct dom_sid *sid,
- enum lsa_SidType *type)
+struct wcache_name_to_sid_state {
+ struct dom_sid *sid;
+ enum lsa_SidType *type;
+ bool offline;
+ bool found;
+};
+
+static void wcache_name_to_sid_fn(const struct dom_sid *sid,
+ enum lsa_SidType type,
+ bool expired,
+ void *private_data)
{
- struct winbind_cache *cache = get_cache(domain);
- struct cache_entry *centry;
- NTSTATUS status;
- char *uname;
+ struct wcache_name_to_sid_state *state = private_data;
- if (cache->tdb == NULL) {
- return NT_STATUS_NOT_FOUND;
- }
+ *state->sid = *sid;
+ *state->type = type;
+ state->found = (!expired || state->offline);
+}
- uname = talloc_strdup_upper(talloc_tos(), name);
- if (uname == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+static NTSTATUS wcache_name_to_sid(struct winbindd_domain *domain,
+ const char *domain_name,
+ const char *name,
+ struct dom_sid *sid,
+ enum lsa_SidType *type)
+{
+ struct wcache_name_to_sid_state state = {
+ .sid = sid, .type = type, .found = false,
+ .offline = is_domain_offline(domain),
+ };
+ bool ok;
- centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
- TALLOC_FREE(uname);
- if (centry == NULL) {
+ ok = namemap_cache_find_name(domain_name, name, wcache_name_to_sid_fn,
+ &state);
+ if (!ok) {
+ DBG_DEBUG("namemap_cache_find_name failed\n");
return NT_STATUS_NOT_FOUND;
}
-
- status = centry->status;
- if (NT_STATUS_IS_OK(status)) {
- *type = (enum lsa_SidType)centry_uint32(centry);
- centry_sid(centry, sid);
+ if (!state.found) {
+ DBG_DEBUG("cache entry not found\n");
+ return NT_STATUS_NOT_FOUND;
+ }
+ if (*type == SID_NAME_UNKNOWN) {
+ return NT_STATUS_NONE_MAPPED;
}
- DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status: "
- "%s\n", domain->name, nt_errstr(status) ));
-
- centry_free(centry);
- return status;
+ return NT_STATUS_OK;
}
/* 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,
- uint32_t flags,
- struct dom_sid *sid,
- enum lsa_SidType *type)
+NTSTATUS wb_cache_name_to_sid(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ const char *name,
+ uint32_t flags,
+ struct dom_sid *sid,
+ enum lsa_SidType *type)
{
NTSTATUS status;
bool old_status;
+ const char *dom_name;
old_status = domain->online;
DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
+ winbindd_domain_init_backend(domain);
status = domain->backend->name_to_sid(domain, mem_ctx, domain_name,
- name, flags, sid, type);
+ name, flags, &dom_name, sid, type);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
}
}
/* and save it */
- refresh_sequence_number(domain, false);
if (domain->online &&
(NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) {
- wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
+ enum lsa_SidType save_type = *type;
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
+ save_type = SID_NAME_UNKNOWN;
+ }
+
+ wcache_save_name_to_sid(domain, status, domain_name, name, sid,
+ save_type);
/* Only save the reverse mapping if this was not a UPN */
if (!strchr(name, '@')) {
return NT_STATUS_INVALID_PARAMETER;
}
(void)strlower_m(discard_const_p(char, name));
- wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type);
+ wcache_save_sid_to_name(domain, status, sid,
+ dom_name, name, save_type);
}
}
return status;
}
-NTSTATUS wcache_sid_to_name(struct winbindd_domain *domain,
- const struct dom_sid *sid,
- TALLOC_CTX *mem_ctx,
- char **domain_name,
- char **name,
- enum lsa_SidType *type)
+struct wcache_sid_to_name_state {
+ TALLOC_CTX *mem_ctx;
+ char **domain_name;
+ char **name;
+ enum lsa_SidType *type;
+ bool offline;
+ bool found;
+};
+
+static void wcache_sid_to_name_fn(const char *domain,
+ const char *name,
+ enum lsa_SidType type,
+ bool expired,
+ void *private_data)
{
- struct winbind_cache *cache = get_cache(domain);
- struct cache_entry *centry;
- char *sid_string;
- NTSTATUS status;
+ struct wcache_sid_to_name_state *state = private_data;
- if (cache->tdb == NULL) {
- return NT_STATUS_NOT_FOUND;
+ *state->domain_name = talloc_strdup(state->mem_ctx, domain);
+ if (*state->domain_name == NULL) {
+ return;
}
-
- sid_string = sid_string_tos(sid);
- if (sid_string == NULL) {
- return NT_STATUS_NO_MEMORY;
+ *state->name = talloc_strdup(state->mem_ctx, name);
+ if (*state->name == NULL) {
+ return;
}
+ *state->type = type;
+ state->found = (!expired || state->offline);
+}
- centry = wcache_fetch(cache, domain, "SN/%s", sid_string);
- TALLOC_FREE(sid_string);
- if (centry == NULL) {
+static NTSTATUS wcache_sid_to_name(struct winbindd_domain *domain,
+ const struct dom_sid *sid,
+ TALLOC_CTX *mem_ctx,
+ char **domain_name,
+ char **name,
+ enum lsa_SidType *type)
+{
+ struct wcache_sid_to_name_state state = {
+ .mem_ctx = mem_ctx, .found = false,
+ .domain_name = domain_name, .name = name, .type = type,
+ .offline = is_domain_offline(domain)
+ };
+ bool ok;
+
+ ok = namemap_cache_find_sid(sid, wcache_sid_to_name_fn, &state);
+ if (!ok) {
+ DBG_DEBUG("namemap_cache_find_name failed\n");
return NT_STATUS_NOT_FOUND;
}
-
- if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum lsa_SidType)centry_uint32(centry);
- *domain_name = centry_string(centry, mem_ctx);
- *name = centry_string(centry, mem_ctx);
+ if (!state.found) {
+ DBG_DEBUG("cache entry not found\n");
+ return NT_STATUS_NOT_FOUND;
+ }
+ if (*type == SID_NAME_UNKNOWN) {
+ return NT_STATUS_NONE_MAPPED;
}
- status = centry->status;
- centry_free(centry);
-
- DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status: "
- "%s\n", domain->name, nt_errstr(status) ));
-
- return status;
+ return NT_STATUS_OK;
}
/* convert a sid to a user or group name. The sid is guaranteed to be in the domain
given */
-static NTSTATUS sid_to_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *sid,
- char **domain_name,
- char **name,
- enum lsa_SidType *type)
+NTSTATUS wb_cache_sid_to_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *sid,
+ char **domain_name,
+ char **name,
+ enum lsa_SidType *type)
{
NTSTATUS status;
bool old_status;
DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n",
domain->name ));
+ winbindd_domain_init_backend(domain);
+
status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
}
}
/* and save it */
- refresh_sequence_number(domain, false);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return status;
}
-static NTSTATUS rids_to_names(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *domain_sid,
- uint32 *rids,
- size_t num_rids,
- char **domain_name,
- char ***names,
- enum lsa_SidType **types)
+NTSTATUS wb_cache_rids_to_names(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *domain_sid,
+ uint32_t *rids,
+ size_t num_rids,
+ char **domain_name,
+ char ***names,
+ enum lsa_SidType **types)
{
struct winbind_cache *cache = get_cache(domain);
size_t i;
for (i=0; i<num_rids; i++) {
struct dom_sid sid;
- struct cache_entry *centry;
- fstring tmp;
+ NTSTATUS status;
+ enum lsa_SidType type;
+ char *dom, *name;
if (!sid_compose(&sid, domain_sid, rids[i])) {
result = NT_STATUS_INTERNAL_ERROR;
goto error;
}
- centry = wcache_fetch(cache, domain, "SN/%s",
- sid_to_fstring(tmp, &sid));
- if (!centry) {
- goto do_query;
- }
+ status = wcache_sid_to_name(domain, &sid, *names, &dom,
+ &name, &type);
(*types)[i] = SID_NAME_UNKNOWN;
(*names)[i] = talloc_strdup(*names, "");
- if (NT_STATUS_IS_OK(centry->status)) {
- char *dom;
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ /* not cached */
+ goto do_query;
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
have_mapped = true;
- (*types)[i] = (enum lsa_SidType)centry_uint32(centry);
+ (*types)[i] = type;
- dom = centry_string(centry, mem_ctx);
if (*domain_name == NULL) {
*domain_name = dom;
} else {
- talloc_free(dom);
+ TALLOC_FREE(dom);
}
- (*names)[i] = centry_string(centry, *names);
+ (*names)[i] = name;
- } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)
- || NT_STATUS_EQUAL(centry->status, STATUS_SOME_UNMAPPED)) {
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
have_unmapped = true;
-
} else {
/* something's definitely wrong */
- result = centry->status;
+ result = status;
goto error;
}
-
- centry_free(centry);
}
if (!have_mapped) {
names, types);
if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
- NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+ NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
if (!domain->internal && old_status) {
set_domain_offline(domain);
}
old_status) {
have_mapped = have_unmapped = false;
+ *names = talloc_array(mem_ctx, char *, num_rids);
+ if (*names == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto error;
+ }
+
+ *types = talloc_array(mem_ctx, enum lsa_SidType,
+ num_rids);
+ if (*types == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto error;
+ }
+
for (i=0; i<num_rids; i++) {
struct dom_sid sid;
- struct cache_entry *centry;
- fstring tmp;
+ NTSTATUS status;
+ enum lsa_SidType type;
+ char *dom, *name;
if (!sid_compose(&sid, domain_sid, rids[i])) {
result = NT_STATUS_INTERNAL_ERROR;
goto error;
}
- centry = wcache_fetch(cache, domain, "SN/%s",
- sid_to_fstring(tmp, &sid));
- if (!centry) {
- (*types)[i] = SID_NAME_UNKNOWN;
- (*names)[i] = talloc_strdup(*names, "");
- continue;
- }
+ status = wcache_sid_to_name(domain, &sid,
+ *names, &dom,
+ &name, &type);
(*types)[i] = SID_NAME_UNKNOWN;
(*names)[i] = talloc_strdup(*names, "");
- if (NT_STATUS_IS_OK(centry->status)) {
- char *dom;
+ if (NT_STATUS_IS_OK(status)) {
have_mapped = true;
- (*types)[i] = (enum lsa_SidType)centry_uint32(centry);
+ (*types)[i] = type;
- dom = centry_string(centry, mem_ctx);
if (*domain_name == NULL) {
*domain_name = dom;
} else {
- talloc_free(dom);
+ TALLOC_FREE(dom);
}
- (*names)[i] = centry_string(centry, *names);
+ (*names)[i] = name;
- } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
+ } else if (NT_STATUS_EQUAL(
+ status,
+ NT_STATUS_NONE_MAPPED)) {
have_unmapped = true;
-
} else {
/* something's definitely wrong */
- result = centry->status;
+ result = status;
goto error;
}
-
- centry_free(centry);
}
if (!have_mapped) {
return result;
}
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
for (i=0; i<num_rids; i++) {
struct dom_sid sid;
return result;
}
-NTSTATUS wcache_query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- struct wbint_userinfo *info)
+static NTSTATUS wcache_query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ struct wbint_userinfo *info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
- char *sid_string;
+ struct dom_sid_buf sid_string;
if (cache->tdb == NULL) {
return NT_STATUS_NOT_FOUND;
}
- sid_string = sid_string_tos(user_sid);
- if (sid_string == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- centry = wcache_fetch(cache, domain, "U/%s", sid_string);
- TALLOC_FREE(sid_string);
+ centry = wcache_fetch(
+ cache, domain, "U/%s", dom_sid_str_buf(user_sid, &sid_string));
if (centry == NULL) {
return NT_STATUS_NOT_FOUND;
}
and the rest of the data doesn't matter */
status = centry->status;
if (NT_STATUS_IS_OK(status)) {
+ info->domain_name = centry_string(centry, mem_ctx);
info->acct_name = centry_string(centry, mem_ctx);
info->full_name = centry_string(centry, mem_ctx);
info->homedir = centry_string(centry, mem_ctx);
info->shell = centry_string(centry, mem_ctx);
+ info->uid = centry_uint32(centry);
info->primary_gid = centry_uint32(centry);
+ info->primary_group_name = centry_string(centry, mem_ctx);
centry_sid(centry, &info->user_sid);
centry_sid(centry, &info->group_sid);
}
return status;
}
-/* Lookup user information from a rid */
-static NTSTATUS query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- struct wbint_userinfo *info)
+
+/**
+* @brief Query a fullname from the username cache (for further gecos processing)
+*
+* @param domain A pointer to the winbindd_domain struct.
+* @param mem_ctx The talloc context.
+* @param user_sid The user sid.
+* @param full_name A pointer to the full_name string.
+*
+* @return NTSTATUS code
+*/
+NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ const char **full_name)
{
NTSTATUS status;
- bool old_status;
+ struct wbint_userinfo info;
- old_status = domain->online;
- status = wcache_query_user(domain, mem_ctx, user_sid, info);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ status = wcache_query_user(domain, mem_ctx, user_sid, &info);
+ if (!NT_STATUS_IS_OK(status)) {
return status;
}
- ZERO_STRUCTP(info);
-
- /* Return status value returned by seq number check */
-
- if (!NT_STATUS_IS_OK(domain->last_status))
- return domain->last_status;
-
- DEBUG(10,("query_user: [Cached] - doing backend query for info for domain %s\n",
- domain->name ));
-
- status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
- NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
- if (!domain->internal && old_status) {
- set_domain_offline(domain);
- }
- if (!domain->internal &&
- !domain->online &&
- old_status) {
- NTSTATUS cache_status;
- cache_status = wcache_query_user(domain, mem_ctx, user_sid, info);
- return cache_status;
+ if (info.full_name != NULL) {
+ *full_name = talloc_strdup(mem_ctx, info.full_name);
+ if (*full_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
}
- /* and save it */
- refresh_sequence_number(domain, false);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- wcache_save_user(domain, status, info);
- return status;
+ return NT_STATUS_OK;
}
-NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- uint32_t *pnum_sids,
- struct dom_sid **psids)
+static NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
uint32_t i, num_sids;
struct dom_sid *sids;
- fstring sid_string;
+ struct dom_sid_buf sid_string;
if (cache->tdb == NULL) {
return NT_STATUS_NOT_FOUND;
}
- centry = wcache_fetch(cache, domain, "UG/%s",
- sid_to_fstring(sid_string, user_sid));
+ centry = wcache_fetch(
+ cache,
+ domain,
+ "UG/%s",
+ dom_sid_str_buf(user_sid, &sid_string));
if (centry == NULL) {
return NT_STATUS_NOT_FOUND;
}
}
/* Lookup groups a user is a member of. */
-static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *user_sid,
- uint32 *num_groups, struct dom_sid **user_gids)
+NTSTATUS wb_cache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *num_groups,
+ struct dom_sid **user_gids)
{
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i;
- fstring sid_string;
+ struct dom_sid_buf sid_string;
bool old_status;
old_status = domain->online;
goto skip_save;
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry_put_sid(centry, &(*user_gids)[i]);
}
- centry_end(centry, "UG/%s", sid_to_fstring(sid_string, user_sid));
+ centry_end(centry, "UG/%s", dom_sid_str_buf(user_sid, &sid_string));
centry_free(centry);
skip_save:
return NULL;
}
for (i=0; i<num_sids; i++) {
- fstring tmp;
+ struct dom_sid_buf tmp;
sidlist = talloc_asprintf_append_buffer(
- sidlist, "/%s", sid_to_fstring(tmp, &sids[i]));
+ sidlist,
+ "/%s",
+ dom_sid_str_buf(&sids[i], &tmp));
if (sidlist == NULL) {
return NULL;
}
return sidlist;
}
-NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx, uint32_t num_sids,
- const struct dom_sid *sids,
- uint32_t *pnum_aliases, uint32_t **paliases)
+static NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32_t num_sids,
+ const struct dom_sid *sids,
+ uint32_t *pnum_aliases,
+ uint32_t **paliases)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
- uint32_t num_aliases;
+ uint32_t i, num_aliases;
uint32_t *aliases;
NTSTATUS status;
char *sidlist;
- int i;
if (cache->tdb == NULL) {
return NT_STATUS_NOT_FOUND;
return status;
}
-static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 num_sids, const struct dom_sid *sids,
- uint32 *num_aliases, uint32 **alias_rids)
+NTSTATUS wb_cache_lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32_t num_sids,
+ const struct dom_sid *sids,
+ uint32_t *num_aliases,
+ uint32_t **alias_rids)
{
struct cache_entry *centry = NULL;
NTSTATUS status;
char *sidlist;
- int i;
+ uint32_t i;
bool old_status;
old_status = domain->online;
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return status;
}
-NTSTATUS wcache_lookup_groupmem(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *group_sid,
- uint32_t *num_names,
- struct dom_sid **sid_mem, char ***names,
- uint32_t **name_types)
+static NTSTATUS wcache_lookup_groupmem(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *group_sid,
+ uint32_t *num_names,
+ struct dom_sid **sid_mem, char ***names,
+ uint32_t **name_types)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i;
- char *sid_string;
+ struct dom_sid_buf sid_string;
if (cache->tdb == NULL) {
return NT_STATUS_NOT_FOUND;
}
- sid_string = sid_string_tos(group_sid);
- if (sid_string == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- centry = wcache_fetch(cache, domain, "GM/%s", sid_string);
- TALLOC_FREE(sid_string);
+ centry = wcache_fetch(
+ cache,
+ domain,
+ "GM/%s",
+ dom_sid_str_buf(group_sid, &sid_string));
if (centry == NULL) {
return NT_STATUS_NOT_FOUND;
}
*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);
+ *name_types = talloc_array(mem_ctx, uint32_t, *num_names);
if ((*sid_mem == NULL) || (*names == NULL) || (*name_types == NULL)) {
TALLOC_FREE(*sid_mem);
return status;
}
-static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *group_sid,
- enum lsa_SidType type,
- uint32 *num_names,
- struct dom_sid **sid_mem, char ***names,
- uint32 **name_types)
+NTSTATUS wb_cache_lookup_groupmem(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *group_sid,
+ enum lsa_SidType type,
+ uint32_t *num_names,
+ struct dom_sid **sid_mem,
+ char ***names,
+ uint32_t **name_types)
{
struct cache_entry *centry = NULL;
NTSTATUS status;
unsigned int i;
- fstring sid_string;
+ struct dom_sid_buf sid_string;
bool old_status;
old_status = domain->online;
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
centry_put_string(centry, (*names)[i]);
centry_put_uint32(centry, (*name_types)[i]);
}
- centry_end(centry, "GM/%s", sid_to_fstring(sid_string, group_sid));
+ centry_end(centry,
+ "GM/%s",
+ dom_sid_str_buf(group_sid, &sid_string));
centry_free(centry);
skip_save:
}
/* find the sequence number for a domain */
-static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
+NTSTATUS wb_cache_sequence_number(struct winbindd_domain *domain,
+ uint32_t *seq)
{
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
*seq = domain->sequence_number;
/* enumerate trusted domains
* (we need to have the list of trustdoms in the cache when we go offline) -
* Guenther */
-static NTSTATUS trusted_domains(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- struct netr_DomainTrustList *trusts)
+NTSTATUS wb_cache_trusted_domains(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ struct netr_DomainTrustList *trusts)
{
NTSTATUS status;
struct winbind_cache *cache;
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
bool retval = false;
- int i;
+ size_t i;
bool old_status;
old_status = domain->online;
}
/* get lockout policy */
-static NTSTATUS lockout_policy(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- struct samr_DomInfo12 *policy)
+NTSTATUS wb_cache_lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ struct samr_DomInfo12 *policy)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
}
/* get password policy */
-static NTSTATUS password_policy(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- struct samr_DomInfo1 *policy)
+NTSTATUS wb_cache_password_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ struct samr_DomInfo1 *policy)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
}
}
/* and save it */
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
void wcache_invalidate_samlogon(struct winbindd_domain *domain,
const struct dom_sid *sid)
{
- fstring key_str, sid_string;
+ fstring key_str;
+ struct dom_sid_buf sid_string;
struct winbind_cache *cache;
- /* dont clear cached U/SID and UG/SID entries when we want to logon
+ /* don't clear cached U/SID and UG/SID entries when we want to logon
* offline - gd */
if (lp_winbind_offline_logon()) {
}
/* Clear U/SID cache entry */
- fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, sid));
+ fstr_sprintf(key_str, "U/%s", dom_sid_str_buf(sid, &sid_string));
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", dom_sid_str_buf(sid, &sid_string));
DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
tdb_delete(cache->tdb, string_tdb_data(key_str));
return true;
}
-bool init_wcache(void)
+static bool init_wcache(void)
{
+ char *db_path;
+
if (wcache == NULL) {
wcache = SMB_XMALLOC_P(struct winbind_cache);
ZERO_STRUCTP(wcache);
if (wcache->tdb != NULL)
return true;
+ db_path = wcache_path();
+ if (db_path == NULL) {
+ return false;
+ }
+
/* when working offline we must not clear the cache on restart */
- wcache->tdb = tdb_open_log(state_path("winbindd_cache.tdb"),
+ wcache->tdb = tdb_open_log(db_path,
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
TDB_INCOMPATIBLE_HASH |
(lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
O_RDWR|O_CREAT, 0600);
-
+ TALLOC_FREE(db_path);
if (wcache->tdb == NULL) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
return false;
bool initialize_winbindd_cache(void)
{
bool cache_bad = true;
- uint32 vers;
+ uint32_t vers;
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n"));
}
if (cache_bad) {
+ char *db_path;
+
DEBUG(0,("initialize_winbindd_cache: clearing cache "
"and re-creating with version number %d\n",
WINBINDD_CACHE_VERSION ));
tdb_close(wcache->tdb);
wcache->tdb = NULL;
- if (unlink(state_path("winbindd_cache.tdb")) == -1) {
+ db_path = wcache_path();
+ if (db_path == NULL) {
+ return false;
+ }
+
+ if (unlink(db_path) == -1) {
DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ",
- state_path("winbindd_cache.tdb"),
+ db_path,
strerror(errno) ));
+ TALLOC_FREE(db_path);
return false;
}
+ TALLOC_FREE(db_path);
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: re-initialization "
"init_wcache failed.\n"));
/* 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_compat(wcache->tdb) ));
+ tdb_errorstr(wcache->tdb) ));
return false;
}
}
return NT_STATUS_IS_OK(status);
}
-bool lookup_cached_name(const char *domain_name,
+bool lookup_cached_name(const char *namespace,
+ const char *domain_name,
const char *name,
struct dom_sid *sid,
enum lsa_SidType *type)
NTSTATUS status;
bool original_online_state;
- domain = find_lookup_domain_from_name(domain_name);
+ domain = find_lookup_domain_from_name(namespace);
if (domain == NULL) {
return false;
}
return NT_STATUS_IS_OK(status);
}
+/*
+ * Cache a name to sid without checking the sequence number.
+ * Used when caching from a trusted PAC.
+ */
+
+void cache_name2sid_trusted(struct winbindd_domain *domain,
+ const char *domain_name,
+ const char *name,
+ enum lsa_SidType type,
+ const struct dom_sid *sid)
+{
+ /*
+ * Ensure we store the mapping with the
+ * existing sequence number from the cache.
+ */
+ get_cache(domain);
+ (void)fetch_cache_seqnum(domain, time(NULL));
+ wcache_save_name_to_sid(domain,
+ NT_STATUS_OK,
+ domain_name,
+ name,
+ sid,
+ type);
+}
+
void cache_name2sid(struct winbindd_domain *domain,
const char *domain_name, const char *name,
enum lsa_SidType type, const struct dom_sid *sid)
{
- refresh_sequence_number(domain, false);
+ refresh_sequence_number(domain);
wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
sid, type);
}
}
/* flush the cache */
-void wcache_flush_cache(void)
+static void wcache_flush_cache(void)
{
+ char *db_path;
+
if (!wcache)
return;
if (wcache->tdb) {
return;
}
+ db_path = wcache_path();
+ if (db_path == NULL) {
+ return;
+ }
+
/* when working offline we must not clear the cache on restart */
- wcache->tdb = tdb_open_log(state_path("winbindd_cache.tdb"),
- WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+ wcache->tdb = tdb_open_log(db_path,
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
TDB_INCOMPATIBLE_HASH |
(lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
O_RDWR|O_CREAT, 0600);
-
+ TALLOC_FREE(db_path);
if (!wcache->tdb) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
return;
struct winbind_cache *cache = get_cache(domain);
NTSTATUS status;
int ret;
- struct cred_list *cred, *oldest = NULL;
+ struct cred_list *cred, *next, *oldest = NULL;
if (!cache->tdb) {
return NT_STATUS_INTERNAL_DB_ERROR;
/* we possibly already have an entry */
if (sid && NT_STATUS_IS_OK(wcache_cached_creds_exist(domain, sid))) {
- fstring key_str, tmp;
+ fstring key_str;
+ struct dom_sid_buf tmp;
DEBUG(11,("we already have an entry, deleting that\n"));
- fstr_sprintf(key_str, "CRED/%s", sid_to_fstring(tmp, sid));
+ fstr_sprintf(key_str, "CRED/%s", dom_sid_str_buf(sid, &tmp));
tdb_delete(cache->tdb, string_tdb_data(key_str));
TDB_DATA data;
time_t t;
- data = tdb_fetch_compat(cache->tdb, string_tdb_data(cred->name));
+ data = tdb_fetch(cache->tdb, string_tdb_data(cred->name));
if (!data.dptr) {
DEBUG(10,("wcache_remove_oldest_cached_creds: entry for [%s] not found\n",
cred->name));
status = NT_STATUS_UNSUCCESSFUL;
}
done:
- SAFE_FREE(wcache_cred_list);
+ for (cred = wcache_cred_list; cred; cred = next) {
+ next = cred->next;
+ DLIST_REMOVE(wcache_cred_list, cred);
+ SAFE_FREE(cred);
+ }
SAFE_FREE(oldest);
return status;
struct cache_entry *centry;
centry = SMB_XMALLOC_P(struct cache_entry);
- centry->data = (unsigned char *)memdup(data.dptr, data.dsize);
+ centry->data = (unsigned char *)smb_memdup(data.dptr, data.dsize);
if (!centry->data) {
SAFE_FREE(centry);
return NULL;
return 0;
}
-static int validate_ns(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_uint32(centry);
- if (NT_STATUS_IS_OK(centry->status)) {
- struct dom_sid sid;
- (void)centry_sid(centry, &sid);
- }
-
- centry_free(centry);
-
- if (!(state->success)) {
- return 1;
- }
- DEBUG(10,("validate_ns: %s ok\n", keystr));
- return 0;
-}
-
-static int validate_sn(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;
- }
-
- if (NT_STATUS_IS_OK(centry->status)) {
- (void)centry_uint32(centry);
- (void)centry_string(centry, mem_ctx);
- (void)centry_string(centry, mem_ctx);
- }
-
- centry_free(centry);
-
- if (!(state->success)) {
- return 1;
- }
- DEBUG(10,("validate_sn: %s ok\n", keystr));
- return 0;
-}
-
static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
struct tdb_validation_status *state)
{
(void)centry_string(centry, mem_ctx);
(void)centry_string(centry, mem_ctx);
(void)centry_string(centry, mem_ctx);
+ (void)centry_string(centry, mem_ctx);
(void)centry_uint32(centry);
+ (void)centry_uint32(centry);
+ (void)centry_string(centry, mem_ctx);
(void)centry_sid(centry, &sid);
(void)centry_sid(centry, &sid);
struct tdb_validation_status *state)
{
struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
- int32 num_entries, i;
+ int32_t num_entries, i;
if (!centry) {
return 1;
}
- num_entries = (int32)centry_uint32(centry);
+ num_entries = (int32_t)centry_uint32(centry);
for (i=0; i< num_entries; i++) {
- struct dom_sid sid;
- (void)centry_string(centry, mem_ctx);
- (void)centry_string(centry, mem_ctx);
- (void)centry_string(centry, mem_ctx);
- (void)centry_string(centry, mem_ctx);
- (void)centry_sid(centry, &sid);
- (void)centry_sid(centry, &sid);
+ (void)centry_uint32(centry);
}
centry_free(centry);
struct tdb_validation_status *state)
{
struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
- int32 num_entries, i;
+ int32_t num_entries, i;
if (!centry) {
return 1;
struct tdb_validation_status *state)
{
struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
- int32 num_groups, i;
+ int32_t num_groups, i;
if (!centry) {
return 1;
struct tdb_validation_status *state)
{
struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
- int32 num_aliases, i;
+ int32_t num_aliases, i;
if (!centry) {
return 1;
struct tdb_validation_status *state)
{
struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
- int32 num_names, i;
+ int32_t num_names, i;
if (!centry) {
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)
if (!(state->success)) {
return 1;
}
- DEBUG(10,("validate_pwinfo: %s ok\n", keystr));
+ DBG_DEBUG("%s ok\n", keystr);
return 0;
}
int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct tdb_validation_status* state);
} key_val[] = {
{"SEQNUM/", validate_seqnum},
- {"NS/", validate_ns},
- {"SN/", validate_sn},
{"U/", validate_u},
{"LOC_POL/", validate_loc_pol},
{"PWD_POL/", validate_pwd_pol},
{"GM/", validate_gm},
{"DR/", validate_dr},
{"DE/", validate_de},
- {"NSS/PWINFO/", validate_pwinfo},
{"TRUSTDOMCACHE/", validate_trustdomcache},
{"NSS/NA/", validate_nss_na},
{"NSS/AN/", validate_nss_an},
struct tdb_validation_status *v_state = (struct tdb_validation_status *)state;
/* Paranoia check. */
- if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0) {
+ if (strncmp("UA/", (const char *)kbuf.dptr, 3) == 0 ||
+ strncmp("NDR/", (const char *)kbuf.dptr, 4) == 0) {
max_key_len = 1024 * 1024;
}
if (kbuf.dsize > max_key_len) {
}
DEBUG(0,("cache_traverse_validate_fn: unknown cache entry\nkey :\n"));
- dump_data(0, (uint8 *)kbuf.dptr, kbuf.dsize);
+ dump_data(0, (uint8_t *)kbuf.dptr, kbuf.dsize);
DEBUG(0,("data :\n"));
- dump_data(0, (uint8 *)dbuf.dptr, dbuf.dsize);
+ dump_data(0, (uint8_t *)dbuf.dptr, dbuf.dsize);
v_state->unknown_key = true;
v_state->success = false;
return 1; /* terminate. */
int winbindd_validate_cache(void)
{
int ret = -1;
- const char *tdb_path = state_path("winbindd_cache.tdb");
+ char *tdb_path = NULL;
TDB_CONTEXT *tdb = NULL;
uint32_t vers_id;
bool ok;
DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
smb_panic_fn = validate_panic;
- tdb = tdb_open_log(tdb_path,
+ tdb_path = wcache_path();
+ if (tdb_path == NULL) {
+ goto done;
+ }
+
+ tdb = tdb_open_log(tdb_path,
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
TDB_INCOMPATIBLE_HASH |
- ( lp_winbind_offline_logon()
- ? TDB_DEFAULT
+ ( lp_winbind_offline_logon()
+ ? TDB_DEFAULT
: TDB_DEFAULT | TDB_CLEAR_IF_FIRST ),
- O_RDWR|O_CREAT,
+ O_RDWR|O_CREAT,
0600);
if (!tdb) {
DEBUG(0, ("winbindd_validate_cache: "
}
done:
+ TALLOC_FREE(tdb_path);
DEBUG(10, ("winbindd_validate_cache: restoring panic function\n"));
smb_panic_fn = smb_panic;
return ret;
int winbindd_validate_cache_nobackup(void)
{
int ret = -1;
- const char *tdb_path = state_path("winbindd_cache.tdb");
+ char *tdb_path;
DEBUG(10, ("winbindd_validate_cache: replacing panic function\n"));
smb_panic_fn = validate_panic;
+ tdb_path = wcache_path();
+ if (tdb_path == NULL) {
+ goto err_panic_restore;
+ }
if (wcache == NULL || wcache->tdb == NULL) {
ret = tdb_validate_open(tdb_path, cache_traverse_validate_fn);
"successful.\n"));
}
+ TALLOC_FREE(tdb_path);
+err_panic_restore:
DEBUG(10, ("winbindd_validate_cache_nobackup: restoring panic "
"function\n"));
smb_panic_fn = smb_panic;
size_t *num_domains )
{
struct winbindd_tdc_domain *list = NULL;
- size_t idx;
- int i;
+ size_t i, idx;
bool set_only = false;
/* don't allow duplicates */
if ( !list )
return false;
- list[idx].domain_name = talloc_strdup( list, new_dom->name );
- list[idx].dns_name = talloc_strdup( list, new_dom->alt_name );
+ list[idx].domain_name = talloc_strdup(list, new_dom->name);
+ if (list[idx].domain_name == NULL) {
+ return false;
+ }
+ if (new_dom->alt_name != NULL) {
+ list[idx].dns_name = talloc_strdup(list, new_dom->alt_name);
+ if (list[idx].dns_name == NULL) {
+ return false;
+ }
+ }
if ( !is_null_sid( &new_dom->sid ) ) {
sid_copy( &list[idx].sid, &new_dom->sid );
unsigned char *buffer = NULL;
int len = 0;
int buflen = 0;
- int i = 0;
+ size_t i = 0;
DEBUG(10,("pack_tdc_domains: Packing %d trusted domains\n",
(int)num_domains));
len = 0;
/* Store the number of array items first */
- len += tdb_pack( buffer+len, buflen-len, "d",
+ len += tdb_pack( buffer ? buffer+len : NULL,
+ buffer ? buflen-len : 0, "d",
num_domains );
/* now pack each domain trust record */
for ( i=0; i<num_domains; i++ ) {
- fstring tmp;
+ struct dom_sid_buf tmp;
if ( buflen > 0 ) {
DEBUG(10,("pack_tdc_domains: Packing domain %s (%s)\n",
domains[i].dns_name ? domains[i].dns_name : "UNKNOWN" ));
}
- len += tdb_pack( buffer+len, buflen-len, "fffddd",
+ len += tdb_pack( buffer ? buffer+len : NULL,
+ buffer ? buflen-len : 0, "fffddd",
domains[i].domain_name,
- domains[i].dns_name,
- sid_to_fstring(tmp, &domains[i].sid),
+ domains[i].dns_name ? domains[i].dns_name : "",
+ dom_sid_str_buf(&domains[i].sid, &tmp),
domains[i].trust_flags,
domains[i].trust_attribs,
domains[i].trust_type );
struct winbindd_tdc_domain **domains )
{
fstring domain_name, dns_name, sid_string;
- uint32 type, attribs, flags;
+ uint32_t type, attribs, flags;
int num_domains;
int len = 0;
int i;
}
for ( i=0; i<num_domains; i++ ) {
- len += tdb_unpack( buf+len, buflen-len, "fffddd",
+ int this_len;
+
+ this_len = tdb_unpack( buf+len, buflen-len, "fffddd",
domain_name,
dns_name,
sid_string,
&attribs,
&type );
- if ( len == -1 ) {
+ if ( this_len == -1 ) {
DEBUG(5,("unpack_tdc_domains: Failed to unpack domain array\n"));
TALLOC_FREE( list );
return 0;
}
+ len += this_len;
DEBUG(11,("unpack_tdc_domains: Unpacking domain %s (%s) "
"SID %s, flags = 0x%x, attribs = 0x%x, type = 0x%x\n",
flags, attribs, type));
list[i].domain_name = talloc_strdup( list, domain_name );
- list[i].dns_name = talloc_strdup( list, dns_name );
+ list[i].dns_name = NULL;
+ if (dns_name[0] != '\0') {
+ list[i].dns_name = talloc_strdup(list, dns_name);
+ }
if ( !string_to_sid( &(list[i].sid), sid_string ) ) {
DEBUG(10,("unpack_tdc_domains: no SID for domain %s\n",
domain_name));
if ( !key.dptr )
return false;
- data = tdb_fetch_compat( wcache->tdb, key );
+ data = tdb_fetch( wcache->tdb, key );
SAFE_FREE( key.dptr );
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
bool ret = false;
+ struct dom_sid_buf buf;
DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, "
"flags = 0x%x, attributes = 0x%x, type = 0x%x\n",
domain->name, domain->alt_name,
- sid_string_dbg(&domain->sid),
+ dom_sid_str_buf(&domain->sid, &buf),
domain->domain_flags,
domain->domain_trust_attribs,
domain->domain_type));
return ret;
}
+static struct winbindd_tdc_domain *wcache_tdc_dup_domain(
+ TALLOC_CTX *mem_ctx, const struct winbindd_tdc_domain *src)
+{
+ struct winbindd_tdc_domain *dst;
+
+ dst = talloc(mem_ctx, struct winbindd_tdc_domain);
+ if (dst == NULL) {
+ goto fail;
+ }
+ dst->domain_name = talloc_strdup(dst, src->domain_name);
+ if (dst->domain_name == NULL) {
+ goto fail;
+ }
+
+ dst->dns_name = NULL;
+ if (src->dns_name != NULL) {
+ dst->dns_name = talloc_strdup(dst, src->dns_name);
+ if (dst->dns_name == NULL) {
+ goto fail;
+ }
+ }
+
+ sid_copy(&dst->sid, &src->sid);
+ dst->trust_flags = src->trust_flags;
+ dst->trust_type = src->trust_type;
+ dst->trust_attribs = src->trust_attribs;
+ return dst;
+fail:
+ TALLOC_FREE(dst);
+ return NULL;
+}
+
/*********************************************************************
********************************************************************/
{
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
- int i;
+ size_t i;
struct winbindd_tdc_domain *d = NULL;
DEBUG(10,("wcache_tdc_fetch_domain: Searching for domain %s\n", name));
DEBUG(10,("wcache_tdc_fetch_domain: Found domain %s\n",
name));
- d = talloc( 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;
-
+ d = wcache_tdc_dup_domain(ctx, &dom_list[i]);
break;
}
}
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 NULL;
- }
-
- /* fetch the list */
-
- wcache_tdc_fetch_list(&dom_list, &num_domains);
-
- for (i = 0; i<num_domains; i++) {
- if (dom_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(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;
-}
-
-
/*********************************************************************
********************************************************************/
return;
}
-
-/*********************************************************************
- ********************************************************************/
-
-static void wcache_save_user_pwinfo(struct winbindd_domain *domain,
- NTSTATUS status,
- const struct dom_sid *user_sid,
- const char *homedir,
- const char *shell,
- const char *gecos,
- uint32 gid)
-{
- struct cache_entry *centry;
- fstring tmp;
-
- if ( (centry = centry_start(domain, status)) == NULL )
- return;
-
- centry_put_string( centry, homedir );
- centry_put_string( centry, shell );
- centry_put_string( centry, gecos );
- centry_put_uint32( centry, gid );
-
- centry_end(centry, "NSS/PWINFO/%s", sid_to_fstring(tmp, user_sid) );
-
- DEBUG(10,("wcache_save_user_pwinfo: %s\n", sid_string_dbg(user_sid) ));
-
- centry_free(centry);
-}
-
-#ifdef HAVE_ADS
-
-NTSTATUS nss_get_info_cached( struct winbindd_domain *domain,
- const struct dom_sid *user_sid,
- TALLOC_CTX *ctx,
- const char **homedir, const char **shell,
- const char **gecos, gid_t *p_gid)
-{
- struct winbind_cache *cache = get_cache(domain);
- struct cache_entry *centry = NULL;
- NTSTATUS nt_status;
- fstring tmp;
-
- if (!cache->tdb)
- goto do_query;
-
- centry = wcache_fetch(cache, domain, "NSS/PWINFO/%s",
- sid_to_fstring(tmp, user_sid));
-
- if (!centry)
- goto do_query;
-
- *homedir = centry_string( centry, ctx );
- *shell = centry_string( centry, ctx );
- *gecos = centry_string( centry, ctx );
- *p_gid = centry_uint32( centry );
-
- centry_free(centry);
-
- DEBUG(10,("nss_get_info_cached: [Cached] - user_sid %s\n",
- sid_string_dbg(user_sid)));
-
- return NT_STATUS_OK;
-
-do_query:
-
- 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 ( 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 );
- }
-
- if ( NT_STATUS_EQUAL( nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ) ) {
- DEBUG(5,("nss_get_info_cached: Setting domain %s offline\n",
- domain->name ));
- set_domain_offline( domain );
- }
-
- return nt_status;
-}
-
-#endif
-
-/* the cache backend methods are exposed via this structure */
-struct winbindd_methods cache_methods = {
- true,
- query_user_list,
- enum_dom_groups,
- enum_local_groups,
- name_to_sid,
- sid_to_name,
- rids_to_names,
- query_user,
- lookup_usergroups,
- lookup_useraliases,
- lookup_groupmem,
- sequence_number,
- lockout_policy,
- password_policy,
- trusted_domains
-};
-
-static bool wcache_ndr_key(TALLOC_CTX *mem_ctx, char *domain_name,
+static bool wcache_ndr_key(TALLOC_CTX *mem_ctx, const char *domain_name,
uint32_t opnum, const DATA_BLOB *req,
TDB_DATA *pkey)
{
if (!wcache_ndr_key(talloc_tos(), domain->name, opnum, req, &key)) {
return false;
}
- data = tdb_fetch_compat(wcache->tdb, key);
+ data = tdb_fetch(wcache->tdb, key);
TALLOC_FREE(key.dptr);
if (data.dptr == NULL) {
goto fail;
}
- if (!is_domain_offline(domain)) {
+ if (is_domain_online(domain)) {
uint32_t entry_seqnum, dom_seqnum, last_check;
uint64_t entry_timeout;
goto fail;
}
entry_timeout = BVAL(data.dptr, 4);
- if (time(NULL) > entry_timeout) {
+ if (time(NULL) > (time_t)entry_timeout) {
DEBUG(10, ("Entry has timed out\n"));
goto fail;
}