summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.