Revert "TODO: s4:torture/rpc/netlogon: check r.out.result in test_LogonControl2()"
[metze/samba/wip.git] / source4 / torture / rpc / netlogon.c
index dac876ce7069294e0d82d7055545b4ad939466b7..b3dc06de588aac454ebb8d423cbaa1b4269e54ac 100644 (file)
@@ -107,7 +107,8 @@ static bool test_LogonUasLogon(struct torture_context *tctx,
        struct dcerpc_binding_handle *b = p->binding_handle;
 
        r.in.server_name = NULL;
-       r.in.account_name = cli_credentials_get_username(cmdline_credentials);
+       r.in.account_name = cli_credentials_get_username(
+                               popt_get_cmdline_credentials());
        r.in.workstation = TEST_MACHINE_NAME;
        r.out.info = &info;
 
@@ -126,7 +127,8 @@ static bool test_LogonUasLogoff(struct torture_context *tctx,
        struct dcerpc_binding_handle *b = p->binding_handle;
 
        r.in.server_name = NULL;
-       r.in.account_name = cli_credentials_get_username(cmdline_credentials);
+       r.in.account_name = cli_credentials_get_username(
+                               popt_get_cmdline_credentials());
        r.in.workstation = TEST_MACHINE_NAME;
        r.out.info = &info;
 
@@ -359,6 +361,121 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
        return true;
 }
 
+bool test_SetupCredentialsDowngrade(struct torture_context *tctx,
+                                       struct dcerpc_pipe *p,
+                                       struct cli_credentials *machine_credentials)
+{
+       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 *b = p->binding_handle;
+       uint32_t negotiate_flags = 0;
+
+       machine_name = cli_credentials_get_workstation(machine_credentials);
+       plain_pass = cli_credentials_get_password(machine_credentials);
+
+       torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+       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(b, tctx, &r),
+               "ServerReqChallenge failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed");
+
+       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 = &negotiate_flags;
+       a.in.credentials = &credentials3;
+       a.out.return_credentials = &credentials3;
+       a.out.negotiate_flags = &negotiate_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,
+                                          negotiate_flags);
+
+       torture_assert(tctx, creds != NULL, "memory allocation");
+
+       torture_comment(tctx, "Testing ServerAuthenticate3\n");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
+               "ServerAuthenticate3 failed");
+       torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_DOWNGRADE_DETECTED, "ServerAuthenticate3 should have failed");
+
+       negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+       creds = netlogon_creds_client_init(tctx, a.in.account_name,
+                                          a.in.computer_name,
+                                          a.in.secure_channel_type,
+                                          &credentials1, &credentials2,
+                                          &mach_password, &credentials3,
+                                          negotiate_flags);
+
+       torture_assert(tctx, creds != NULL, "memory allocation");
+
+       torture_comment(tctx, "Testing ServerAuthenticate3\n");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
+               "ServerAuthenticate3 failed");
+       torture_assert_ntstatus_ok(tctx, a.out.result, "ServerAuthenticate3 should succeed");
+
+       torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
+
+       torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags);
+
+       /* Prove that requesting a challenge again won't break it */
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+               "ServerReqChallenge failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "ServerReqChallenge failed");
+
+       return true;
+}
+
+bool test_SetupCredentialsPipe(const struct dcerpc_pipe *p1,
+                              struct torture_context *tctx,
+                              struct cli_credentials *machine_credentials,
+                              struct netlogon_creds_CredentialState *creds,
+                              uint32_t additional_flags,
+                              struct dcerpc_pipe **_p2)
+{
+       NTSTATUS status;
+       struct dcerpc_binding *b2 = NULL;
+       struct dcerpc_pipe *p2 = NULL;
+
+       b2 = dcerpc_binding_dup(tctx, p1->binding);
+       torture_assert(tctx, b2 != NULL, "dcerpc_binding_dup");
+       dcerpc_binding_set_flags(b2,
+                                DCERPC_SCHANNEL | additional_flags,
+                                DCERPC_AUTH_OPTIONS);
+
+       cli_credentials_set_netlogon_creds(machine_credentials, creds);
+       status = dcerpc_pipe_connect_b(tctx, &p2, b2,
+                                      &ndr_table_netlogon,
+                                      machine_credentials,
+                                      tctx->ev, tctx->lp_ctx);
+       cli_credentials_set_netlogon_creds(machine_credentials, NULL);
+       torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b schannel");
+
+       *_p2 = p2;
+       return true;
+}
+
 /*
   try a change password for our machine account
 */
