summaryrefslogtreecommitdiff
path: root/source4/torture/rpc
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2017-06-26 16:40:45 +1200
committerStefan Metzmacher <metze@samba.org>2017-06-27 16:57:42 +0200
commit1bd627b1fc37ca676e2f35d63c6d94826b383148 (patch)
tree578ee94162fbd246e28a44ad456cd554c1d761f5 /source4/torture/rpc
parent38033ed1d2df96c0c304f21b4cabef232640cf3d (diff)
downloadsamba-1bd627b1fc37ca676e2f35d63c6d94826b383148.tar.gz
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>
Diffstat (limited to 'source4/torture/rpc')
-rw-r--r--source4/torture/rpc/netlogon.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 29025da05c7..b3dc06de588 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -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);