summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-08-19 20:42:04 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:43 -0500
commitffa590854ab5f2563c3398ae9ae3182e6abe3f82 (patch)
tree136d175541152b0699d0cd9cf954c2cda2ccb982
parentb41e14abfdc7301d5ae26ad95c031aa36c190fc8 (diff)
downloadsamba-ffa590854ab5f2563c3398ae9ae3182e6abe3f82.tar.gz
samba-ffa590854ab5f2563c3398ae9ae3182e6abe3f82.tar.bz2
samba-ffa590854ab5f2563c3398ae9ae3182e6abe3f82.zip
r17612: 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. (This used to be commit 629faa530f0422755823644f1c23bea74830912f)
-rw-r--r--source3/include/ntlmssp.h3
-rw-r--r--source3/libsmb/ntlmssp.c56
-rw-r--r--source3/libsmb/smbencrypt.c68
3 files changed, 86 insertions, 41 deletions
diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h
index a158fb614f..d15ce18021 100644
--- a/source3/include/ntlmssp.h
+++ b/source3/include/ntlmssp.h
@@ -89,7 +89,8 @@ typedef struct ntlmssp_state
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 */
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index a6fb3b426b..fd639ffd9f 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -155,18 +155,37 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
}
/**
- * 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 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
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 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
/* 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 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
}
} 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 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
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);
}
}
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index ddfe696b48..96c086d680 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -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 @@ void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p
}
-/* 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 @@ void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
#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 @@ static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16],
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 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
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.