diff options
-rw-r--r-- | source4/torture/rpc/netlogon.c | 197 |
1 files changed, 126 insertions, 71 deletions
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 75f903d8c8..abdd87ab38 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -264,6 +264,7 @@ static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } enum ntlm_break { + BREAK_BOTH, BREAK_NONE, BREAK_LM, BREAK_NT, @@ -329,6 +330,14 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, nt_response->data[0]++; } break; + case BREAK_BOTH: + if (lm_response && lm_response->data) { + lm_response->data[0]++; + } + if (nt_response && nt_response->data) { + nt_response->data[0]++; + } + break; case NO_LM: data_blob_free(lm_response); break; @@ -474,7 +483,7 @@ static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm if (break_which == NO_NT && !lm_good) { return True; } - return break_which == BREAK_NT; + return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); } if (!NT_STATUS_IS_OK(nt_status)) { @@ -678,11 +687,14 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum NTSTATUS nt_status; DATA_BLOB ntlmv2_response = data_blob(NULL, 0); DATA_BLOB lmv2_response = data_blob(NULL, 0); + DATA_BLOB lmv2_session_key = data_blob(NULL, 0); DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0); DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup()); + uint8_t lm_session_key[8]; uint8_t user_session_key[16]; + ZERO_STRUCT(lm_session_key); ZERO_STRUCT(user_session_key); /* TODO - test with various domain cases, and without domain */ @@ -690,7 +702,7 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum samlogon_state->password, &samlogon_state->chall, &names_blob, &lmv2_response, &ntlmv2_response, - &ntlmv2_session_key)) { + &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return False; } @@ -701,26 +713,58 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum &samlogon_state->chall, &lmv2_response, &ntlmv2_response, - NULL, + lm_session_key, user_session_key, error_string); data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); + if (!NT_STATUS_IS_OK(nt_status)) { - return break_which == BREAK_NT; + return break_which == BREAK_BOTH; } - if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, - sizeof(user_session_key)) != 0) { - printf("USER (NTLMv2) Session Key does not match expectations!\n"); - printf("user_session_key:\n"); - dump_data(1, (const char *)user_session_key, 16); - printf("expected:\n"); - dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length); - pass = False; + if (break_which == NO_NT) { + if (memcmp(lmv2_session_key.data, user_session_key, + sizeof(user_session_key)) != 0) { + printf("USER (NTLMv2) Session Key does not match expectations!\n"); + printf("user_session_key:\n"); + dump_data(1, (const char *)user_session_key, 16); + printf("expected:\n"); + dump_data(1, (const char *)lmv2_session_key.data, ntlmv2_session_key.length); + pass = False; + } + if (memcmp(lmv2_session_key.data, lm_session_key, + sizeof(lm_session_key)) != 0) { + printf("LM (NTLMv2) Session Key does not match expectations!\n"); + printf("lm_session_key:\n"); + dump_data(1, (const char *)lm_session_key, 8); + printf("expected:\n"); + dump_data(1, (const char *)lmv2_session_key.data, 8); + pass = False; + } + } else { + if (memcmp(ntlmv2_session_key.data, user_session_key, + sizeof(user_session_key)) != 0) { + printf("USER (NTLMv2) Session Key does not match expectations!\n"); + printf("user_session_key:\n"); + dump_data(1, (const char *)user_session_key, 16); + printf("expected:\n"); + dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length); + pass = False; + } + if (memcmp(ntlmv2_session_key.data, lm_session_key, + sizeof(lm_session_key)) != 0) { + printf("LM (NTLMv2) Session Key does not match expectations!\n"); + printf("lm_session_key:\n"); + dump_data(1, (const char *)lm_session_key, 8); + printf("expected:\n"); + dump_data(1, (const char *)ntlmv2_session_key.data, 8); + pass = False; + } } + return pass; } @@ -766,6 +810,10 @@ static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char ** return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string); } +static BOOL test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) +{ + return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string); +} static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string); @@ -776,6 +824,11 @@ static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, cha return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string); } +static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) +{ + return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, error_string); +} + static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) { NTSTATUS nt_status; @@ -878,6 +931,7 @@ static const struct ntlm_tests { } test_table[] = { {test_lm, "LM", False}, {test_lm_ntlm, "LM and NTLM", False}, + {test_lm_ntlm_both_broken, "LM and NTLM, both broken", False}, {test_ntlm, "NTLM", False}, {test_ntlm_in_lm, "NTLM in LM", False}, {test_ntlm_in_both, "NTLM in both", False}, @@ -886,6 +940,7 @@ static const struct ntlm_tests { {test_lmv2, "LMv2", False}, {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False}, {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False}, + {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_plaintext_none_broken, "Plaintext", True}, @@ -959,6 +1014,65 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return ret; } +/* + test an ADS style interactive domain login +*/ +static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct creds_CredentialState *creds) +{ + NTSTATUS status; + struct netr_LogonSamLogonWithFlags r; + struct netr_Authenticator a, ra; + struct netr_PasswordInfo pinfo; + const char *plain_pass; + + ZERO_STRUCT(r); + ZERO_STRUCT(ra); + + creds_client_authenticator(creds, &a); + + r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); + r.in.workstation = TEST_MACHINE_NAME; + r.in.credential = &a; + r.in.return_authenticator = &ra; + r.in.logon_level = 5; + r.in.logon.password = &pinfo; + r.in.validation_level = 6; + r.in.flags = 0; + + pinfo.identity_info.domain_name.string = lp_parm_string(-1, "torture", "userdomain"); + pinfo.identity_info.parameter_control = 0; + pinfo.identity_info.logon_id_low = 0; + pinfo.identity_info.logon_id_high = 0; + pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username"); + pinfo.identity_info.workstation.string = TEST_MACHINE_NAME; + + plain_pass = lp_parm_string(-1, "torture", "password"); + + E_deshash(plain_pass, pinfo.lmpassword.hash); + E_md4hash(plain_pass, pinfo.ntpassword.hash); + + creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); + creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); + + printf("Testing netr_LogonSamLogonWithFlags\n"); + + status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status)); + exit(1); + return False; + } + + if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { + printf("Credential chaining failed\n"); + return False; + } + + return True; +} + + /* try a change password for our machine account @@ -1533,65 +1647,6 @@ static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem } -/* - test an ADS style interactive domain login -*/ -static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds) -{ - NTSTATUS status; - struct netr_LogonSamLogonWithFlags r; - struct netr_Authenticator a, ra; - struct netr_PasswordInfo pinfo; - const char *plain_pass; - - ZERO_STRUCT(r); - ZERO_STRUCT(ra); - - creds_client_authenticator(creds, &a); - - r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); - r.in.workstation = TEST_MACHINE_NAME; - r.in.credential = &a; - r.in.return_authenticator = &ra; - r.in.logon_level = 5; - r.in.logon.password = &pinfo; - r.in.validation_level = 6; - r.in.flags = 0; - - pinfo.identity_info.domain_name.string = lp_parm_string(-1, "torture", "userdomain"); - pinfo.identity_info.parameter_control = 0; - pinfo.identity_info.logon_id_low = 0; - pinfo.identity_info.logon_id_high = 0; - pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username"); - pinfo.identity_info.workstation.string = TEST_MACHINE_NAME; - - plain_pass = lp_parm_string(-1, "torture", "password"); - - E_deshash(plain_pass, pinfo.lmpassword.hash); - E_md4hash(plain_pass, pinfo.ntpassword.hash); - - creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); - creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); - - printf("Testing netr_LogonSamLogonWithFlags\n"); - - status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r); - if (!NT_STATUS_IS_OK(status)) { - printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status)); - exit(1); - return False; - } - - if (!creds_client_check(creds, &r.out.return_authenticator->cred)) { - printf("Credential chaining failed\n"); - return False; - } - - return True; -} - - static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; |