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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/ndr_samr_c.h"
#include "auth/auth.h"
#include "lib/crypto/crypto.h"
#include "lib/cmdline/popt_common.h"
#define TEST_MACHINE_NAME "samlogontest"
#define TEST_USER_NAME "samlogontestuser"
+#define TEST_USER_NAME_WRONG_WKS "samlogontest2"
+#define TEST_USER_NAME_WRONG_TIME "samlogontest3"
enum ntlm_break {
BREAK_BOTH,
}
switch (samlogon_state->function_level) {
- case DCERPC_NETR_LOGONSAMLOGON:
+ case NDR_NETR_LOGONSAMLOGON:
ZERO_STRUCT(samlogon_state->auth2);
creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
if (!r->out.return_authenticator ||
!creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
- printf("Credential chaining failed\n");
+ d_printf("Credential chaining failed\n");
}
if (!NT_STATUS_IS_OK(status)) {
if (error_string) {
break;
}
break;
- case DCERPC_NETR_LOGONSAMLOGONEX:
+ case NDR_NETR_LOGONSAMLOGONEX:
status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
if (!NT_STATUS_IS_OK(status)) {
if (error_string) {
break;
}
break;
- case DCERPC_NETR_LOGONSAMLOGONWITHFLAGS:
+ case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
ZERO_STRUCT(samlogon_state->auth2);
creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
if (!r_flags->out.return_authenticator ||
!creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
- printf("Credential chaining failed\n");
+ d_printf("Credential chaining failed\n");
}
if (!NT_STATUS_IS_OK(status)) {
if (error_string) {
}
if (!base) {
- printf("No user info returned from 'successful' SamLogon*() call!\n");
+ d_printf("No user info returned from 'successful' SamLogon*() call!\n");
return NT_STATUS_INVALID_PARAMETER;
}
if (memcmp(lm_hash, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Key does not match expectations!\n");
- printf("lm_key:\n");
+ d_printf("LM Key does not match expectations!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_hash, 8);
pass = False;
}
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");
- printf("user_session_key:\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, sizeof(user_session_key));
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_key_expected, sizeof(lm_key_expected));
pass = False;
}
if (memcmp(session_key.data, user_session_key,
sizeof(user_session_key)) != 0) {
*error_string = strdup("NT Session Key does not match expectations!\n");
- printf("user_session_key:\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, session_key.data, session_key.length);
pass = False;
}
if (lm_good) {
if (memcmp(lm_hash, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Key does not match expectations!\n");
- printf("lm_key:\n");
+ d_printf("LM Key does not match expectations!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_hash, 8);
pass = False;
}
} else {
if (memcmp(session_key.data, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Key does not match expectations (first 8 session key)!\n");
- printf("lm_key:\n");
+ d_printf("LM Key does not match expectations (first 8 session key)!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, session_key.data, 8);
pass = False;
}
memset(lm_key_expected+8, '\0', 8);
if (memcmp(lm_key_expected, user_session_key,
16) != 0) {
- printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
- printf("user_session_key:\n");
+ d_printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, sizeof(user_session_key));
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_key_expected, sizeof(lm_key_expected));
pass = False;
}
if (memcmp(lm_hash, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Key does not match expectations!\n");
- printf("lm_key:\n");
+ d_printf("LM Key does not match expectations!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_hash, 8);
pass = False;
}
if (memcmp(session_key.data, user_session_key,
sizeof(user_session_key)) != 0) {
- printf("NT Session Key does not match expectations!\n");
- printf("user_session_key:\n");
+ d_printf("NT Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, session_key.data, session_key.length);
pass = False;
}
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");
+ d_printf("USER (LMv2) Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_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");
+ d_printf("LM (LMv2) Session Key does not match expectations!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lmv2_session_key.data, 8);
pass = False;
}
sizeof(user_session_key)) != 0) {
if (memcmp(lmv2_session_key.data, user_session_key,
sizeof(user_session_key)) == 0) {
- printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
- printf("user_session_key:\n");
+ d_printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
pass = False;
} else {
- printf("USER (NTLMv2) Session Key does not match expectations!\n");
- printf("user_session_key:\n");
+ d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
pass = False;
}
sizeof(lm_session_key)) != 0) {
if (memcmp(lmv2_session_key.data, lm_session_key,
sizeof(lm_session_key)) == 0) {
- printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
- printf("user_session_key:\n");
+ d_printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
+ d_printf("user_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, ntlmv2_session_key.data, 8);
pass = False;
} else {
- printf("LM (NTLMv2) Session Key does not match expectations!\n");
- printf("lm_session_key:\n");
+ d_printf("LM (NTLMv2) Session Key does not match expectations!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, ntlmv2_session_key.data, 8);
pass = False;
}
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");
+ d_printf("USER (LMv2) Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_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");
+ d_printf("LM (LMv2) Session Key does not match expectations!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lmv2_session_key.data, 8);
pass = False;
}
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");
+ d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_printf("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,
sizeof(lm_session_key)) != 0) {
- printf("LM Session Key does not match expectations!\n");
- printf("lm_session_key:\n");
+ d_printf("LM Session Key does not match expectations!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_hash, 8);
pass = False;
}
static const uint8_t zeros[8];
if (memcmp(zeros, lm_session_key,
sizeof(lm_session_key)) != 0) {
- printf("LM Session Key does not match expectations (zeros)!\n");
- printf("lm_session_key:\n");
+ d_printf("LM Session Key does not match expectations (zeros)!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, zeros, 8);
pass = False;
}
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");
+ d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
+ d_printf("user_session_key:\n");
dump_data(1, user_session_key, 16);
- printf("expected:\n");
+ d_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");
+ d_printf("LM (NTLMv2) Session Key does not match expectations!\n");
+ d_printf("lm_session_key:\n");
dump_data(1, lm_session_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, ntlm_session_key.data, 8);
pass = False;
}
if (lm_good) {
if (memcmp(lm_hash, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Key does not match expectations!\n");
- printf("lm_key:\n");
+ d_printf("LM Key does not match expectations!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, lm_hash, 8);
pass = False;
}
static const uint8_t zeros[8];
if (memcmp(zeros, lm_key,
sizeof(lm_key)) != 0) {
- printf("LM Session Key does not match expectations (zeros)!\n");
- printf("lm_key:\n");
+ d_printf("LM Session Key does not match expectations (zeros)!\n");
+ d_printf("lm_key:\n");
dump_data(1, lm_key, 8);
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, zeros, 8);
pass = False;
}
}
if (memcmp(nt_key, user_session_key, 16) != 0) {
- printf("NT Session Key does not match expectations (should be NT Key)!\n");
- printf("user_session_key:\n");
+ 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));
- printf("expected:\n");
+ d_printf("expected:\n");
dump_data(1, nt_key, sizeof(nt_key));
pass = False;
}
int validation_levels[] = {2,3,6};
int logon_levels[] = { 2, 6 };
int function_levels[] = {
- DCERPC_NETR_LOGONSAMLOGON,
- DCERPC_NETR_LOGONSAMLOGONEX,
- DCERPC_NETR_LOGONSAMLOGONWITHFLAGS };
+ NDR_NETR_LOGONSAMLOGON,
+ NDR_NETR_LOGONSAMLOGONEX,
+ NDR_NETR_LOGONSAMLOGONWITHFLAGS };
struct samlogon_state samlogon_state;
- printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
+ d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
samlogon_state.comment = comment;
samlogon_state.account_name = account_name;
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)) {
- printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
+ 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,
logon_levels[l], function_levels[f]);
if (test_table[i].expect_fail) {
- printf(" failed (expected, test incomplete): %s\n", error_string);
+ d_printf(" failed (expected, test incomplete): %s\n", error_string);
} else {
- printf(" failed: %s\n", error_string);
+ d_printf(" failed: %s\n", error_string);
ret = False;
}
SAFE_FREE(error_string);
creds_des_encrypt(creds, &pinfo.ntpassword);
}
- printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
+ d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
if (!r.out.return_authenticator
|| !creds_client_check(creds, &r.out.return_authenticator->cred)) {
- printf("Credential chaining failed\n");
+ d_printf("Credential chaining failed\n");
talloc_free(fn_ctx);
return False;
}
talloc_free(fn_ctx);
if (!NT_STATUS_EQUAL(expected_error, status)) {
- printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
+ d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));
return False;
}
-BOOL torture_rpc_samlogon(void)
+BOOL torture_rpc_samlogon(struct torture_context *torture)
{
NTSTATUS status;
struct dcerpc_pipe *p;
struct cli_credentials *machine_credentials;
TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
BOOL ret = True;
- struct test_join *join_ctx;
- struct test_join *user_ctx;
- char *user_password;
+ struct test_join *join_ctx = NULL;
+ struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
+ char *user_password, *user_password_wrong_wks, *user_password_wrong_time;
const char *old_user_password;
char *test_machine_account;
- const char *binding = lp_parm_string(-1, "torture", "binding");
const char *userdomain;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
int i;
int ci;
join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_WSTRUST,
&machine_credentials);
if (!join_ctx) {
- printf("Failed to join as Workstation\n");
+ d_printf("Failed to join as Workstation\n");
return False;
}
- userdomain = lp_parm_string(-1, "torture", "userdomain");
- if (!userdomain) {
- userdomain = lp_workgroup();
- }
+ userdomain = torture_setting_string(torture, "userdomain", lp_workgroup());
- user_ctx = torture_create_testuser(TEST_USER_NAME,
+ user_ctx = torture_create_testuser(torture,
+ TEST_USER_NAME,
userdomain,
ACB_NORMAL,
(const char **)&user_password);
if (!user_ctx) {
- printf("Failed to join as Workstation\n");
+ d_printf("Failed to create a test user\n");
return False;
}
old_user_password = user_password;
test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), mem_ctx,
- 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,
+ (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;
+ }
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
+ s.in.info = &u;
+ s.in.level = 21;
+
+ u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
+ u.info21.workstations.string = "not" TEST_MACHINE_NAME;
- status = dcerpc_parse_binding(mem_ctx, binding, &b);
+ status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_wks), mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status));
+ ret = False;
+ goto failed;
+ }
+
+ user_ctx_wrong_time
+ = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
+ userdomain,
+ 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;
+ }
+
+ ZERO_STRUCT(u);
+ s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
+ s.in.info = &u;
+ s.in.level = 21;
+
+ u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
+ u.info21.workstations.string = TEST_MACHINE_NAME;
+ u.info21.logon_hours.units_per_week = 168;
+ u.info21.logon_hours.bits = talloc_zero_size(mem_ctx, 168);
+
+ status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_time), 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;
+ }
+
+ status = torture_rpc_binding(torture, &b);
if (!NT_STATUS_IS_OK(status)) {
- printf("Bad binding string %s\n", binding);
ret = False;
goto failed;
}
b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
- &dcerpc_table_netlogon,
+ &ndr_table_netlogon,
machine_credentials, NULL);
if (!NT_STATUS_IS_OK(status)) {
- printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
+ d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
ret = False;
goto failed;
}
.expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
.expected_network_error = NT_STATUS_OK,
.old_password = True
+ },
+ {
+ .comment = "test user (wong workstation): domain\\user",
+ .domain = userdomain,
+ .username = TEST_USER_NAME_WRONG_WKS,
+ .password = user_password_wrong_wks,
+ .network_login = True,
+ .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
+ .expected_network_error = NT_STATUS_INVALID_WORKSTATION
}
};
torture_leave_domain(join_ctx);
torture_leave_domain(user_ctx);
+ torture_leave_domain(user_ctx_wrong_wks);
+ torture_leave_domain(user_ctx_wrong_time);
return ret;
}