1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

smbtorture: Add more tests around NETLOGON challenge reuse

The existing tests did not actually demonstrate what they
thought they did until the credential values were refreshed.

The new test showed this, because Samba fails it (windows passes)
due to the way we keep the last challenge on the connection.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Andrew Bartlett 2017-06-26 16:40:45 +12:00 committed by Stefan Metzmacher
parent 38033ed1d2
commit 1bd627b1fc
2 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,4 @@
# This test passes against Windows 2008R2, but not Samba as we
# keep a per-socket cache in addition to the name cache, which is
# not invalidated if the name-based global cache is used.
^samba4\.rpc\.netlogon.*\.netlogon\.ServerReqChallengeReuseGlobal3

View File

@ -1393,6 +1393,14 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 failed on b2");
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
/* We have to re-run this part */
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b3, tctx, &a),
"ServerAuthenticate3 failed on b3");
torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_ACCESS_DENIED,
@ -1472,6 +1480,14 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 failed on b");
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
/* We have to re-run this part */
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b2, tctx, &a),
"ServerAuthenticate3 failed on b2");
torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_ACCESS_DENIED,
@ -1479,6 +1495,217 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx,
return true;
}
/*
* Test if use of the globally cached challenge will wipe out the
* per-pipe challenge
*/
static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx,
struct dcerpc_pipe *p1,
struct cli_credentials *machine_credentials)
{
uint32_t flags = NETLOGON_NEG_AUTH2_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
struct netr_ServerReqChallenge r;
struct netr_ServerAuthenticate3 a;
struct netr_Credential credentials1, credentials2, credentials3;
struct netlogon_creds_CredentialState *creds;
struct samr_Password mach_password;
uint32_t rid;
const char *machine_name;
const char *plain_pass;
struct dcerpc_binding_handle *b1 = p1->binding_handle;
struct dcerpc_pipe *p2 = NULL;
struct dcerpc_binding_handle *b2 = NULL;
machine_name = cli_credentials_get_workstation(machine_credentials);
plain_pass = cli_credentials_get_password(machine_credentials);
torture_comment(tctx, "Testing ServerReqChallenge on b1\n");
torture_assert_ntstatus_ok(tctx,
dcerpc_pipe_connect_b(tctx, &p2, p1->binding,
&ndr_table_netlogon,
machine_credentials,
tctx->ev, tctx->lp_ctx),
"dcerpc_pipe_connect_b failed");
b2 = p2->binding_handle;
r.in.server_name = NULL;
r.in.computer_name = machine_name;
r.in.credentials = &credentials1;
r.out.return_credentials = &credentials2;
generate_random_buffer(credentials1.data, sizeof(credentials1.data));
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
"ServerReqChallenge failed on b1");
torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed on b1");
E_md4hash(plain_pass, mach_password.hash);
a.in.server_name = NULL;
a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
a.in.secure_channel_type = cli_credentials_get_secure_channel_type(machine_credentials);
a.in.computer_name = machine_name;
a.in.negotiate_flags = &flags;
a.in.credentials = &credentials3;
a.out.return_credentials = &credentials3;
a.out.negotiate_flags = &flags;
a.out.rid = &rid;
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert(tctx, creds != NULL, "memory allocation");
torture_comment(tctx, "Testing ServerAuthenticate3 on b2\n");
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b2, tctx, &a),
"ServerAuthenticate3 failed on b2");
torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 failed on b");
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
/* We have to re-run this part */
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert(tctx, creds != NULL, "memory allocation");
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b1, tctx, &a),
"ServerAuthenticate3 failed on b1");
torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_ACCESS_DENIED,
"ServerAuthenticate3 should have failed on b1, due to credential reuse");
return true;
}
/*
* Test if more than one globally cached challenge works
*/
static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
struct dcerpc_pipe *p1,
struct cli_credentials *machine_credentials)
{
uint32_t flags = NETLOGON_NEG_AUTH2_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
struct netr_ServerReqChallenge r;
struct netr_ServerAuthenticate3 a;
struct netr_Credential credentials1, credentials1_random,
credentials2, credentials3, credentials_discard;
struct netlogon_creds_CredentialState *creds;
struct samr_Password mach_password;
uint32_t rid;
const char *machine_name;
const char *plain_pass;
struct dcerpc_binding_handle *b1 = p1->binding_handle;
struct dcerpc_pipe *p2 = NULL;
struct dcerpc_binding_handle *b2 = NULL;
machine_name = cli_credentials_get_workstation(machine_credentials);
plain_pass = cli_credentials_get_password(machine_credentials);
torture_comment(tctx, "Testing ServerReqChallenge on b1\n");
torture_assert_ntstatus_ok(tctx,
dcerpc_pipe_connect_b(tctx, &p2, p1->binding,
&ndr_table_netlogon,
machine_credentials,
tctx->ev, tctx->lp_ctx),
"dcerpc_pipe_connect_b failed");
b2 = p2->binding_handle;
r.in.server_name = NULL;
r.in.computer_name = "CHALTEST1";
r.in.credentials = &credentials1_random;
r.out.return_credentials = &credentials_discard;
generate_random_buffer(credentials1_random.data,
sizeof(credentials1_random.data));
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
"ServerReqChallenge failed on b1");
torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed on b1");
/* Now ask for the actual client name */
r.in.server_name = NULL;
r.in.computer_name = machine_name;
r.in.credentials = &credentials1;
r.out.return_credentials = &credentials2;
generate_random_buffer(credentials1.data, sizeof(credentials1.data));
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
"ServerReqChallenge failed on b1");
torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed on b1");
r.in.server_name = NULL;
r.in.computer_name = "CHALTEST2";
r.in.credentials = &credentials1_random;
r.out.return_credentials = &credentials_discard;
generate_random_buffer(credentials1_random.data,
sizeof(credentials1_random.data));
r.in.server_name = NULL;
r.in.computer_name = "CHALTEST3";
r.in.credentials = &credentials1_random;
r.out.return_credentials = &credentials_discard;
generate_random_buffer(credentials1_random.data,
sizeof(credentials1_random.data));
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
"ServerReqChallenge failed on b1");
torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed on b1");
E_md4hash(plain_pass, mach_password.hash);
a.in.server_name = NULL;
a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
a.in.secure_channel_type = cli_credentials_get_secure_channel_type(machine_credentials);
a.in.computer_name = machine_name;
a.in.negotiate_flags = &flags;
a.in.credentials = &credentials3;
a.out.return_credentials = &credentials3;
a.out.negotiate_flags = &flags;
a.out.rid = &rid;
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert(tctx, creds != NULL, "memory allocation");
torture_comment(tctx, "Testing ServerAuthenticate3 on b2 (must use global credentials)\n");
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b2, tctx, &a),
"ServerAuthenticate3 failed on b2");
torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 failed on b2");
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
/* We have to re-run this part */
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b1, tctx, &a),
"ServerAuthenticate3 failed on b1");
torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_ACCESS_DENIED,
"ServerAuthenticate3 should have failed on b1, due to credential reuse");
return true;
}
static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
struct dcerpc_pipe *p,
struct cli_credentials *machine_credentials)
@ -1538,6 +1765,14 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 failed");
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
/* We have to re-run this part */
creds = netlogon_creds_client_init(tctx, a.in.account_name,
a.in.computer_name,
a.in.secure_channel_type,
&credentials1, &credentials2,
&mach_password, &credentials3,
flags);
torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
"ServerAuthenticate3 failed");
torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_ACCESS_DENIED,
@ -4550,6 +4785,8 @@ struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeGlobal", test_ServerReqChallengeGlobal);
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeReuseGlobal", test_ServerReqChallengeReuseGlobal);
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeReuseGlobal2", test_ServerReqChallengeReuseGlobal2);
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeReuseGlobal3", test_ServerReqChallengeReuseGlobal3);
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeReuseGlobal4", test_ServerReqChallengeReuseGlobal4);
torture_rpc_tcase_add_test_creds(tcase, "ServerReqChallengeReuse", test_ServerReqChallengeReuse);
torture_rpc_tcase_add_test_creds(tcase, "SetPassword", test_SetPassword);
torture_rpc_tcase_add_test_creds(tcase, "SetPassword2", test_SetPassword2);