svn commit: samba r17612 - in branches/SAMBA_3_0/source: include libsmb

jra at samba.org jra at samba.org
Sat Aug 19 20:42:05 GMT 2006


Author: jra
Date: 2006-08-19 20:42:04 +0000 (Sat, 19 Aug 2006)
New Revision: 17612

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

Log:
Modify NTLMSSP session code so that it doesn't store
a copy of the plaintext password, only the NT and LM
hashes (all it needs). Fix smbencrypt to expose hash
verions of plaintext function. Andrew Bartlett, you
might want to look at this for gensec.
This should make it easier for winbindd to store
cached credentials without having to store plaintext
passwords in an NTLM-only environment (non krb5).
Jeremy.

Modified:
   branches/SAMBA_3_0/source/include/ntlmssp.h
   branches/SAMBA_3_0/source/libsmb/ntlmssp.c
   branches/SAMBA_3_0/source/libsmb/smbencrypt.c


Changeset:
Modified: branches/SAMBA_3_0/source/include/ntlmssp.h
===================================================================
--- branches/SAMBA_3_0/source/include/ntlmssp.h	2006-08-19 20:37:39 UTC (rev 17611)
+++ branches/SAMBA_3_0/source/include/ntlmssp.h	2006-08-19 20:42:04 UTC (rev 17612)
@@ -89,7 +89,8 @@
 	char *user;
 	char *domain;
 	char *workstation;
-	char *password;
+	unsigned char *nt_hash;
+	unsigned char *lm_hash;
 	char *server_domain;
 
 	DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */

Modified: branches/SAMBA_3_0/source/libsmb/ntlmssp.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/ntlmssp.c	2006-08-19 20:37:39 UTC (rev 17611)
+++ branches/SAMBA_3_0/source/libsmb/ntlmssp.c	2006-08-19 20:42:04 UTC (rev 17612)
@@ -155,18 +155,37 @@
 }
 
 /** 
- * Set a password on an NTLMSSP context - ensures it is talloc()ed 
+ * Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed 
  *
  */
+NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state,
+		const unsigned char lm_hash[16],
+		const unsigned char nt_hash[16]) 
+{
+	ntlmssp_state->lm_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16);
+	ntlmssp_state->nt_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16);
+	if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	return NT_STATUS_OK;
+}
+
+/** 
+ * Converts a password to the hashes on an NTLMSSP context.
+ *
+ */
 NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password) 
 {
 	if (!password) {
-		ntlmssp_state->password = NULL;
+		ntlmssp_state->lm_hash = NULL;
+		ntlmssp_state->nt_hash = NULL;
 	} else {
-		ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
-		if (!ntlmssp_state->password) {
-			return NT_STATUS_NO_MEMORY;
-		}
+		unsigned char lm_hash[16];
+		unsigned char nt_hash[16];
+
+		E_deshash(password, lm_hash);
+		E_md4hash(password, nt_hash);
+		return ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);
 	}
 	return NT_STATUS_OK;
 }
@@ -1029,7 +1048,7 @@
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	if (!ntlmssp_state->password) {
+	if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
 		static const uchar zeros[16];
 		/* do nothing - blobs are zero length */
 
@@ -1049,9 +1068,9 @@
 		/* TODO: if the remote server is standalone, then we should replace 'domain'
 		   with the server name as supplied above */
 		
-		if (!SMBNTLMv2encrypt(ntlmssp_state->user, 
+		if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user, 
 				      ntlmssp_state->domain, 
-				      ntlmssp_state->password, &challenge_blob, 
+				      ntlmssp_state->nt_hash, &challenge_blob, 
 				      &struct_blob, 
 				      &lm_response, &nt_response, &session_key)) {
 			data_blob_free(&challenge_blob);
@@ -1060,11 +1079,9 @@
 		}
 	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
 		struct MD5Context md5_session_nonce_ctx;
-		uchar nt_hash[16];
 		uchar session_nonce[16];
 		uchar session_nonce_hash[16];
 		uchar user_session_key[16];
-		E_md4hash(ntlmssp_state->password, nt_hash);
 		
 		lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
 		generate_random_buffer(lm_response.data, 8);
@@ -1083,40 +1100,35 @@
 		dump_data(5, (const char *)session_nonce_hash, 8);
 		
 		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
-		SMBNTencrypt(ntlmssp_state->password,
+		SMBNTencrypt_hash(ntlmssp_state->nt_hash,
 			     session_nonce_hash,
 			     nt_response.data);
 
 		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
 
-		SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key);
+		SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key);
 		hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
 		dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
 	} else {
-		uchar lm_hash[16];
-		uchar nt_hash[16];
-		E_deshash(ntlmssp_state->password, lm_hash);
-		E_md4hash(ntlmssp_state->password, nt_hash);
-		
 		/* lanman auth is insecure, it may be disabled */
 		if (lp_client_lanman_auth()) {
 			lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
-			SMBencrypt(ntlmssp_state->password,challenge_blob.data,
+			SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
 				   lm_response.data);
 		}
 		
 		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
-		SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
+		SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
 			     nt_response.data);
 		
 		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
 		if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
 		    && lp_client_lanman_auth()) {
-			SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data,
+			SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
 					session_key.data);
 			dump_data_pw("LM session key\n", session_key.data, session_key.length);
 		} else {
-			SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+			SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data);
 			dump_data_pw("NT session key:\n", session_key.data, session_key.length);
 		}
 	}

