diff options
author | Jeremy Allison <jra@samba.org> | 2006-08-19 20:42:04 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:38:43 -0500 |
commit | ffa590854ab5f2563c3398ae9ae3182e6abe3f82 (patch) | |
tree | 136d175541152b0699d0cd9cf954c2cda2ccb982 | |
parent | b41e14abfdc7301d5ae26ad95c031aa36c190fc8 (diff) | |
download | samba-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.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. |