mirror of
https://github.com/samba-team/samba.git
synced 2025-02-03 13:47:25 +03:00
r17617: Take Andrew Bartletts excellent advice and don't store
the nt hash directly in the winbindd cache, store a salted version (MD5 of salt + nt_hash). This is what we do in the LDAP password history code. We store this salted cache entry under the same name as an old entry (CRED/<sid>) but detect it on read by checking if there are 17 bytes of data after the first stored hash (1 byte len, 16 bytes hash). GD PLEASE CHECK. Jeremy. (This used to be commit 89d0163a97edaa46049406ea3e2152bee4e0d1b2)
This commit is contained in:
parent
b2d5dd7281
commit
4031af7606
@ -47,6 +47,7 @@ struct cache_entry {
|
||||
};
|
||||
|
||||
#define WINBINDD_MAX_CACHE_SIZE (50*1024*1024)
|
||||
#define WINBINDD_CACHE_VERSION "WB_CACHE_VERSION_1"
|
||||
|
||||
static struct winbind_cache *wcache;
|
||||
|
||||
@ -874,11 +875,14 @@ NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Lookup creds for a SID */
|
||||
/* Lookup creds for a SID - copes with old (unsalted) creds as well
|
||||
as new salted ones. */
|
||||
|
||||
NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
const uint8 **cached_nt_pass)
|
||||
const uint8 **cached_nt_pass,
|
||||
const uint8 **cached_salt)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
struct cache_entry *centry = NULL;
|
||||
@ -898,19 +902,37 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
|
||||
return NT_STATUS_INVALID_SID;
|
||||
}
|
||||
|
||||
/* Try and get a salted cred first. If we can't
|
||||
fall back to an unsalted cred. */
|
||||
|
||||
centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid));
|
||||
|
||||
if (!centry) {
|
||||
DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n",
|
||||
sid_string_static(sid)));
|
||||
sid_string_static(sid)));
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
t = centry_time(centry);
|
||||
|
||||
/* In the salted case this isn't actually the nt_hash itself,
|
||||
but the MD5 of the salt + nt_hash. Let the caller
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
} else {
|
||||
*cached_salt = NULL;
|
||||
}
|
||||
|
||||
#if DEBUG_PASSWORD
|
||||
dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
|
||||
dump_data(100, (const char *)*cached_nt_pass, NT_HASH_LEN);
|
||||
if (*cached_salt) {
|
||||
dump_data(100, (const char *)*cached_salt, NT_HASH_LEN);
|
||||
}
|
||||
#endif
|
||||
status = centry->status;
|
||||
|
||||
@ -921,6 +943,8 @@ NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Store creds for a SID - only writes out new salted ones. */
|
||||
|
||||
NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
@ -929,6 +953,8 @@ NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
|
||||
struct cache_entry *centry;
|
||||
fstring sid_string;
|
||||
uint32 rid;
|
||||
uint8 cred_salt[NT_HASH_LEN];
|
||||
uint8 salted_hash[NT_HASH_LEN];
|
||||
|
||||
if (is_null_sid(sid)) {
|
||||
return NT_STATUS_INVALID_SID;
|
||||
@ -948,7 +974,13 @@ NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
|
||||
#endif
|
||||
|
||||
centry_put_time(centry, time(NULL));
|
||||
centry_put_hash16(centry, nt_pass);
|
||||
|
||||
/* Create a salt and then salt the hash. */
|
||||
generate_random_buffer(cred_salt, NT_HASH_LEN);
|
||||
E_md5hash(cred_salt, nt_pass, salted_hash);
|
||||
|
||||
centry_put_hash16(centry, salted_hash);
|
||||
centry_put_hash16(centry, cred_salt);
|
||||
centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid));
|
||||
|
||||
DEBUG(10,("wcache_save_creds: %s\n", sid_string));
|
||||
|
@ -31,12 +31,13 @@ NTSTATUS winbindd_get_creds(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
NET_USER_INFO_3 **info3,
|
||||
const uint8 *cached_nt_pass[NT_HASH_LEN])
|
||||
const uint8 *cached_nt_pass[NT_HASH_LEN],
|
||||
const uint8 *cred_salt[NT_HASH_LEN])
|
||||
{
|
||||
NET_USER_INFO_3 *info;
|
||||
NTSTATUS status;
|
||||
|
||||
status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass);
|
||||
status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass, cred_salt);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
@ -736,8 +736,10 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
|
||||
enum SID_NAME_USE type;
|
||||
uchar new_nt_pass[NT_HASH_LEN];
|
||||
const uint8 *cached_nt_pass;
|
||||
const uint8 *cached_salt;
|
||||
NET_USER_INFO_3 *my_info3;
|
||||
time_t kickoff_time, must_change_time;
|
||||
BOOL password_good = False;
|
||||
|
||||
*info3 = NULL;
|
||||
|
||||
@ -768,7 +770,8 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
|
||||
state->mem_ctx,
|
||||
&sid,
|
||||
&my_info3,
|
||||
&cached_nt_pass);
|
||||
&cached_nt_pass,
|
||||
&cached_salt);
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
|
||||
return result;
|
||||
@ -781,9 +784,26 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
|
||||
#if DEBUG_PASSWORD
|
||||
dump_data(100, (const char *)new_nt_pass, NT_HASH_LEN);
|
||||
dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
|
||||
if (cached_salt) {
|
||||
dump_data(100, (const char *)cached_salt, NT_HASH_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN)) {
|
||||
if (cached_salt) {
|
||||
/* In this case we didn't store the nt_hash itself,
|
||||
but the MD5 combination of salt + nt_hash. */
|
||||
uchar salted_hash[NT_HASH_LEN];
|
||||
E_md5hash(cached_salt, new_nt_pass, salted_hash);
|
||||
|
||||
password_good = (memcmp(cached_nt_pass, salted_hash, NT_HASH_LEN) == 0) ?
|
||||
True : False;
|
||||
} else {
|
||||
/* Old cached cred - direct store of nt_hash (bad bad bad !). */
|
||||
password_good = (memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN) == 0) ?
|
||||
True : False;
|
||||
}
|
||||
|
||||
if (password_good) {
|
||||
|
||||
/* User *DOES* know the password, update logon_time and reset
|
||||
* bad_pw_count */
|
||||
|
Loading…
x
Reference in New Issue
Block a user