samlogon.c
来自「samba最新软件」· C语言 代码 · 共 1,856 行 · 第 1/4 页
C
1,856 行
{ return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);}static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);}/* * Test the NTLMv2 response only */static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);}static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);}static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) { return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);}static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);}static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) { 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, UPPER_DOMAIN, error_string);}static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);}static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);}#if 0static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);}#endifstatic bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);}static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, 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, UPPER_DOMAIN, error_string);}static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, 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, UPPER_DOMAIN, error_string);}static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, 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, UPPER_DOMAIN, error_string);}static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, 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); bool lm_good; 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); lm_good = 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->parameter_control, &samlogon_state->chall, &lm_response, &nt_response, lm_key, user_session_key, error_string); if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { /* for 'old' passwords, we allow the server to be OK or wrong password */ if (samlogon_state->old_password) { return true; } return false; } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { SAFE_FREE(*error_string); asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); return false; } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { return true; } else if (!NT_STATUS_IS_OK(nt_status)) { return false; } if (lm_good) { if (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { d_printf("LM Key does not match expectations!\n"); d_printf("lm_key:\n"); dump_data(1, lm_key, 8); d_printf("expected:\n"); dump_data(1, lm_hash, 8); pass = false; } } else { static const uint8_t zeros[8]; if (memcmp(zeros, lm_key, sizeof(lm_key)) != 0) { d_printf("LM Session Key does not match expectations (zeros)!\n"); d_printf("lm_key:\n"); dump_data(1, lm_key, 8); d_printf("expected:\n"); dump_data(1, zeros, 8); pass = false; } } if (memcmp(nt_key, user_session_key, 16) != 0) { d_printf("NT Session Key does not match expectations (should be NT Key)!\n"); d_printf("user_session_key:\n"); dump_data(1, user_session_key, sizeof(user_session_key)); d_printf("expected:\n"); dump_data(1, 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; DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB lm_response = data_blob(NULL, 0); char *password; char *dospw; void *unicodepw; uint8_t user_session_key[16]; uint8_t lm_key[16]; uint8_t lm_hash[16]; static const uint8_t zeros[8]; DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros)); bool lm_good = E_deshash(samlogon_state->password, lm_hash); ZERO_STRUCT(user_session_key); if ((push_ucs2_talloc(samlogon_state->mem_ctx, samlogon_state->iconv_convenience, &unicodepw, samlogon_state->password)) == -1) { DEBUG(0, ("push_ucs2_allocate failed!\n")); exit(1); } 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); if ((convert_string_talloc(samlogon_state->mem_ctx, samlogon_state->iconv_convenience, CH_UNIX, CH_DOS, password, strlen(password)+1, (void**)&dospw)) == -1) { DEBUG(0, ("convert_string_talloc failed!\n")); exit(1); } lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw)); nt_status = check_samlogon(samlogon_state, break_which, samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED, &chall, &lm_response, &nt_response, lm_key, user_session_key, error_string); if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { /* for 'old' passwords, we allow the server to be OK or wrong password */ if (samlogon_state->old_password) { return true; } /* for 'long' passwords, the LM password is invalid */ if (break_which == NO_NT && !lm_good) { return true; } return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) { return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT)); } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { SAFE_FREE(*error_string); asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); return false; } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { return true; } else if (!NT_STATUS_IS_OK(nt_status)) { return false; } if (break_which == NO_NT && !lm_good) { *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!"); return false; } return true;}static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_plaintext(samlogon_state, BREAK_NONE, error_string);}static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_plaintext(samlogon_state, BREAK_LM, error_string);}static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state, char **error_string) { return test_plaintext(samlogon_state, BREAK_NT, error_string);}static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state, char **error_string) { return test_plaintext(samlogon_state, NO_LM, error_string);}static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state, char **error_string) { return test_plaintext(samlogon_state, NO_NT, error_string);}/* Tests: - LM only - NT and LM - NT - NT in LM field - NT in both fields - NTLMv2 - NTLMv2 and LMv2 - LMv2 - plaintext tests (in challenge-response fields) check we get the correct session key in each case check what values we get for the LM session key */static const struct ntlm_tests { bool (*fn)(struct samlogon_state *, char **); const char *name; bool expect_fail;} test_table[] = { {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},#if 0 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},#endif {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}, {test_ntlmv2, "NTLMv2", false}, {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false}, {test_lmv2, "LMv2", false}, {test_lmv2_no_dom, "LMv2 (no domain)", false}, {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false}, {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false}, {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},#if 0 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},#endif {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false}, {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", 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_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false}, {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false}, {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false}, {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false}, {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false}, {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false}, {test_plaintext_none_broken, "Plaintext", false}, {test_plaintext_lm_broken, "Plaintext LM broken", false}, {test_plaintext_nt_broken, "Plaintext NT broken", false}, {test_plaintext_nt_only, "Plaintext NT only", false}, {test_plaintext_lm_only, "Plaintext LM only", false}, {NULL, NULL}};/* try a netlogon SamLogon*/static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct torture_context *tctx, struct creds_CredentialState *creds, const char *comment, const char *account_domain, const char *account_name, const char *plain_pass, uint32_t parameter_control, NTSTATUS expected_error, bool old_password, int n_subtests){ TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context"); int i, v, l, f; bool ret = true; int validation_levels[] = {2,3,6}; int logon_levels[] = { 2, 6 }; int function_levels[] = { NDR_NETR_LOGONSAMLOGON, NDR_NETR_LOGONSAMLOGONEX, NDR_NETR_LOGONSAMLOGONWITHFLAGS }; struct samlogon_state samlogon_state; d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n"); samlogon_state.comment = comment; samlogon_state.account_name = account_name; samlogon_state.account_domain = account_domain; samlogon_state.password = plain_pass; samlogon_state.p = p; samlogon_state.creds = creds; samlogon_state.expected_error = expected_error; samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8); samlogon_state.parameter_control = parameter_control; samlogon_state.old_password = old_password; samlogon_state.iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); generate_random_buffer(samlogon_state.chall.data, 8); samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME; samlogon_state.r_flags.in.credential = &samlogon_state.auth; samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2; samlogon_state.r_flags.in.flags = 0; samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME; samlogon_state.r_ex.in.flags = 0; samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); samlogon_state.r.in.computer_name = TEST_MACHINE_NAME; samlogon_state.r.in.credential = &samlogon_state.auth; samlogon_state.r.in.return_authenticator = &samlogon_state.auth2; for (f=0;f<ARRAY_SIZE(function_levels);f++) { for (i=0; test_table[i].fn; i++) { if (n_subtests && (i > n_subtests)) { continue; } for (v=0;v<ARRAY_SIZE(validation_levels);v++) { for (l=0;l<ARRAY_SIZE(logon_levels);l++) { char *error_string = NULL; TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop"); samlogon_state.mem_ctx = tmp_ctx; samlogon_state.function_level = function_levels[f]; samlogon_state.r.in.validation_level = validation_levels[v]; samlogon_state.r.in.logon_level = logon_levels[l]; samlogon_state.r_ex.in.validation_level = validation_levels[v]; samlogon_state.r_ex.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]; if (!test_table[i].fn(&samlogon_state, &error_string)) { d_printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n", samlogon_state.comment, samlogon_state.account_domain, samlogon_state.account_name, test_table[i].name, validation_levels[v], logon_levels[l], function_levels[f]); if (test_table[i].expect_fail) { d_printf(" failed (expected, test incomplete): %s\n", error_string); } else { d_printf(" failed: %s\n", error_string);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?