summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/torture/rpc/samlogon.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 29a87f9804..0c5afd44fe 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -626,6 +626,135 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
}
/*
+ * Test the NTLM and LMv2 responses
+ */
+
+static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
+{
+ BOOL pass = True;
+ 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());
+
+ DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
+ DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
+
+ uint8_t lm_hash[16];
+ uint8_t lm_session_key[8];
+ uint8_t user_session_key[16];
+ uint8_t nt_hash[16];
+
+ SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
+ ntlm_response.data);
+ E_md4hash(samlogon_state->password, nt_hash);
+ SMBsesskeygen_ntv1(nt_hash,
+ ntlm_session_key.data);
+ E_deshash(samlogon_state->password, lm_hash);
+
+ ZERO_STRUCT(lm_session_key);
+ ZERO_STRUCT(user_session_key);
+
+ /* TODO - test with various domain cases, and without domain */
+ if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain,
+ samlogon_state->password, &samlogon_state->chall,
+ &names_blob,
+ &lmv2_response, &ntlmv2_response,
+ &lmv2_session_key, &ntlmv2_session_key)) {
+ data_blob_free(&names_blob);
+ return False;
+ }
+ data_blob_free(&names_blob);
+
+ nt_status = check_samlogon(samlogon_state,
+ break_which,
+ &samlogon_state->chall,
+ &lmv2_response,
+ &ntlm_response,
+ lm_session_key,
+ user_session_key,
+ error_string);
+
+ data_blob_free(&lmv2_response);
+ data_blob_free(&ntlmv2_response);
+
+
+ if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
+ return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return False;
+ }
+
+ switch (break_which) {
+ case NO_NT:
+ if (memcmp(lmv2_session_key.data, user_session_key,
+ sizeof(user_session_key)) != 0) {
+ printf("USER (LMv2) Session Key does not match expectations!\n");
+ printf("user_session_key:\n");
+ dump_data(1, user_session_key, 16);
+ printf("expected:\n");
+ dump_data(1, 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 (LMv2) Session Key does not match expectations!\n");
+ printf("lm_session_key:\n");
+ dump_data(1, lm_session_key, 8);
+ printf("expected:\n");
+ dump_data(1, lmv2_session_key.data, 8);
+ pass = False;
+ }
+ break;
+ case BREAK_LM:
+ if (memcmp(ntlm_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, user_session_key, 16);
+ printf("expected:\n");
+ dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
+ pass = False;
+ }
+ if (memcmp(lm_hash, lm_session_key,
+ sizeof(lm_session_key)) != 0) {
+ printf("LM Session Key does not match expectations!\n");
+ printf("lm_session_key:\n");
+ dump_data(1, lm_session_key, 8);
+ printf("expected:\n");
+ dump_data(1, lm_hash, 8);
+ pass = False;
+ }
+ break;
+ default:
+ if (memcmp(ntlm_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, user_session_key, 16);
+ printf("expected:\n");
+ dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
+ pass = False;
+ }
+ if (memcmp(ntlm_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, lm_session_key, 8);
+ printf("expected:\n");
+ dump_data(1, ntlm_session_key.data, 8);
+ pass = False;
+ }
+ }
+
+ return pass;
+}
+
+/*
* Test the NTLMv2 and LMv2 responses
*/
@@ -686,6 +815,21 @@ static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char
return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, error_string);
}
+static BOOL test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
+{
+ return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
+}
+
+static BOOL test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
+{
+ return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, error_string);
+}
+
+static BOOL test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
+{
+ return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, error_string);
+}
+
/*
* Test the NTLM2 response (extra challenge in LM feild)
*
@@ -885,6 +1029,9 @@ static const struct ntlm_tests {
{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_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", False},
+ {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", False},
+ {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", False},
{test_plaintext_none_broken, "Plaintext", True},
{test_plaintext_lm_broken, "Plaintext LM broken", True},
{test_plaintext_nt_broken, "Plaintext NT broken", True},