X-Git-Url: http://git.samba.org/?a=blobdiff_plain;ds=sidebyside;f=source4%2Ftorture%2Frpc%2Fsamlogon.c;h=bd85c229ac8e66b4d830076f8694b8577620b525;hb=563cc67ac65c2061971c4b02ac7037e00f1f9ae8;hp=338a168b5c9232ee0f0b1d2002b367f123113145;hpb=aecd9dd19573b2b27a301d3aca2ed201b9c3b8ce;p=samba.git diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index 338a168b5c9..bd85c229ac8 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. test suite for netlogon SamLogon operations @@ -6,17 +6,17 @@ Copyright (C) Andrew Tridgell 2003 Copyright (C) Andrew Bartlett 2003-2004 Copyright (C) Tim Potter 2003 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -27,8 +27,9 @@ #include "librpc/gen_ndr/ndr_samr_c.h" #include "../lib/crypto/crypto.h" #include "lib/cmdline/popt_common.h" -#include "torture/rpc/rpc.h" +#include "torture/rpc/torture_rpc.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/schannel.h" #include "libcli/auth/libcli_auth.h" #include "param/param.h" @@ -48,6 +49,7 @@ enum ntlm_break { struct samlogon_state { TALLOC_CTX *mem_ctx; + struct torture_context *tctx; const char *comment; const char *account_name; const char *account_domain; @@ -65,21 +67,20 @@ struct samlogon_state { NTSTATUS expected_error; bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */ DATA_BLOB chall; - struct smb_iconv_convenience *iconv_convenience; }; -/* +/* Authenticate a user with a challenge/response, checking session key and valid authentication types */ -static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, +static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, enum ntlm_break break_which, uint32_t parameter_control, - DATA_BLOB *chall, - DATA_BLOB *lm_response, - DATA_BLOB *nt_response, - uint8_t lm_key[8], - uint8_t user_session_key[16], + DATA_BLOB *chall, + DATA_BLOB *lm_response, + DATA_BLOB *nt_response, + uint8_t lm_key[8], + uint8_t user_session_key[16], char **error_string) { NTSTATUS status; @@ -89,20 +90,20 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, struct netr_NetworkInfo ninfo; struct netr_SamBaseInfo *base = NULL; uint16_t validation_level = 0; - + samlogon_state->r.in.logon->network = &ninfo; samlogon_state->r_ex.in.logon->network = &ninfo; samlogon_state->r_flags.in.logon->network = &ninfo; - + ninfo.identity_info.domain_name.string = samlogon_state->account_domain; ninfo.identity_info.parameter_control = parameter_control; ninfo.identity_info.logon_id_low = 0; ninfo.identity_info.logon_id_high = 0; ninfo.identity_info.account_name.string = samlogon_state->account_name; ninfo.identity_info.workstation.string = TEST_MACHINE_NAME; - + memcpy(ninfo.challenge, chall->data, 8); - + switch (break_which) { case BREAK_NONE: break; @@ -131,7 +132,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, data_blob_free(nt_response); break; } - + if (nt_response) { ninfo.nt.data = nt_response->data; ninfo.nt.length = nt_response->length; @@ -139,7 +140,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, ninfo.nt.data = NULL; ninfo.nt.length = 0; } - + if (lm_response) { ninfo.lm.data = lm_response->data; ninfo.lm.length = lm_response->length; @@ -147,29 +148,37 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, ninfo.lm.data = NULL; ninfo.lm.length = 0; } - + switch (samlogon_state->function_level) { - case NDR_NETR_LOGONSAMLOGON: + case NDR_NETR_LOGONSAMLOGON: ZERO_STRUCT(samlogon_state->auth2); netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); r->out.return_authenticator = NULL; status = dcerpc_netr_LogonSamLogon_r(samlogon_state->p->binding_handle, samlogon_state->mem_ctx, r); - if (!r->out.return_authenticator || - !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) { - d_printf("Credential chaining failed\n"); - } if (!NT_STATUS_IS_OK(status)) { if (error_string) { *error_string = strdup(nt_errstr(status)); } return status; } + if (!r->out.return_authenticator || + !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) { + torture_comment(samlogon_state->tctx, "Credential chaining failed\n"); + } + if (!NT_STATUS_IS_OK(r->out.result)) { + if (error_string) { + *error_string = strdup(nt_errstr(r->out.result)); + } + return r->out.result; + } validation_level = r->in.validation_level; - netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r->out.validation); + netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, + validation_level, + r->out.validation); switch (validation_level) { case 2: @@ -183,7 +192,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, break; } break; - case NDR_NETR_LOGONSAMLOGONEX: + case NDR_NETR_LOGONSAMLOGONEX: status = dcerpc_netr_LogonSamLogonEx_r(samlogon_state->p->binding_handle, samlogon_state->mem_ctx, r_ex); if (!NT_STATUS_IS_OK(status)) { @@ -192,10 +201,18 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, } return status; } + if (!NT_STATUS_IS_OK(r_ex->out.result)) { + if (error_string) { + *error_string = strdup(nt_errstr(r_ex->out.result)); + } + return r_ex->out.result; + } validation_level = r_ex->in.validation_level; - netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_ex->out.validation); + netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, + validation_level, + r_ex->out.validation); switch (validation_level) { case 2: @@ -209,27 +226,35 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, break; } break; - case NDR_NETR_LOGONSAMLOGONWITHFLAGS: + case NDR_NETR_LOGONSAMLOGONWITHFLAGS: ZERO_STRUCT(samlogon_state->auth2); netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); r_flags->out.return_authenticator = NULL; status = dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state->p->binding_handle, samlogon_state->mem_ctx, r_flags); - if (!r_flags->out.return_authenticator || - !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) { - d_printf("Credential chaining failed\n"); - } if (!NT_STATUS_IS_OK(status)) { if (error_string) { *error_string = strdup(nt_errstr(status)); } return status; } - + if (!r_flags->out.return_authenticator || + !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) { + torture_comment(samlogon_state->tctx, "Credential chaining failed\n"); + } + if (!NT_STATUS_IS_OK(r_flags->out.result)) { + if (error_string) { + *error_string = strdup(nt_errstr(r_flags->out.result)); + } + return r_flags->out.result; + } + validation_level = r_flags->in.validation_level; - netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_flags->out.validation); + netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds, + validation_level, + r_flags->out.validation); switch (validation_level) { case 2: @@ -247,9 +272,9 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, /* can't happen */ return NT_STATUS_INVALID_PARAMETER; } - + if (!base) { - d_printf("No user info returned from 'successful' SamLogon*() call!\n"); + torture_comment(samlogon_state->tctx, "No user info returned from 'successful' SamLogon*() call!\n"); return NT_STATUS_INVALID_PARAMETER; } @@ -259,16 +284,16 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, if (lm_key) { memcpy(lm_key, base->LMSessKey.key, 8); } - + return status; -} +} -/* +/* * Test the normal 'LM and NTLM' combination */ -static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) +static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) { bool pass = true; bool lm_good; @@ -281,7 +306,7 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm uint8_t user_session_key[16]; uint8_t lm_hash[16]; uint8_t nt_hash[16]; - + ZERO_STRUCT(lm_key); ZERO_STRUCT(user_session_key); @@ -289,9 +314,9 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm if (!lm_good) { ZERO_STRUCT(lm_hash); } else { - E_deshash(samlogon_state->password, lm_hash); + E_deshash(samlogon_state->password, lm_hash); } - + SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); E_md4hash(samlogon_state->password, nt_hash); @@ -303,10 +328,10 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm &samlogon_state->chall, &lm_response, &nt_response, - lm_key, + lm_key, user_session_key, error_string); - + data_blob_free(&lm_response); if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { @@ -336,12 +361,12 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm return false; } - if (memcmp(lm_hash, lm_key, + if (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { - d_printf("LM Key does not match expectations!\n"); - d_printf("lm_key:\n"); + torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_hash, 8); pass = false; } @@ -352,24 +377,24 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm uint8_t lm_key_expected[16]; memcpy(lm_key_expected, lm_hash, 8); memset(lm_key_expected+8, '\0', 8); - if (memcmp(lm_key_expected, user_session_key, + if (memcmp(lm_key_expected, user_session_key, 16) != 0) { *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, sizeof(user_session_key)); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_key_expected, sizeof(lm_key_expected)); pass = false; } break; } default: - if (memcmp(session_key.data, user_session_key, + if (memcmp(session_key.data, user_session_key, sizeof(user_session_key)) != 0) { *error_string = strdup("NT Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, session_key.data, session_key.length); pass = false; } @@ -377,30 +402,30 @@ static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm return pass; } -/* +/* * Test LM authentication, no NT response supplied */ -static bool test_lm(struct samlogon_state *samlogon_state, char **error_string) +static bool test_lm(struct samlogon_state *samlogon_state, char **error_string) { return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string); } -/* +/* * Test the NTLM response only, no LM. */ -static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string) +static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string) { return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string); } -/* +/* * Test the NTLM response only, but in the LM field. */ -static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) +static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) { bool lm_good; bool pass = true; @@ -412,17 +437,17 @@ static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_ uint8_t lm_hash[16]; uint8_t user_session_key[16]; uint8_t nt_hash[16]; - + ZERO_STRUCT(lm_key); ZERO_STRUCT(user_session_key); - SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, + SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); E_md4hash(samlogon_state->password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, + SMBsesskeygen_ntv1(nt_hash, session_key.data); - lm_good = E_deshash(samlogon_state->password, lm_hash); + lm_good = E_deshash(samlogon_state->password, lm_hash); if (!lm_good) { ZERO_STRUCT(lm_hash); } @@ -432,10 +457,10 @@ static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_ &samlogon_state->chall, &nt_response, NULL, - lm_key, + 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) { @@ -453,23 +478,23 @@ static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_ } if (lm_good) { - if (memcmp(lm_hash, lm_key, + if (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { - d_printf("LM Key does not match expectations!\n"); - d_printf("lm_key:\n"); + torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_hash, 8); pass = false; } #if 0 } else { - if (memcmp(session_key.data, lm_key, + if (memcmp(session_key.data, lm_key, sizeof(lm_key)) != 0) { - d_printf("LM Key does not match expectations (first 8 session key)!\n"); - d_printf("lm_key:\n"); + torture_comment(samlogon_state->tctx, "LM Key does not match expectations (first 8 session key)!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, session_key.data, 8); pass = false; } @@ -479,12 +504,12 @@ static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_ uint8_t lm_key_expected[16]; memcpy(lm_key_expected, lm_hash, 8); memset(lm_key_expected+8, '\0', 8); - if (memcmp(lm_key_expected, user_session_key, + if (memcmp(lm_key_expected, user_session_key, 16) != 0) { - d_printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be first-8 LM hash)!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, sizeof(user_session_key)); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_key_expected, sizeof(lm_key_expected)); pass = false; } @@ -492,11 +517,11 @@ static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_ return pass; } -/* +/* * Test the NTLM response only, but in the both the NT and LM fields. */ -static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) +static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) { bool pass = true; bool lm_good; @@ -508,17 +533,17 @@ static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **erro uint8_t lm_hash[16]; uint8_t user_session_key[16]; uint8_t nt_hash[16]; - + ZERO_STRUCT(lm_key); ZERO_STRUCT(user_session_key); - SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, + SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); E_md4hash(samlogon_state->password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, + SMBsesskeygen_ntv1(nt_hash, session_key.data); - lm_good = E_deshash(samlogon_state->password, lm_hash); + lm_good = E_deshash(samlogon_state->password, lm_hash); if (!lm_good) { ZERO_STRUCT(lm_hash); } @@ -527,12 +552,12 @@ static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **erro BREAK_NONE, samlogon_state->parameter_control, &samlogon_state->chall, - NULL, + NULL, &nt_response, - lm_key, + 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) { @@ -553,21 +578,21 @@ static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **erro return false; } - if (memcmp(lm_hash, lm_key, + if (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { - d_printf("LM Key does not match expectations!\n"); - d_printf("lm_key:\n"); + torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_hash, 8); pass = false; } - if (memcmp(session_key.data, user_session_key, + if (memcmp(session_key.data, user_session_key, sizeof(user_session_key)) != 0) { - d_printf("NT Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, session_key.data, session_key.length); pass = false; } @@ -576,7 +601,7 @@ static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **erro return pass; } -/* +/* * Test the NTLMv2 and LMv2 responses */ @@ -585,10 +610,10 @@ enum ntlmv2_domain { NO_DOMAIN }; -static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, - enum ntlm_break break_which, - enum ntlmv2_domain ntlmv2_domain, - char **error_string) +static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, + enum ntlm_break break_which, + enum ntlmv2_domain ntlmv2_domain, + char **error_string) { bool pass = true; NTSTATUS nt_status; @@ -603,25 +628,25 @@ static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, ZERO_STRUCT(lm_session_key); ZERO_STRUCT(user_session_key); - + switch (ntlmv2_domain) { case UPPER_DOMAIN: - if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, - samlogon_state->account_name, samlogon_state->account_domain, + if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, + samlogon_state->account_name, samlogon_state->account_domain, samlogon_state->password, &samlogon_state->chall, &names_blob, - &lmv2_response, &ntlmv2_response, + &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return false; } break; case NO_DOMAIN: - if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, + if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, samlogon_state->account_name, "", samlogon_state->password, &samlogon_state->chall, &names_blob, - &lmv2_response, &ntlmv2_response, + &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return false; @@ -636,10 +661,10 @@ static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, &samlogon_state->chall, &lmv2_response, &ntlmv2_response, - lm_session_key, + lm_session_key, user_session_key, error_string); - + data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); @@ -667,59 +692,59 @@ static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, case NO_NT: if (memcmp(lmv2_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { - d_printf("USER (LMv2) Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length); pass = false; } - if (memcmp(lmv2_session_key.data, lm_session_key, + if (memcmp(lmv2_session_key.data, lm_session_key, sizeof(lm_session_key)) != 0) { - d_printf("LM (LMv2) Session Key does not match expectations!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lmv2_session_key.data, 8); pass = false; } break; default: - if (memcmp(ntlmv2_session_key.data, user_session_key, + if (memcmp(ntlmv2_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { if (memcmp(lmv2_session_key.data, user_session_key, sizeof(user_session_key)) == 0) { - d_printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); pass = false; - + } else { - d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); pass = false; } } - if (memcmp(ntlmv2_session_key.data, lm_session_key, + if (memcmp(ntlmv2_session_key.data, lm_session_key, sizeof(lm_session_key)) != 0) { if (memcmp(lmv2_session_key.data, lm_session_key, sizeof(lm_session_key)) == 0) { - d_printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlmv2_session_key.data, 8); pass = false; } else { - d_printf("LM (NTLMv2) Session Key does not match expectations!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlmv2_session_key.data, 8); pass = false; } @@ -729,14 +754,14 @@ static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, return pass; } -/* +/* * Test the NTLM and LMv2 responses */ -static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, - enum ntlm_break break_which, - enum ntlmv2_domain ntlmv2_domain, - char **error_string) +static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, + enum ntlm_break break_which, + enum ntlmv2_domain ntlmv2_domain, + char **error_string) { bool pass = true; NTSTATUS nt_status; @@ -755,13 +780,13 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, uint8_t user_session_key[16]; uint8_t nt_hash[16]; - SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, + SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, ntlm_response.data); E_md4hash(samlogon_state->password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, + SMBsesskeygen_ntv1(nt_hash, ntlm_session_key.data); - lm_good = E_deshash(samlogon_state->password, lm_hash); + lm_good = E_deshash(samlogon_state->password, lm_hash); if (!lm_good) { ZERO_STRUCT(lm_hash); } @@ -772,11 +797,11 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, switch (ntlmv2_domain) { case UPPER_DOMAIN: /* TODO - test with various domain cases, and without domain */ - if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, - samlogon_state->account_name, samlogon_state->account_domain, + if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, + samlogon_state->account_name, samlogon_state->account_domain, samlogon_state->password, &samlogon_state->chall, &names_blob, - &lmv2_response, &ntlmv2_response, + &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return false; @@ -784,11 +809,11 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, break; case NO_DOMAIN: /* TODO - test with various domain cases, and without domain */ - if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, + if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, samlogon_state->account_name, "", samlogon_state->password, &samlogon_state->chall, &names_blob, - &lmv2_response, &ntlmv2_response, + &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return false; @@ -804,10 +829,10 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, &samlogon_state->chall, &lmv2_response, &ntlm_response, - lm_session_key, + lm_session_key, user_session_key, error_string); - + data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); @@ -832,74 +857,74 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, switch (break_which) { case NO_NT: - if (memcmp(lmv2_session_key.data, user_session_key, + if (memcmp(lmv2_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { - d_printf("USER (LMv2) Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length); pass = false; } - if (memcmp(lmv2_session_key.data, lm_session_key, + if (memcmp(lmv2_session_key.data, lm_session_key, sizeof(lm_session_key)) != 0) { - d_printf("LM (LMv2) Session Key does not match expectations!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "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, + if (memcmp(ntlm_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { - d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlm_session_key.data, ntlm_session_key.length); pass = false; } if (lm_good) { - if (memcmp(lm_hash, lm_session_key, + if (memcmp(lm_hash, lm_session_key, sizeof(lm_session_key)) != 0) { - d_printf("LM Session Key does not match expectations!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_hash, 8); pass = false; } } else { static const uint8_t zeros[8]; - if (memcmp(zeros, lm_session_key, + if (memcmp(zeros, lm_session_key, sizeof(lm_session_key)) != 0) { - d_printf("LM Session Key does not match expectations (zeros)!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, zeros, 8); pass = false; } } break; default: - if (memcmp(ntlm_session_key.data, user_session_key, + if (memcmp(ntlm_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { - d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); - d_printf("user_session_key:\n"); + torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, 16); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlm_session_key.data, ntlm_session_key.length); pass = false; } - if (memcmp(ntlm_session_key.data, lm_session_key, + if (memcmp(ntlm_session_key.data, lm_session_key, sizeof(lm_session_key)) != 0) { - d_printf("LM (NTLMv2) Session Key does not match expectations!\n"); - d_printf("lm_session_key:\n"); + torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_session_key:\n"); dump_data(1, lm_session_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, ntlm_session_key.data, 8); pass = false; } @@ -908,132 +933,132 @@ static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, return pass; } -/* +/* * Test the NTLMv2 and LMv2 responses */ -static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) +static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string); } #if 0 -static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) +static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) { return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string); } #endif -/* +/* * Test the LMv2 response only */ -static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string) +static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string) { 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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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 0 -static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) +static 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); } #endif -static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **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, UPPER_DOMAIN, error_string); } -static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **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) +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) +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) +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) +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) +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) +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 @@ -1041,7 +1066,7 @@ static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state * (NETLOGON is the wrong place). */ -static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) +static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) { bool pass = true; NTSTATUS nt_status; @@ -1057,22 +1082,22 @@ static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_strin 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, + SMBsesskeygen_ntv1((const uint8_t *)nt_hash, nt_key); SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); @@ -1091,10 +1116,10 @@ static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_strin &samlogon_state->chall, &lm_response, &nt_response, - lm_key, + 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) { @@ -1112,32 +1137,32 @@ static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_strin } if (lm_good) { - if (memcmp(lm_hash, lm_key, + if (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { - d_printf("LM Key does not match expectations!\n"); - d_printf("lm_key:\n"); + torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, lm_hash, 8); pass = false; } } else { static const uint8_t zeros[8]; - if (memcmp(zeros, lm_key, + 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"); + torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n"); + torture_comment(samlogon_state->tctx, "lm_key:\n"); dump_data(1, lm_key, 8); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "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"); + torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be NT Key)!\n"); + torture_comment(samlogon_state->tctx, "user_session_key:\n"); dump_data(1, user_session_key, sizeof(user_session_key)); - d_printf("expected:\n"); + torture_comment(samlogon_state->tctx, "expected:\n"); dump_data(1, nt_key, sizeof(nt_key)); pass = false; } @@ -1152,18 +1177,18 @@ static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea char *password; char *dospw; smb_ucs2_t *unicodepw; - + size_t converted_size = 0; 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); + bool lm_good = E_deshash(samlogon_state->password, lm_hash); ZERO_STRUCT(user_session_key); - - if (!push_ucs2_talloc(samlogon_state->mem_ctx, - &unicodepw, samlogon_state->password, NULL)) { + + if (!push_ucs2_talloc(samlogon_state->mem_ctx, + &unicodepw, samlogon_state->password, &converted_size)) { DEBUG(0, ("push_ucs2_allocate failed!\n")); exit(1); } @@ -1172,11 +1197,10 @@ static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password); - if (!convert_string_talloc_convenience(samlogon_state->mem_ctx, - samlogon_state->iconv_convenience, - CH_UNIX, CH_DOS, - password, strlen(password)+1, - (void**)&dospw, NULL, false)) { + if (!convert_string_talloc(samlogon_state->mem_ctx, + CH_UNIX, CH_DOS, + password, strlen(password)+1, + (void**)&dospw, &converted_size)) { DEBUG(0, ("convert_string_talloc failed!\n")); exit(1); } @@ -1189,10 +1213,10 @@ static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea &chall, &lm_response, &nt_response, - lm_key, + 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) { @@ -1223,36 +1247,36 @@ static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea return true; } -static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state, +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, +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, +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, +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, +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 and LM - NT - NT in LM field - NT in both fields @@ -1260,10 +1284,10 @@ static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state, - 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 { @@ -1313,11 +1337,11 @@ static const struct ntlm_tests { /* try a netlogon SamLogon */ -static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, +static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct torture_context *tctx, - struct netlogon_creds_CredentialState *creds, + struct netlogon_creds_CredentialState *creds, const char *comment, - const char *account_domain, const char *account_name, + 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) @@ -1326,8 +1350,8 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, int i, v, l, f; bool ret = true; int validation_levels[] = {2,3,6}; - int logon_levels[] = { 2, 6 }; - int function_levels[] = { + int logon_levels[] = { NetlogonNetworkInformation, NetlogonNetworkTransitiveInformation }; + int function_levels[] = { NDR_NETR_LOGONSAMLOGON, NDR_NETR_LOGONSAMLOGONEX, NDR_NETR_LOGONSAMLOGONWITHFLAGS }; @@ -1340,21 +1364,21 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, ZERO_STRUCT(logon); - d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n"); - + torture_comment(tctx, "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.workgroup = lp_workgroup(tctx->lp_ctx); - samlogon_state.netbios_name = lp_netbios_name(tctx->lp_ctx); + samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx); + samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx); 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); + samlogon_state.tctx = tctx; generate_random_buffer(samlogon_state.chall.data, 8); samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); @@ -1402,17 +1426,17 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 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", + torture_comment(tctx, "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], + 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); + torture_comment(tctx, " failed (expected, test incomplete): %s\n", error_string); } else { - d_printf(" failed: %s\n", error_string); + torture_comment(tctx, " failed: %s\n", error_string); ret = false; } SAFE_FREE(error_string); @@ -1430,15 +1454,17 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, test an ADS style interactive domain logon */ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds, + struct torture_context *tctx, + struct netlogon_creds_CredentialState *creds, const char *comment, const char *workstation_name, const char *account_domain, const char *account_name, - const char *plain_pass, uint32_t parameter_control, + const char *plain_pass, uint32_t parameter_control, NTSTATUS expected_error) { NTSTATUS status; TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context"); + bool ret = true; struct netr_LogonSamLogonWithFlags r; struct netr_Authenticator a, ra; struct netr_PasswordInfo pinfo; @@ -1464,7 +1490,7 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.computer_name = TEST_MACHINE_NAME; r.in.credential = &a; r.in.return_authenticator = &ra; - r.in.logon_level = 5; + r.in.logon_level = NetlogonInteractiveTransitiveInformation; r.in.logon = &logon; r.in.validation_level = 6; r.in.flags = &flags; @@ -1492,28 +1518,127 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, netlogon_creds_des_encrypt(creds, &pinfo.ntpassword); } - d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment); + torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment); + + torture_assert_ntstatus_ok_goto(tctx, + dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r), + ret, failed, + talloc_asprintf(tctx, "%s: netr_LogonSamLogonWithFlags - %s\n", + __location__, nt_errstr(status))); - status = dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r); - if (!r.out.return_authenticator - || !netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { - d_printf("Credential chaining failed\n"); + if (!r.out.return_authenticator) { talloc_free(fn_ctx); - return false; + torture_fail(tctx, "no authenticator returned"); } + torture_assert_goto(tctx, + netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), + ret, failed, + "Credential chaining failed\n"); + + torture_assert_ntstatus_equal(tctx, r.out.result, expected_error, + talloc_asprintf(tctx, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", + account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result))); + + ret = true; + failed: talloc_free(fn_ctx); - if (!NT_STATUS_EQUAL(expected_error, status)) { - d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", - account_domain, account_name, nt_errstr(expected_error), nt_errstr(status)); + return ret; +} + +/* This sets and resets the "minPwdAge" (in order to allow immediate user + * password changes). The behaviour is controlled by the "set" boolean. */ +static bool handle_minPwdAge(struct torture_context *torture, + TALLOC_CTX *mem_ctx, bool set) +{ + struct dcerpc_pipe *p; + struct policy_handle connect_handle, domain_handle; + struct samr_Connect c_r; + struct samr_LookupDomain ld_r; + struct samr_OpenDomain od_r; + struct samr_QueryDomainInfo qdi_r; + struct samr_SetDomainInfo sdi_r; + struct samr_Close cl_r; + struct lsa_String domName; + struct dom_sid *domSid = NULL; + union samr_DomainInfo *domInfo = NULL; + static int64_t old_minPwdAge = 0; + NTSTATUS status; + + status = torture_rpc_connection(torture, &p, &ndr_table_samr); + if (!NT_STATUS_IS_OK(status)) { return false; } - return true; -} + c_r.in.system_name = 0; + c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + c_r.out.connect_handle = &connect_handle; + + torture_assert_ntstatus_ok(torture, + dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r), + "Connect failed"); + torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed"); + + ld_r.in.connect_handle = &connect_handle; + ld_r.in.domain_name = &domName; + ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx); + ld_r.out.sid = &domSid; + + torture_assert_ntstatus_ok(torture, + dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r), + "LookupDomain failed"); + torture_assert_ntstatus_ok(torture, ld_r.out.result, + "LookupDomain failed"); + + od_r.in.connect_handle = &connect_handle; + od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + od_r.in.sid = *ld_r.out.sid; + od_r.out.domain_handle = &domain_handle; + + torture_assert_ntstatus_ok(torture, + dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r), + "OpenDomain failed"); + torture_assert_ntstatus_ok(torture, od_r.out.result, + "OpenDomain failed"); + + qdi_r.in.domain_handle = &domain_handle; + qdi_r.in.level = DomainPasswordInformation; + qdi_r.out.info = &domInfo; + + torture_assert_ntstatus_ok(torture, + dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r), + "QueryDomainInfo failed"); + torture_assert_ntstatus_ok(torture, qdi_r.out.result, + "QueryDomainInfo failed"); + + if (set) { + old_minPwdAge = domInfo->info1.min_password_age; + domInfo->info1.min_password_age = 0; + } else { + domInfo->info1.min_password_age = old_minPwdAge; + } + + sdi_r.in.domain_handle = &domain_handle; + sdi_r.in.level = DomainPasswordInformation; + sdi_r.in.info = domInfo; + + torture_assert_ntstatus_ok(torture, + dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r), + "SetDomainInfo failed"); + torture_assert_ntstatus_ok(torture, sdi_r.out.result, + "SetDomainInfo failed"); + + cl_r.in.handle = &connect_handle; + cl_r.out.handle = &connect_handle; + torture_assert_ntstatus_ok(torture, + dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r), + "Close failed"); + torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed"); + return true; +} bool torture_rpc_samlogon(struct torture_context *torture) { @@ -1538,52 +1663,47 @@ bool torture_rpc_samlogon(struct torture_context *torture) NETLOGON_NEG_AUTH2_FLAGS, NETLOGON_NEG_ARCFOUR, NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT, - NETLOGON_NEG_AUTH2_ADS_FLAGS, - 0 /* yes, this is a valid flag, causes the use of DES */ + NETLOGON_NEG_AUTH2_ADS_FLAGS, + 0 /* yes, this is a valid flag, causes the use of DES */ }; struct netlogon_creds_CredentialState *creds; struct dcerpc_pipe *tmp_p = NULL; + torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true), + "handle_minPwdAge error!"); + test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME); /* We only need to join as a workstation here, and in future, * if we wish to test against trusted domains, we must be a * workstation here */ - join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, + join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, &machine_credentials); - if (!join_ctx) { - d_printf("Failed to join as Workstation\n"); - return false; - } + torture_assert(torture, join_ctx, "Failed to join as Workstation\n"); - userdomain = torture_setting_string(torture, "userdomain", lp_workgroup(torture->lp_ctx)); + userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx)); user_ctx = torture_create_testuser(torture, TEST_USER_NAME, userdomain, - ACB_NORMAL, + ACB_NORMAL, (const char **)&user_password); - if (!user_ctx) { - d_printf("Failed to create a test user\n"); - return false; - } + torture_assert(torture, user_ctx, "Failed to create a test user\n"); old_user_password = user_password; tmp_p = torture_join_samr_pipe(user_ctx); test_ChangePasswordUser3(tmp_p, torture, - TEST_USER_NAME, 16 /* > 14 */, &user_password, + TEST_USER_NAME, 16 /* > 14 */, &user_password, NULL, 0, false); user_ctx_wrong_wks = torture_create_testuser(torture, TEST_USER_NAME_WRONG_WKS, userdomain, - ACB_NORMAL, + ACB_NORMAL, (const char **)&user_password_wrong_wks); - if (!user_ctx_wrong_wks) { - d_printf("Failed to create a test user (wrong workstation test)\n"); - return false; - } + torture_assert(torture, user_ctx_wrong_wks, + "Failed to create a test user (wrong workstation test)\n"); ZERO_STRUCT(u); s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks); @@ -1595,21 +1715,18 @@ bool torture_rpc_samlogon(struct torture_context *torture) tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks); status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s); - if (!NT_STATUS_IS_OK(status)) { - printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)); - ret = false; - goto failed; - } + torture_assert_ntstatus_ok_goto(torture, status, ret, failed, + talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status))); + torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed, + talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result))); user_ctx_wrong_time = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME, userdomain, - ACB_NORMAL, + ACB_NORMAL, (const char **)&user_password_wrong_time); - if (!user_ctx_wrong_time) { - d_printf("Failed to create a test user (wrong workstation test)\n"); - return false; - } + torture_assert(torture, user_ctx_wrong_time, + "Failed to create a test user (wrong workstation test)\n"); ZERO_STRUCT(u); s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time); @@ -1623,11 +1740,10 @@ bool torture_rpc_samlogon(struct torture_context *torture) tmp_p = torture_join_samr_pipe(user_ctx_wrong_time); status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s); - if (!NT_STATUS_IS_OK(status)) { - printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)); - ret = false; - goto failed; - } + torture_assert_ntstatus_ok_goto(torture, status, ret, failed, + talloc_asprintf(torture, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status))); + torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed, + talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result))); status = torture_rpc_binding(torture, &b); if (!NT_STATUS_IS_OK(status)) { @@ -1641,15 +1757,12 @@ bool torture_rpc_samlogon(struct torture_context *torture) b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128; - status = dcerpc_pipe_connect_b(mem_ctx, &p, b, + status = dcerpc_pipe_connect_b(mem_ctx, &p, b, &ndr_table_netlogon, machine_credentials, torture->ev, torture->lp_ctx); - if (!NT_STATUS_IS_OK(status)) { - d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status)); - ret = false; - goto failed; - } + torture_assert_ntstatus_ok_goto(torture, status, ret, failed, + talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status))); status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { @@ -1658,7 +1771,7 @@ bool torture_rpc_samlogon(struct torture_context *torture) } { - + struct { const char *comment; const char *domain; @@ -1691,8 +1804,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) { .comment = "user@domain", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", cli_credentials_get_username(cmdline_credentials), cli_credentials_get_domain(cmdline_credentials) ), @@ -1704,8 +1817,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) { .comment = "user@realm", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", cli_credentials_get_username(cmdline_credentials), cli_credentials_get_realm(cmdline_credentials) ), @@ -1744,11 +1857,11 @@ bool torture_rpc_samlogon(struct torture_context *torture) { .comment = "machine user@domain", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", cli_credentials_get_username(machine_credentials), cli_credentials_get_domain(machine_credentials) - ), + ), .password = cli_credentials_get_password(machine_credentials), .network_login = false, /* works for some things, but not NTLMv2. Odd */ .expected_interactive_error = NT_STATUS_NO_SUCH_USER, @@ -1757,8 +1870,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) { .comment = "machine user@realm", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", cli_credentials_get_username(machine_credentials), cli_credentials_get_realm(machine_credentials) ), @@ -1767,7 +1880,7 @@ bool torture_rpc_samlogon(struct torture_context *torture) .expected_interactive_error = NT_STATUS_NO_SUCH_USER, .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT }, - { + { .comment = "test user (long pw): domain\\user", .domain = userdomain, .username = TEST_USER_NAME, @@ -1777,12 +1890,12 @@ bool torture_rpc_samlogon(struct torture_context *torture) .expected_network_error = NT_STATUS_OK }, { - .comment = "test user (long pw): user@realm", + .comment = "test user (long pw): user@realm", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", TEST_USER_NAME, - lp_realm(torture->lp_ctx)), + lpcfg_realm(torture->lp_ctx)), .password = user_password, .network_login = true, .expected_interactive_error = NT_STATUS_OK, @@ -1791,8 +1904,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) { .comment = "test user (long pw): user@domain", .domain = NULL, - .username = talloc_asprintf(mem_ctx, - "%s@%s", + .username = talloc_asprintf(mem_ctx, + "%s@%s", TEST_USER_NAME, userdomain), .password = user_password, @@ -1801,7 +1914,7 @@ bool torture_rpc_samlogon(struct torture_context *torture) .expected_network_error = NT_STATUS_OK }, /* Oddball, can we use the old password ? */ - { + { .comment = "test user: user\\domain OLD PASSWORD", .domain = userdomain, .username = TEST_USER_NAME, @@ -1811,8 +1924,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) .expected_network_error = NT_STATUS_OK, .old_password = true }, - { - .comment = "test user (wong workstation): domain\\user", + { + .comment = "test user (wrong workstation): domain\\user", .domain = userdomain, .username = TEST_USER_NAME_WRONG_WKS, .password = user_password_wrong_wks, @@ -1821,11 +1934,11 @@ bool torture_rpc_samlogon(struct torture_context *torture) .expected_network_error = NT_STATUS_INVALID_WORKSTATION } }; - + /* Try all the tests for different username forms */ for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) { - - if (!test_InteractiveLogon(p, mem_ctx, creds, + + if (!test_InteractiveLogon(p, mem_ctx, torture, creds, usercreds[ci].comment, TEST_MACHINE_NAME, usercreds[ci].domain, @@ -1834,10 +1947,11 @@ bool torture_rpc_samlogon(struct torture_context *torture) usercreds[ci].parameter_control, usercreds[ci].expected_interactive_error)) { ret = false; + goto failed; } - + if (usercreds[ci].network_login) { - if (!test_SamLogon(p, mem_ctx, torture, creds, + if (!test_SamLogon(p, mem_ctx, torture, creds, usercreds[ci].comment, usercreds[ci].domain, usercreds[ci].username, @@ -1847,6 +1961,7 @@ bool torture_rpc_samlogon(struct torture_context *torture) usercreds[ci].old_password, 0)) { ret = false; + goto failed; } } } @@ -1858,7 +1973,11 @@ bool torture_rpc_samlogon(struct torture_context *torture) for (i=0; i < ARRAY_SIZE(credential_flags); i++) { /* TODO: Somehow we lost setting up the different credential flags here! */ - if (!test_InteractiveLogon(p, mem_ctx, creds, + torture_comment(torture, + "Testing with flags: 0x%08x\n", + credential_flags[i]); + + if (!test_InteractiveLogon(p, mem_ctx, torture, creds, usercreds[0].comment, TEST_MACHINE_NAME, usercreds[0].domain, @@ -1867,8 +1986,9 @@ bool torture_rpc_samlogon(struct torture_context *torture) usercreds[0].parameter_control, usercreds[0].expected_interactive_error)) { ret = false; + goto failed; } - + if (usercreds[0].network_login) { if (!test_SamLogon(p, mem_ctx, torture, creds, usercreds[0].comment, @@ -1880,12 +2000,16 @@ bool torture_rpc_samlogon(struct torture_context *torture) usercreds[0].old_password, 1)) { ret = false; + goto failed; } } } } failed: + torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false), + "handle_minPwdAge error!"); + talloc_free(mem_ctx); torture_leave_domain(torture, join_ctx);