torture: Add new test ServerReqChallengeReuseGlobal to rpc.netlogon
authorAndrew Bartlett <abartlet@samba.org>
Wed, 14 Dec 2016 02:12:12 +0000 (15:12 +1300)
committerStefan Metzmacher <metze@samba.org>
Wed, 14 Dec 2016 10:55:18 +0000 (11:55 +0100)
This tests ensures we can not re-use the entries in global challenge table.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/torture/rpc/netlogon.c

index 277c3cfcb820cc4ae7498feb75f3207ec318c8d4..66311123335f083ea28debc735a5ced566442c26 100644 (file)
@@ -1306,6 +1306,97 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
        return true;
 }
 
+/*
+ * Test the re-use of the challenge is not possible on a third
+ * connection, after first useing it second one.
+ */
+
+static bool test_ServerReqChallengeReuseGlobal(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;
+       struct dcerpc_pipe *p3 = NULL;
+       struct dcerpc_binding_handle *b3 = 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;
+
+       torture_assert_ntstatus_ok(tctx,
+               dcerpc_pipe_connect_b(tctx, &p3, p1->binding,
+                                     &ndr_table_netlogon,
+                                     machine_credentials,
+                                     tctx->ev, tctx->lp_ctx),
+               "dcerpc_pipe_connect_b failed");
+       b3 = p3->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 b2");
+       torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
+
+       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,
+                                     "ServerAuthenticate3 should have failed on b3, due to credential reuse");
+       return true;
+}
+
 static bool test_SamLogon_NULL_domain(struct torture_context *tctx,
                                      struct dcerpc_pipe *p,
                                      struct cli_credentials *credentials)
@@ -4291,6 +4382,7 @@ struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
        torture_rpc_tcase_add_test_creds(tcase, "SamLogon", test_SamLogon);
        torture_rpc_tcase_add_test_creds(tcase, "invalidAuthenticate2", test_invalidAuthenticate2);
        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, "SetPassword", test_SetPassword);
        torture_rpc_tcase_add_test_creds(tcase, "SetPassword2", test_SetPassword2);
        torture_rpc_tcase_add_test_creds(tcase, "SetPassword2_AES", test_SetPassword2_AES);