summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/utils/ntlm_auth.c186
1 files changed, 174 insertions, 12 deletions
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index c4beb4ef1a..fda4869f36 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -683,7 +683,7 @@ static BOOL test_ntlm(void)
}
/*
- * Test the NTLM response only, but in the LM feild.
+ * Test the NTLM response only, but in the LM field.
*/
static BOOL test_ntlm_in_lm(void)
@@ -749,7 +749,7 @@ static BOOL test_ntlm_in_lm(void)
}
/*
- * Test the NTLM response only, but in the both the NT and LM feilds.
+ * Test the NTLM response only, but in the both the NT and LM fields.
*/
static BOOL test_ntlm_in_both(void)
@@ -1048,13 +1048,171 @@ static BOOL test_lmv2(void)
}
/*
+ * Test the normal 'LM and NTLM' combination but deliberately break one
+ */
+
+static BOOL test_ntlm_broken(BOOL break_lm)
+{
+ BOOL pass = True;
+ NTSTATUS nt_status;
+ uint32 flags = 0;
+ DATA_BLOB lm_response = data_blob(NULL, 24);
+ DATA_BLOB nt_response = data_blob(NULL, 24);
+ DATA_BLOB session_key = data_blob(NULL, 16);
+
+ uchar lm_key[8];
+ uchar nt_key[16];
+ uchar lm_hash[16];
+ uchar nt_hash[16];
+ DATA_BLOB chall = get_challenge();
+ char *error_string;
+
+ ZERO_STRUCT(lm_key);
+ ZERO_STRUCT(nt_key);
+
+ flags |= WINBIND_PAM_LMKEY;
+ flags |= WINBIND_PAM_NTKEY;
+
+ SMBencrypt(opt_password,chall.data,lm_response.data);
+ E_deshash(opt_password, lm_hash);
+
+ SMBNTencrypt(opt_password,chall.data,nt_response.data);
+
+ E_md4hash(opt_password, nt_hash);
+ SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
+
+ if (break_lm)
+ lm_response.data[0]++;
+ else
+ nt_response.data[0]++;
+
+ nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
+ opt_workstation,
+ &chall,
+ &lm_response,
+ &nt_response,
+ flags,
+ lm_key,
+ nt_key,
+ &error_string);
+
+ data_blob_free(&lm_response);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ d_printf("%s (0x%x)\n",
+ error_string,
+ NT_STATUS_V(nt_status));
+ SAFE_FREE(error_string);
+ return False;
+ }
+
+ if (memcmp(lm_hash, lm_key,
+ sizeof(lm_key)) != 0) {
+ DEBUG(1, ("LM Key does not match expectations!\n"));
+ DEBUG(1, ("lm_key:\n"));
+ dump_data(1, lm_key, 8);
+ DEBUG(1, ("expected:\n"));
+ dump_data(1, lm_hash, 8);
+ pass = False;
+ }
+ if (memcmp(session_key.data, nt_key,
+ sizeof(nt_key)) != 0) {
+ DEBUG(1, ("NT Session Key does not match expectations!\n"));
+ DEBUG(1, ("nt_key:\n"));
+ dump_data(1, nt_key, 16);
+ DEBUG(1, ("expected:\n"));
+ dump_data(1, session_key.data, session_key.length);
+ pass = False;
+ }
+ return pass;
+}
+
+static BOOL test_ntlm_lm_broken(void)
+{
+ return test_ntlm_broken(True);
+}
+
+static BOOL test_ntlm_ntlm_broken(void)
+{
+ return test_ntlm_broken(False);
+}
+
+static BOOL test_ntlmv2_broken(BOOL break_lmv2)
+{
+ BOOL pass = True;
+ NTSTATUS nt_status;
+ uint32 flags = 0;
+ DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
+ DATA_BLOB lmv2_response = data_blob(NULL, 0);
+ DATA_BLOB nt_session_key = data_blob(NULL, 0);
+ DATA_BLOB lm_session_key = data_blob(NULL, 0);
+
+ uchar lm_key[16];
+ uchar nt_key[16];
+ DATA_BLOB chall = get_challenge();
+ char *error_string;
+
+ ZERO_STRUCT(nt_key);
+ ZERO_STRUCT(lm_key);
+
+ flags |= WINBIND_PAM_LMKEY;
+ flags |= WINBIND_PAM_NTKEY;
+
+ if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, chall,
+ &lmv2_response, &ntlmv2_response,
+ &lm_session_key, &nt_session_key)) {
+ return False;
+ }
+
+ /* Heh - this should break the appropriate password hash nicely! */
+
+ if (break_lmv2)
+ lmv2_response.data[0]++;
+ else
+ ntlmv2_response.data[0]++;
+
+ nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
+ opt_workstation,
+ &chall,
+ &lmv2_response,
+ &ntlmv2_response,
+ flags,
+ lm_key,
+ nt_key,
+ &error_string);
+
+ data_blob_free(&lmv2_response);
+ data_blob_free(&ntlmv2_response);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ d_printf("%s (0x%x)\n",
+ error_string,
+ NT_STATUS_V(nt_status));
+ SAFE_FREE(error_string);
+ return False;
+ }
+
+ return pass;
+}
+
+static BOOL test_ntlmv2_lmv2_broken(void)
+{
+ return test_ntlmv2_broken(True);
+}
+
+static BOOL test_ntlmv2_ntlmv2_broken(void)
+{
+ return test_ntlmv2_broken(False);
+}
+
+/*
Tests:
- LM only
- NT and LM
- NT
- - NT in LM feild
- - NT in both feilds
+ - NT in LM field
+ - NT in both fields
- NTLMv2
- NTLMv2 and LMv2
- LMv2
@@ -1068,14 +1226,18 @@ struct ntlm_tests {
BOOL (*fn)(void);
const char *name;
} test_table[] = {
- {test_lm, "test LM"},
- {test_lm_ntlm, "test LM and NTLM"},
- {test_ntlm, "test NTLM"},
- {test_ntlm_in_lm, "test NTLM in LM"},
- {test_ntlm_in_both, "test NTLM in both"},
- {test_ntlmv2, "test NTLMv2"},
- {test_lmv2_ntlmv2, "test NTLMv2 and LMv2"},
- {test_lmv2, "test LMv2"}
+ {test_lm, "LM"},
+ {test_lm_ntlm, "LM and NTLM"},
+ {test_ntlm, "NTLM"},
+ {test_ntlm_in_lm, "NTLM in LM"},
+ {test_ntlm_in_both, "NTLM in both"},
+ {test_ntlmv2, "NTLMv2"},
+ {test_lmv2_ntlmv2, "NTLMv2 and LMv2"},
+ {test_lmv2, "LMv2"},
+ {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken"},
+ {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken"},
+ {test_ntlm_lm_broken, "NTLM and LM, LM broken"},
+ {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken"}
};
static BOOL diagnose_ntlm_auth(void)