svn commit: samba r17617 - in branches/SAMBA_3_0/source/nsswitch: .

jra at samba.org jra at samba.org
Sun Aug 20 03:53:43 GMT 2006


Author: jra
Date: 2006-08-20 03:53:42 +0000 (Sun, 20 Aug 2006)
New Revision: 17617

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17617

Log:
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.

Modified:
   branches/SAMBA_3_0/source/nsswitch/winbindd_cache.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_creds.c
   branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c


Changeset:
Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_cache.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_cache.c	2006-08-20 01:25:26 UTC (rev 17616)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_cache.c	2006-08-20 03:53:42 UTC (rev 17617)
@@ -47,6 +47,7 @@
 };
 
 #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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 #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));

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_creds.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_creds.c	2006-08-20 01:25:26 UTC (rev 17616)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_creds.c	2006-08-20 03:53:42 UTC (rev 17617)
@@ -31,12 +31,13 @@
 			    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;
 	}

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c	2006-08-20 01:25:26 UTC (rev 17616)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c	2006-08-20 03:53:42 UTC (rev 17617)
@@ -736,8 +736,10 @@
 	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 @@
 				    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,10 +784,27 @@
 #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 */
 	



More information about the samba-cvs mailing list