diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-11-11 01:29:34 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:43 -0500 |
commit | 5afda90c95e2e120f1121afb6b9fe7f5222ffa1e (patch) | |
tree | 43d35051147fe0417f67b159e74bc60ec3a2ee8f /source4/torture/rpc/netlogon.c | |
parent | 0d696dc0e9867889fe198e61ed576af51ee732d1 (diff) | |
download | samba-5afda90c95e2e120f1121afb6b9fe7f5222ffa1e.tar.gz samba-5afda90c95e2e120f1121afb6b9fe7f5222ffa1e.tar.bz2 samba-5afda90c95e2e120f1121afb6b9fe7f5222ffa1e.zip |
r3676: Add a negitive test for NTLM2 session security (which should not
appear in netlogon, despite what the LM response may look like).
Make the logon tests less verbose - only print test names on failure.
Andrew Bartlett
(This used to be commit 49c335bcd8852bcf2f4663b9fd514bf3da0fa50d)
Diffstat (limited to 'source4/torture/rpc/netlogon.c')
-rw-r--r-- | source4/torture/rpc/netlogon.c | 106 |
1 files changed, 96 insertions, 10 deletions
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 7453814ec1..0551151db8 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -25,6 +25,7 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_netlogon.h" #include "auth/auth.h" +#include "lib/crypto/crypto.h" static const char *machine_password; @@ -309,8 +310,6 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, uint16 validation_level; - printf("testing netr_LogonSamLogon\n"); - samlogon_state->r.in.logon.network = &ninfo; samlogon_state->r_flags.in.logon.network = &ninfo; @@ -763,7 +762,7 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum data_blob_free(&ntlmv2_response); - if (!NT_STATUS_IS_OK(nt_status)) { + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { return break_which == BREAK_BOTH; } @@ -873,6 +872,90 @@ static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, error_string); } +/* + * Test the NTLM2 response (extra challenge in LM feild) + * + * This test is the same as the 'break LM' test, but checks that the + * server implements NTLM2 session security in the right place + * (NETLOGON is the wrong place). + */ + +static BOOL test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) +{ + BOOL pass = True; + NTSTATUS nt_status; + DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); + DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); + + uint8_t lm_key[8]; + uint8_t nt_hash[16]; + uint8_t lm_hash[16]; + uint8_t nt_key[16]; + uint8_t user_session_key[16]; + uint8_t expected_user_session_key[16]; + uint8_t session_nonce_hash[16]; + uint8_t client_chall[8]; + + struct MD5Context md5_session_nonce_ctx; + HMACMD5Context hmac_ctx; + + ZERO_STRUCT(user_session_key); + ZERO_STRUCT(lm_key); + generate_random_buffer(client_chall, 8); + + MD5Init(&md5_session_nonce_ctx); + MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8); + MD5Update(&md5_session_nonce_ctx, client_chall, 8); + MD5Final(session_nonce_hash, &md5_session_nonce_ctx); + + E_md4hash(samlogon_state->password, (uint8_t *)nt_hash); + E_deshash(samlogon_state->password, (uint8_t *)lm_hash); + SMBsesskeygen_ntv1((const uint8_t *)nt_hash, + nt_key); + + SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); + + memcpy(lm_response.data, session_nonce_hash, 8); + memset(lm_response.data + 8, 0, 16); + + hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx); + hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx); + hmac_md5_update(client_chall, 8, &hmac_ctx); + hmac_md5_final(expected_user_session_key, &hmac_ctx); + + nt_status = check_samlogon(samlogon_state, + BREAK_NONE, + &samlogon_state->chall, + &lm_response, + &nt_response, + lm_key, + user_session_key, + error_string); + + if (!NT_STATUS_IS_OK(nt_status)) { + return False; + } + + if (memcmp(lm_hash, lm_key, + sizeof(lm_key)) != 0) { + printf("LM Key does not match expectations!\n"); + printf("lm_key:\n"); + dump_data(1, (const char *)lm_key, 8); + printf("expected:\n"); + dump_data(1, (const char *)lm_hash, 8); + pass = False; + } + if (memcmp(nt_key, user_session_key, 16) != 0) { + printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n"); + printf("user_session_key:\n"); + dump_data(1, (const char *)user_session_key, sizeof(user_session_key)); + printf("expected:\n"); + dump_data(1, (const char *)nt_key, sizeof(nt_key)); + pass = False; + } + return pass; +} + static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) { NTSTATUS nt_status; @@ -895,7 +978,7 @@ static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea exit(1); } - nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, utf16_len(unicodepw)); + nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2); password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password); @@ -987,6 +1070,7 @@ static const struct ntlm_tests { {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", False}, {test_ntlm_lm_broken, "NTLM and LM, LM broken", False}, {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False}, + {test_ntlm2, "NTLM2 (NTLMv2 session security)", False}, {test_plaintext_none_broken, "Plaintext", True}, {test_plaintext_lm_broken, "Plaintext LM broken", True}, {test_plaintext_nt_broken, "Plaintext NT broken", True}, @@ -1009,6 +1093,8 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) DCERPC_NETR_LOGONSAMLOGONWITHFLAGS }; struct samlogon_state samlogon_state; + printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n"); + samlogon_state.mem_ctx = mem_ctx; samlogon_state.account_name = lp_parm_string(-1, "torture", "username"); samlogon_state.account_domain = lp_parm_string(-1, "torture", "userdomain"); @@ -1052,15 +1138,15 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) samlogon_state.r.in.logon_level = logon_levels[l]; samlogon_state.r_flags.in.validation_level = validation_levels[v]; samlogon_state.r_flags.in.logon_level = logon_levels[l]; - printf("Testing SamLogon with '%s' at validation level %d, logon level %d, function %d\n", - test_table[i].name, validation_levels[v], - logon_levels[l], function_levels[f]); - if (!test_table[i].fn(&samlogon_state, &error_string)) { + printf("Testing '%s' at validation level %d, logon level %d, function %d: \n", + test_table[i].name, validation_levels[v], + logon_levels[l], function_levels[f]); + if (test_table[i].expect_fail) { - printf("Test %s failed (expected, test incomplete): %s\n", test_table[i].name, error_string); + printf(" failed (expected, test incomplete): %s\n", error_string); } else { - printf("Test %s failed: %s\n", test_table[i].name, error_string); + printf(" failed: %s\n", error_string); ret = False; } SAFE_FREE(error_string); |