@@ -436,7 +553,7 @@ static bool test_SetPassword(struct torture_context *tctx,
   try a change password for our machine account
 */
 static bool test_SetPassword_flags(struct torture_context *tctx,
-                                  struct dcerpc_pipe *p,
+                                  struct dcerpc_pipe *p1,
                                   struct cli_credentials *machine_credentials,
                                   uint32_t negotiate_flags)
 {
@@ -445,14 +562,20 @@ static bool test_SetPassword_flags(struct torture_context *tctx,
        struct netlogon_creds_CredentialState *creds;
        struct netr_Authenticator credential, return_authenticator;
        struct samr_Password new_password;
-       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
-       if (!test_SetupCredentials2(p, tctx, negotiate_flags,
+       if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
                                    machine_credentials,
                                    cli_credentials_get_secure_channel_type(machine_credentials),
                                    &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
+       b = p->binding_handle;
 
        r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
@@ -532,7 +655,7 @@ static DATA_BLOB netlogon_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
   try a change password for our machine account
 */
 static bool test_SetPassword2_with_flags(struct torture_context *tctx,
-                                        struct dcerpc_pipe *p,
+                                        struct dcerpc_pipe *p1,
                                         struct cli_credentials *machine_credentials,
                                         uint32_t flags)
 {
@@ -544,11 +667,19 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx,
        struct samr_Password nt_hash;
        struct netr_Authenticator credential, return_authenticator;
        struct netr_CryptPassword new_password;
-       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
-       if (!test_SetupCredentials2(p, tctx, flags, machine_credentials, cli_credentials_get_secure_channel_type(machine_credentials), &creds)) {
+       if (!test_SetupCredentials2(p1, tctx, flags, machine_credentials,
+                                   cli_credentials_get_secure_channel_type(machine_credentials),
+                                   &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
+       b = p->binding_handle;
 
        r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
@@ -803,7 +934,6 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
        NTSTATUS status;
        struct netr_LogonSamLogon r;
        struct netr_Authenticator auth, auth2;
-       static const struct netr_Authenticator auth_zero;
        union netr_LogonLevel logon;
        union netr_Validation validation;
        uint8_t authoritative;
@@ -820,7 +950,8 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
                flags |= CLI_CRED_NTLMv2_AUTH;
        }
 
-       cli_credentials_get_ntlm_username_domain(cmdline_credentials, tctx,
+       cli_credentials_get_ntlm_username_domain(popt_get_cmdline_credentials(),
+                                                tctx,
                                                 &ninfo.identity_info.account_name.string,
                                                 &ninfo.identity_info.domain_name.string);
 
@@ -836,12 +967,14 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
        names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(credentials),
                                                cli_credentials_get_domain(credentials));
 
-       status = cli_credentials_get_ntlm_response(cmdline_credentials, tctx,
-                                                  &flags,
-                                                  chal,
-                                                  names_blob,
-                                                  &lm_resp, &nt_resp,
-                                                  NULL, NULL);
+       status = cli_credentials_get_ntlm_response(
+                               popt_get_cmdline_credentials(), tctx,
+                               &flags,
+                               chal,
+                               NULL, /* server_timestamp */
+                               names_blob,
+                               &lm_resp, &nt_resp,
+                               NULL, NULL);
        torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
 
        ninfo.lm.data = lm_resp.data;
@@ -902,7 +1035,7 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
                torture_assert_int_equal(tctx, *r.out.authoritative, 1,
                                         "LogonSamLogon invalid  *r.out.authoritative");
                torture_assert(tctx,
-                              memcmp(&auth2, &auth_zero, sizeof(auth2)) == 0,
+                              all_zero((uint8_t *)&auth2, sizeof(auth2)),
                               "Return authenticator non zero");
        }
 
@@ -940,7 +1073,7 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
                        "LogonSamLogon expected INVALID_PARAMETER");
 
                torture_assert(tctx,
-                              memcmp(&auth2, &auth_zero, sizeof(auth2)) == 0,
+                              all_zero((uint8_t *)&auth2, sizeof(auth2)),
                               "Return authenticator non zero");
                torture_assert_int_equal(tctx, *r.out.authoritative, 1,
                                         "LogonSamLogon invalid  *r.out.authoritative");
@@ -961,7 +1094,7 @@ static bool test_netlogon_ops_args(struct dcerpc_pipe *p, struct torture_context
                        "LogonSamLogon expected INVALID_PARAMETER");
 
                torture_assert(tctx,
-                              memcmp(&auth2, &auth_zero, sizeof(auth2)) == 0,
+                              all_zero((uint8_t *)&auth2, sizeof(auth2)),
                               "Return authenticator non zero");
                torture_assert_int_equal(tctx, *r.out.authoritative, 1,
                                         "LogonSamLogon invalid  *r.out.authoritative");
@@ -1076,42 +1209,394 @@ static bool test_invalidAuthenticate2(struct torture_context *tctx,
 
        torture_comment(tctx, "Testing invalidAuthenticate2\n");
 
-       if (!test_SetupCredentials2(p, tctx, flags,
-                                   credentials,
-                                   cli_credentials_get_secure_channel_type(credentials),
-                                   &creds)) {
-               return false;
-       }
+       if (!test_SetupCredentials2(p, tctx, flags,
+                                   credentials,
+                                   cli_credentials_get_secure_channel_type(credentials),
+                                   &creds)) {
+               return false;
+       }
+
+       if (!test_SetupCredentials2ex(p, tctx, flags,
+                                     credentials,
+                                     "1234567890123456",
+                                     cli_credentials_get_secure_channel_type(credentials),
+                                     STATUS_BUFFER_OVERFLOW,
+                                     &creds)) {
+               return false;
+       }
+
+       if (!test_SetupCredentials2ex(p, tctx, flags,
+                                     credentials,
+                                     "123456789012345",
+                                     cli_credentials_get_secure_channel_type(credentials),
+                                     NT_STATUS_OK,
+                                     &creds)) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool test_ServerReqChallengeGlobal(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 b2");
+       torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
+
+       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");
+
+       /* 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,
+                                     "ServerAuthenticate3 should have failed on b3, due to credential reuse");
+       return true;
+}
+
+/*
+ * Test if use of the per-pipe challenge will wipe out the globally cached challenge
+ */
+static bool test_ServerReqChallengeReuseGlobal2(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(b1, tctx, &a),
+               "ServerAuthenticate3 failed on b");
+       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,
+                                     "ServerAuthenticate3 should have failed on b2, due to credential reuse");
+       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");
 
-       if (!test_SetupCredentials2ex(p, tctx, flags,
-                                     credentials,
-                                     "1234567890123456",
-                                     cli_credentials_get_secure_channel_type(credentials),
-                                     STATUS_BUFFER_OVERFLOW,
-                                     &creds)) {
-               return false;
-       }
+       /* 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);
 
-       if (!test_SetupCredentials2ex(p, tctx, flags,
-                                     credentials,
-                                     "123456789012345",
-                                     cli_credentials_get_secure_channel_type(credentials),
-                                     NT_STATUS_OK,
-                                     &creds)) {
-               return false;
-       }
+       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;
 }
 
-static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
-                                         struct dcerpc_pipe *p1,
-                                         struct cli_credentials *machine_credentials)
+/*
+ * 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, credentials2, credentials3;
+       struct netr_Credential credentials1, credentials1_random,
+               credentials2, credentials3, credentials_discard;
        struct netlogon_creds_CredentialState *creds;
        struct samr_Password mach_password;
        uint32_t rid;
@@ -1134,6 +1619,19 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
                "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;
@@ -1145,6 +1643,26 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
                "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;
@@ -1166,13 +1684,117 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
 
        torture_assert(tctx, creds != NULL, "memory allocation");
 
-       torture_comment(tctx, "Testing ServerAuthenticate3 on b2\n");
+       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)
+{
+       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 *b = p->binding_handle;
+
+       machine_name = cli_credentials_get_workstation(machine_credentials);
+       plain_pass = cli_credentials_get_password(machine_credentials);
+
+       torture_comment(tctx, "Testing ServerReqChallenge on b1\n");
+
+       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(b, tctx, &r),
+               "ServerReqChallenge");
+       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\n");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerAuthenticate3_r(b, tctx, &a),
+               "ServerAuthenticate3 failed");
+       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,
+                                     "ServerAuthenticate3 should have failed on b3, due to credential reuse");
+
+       ZERO_STRUCT(credentials1.data);
+       ZERO_STRUCT(credentials2.data);
+       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 with zero'ed challenge\n");
+
+       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,
+                                     "ServerAuthenticate3 should have failed on b3, due to credential reuse");
        return true;
 }
 
@@ -2115,7 +2737,7 @@ static bool test_LogonControl(struct torture_context *tctx,
                                    (secure_channel_type == SEC_CHAN_WKSTA)) {
                                        torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
                                                "LogonControl returned unexpected error code");
-                               } else {
+                               } else if (!W_ERROR_EQUAL(r.out.result, WERR_NOT_SUPPORTED)) {
                                        torture_assert_werr_ok(tctx, r.out.result,
                                                "LogonControl returned unexpected result");
                                }
@@ -2131,7 +2753,7 @@ static bool test_LogonControl(struct torture_context *tctx,
                                "LogonControl returned unexpected error code");
                        break;
                default:
-                       torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
+                       torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL,
                                "LogonControl returned unexpected error code");
                        break;
                }
@@ -2209,11 +2831,19 @@ static bool test_LogonControl2(struct torture_context *tctx,
        struct netr_LogonControl2 r;
        union netr_CONTROL_DATA_INFORMATION data;
        union netr_CONTROL_QUERY_INFORMATION query;
+       enum netr_SchannelType secure_channel_type = SEC_CHAN_NULL;
        int i;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
        data.domain = lpcfg_workgroup(tctx->lp_ctx);
 
+       if (machine_credentials) {
+               secure_channel_type = cli_credentials_get_secure_channel_type(machine_credentials);
+       }
+
+       torture_comment(tctx, "Testing LogonControl2 with secure channel type: %d\n",
+               secure_channel_type);
+
        r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 
        r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
@@ -2284,8 +2914,14 @@ static bool test_LogonControl2(struct torture_context *tctx,
 
        status = dcerpc_netr_LogonControl2_r(b, tctx, &r);
        torture_assert_ntstatus_ok(tctx, status, "LogonControl2");
-       torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "LogonControl2");
-
+       switch (secure_channel_type) {
+       case SEC_CHAN_NULL:
+               torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED, "LogonControl2");
+               break;
+       default:
+               torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED, "LogonControl2");
+               break;
+       }
        data.debug_level = ~0;
 
        r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
@@ -2297,7 +2933,7 @@ static bool test_LogonControl2(struct torture_context *tctx,
 
        status = dcerpc_netr_LogonControl2_r(b, tctx, &r);
        torture_assert_ntstatus_ok(tctx, status, "LogonControl2");
-       torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "LogonControl2");
+       torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "LogonControl2");
 
        return true;
 }
@@ -2385,11 +3021,19 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
        struct netr_LogonControl2Ex r;
        union netr_CONTROL_DATA_INFORMATION data;
        union netr_CONTROL_QUERY_INFORMATION query;
+       enum netr_SchannelType secure_channel_type = SEC_CHAN_NULL;
        int i;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
        data.domain = lpcfg_workgroup(tctx->lp_ctx);
 
+       if (machine_credentials) {
+               secure_channel_type = cli_credentials_get_secure_channel_type(machine_credentials);
+       }
+
+       torture_comment(tctx, "Testing LogonControl2Ex with secure channel type: %d\n",
+               secure_channel_type);
+
        r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 
        r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
@@ -2399,11 +3043,11 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n",
-                      i, r.in.function_code);
+               torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
 
                status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
        }
 
        data.domain = lpcfg_workgroup(tctx->lp_ctx);
@@ -2414,11 +3058,11 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n",
-                      i, r.in.function_code);
+               torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
 
                status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
        }
 
        data.domain = lpcfg_workgroup(tctx->lp_ctx);
@@ -2429,11 +3073,11 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n",
-                      i, r.in.function_code);
+               torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
 
                status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
        }
 
        data.debug_level = ~0;
@@ -2444,18 +3088,48 @@ static bool test_LogonControl2Ex(struct torture_context *tctx,
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n",
-                      i, r.in.function_code);
+               torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
 
                status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
+       }
+
+       ZERO_STRUCT(data);
+       r.in.function_code = 52;
+       r.in.data = &data;
+
+       torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
+
+       status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
+       switch (secure_channel_type) {
+       case SEC_CHAN_NULL:
+               torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED, "LogonControl2Ex");
+               break;
+       default:
+               torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED, "LogonControl2Ex");
+               break;
        }
+       data.debug_level = ~0;
+
+       r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
+       r.in.data = &data;
+
+       r.in.level = 52;
+       torture_comment(tctx, "Testing LogonControl2Ex function code %s (%d) level %d\n",
+                       function_code_str(tctx, r.in.function_code), r.in.function_code, r.in.level);
+
+       status = dcerpc_netr_LogonControl2Ex_r(b, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "LogonControl2Ex");
+       torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "LogonControl2Ex");
 
        return true;
 }
 
 static bool test_netr_GetForestTrustInformation(struct torture_context *tctx,
-                                               struct dcerpc_pipe *p,
+                                               struct dcerpc_pipe *p1,
                                                struct cli_credentials *machine_credentials)
 {
        struct netr_GetForestTrustInformation r;
@@ -2463,12 +3137,18 @@ static bool test_netr_GetForestTrustInformation(struct torture_context *tctx,
        struct netr_Authenticator a;
        struct netr_Authenticator return_authenticator;
        struct lsa_ForestTrustInformation *forest_trust_info;
-       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
-       if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+       if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
                                    machine_credentials, &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
+       b = p->binding_handle;
 
        netlogon_creds_client_authenticator(creds, &a);
 
@@ -2906,7 +3586,7 @@ static bool test_netr_DsrGetDcSiteCoverageW(struct torture_context *tctx,
                url = talloc_asprintf(tctx, "ldap://%s", dcerpc_server_name(p));
                sam_ctx = ldb_wrap_connect(tctx, tctx->ev, tctx->lp_ctx, url,
                                           NULL,
-                                          cmdline_credentials,
+                                          popt_get_cmdline_credentials(),
                                           0);
 
                torture_assert(tctx, sam_ctx, "Connection to the SAMDB on DC failed!");
@@ -2955,7 +3635,7 @@ static bool test_netr_DsRAddressToSitenamesW(struct torture_context *tctx,
                url = talloc_asprintf(tctx, "ldap://%s", dcerpc_server_name(p));
                sam_ctx = ldb_wrap_connect(tctx, tctx->ev, tctx->lp_ctx, url,
                                           NULL,
-                                          cmdline_credentials,
+                                          popt_get_cmdline_credentials(),
                                           0);
 
                torture_assert(tctx, sam_ctx, "Connection to the SAMDB on DC failed!");
@@ -3132,7 +3812,7 @@ static bool test_netr_DsRAddressToSitenamesExW(struct torture_context *tctx,
                url = talloc_asprintf(tctx, "ldap://%s", dcerpc_server_name(p));
                sam_ctx = ldb_wrap_connect(tctx, tctx->ev, tctx->lp_ctx, url,
                                           NULL,
-                                          cmdline_credentials,
+                                          popt_get_cmdline_credentials(),
                                           0);
 
                torture_assert(tctx, sam_ctx, "Connection to the SAMDB on DC failed!");
@@ -3291,7 +3971,7 @@ static bool test_netr_DsRAddressToSitenamesExW(struct torture_context *tctx,
 }
 
 static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx,
-                                              struct dcerpc_pipe *p,
+                                              struct dcerpc_pipe *p1,
                                               struct cli_credentials *machine_credentials,
                                               uint32_t negotiate_flags)
 {
@@ -3304,14 +3984,20 @@ static bool test_netr_ServerGetTrustInfo_flags(struct torture_context *tctx,
        struct netr_TrustInfo *trust_info;
 
        struct netlogon_creds_CredentialState *creds;
-       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        struct samr_Password nt_hash;
 
-       if (!test_SetupCredentials3(p, tctx, negotiate_flags,
+       if (!test_SetupCredentials3(p1, tctx, negotiate_flags,
                                    machine_credentials, &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
+       b = p->binding_handle;
 
        netlogon_creds_client_authenticator(creds, &a);
 
@@ -3361,7 +4047,7 @@ static bool test_netr_ServerGetTrustInfo_AES(struct torture_context *tctx,
 }
 
 static bool test_GetDomainInfo(struct torture_context *tctx,
-                              struct dcerpc_pipe *p,
+                              struct dcerpc_pipe *p1,
                               struct cli_credentials *machine_credentials)
 {
        struct netr_LogonGetDomainInfo r;
@@ -3384,14 +4070,20 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
        char **spns = NULL;
        int num_spns = 0;
        char *temp_str;
-       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *p = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n");
 
-       if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+       if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
                                    machine_credentials, &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
+       b = p->binding_handle;
 
        /* We won't double-check this when we are over 'local' transports */
        if (dcerpc_server_name(p)) {
@@ -3399,7 +4091,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
                url = talloc_asprintf(tctx, "ldap://%s", dcerpc_server_name(p));
                sam_ctx = ldb_wrap_connect(tctx, tctx->ev, tctx->lp_ctx, url,
                                           NULL,
-                                          cmdline_credentials,
+                                          popt_get_cmdline_credentials(),
                                           0);
 
                torture_assert(tctx, sam_ctx, "Connection to the SAMDB on DC failed!");
@@ -3816,7 +4508,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
 }
 
 static bool test_GetDomainInfo_async(struct torture_context *tctx,
-                                    struct dcerpc_pipe *p,
+                                    struct dcerpc_pipe *p1,
                                     struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
@@ -3830,6 +4522,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx,
        int i;
        union netr_WorkstationInfo query;
        union netr_DomainInfo info;
+       struct dcerpc_pipe *p = NULL;
 
        torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
 
@@ -3837,6 +4530,10 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx,
                                    machine_credentials, &creds)) {
                return false;
        }
+       if (!test_SetupCredentialsPipe(p1, tctx, machine_credentials, creds,
+                                      DCERPC_SIGN | DCERPC_SEAL, &p)) {
+               return false;
+       }
 
        ZERO_STRUCT(r);
        r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
@@ -3891,6 +4588,8 @@ static bool test_ManyGetDCName(struct torture_context *tctx,
                               struct dcerpc_pipe *p)
 {
        NTSTATUS status;
+       struct cli_credentials *anon_creds;
+       struct dcerpc_binding *binding2;
        struct dcerpc_pipe *p2;
        struct lsa_ObjectAttribute attr;
        struct lsa_QosInfo qos;
@@ -3908,16 +4607,24 @@ static bool test_ManyGetDCName(struct torture_context *tctx,
        int i;
 
        if (p->conn->transport.transport != NCACN_NP) {
-               return true;
+               torture_skip(tctx, "test_ManyGetDCName works only with NCACN_NP");
        }
 
        torture_comment(tctx, "Torturing GetDCName\n");
 
-       status = dcerpc_secondary_connection(p, &p2, p->binding);
-       torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
+       anon_creds = cli_credentials_init_anon(tctx);
+       torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
+
+       binding2 = dcerpc_binding_dup(tctx, p->binding);
+       /* Swap the binding details from NETLOGON to LSA */
+       status = dcerpc_epm_map_binding(tctx, binding2, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx);
+       dcerpc_binding_set_assoc_group_id(binding2, 0);
+       torture_assert_ntstatus_ok(tctx, status, "epm map");
 
-       status = dcerpc_bind_auth_none(p2, &ndr_table_lsarpc);
-       torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
+       status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_lsarpc,
+                                                 anon_creds, tctx->lp_ctx,
+                                                 tctx, &p2);
+       torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
        b2 = p2->binding_handle;
 
        qos.len = 0;
@@ -3976,6 +4683,65 @@ static bool test_ManyGetDCName(struct torture_context *tctx,
        return true;
 }
 
+static bool test_lsa_over_netlogon(struct torture_context *tctx,
+                                  struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct cli_credentials *anon_creds;
+       const struct dcerpc_binding *binding2;
+       struct dcerpc_pipe *p2;
+       struct lsa_ObjectAttribute attr;
+       struct lsa_QosInfo qos;
+       struct lsa_OpenPolicy2 o;
+       struct policy_handle lsa_handle;
+
+       struct dcerpc_binding_handle *b2;
+
+
+       if (p->conn->transport.transport != NCACN_NP) {
+               torture_skip(tctx, "test_lsa_over_netlogon works only with NCACN_NP");
+       }
+
+       torture_comment(tctx, "Testing if we can access the LSA server over\n"
+                       " \\\\pipe\\netlogon rather than \\\\pipe\\lsarpc\n");
+
+       anon_creds = cli_credentials_init_anon(tctx);
+       torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
+
+       binding2 = p->binding;
+
+       status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_lsarpc,
+                                                 anon_creds, tctx->lp_ctx,
+                                                 tctx, &p2);
+       torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
+       b2 = p2->binding_handle;
+
+       qos.len = 0;
+       qos.impersonation_level = 2;
+       qos.context_mode = 1;
+       qos.effective_only = 0;
+
+       attr.len = 0;
+       attr.root_dir = NULL;
+       attr.object_name = NULL;
+       attr.attributes = 0;
+       attr.sec_desc = NULL;
+       attr.sec_qos = &qos;
+
+       o.in.system_name = "\\";
+       o.in.attr = &attr;
+       o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       o.out.handle = &lsa_handle;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenPolicy2_r(b2, tctx, &o),
+               "OpenPolicy2 failed");
+       torture_assert_ntstatus_ok(tctx, o.out.result, "OpenPolicy2 failed");
+
+       talloc_free(p2);
+
+       return true;
+}
+
 static bool test_SetPassword_with_flags(struct torture_context *tctx,
                                        struct dcerpc_pipe *p,
                                        struct cli_credentials *machine_credentials)
@@ -4017,6 +4783,11 @@ 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, "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);
        torture_rpc_tcase_add_test_creds(tcase, "SetPassword2_AES", test_SetPassword2_AES);
@@ -4047,6 +4818,9 @@ struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
        torture_rpc_tcase_add_test_creds(tcase, "ServerGetTrustInfo_AES", test_netr_ServerGetTrustInfo_AES);
        torture_rpc_tcase_add_test_creds(tcase, "GetForestTrustInformation", test_netr_GetForestTrustInformation);
 
+       torture_rpc_tcase_add_test(tcase, "lsa_over_netlogon", test_lsa_over_netlogon);
+       torture_rpc_tcase_add_test_creds(tcase, "SetupCredentialsDowngrade", test_SetupCredentialsDowngrade);
+
        return suite;
 }
 
@@ -4074,19 +4848,19 @@ struct torture_suite *torture_rpc_netlogon_admin(TALLOC_CTX *mem_ctx)
        struct torture_suite *suite = torture_suite_create(mem_ctx, "netlogon.admin");
        struct torture_rpc_tcase *tcase;
 
-       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netlogon",
+       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "bdc",
                                                  &ndr_table_netlogon, TEST_MACHINE_NAME);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl", test_LogonControl);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl2", test_LogonControl2);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl2Ex", test_LogonControl2Ex);
 
-       tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netlogon",
+       tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "wkst",
                                                  &ndr_table_netlogon, TEST_MACHINE_NAME);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl", test_LogonControl);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl2", test_LogonControl2);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl2Ex", test_LogonControl2Ex);
 
-       tcase = torture_suite_add_rpc_iface_tcase(suite, "netlogon",
+       tcase = torture_suite_add_rpc_iface_tcase(suite, "admin",
                                                  &ndr_table_netlogon);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl", test_LogonControl);
        torture_rpc_tcase_add_test_creds(tcase, "LogonControl2", test_LogonControl2);