diff options
-rw-r--r-- | source3/include/ntlmssp.h | 3 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp.c | 56 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 68 |
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. |