Modified: branches/SAMBA_3_0/source/libsmb/smbencrypt.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/smbencrypt.c	2006-08-19 20:37:39 UTC (rev 17611)
+++ branches/SAMBA_3_0/source/libsmb/smbencrypt.c	2006-08-19 20:42:04 UTC (rev 17612)
@@ -25,30 +25,38 @@
 #include "includes.h"
 #include "byteorder.h"
 
-/*
-   This implements the X/Open SMB password encryption
-   It takes a password ('unix' string), a 8 byte "crypt key" 
-   and puts 24 bytes of encrypted password into p24 
-
-   Returns False if password must have been truncated to create LM hash
-*/
-BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
+void SMBencrypt_hash(const uchar lm_hash[16], const uchar *c8, uchar p24[24])
 {
-	BOOL ret;
 	uchar p21[21];
 
 	memset(p21,'\0',21);
-	ret = E_deshash(passwd, p21); 
+	memcpy(p21, lm_hash, 16);
 
 	SMBOWFencrypt(p21, c8, p24);
 
 #ifdef DEBUG_PASSWORD
-	DEBUG(100,("SMBencrypt: lm#, challenge, response\n"));
+	DEBUG(100,("SMBencrypt_hash: lm#, challenge, response\n"));
 	dump_data(100, (const char *)p21, 16);
 	dump_data(100, (const char *)c8, 8);
 	dump_data(100, (const char *)p24, 24);
 #endif
+}
 
+/*
+   This implements the X/Open SMB password encryption
+   It takes a password ('unix' string), a 8 byte "crypt key" 
+   and puts 24 bytes of encrypted password into p24 
+
+   Returns False if password must have been truncated to create LM hash
+*/
+
+BOOL SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
+{
+	BOOL ret;
+	uchar lm_hash[16];
+
+	ret = E_deshash(passwd, lm_hash); 
+	SMBencrypt_hash(lm_hash, c8, p24);
 	return ret;
 }
 
@@ -237,15 +245,14 @@
 }
 
 
-/* Does the NT MD4 hash then des encryption. */
+/* Does the des encryption. */
  
-void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
+void SMBNTencrypt_hash(const uchar nt_hash[16], uchar *c8, uchar *p24)
 {
 	uchar p21[21];
  
 	memset(p21,'\0',21);
- 
-	E_md4hash(passwd, p21);    
+	memcpy(p21, nt_hash, 16);
 	SMBOWFencrypt(p21, c8, p24);
 
 #ifdef DEBUG_PASSWORD
@@ -256,6 +263,15 @@
 #endif
 }
 
+/* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
+
+void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
+{
+	uchar nt_hash[16];
+	E_md4hash(passwd, nt_hash);    
+	SMBNTencrypt_hash(nt_hash, c8, p24);
+}
+
 /* Does the md5 encryption from the Key Response for NTLMv2. */
 void SMBOWFencrypt_ntv2(const uchar kr[16],
 			const DATA_BLOB *srv_chal,
@@ -416,15 +432,13 @@
 	return final_response;
 }
 
-BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
+BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const uchar nt_hash[16], 
 		      const DATA_BLOB *server_chal, 
 		      const DATA_BLOB *names_blob,
 		      DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
 		      DATA_BLOB *user_session_key) 
 {
-	uchar nt_hash[16];
 	uchar ntlm_v2_hash[16];
-	E_md4hash(password, nt_hash);
 
 	/* We don't use the NT# directly.  Instead we use it mashed up with
 	   the username and domain.
@@ -455,6 +469,24 @@
 	return True;
 }
 
+/* Plaintext version of the above. */
+
+BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
+		      const DATA_BLOB *server_chal, 
+		      const DATA_BLOB *names_blob,
+		      DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
+		      DATA_BLOB *user_session_key) 
+{
+	uchar nt_hash[16];
+	E_md4hash(password, nt_hash);
+
+	return SMBNTLMv2encrypt_hash(user, domain, nt_hash,
+				server_chal,
+				names_blob,
+				lm_response, nt_response,
+				user_session_key);
+}
+
 /***********************************************************
  encode a password buffer with a unicode password.  The buffer
  is filled with random data to make it harder to attack.



More information about the samba-cvs mailing list