s4-netlogon: merge netr_DatabaseSync2 from s3 idl.
[ira/wip.git] / source4 / torture / rpc / netlogon.c
index ec7eca98bd8f2caa0f81d6a3d33fb657c630cffb..174022248d9fb73cde28a49e0b61deddfc6cf62a 100644 (file)
@@ -9,7 +9,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-
-
-static const char *machine_password;
+#include "torture/torture.h"
+#include "lib/events/events.h"
+#include "auth/auth.h"
+#include "auth/gensec/gensec.h"
+#include "lib/cmdline/popt_common.h"
+#include "torture/rpc/rpc.h"
+#include "torture/rpc/netlogon.h"
+#include "../lib/crypto/crypto.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/ndr_lsa_c.h"
+#include "param/param.h"
 
 #define TEST_MACHINE_NAME "torturetest"
 
-static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_LogonUasLogon(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_LogonUasLogon r;
+       struct netr_UasInfo *info = NULL;
 
        r.in.server_name = NULL;
-       r.in.account_name = lp_parm_string(-1, "torture", "username");
+       r.in.account_name = cli_credentials_get_username(cmdline_credentials);
        r.in.workstation = TEST_MACHINE_NAME;
+       r.out.info = &info;
 
-       printf("Testing LogonUasLogon\n");
-
-       status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("LogonUasLogon - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_LogonUasLogon(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "LogonUasLogon");
 
-       return True;
-       
+       return true;
 }
 
-static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_LogonUasLogoff(struct torture_context *tctx,
+                               struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_LogonUasLogoff r;
+       struct netr_UasLogoffInfo info;
 
        r.in.server_name = NULL;
-       r.in.account_name = lp_parm_string(-1, "torture", "username");
+       r.in.account_name = cli_credentials_get_username(cmdline_credentials);
        r.in.workstation = TEST_MACHINE_NAME;
+       r.out.info = &info;
 
-       printf("Testing LogonUasLogoff\n");
-
-       status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("LogonUasLogoff - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_LogonUasLogoff(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "LogonUasLogoff");
 
-       return True;
-       
+       return true;
 }
 
-static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                                 struct creds_CredentialState *creds)
+static bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx,
+                                 struct cli_credentials *credentials,
+                                 struct creds_CredentialState **creds_out)
 {
        NTSTATUS status;
        struct netr_ServerReqChallenge r;
        struct netr_ServerAuthenticate a;
        struct netr_Credential credentials1, credentials2, credentials3;
-       const char *plain_pass;
-       struct samr_Password mach_password;
+       struct creds_CredentialState *creds;
+       const struct samr_Password *mach_password;
+       const char *machine_name;
+
+       mach_password = cli_credentials_get_nt_hash(credentials, tctx);
+       machine_name = cli_credentials_get_workstation(credentials);
 
-       printf("Testing ServerReqChallenge\n");
+       torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+       creds = talloc(tctx, struct creds_CredentialState);
+       torture_assert(tctx, creds != NULL, "memory allocation");
 
        r.in.server_name = NULL;
-       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.computer_name = machine_name;
        r.in.credentials = &credentials1;
        r.out.credentials = &credentials2;
 
        generate_random_buffer(credentials1.data, sizeof(credentials1.data));
 
-       status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerReqChallenge - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       plain_pass = machine_password;
-       if (!plain_pass) {
-               printf("Unable to fetch machine password!\n");
-               return False;
-       }
-
-       E_md4hash(plain_pass, mach_password.hash);
+       status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
 
        a.in.server_name = NULL;
-       a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
+       a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
        a.in.secure_channel_type = SEC_CHAN_BDC;
-       a.in.computer_name = TEST_MACHINE_NAME;
+       a.in.computer_name = machine_name;
        a.in.credentials = &credentials3;
        a.out.credentials = &credentials3;
 
-       creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
-                         NETLOGON_NEG_AUTH2_FLAGS);
+       creds_client_init(creds, &credentials1, &credentials2, 
+                         mach_password, &credentials3, 
+                         0);
 
-       printf("Testing ServerAuthenticate\n");
+       torture_comment(tctx, "Testing ServerAuthenticate\n");
 
-       status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerAuthenticate - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_ServerAuthenticate(p, tctx, &a);
 
-       if (!creds_client_check(creds, &credentials3)) {
-               printf("Credential chaining failed\n");
-               return False;
+       /* This allows the tests to continue against the more fussy windows 2008 */
+       if (NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED)) {
+               return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
+                                             credentials, SEC_CHAN_BDC, creds_out);
        }
 
-       return True;
+       torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate");
+
+       torture_assert(tctx, creds_client_check(creds, &credentials3), 
+                      "Credential chaining failed");
+
+       *creds_out = creds;
+       return true;
 }
 
-static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                                  uint32_t negotiate_flags,
-                                  struct creds_CredentialState *creds)
+bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx,
+                           uint32_t negotiate_flags,
+                           struct cli_credentials *machine_credentials,
+                           int sec_chan_type,
+                           struct creds_CredentialState **creds_out)
 {
        NTSTATUS status;
        struct netr_ServerReqChallenge r;
        struct netr_ServerAuthenticate2 a;
        struct netr_Credential credentials1, credentials2, credentials3;
+       struct creds_CredentialState *creds;
+       const struct samr_Password *mach_password;
+       const char *machine_name;
        const char *plain_pass;
-       struct samr_Password mach_password;
 
-       printf("Testing ServerReqChallenge\n");
+       mach_password = cli_credentials_get_nt_hash(machine_credentials, tctx);
+       machine_name = cli_credentials_get_workstation(machine_credentials);
+
+       torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+       creds = talloc(tctx, struct creds_CredentialState);
+       torture_assert(tctx, creds != NULL, "memory allocation");
 
        r.in.server_name = NULL;
-       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.computer_name = machine_name;
        r.in.credentials = &credentials1;
        r.out.credentials = &credentials2;
 
        generate_random_buffer(credentials1.data, sizeof(credentials1.data));
 
-       status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerReqChallenge - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       plain_pass = machine_password;
-       if (!plain_pass) {
-               printf("Unable to fetch machine password!\n");
-               return False;
-       }
-
-       E_md4hash(plain_pass, mach_password.hash);
+       status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
 
        a.in.server_name = NULL;
-       a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
-       a.in.secure_channel_type = SEC_CHAN_BDC;
-       a.in.computer_name = TEST_MACHINE_NAME;
+       a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
+       a.in.secure_channel_type = sec_chan_type;
+       a.in.computer_name = machine_name;
        a.in.negotiate_flags = &negotiate_flags;
        a.out.negotiate_flags = &negotiate_flags;
        a.in.credentials = &credentials3;
        a.out.credentials = &credentials3;
 
-       creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
+       creds_client_init(creds, &credentials1, &credentials2, 
+                         mach_password, &credentials3, 
                          negotiate_flags);
 
-       printf("Testing ServerAuthenticate2\n");
+       torture_comment(tctx, "Testing ServerAuthenticate2\n");
 
-       status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_ServerAuthenticate2(p, tctx, &a);
+       torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate2");
 
-       if (!creds_client_check(creds, &credentials3)) {
-               printf("Credential chaining failed\n");
-               return False;
-       }
+       torture_assert(tctx, creds_client_check(creds, &credentials3), 
+               "Credential chaining failed");
 
-       printf("negotiate_flags=0x%08x\n", negotiate_flags);
+       torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags);
 
-       return True;
+       *creds_out = creds;
+       return true;
 }
 
 
-static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                                  uint32_t negotiate_flags,
-                                  struct creds_CredentialState *creds)
+static bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
+                           uint32_t negotiate_flags,
+                           struct cli_credentials *machine_credentials,
+                           struct creds_CredentialState **creds_out)
 {
        NTSTATUS status;
        struct netr_ServerReqChallenge r;
        struct netr_ServerAuthenticate3 a;
        struct netr_Credential credentials1, credentials2, credentials3;
-       const char *plain_pass;
+       struct creds_CredentialState *creds;
        struct samr_Password mach_password;
-       uint32 rid;
+       uint32_t rid;
+       const char *machine_name;
+       const char *plain_pass;
 
-       printf("Testing ServerReqChallenge\n");
+       machine_name = cli_credentials_get_workstation(machine_credentials);
+       plain_pass = cli_credentials_get_password(machine_credentials);
+
+       torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+       creds = talloc(tctx, struct creds_CredentialState);
+       torture_assert(tctx, creds != NULL, "memory allocation");
 
        r.in.server_name = NULL;
-       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.computer_name = machine_name;
        r.in.credentials = &credentials1;
        r.out.credentials = &credentials2;
 
        generate_random_buffer(credentials1.data, sizeof(credentials1.data));
 
-       status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerReqChallenge - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       plain_pass = machine_password;
-       if (!plain_pass) {
-               printf("Unable to fetch machine password!\n");
-               return False;
-       }
+       status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
 
        E_md4hash(plain_pass, mach_password.hash);
 
        a.in.server_name = NULL;
-       a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
+       a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
        a.in.secure_channel_type = SEC_CHAN_BDC;
-       a.in.computer_name = TEST_MACHINE_NAME;
+       a.in.computer_name = machine_name;
        a.in.negotiate_flags = &negotiate_flags;
        a.in.credentials = &credentials3;
        a.out.credentials = &credentials3;
        a.out.negotiate_flags = &negotiate_flags;
        a.out.rid = &rid;
 
-       creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
+       creds_client_init(creds, &credentials1, &credentials2, 
+                         &mach_password, &credentials3,
                          negotiate_flags);
 
-       printf("Testing ServerAuthenticate3\n");
+       torture_comment(tctx, "Testing ServerAuthenticate3\n");
 
-       status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_ServerAuthenticate3(p, tctx, &a);
+       torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate3");
+       torture_assert(tctx, creds_client_check(creds, &credentials3), "Credential chaining failed");
 
-       if (!creds_client_check(creds, &credentials3)) {
-               printf("Credential chaining failed\n");
-               return False;
-       }
-
-       printf("negotiate_flags=0x%08x\n", negotiate_flags);
+       torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags);
+       
+       /* Prove that requesting a challenge again won't break it */
+       status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
 
-       return True;
+       *creds_out = creds;
+       return true;
 }
 
-enum ntlm_break {
-       BREAK_NONE,
-       BREAK_LM,
-       BREAK_NT,
-       NO_LM,
-       NO_NT
-};
-
-struct samlogon_state {
-       TALLOC_CTX *mem_ctx;
-       const char *account_name;
-       const char *password;
-       struct dcerpc_pipe *p;
-       struct netr_LogonSamLogon r;
-       struct netr_Authenticator auth, auth2;
-       struct creds_CredentialState creds;
-       DATA_BLOB chall;
-};
-
-/* 
-   Authenticate a user with a challenge/response, checking session key
-   and valid authentication types
+/*
+  try a change password for our machine account
 */
-static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, 
-                              enum ntlm_break break_which,
-                              DATA_BLOB *chall, 
-                              DATA_BLOB *lm_response, 
-                              DATA_BLOB *nt_response, 
-                              uint8_t lm_key[8], 
-                              uint8_t user_session_key[16], 
-                              char **error_string)
+static bool test_SetPassword(struct torture_context *tctx, 
+                            struct dcerpc_pipe *p,
+                            struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
-       struct netr_LogonSamLogon *r = &samlogon_state->r;
-       int levels[] = { 2, 6 };
-       int i;
-       struct netr_NetworkInfo ninfo;
-
-       for (i=0;i<ARRAY_SIZE(levels);i++) {
-               struct netr_SamBaseInfo *base;
-               
-               printf("testing netr_LogonSamLogon with logon level %d\n", levels[i]);
-
-               samlogon_state->r.in.logon_level = levels[i];
-               samlogon_state->r.in.logon.network = &ninfo;
-       
-               ninfo.identity_info.domain_name.string = lp_workgroup();
-               ninfo.identity_info.parameter_control = 0;
-               ninfo.identity_info.logon_id_low = 0;
-               ninfo.identity_info.logon_id_high = 0;
-               ninfo.identity_info.account_name.string = samlogon_state->account_name;
-               ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
-               
-               memcpy(ninfo.challenge, chall->data, 8);
-               
-               switch (break_which) {
-               case BREAK_NONE:
-                       break;
-               case BREAK_LM:
-                       if (lm_response && lm_response->data) {
-                               lm_response->data[0]++;
-                       }
-                       break;
-               case BREAK_NT:
-                       if (nt_response && nt_response->data) {
-                               nt_response->data[0]++;
-                       }
-                       break;
-               case NO_LM:
-                       data_blob_free(lm_response);
-                       break;
-               case NO_NT:
-                       data_blob_free(nt_response);
-                       break;
-               }
-               
-               if (nt_response) {
-                       ninfo.nt.data = nt_response->data;
-                       ninfo.nt.length = nt_response->length;
-               } else {
-                       ninfo.nt.data = NULL;
-                       ninfo.nt.length = 0;
-               }
-               
-               if (lm_response) {
-                       ninfo.lm.data = lm_response->data;
-                       ninfo.lm.length = lm_response->length;
-               } else {
-                       ninfo.lm.data = NULL;
-                       ninfo.lm.length = 0;
-               }
-               
-               ZERO_STRUCT(samlogon_state->auth2);
-               creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
-               
-               r->out.return_authenticator = NULL;
-               status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (error_string) {
-                               *error_string = strdup(nt_errstr(status));
-                       }
-               }
-               
-               if (!r->out.return_authenticator || 
-                   !creds_client_check(&samlogon_state->creds, &r->out.return_authenticator->cred)) {
-                       printf("Credential chaining failed\n");
-               }
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       /* we cannot check the session key, if the logon failed... */
-                       return status;
-               }
-               
-               /* find and decyrpt the session keys, return in parameters above */
-               if (r->in.validation_level == 2) {
-                       base = &r->out.validation.sam2->base;
-               } else if (r->in.validation_level == 3) {
-                       base = &r->out.validation.sam3->base;
-               } else if (r->in.validation_level == 6) {
-                       base = &r->out.validation.sam6->base;
-               } else {
-                       base = NULL;
-               }
+       struct netr_ServerPasswordSet r;
+       const char *password;
+       struct creds_CredentialState *creds;
 
-               if (r->in.validation_level != 6) {
-                       static const char zeros[16];
-                       
-                       if (memcmp(base->key.key, zeros,  
-                                  sizeof(base->key.key)) != 0) {
-                               creds_arcfour_crypt(&samlogon_state->creds, 
-                                                   base->key.key, 
-                                                   sizeof(base->key.key));
-                       }
-                       
-                       if (user_session_key) {
-                               memcpy(user_session_key, base->key.key, 16);
-                       }
-                       
-                       if (memcmp(base->LMSessKey.key, zeros,  
-                                  sizeof(base->LMSessKey.key)) != 0) {
-                               creds_arcfour_crypt(&samlogon_state->creds, 
-                                                   base->LMSessKey.key, 
-                                                   sizeof(base->LMSessKey.key));
-                       }
-                       
-                       if (lm_key) {
-                               memcpy(lm_key, base->LMSessKey.key, 8);
-                       }
-               } else {
-                       /* they aren't encrypted! */
-                       if (user_session_key) {
-                               memcpy(user_session_key, base->key.key, 16);
-                       }
-                       if (lm_key) {
-                               memcpy(lm_key, base->LMSessKey.key, 8);
-                       }
-               }
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       return status;
-} 
-
-
-/* 
- * Test the normal 'LM and NTLM' combination
- */
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
+       r.in.secure_channel_type = SEC_CHAN_BDC;
+       r.in.computer_name = TEST_MACHINE_NAME;
 
-static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
-{
-       BOOL pass = True;
-       NTSTATUS nt_status;
-       DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
-       DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
-       DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
-
-       uint8_t lm_key[8];
-       uint8_t user_session_key[16];
-       uint8_t lm_hash[16];
-       uint8_t nt_hash[16];
-       
-       ZERO_STRUCT(lm_key);
-       ZERO_STRUCT(user_session_key);
+       password = generate_random_str(tctx, 8);
+       E_md4hash(password, r.in.new_password.hash);
 
-       SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
-       E_deshash(samlogon_state->password, lm_hash); 
+       creds_des_encrypt(creds, &r.in.new_password);
 
-       SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
+       torture_comment(tctx, "Testing ServerPasswordSet on machine account\n");
+       torture_comment(tctx, "Changing machine account password to '%s'\n", 
+                       password);
 
-       E_md4hash(samlogon_state->password, nt_hash);
-       SMBsesskeygen_ntv1(nt_hash, session_key.data);
+       creds_client_authenticator(creds, &r.in.credential);
 
-       nt_status = check_samlogon(samlogon_state,
-                                  break_which,
-                                  &samlogon_state->chall,
-                                  &lm_response,
-                                  &nt_response,
-                                  lm_key, 
-                                  user_session_key,
-                                  error_string);
-       
-       data_blob_free(&lm_response);
+       status = dcerpc_netr_ServerPasswordSet(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet");
 
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return break_which == BREAK_NT;
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
        }
 
-       if (memcmp(lm_hash, lm_key, 
-                  sizeof(lm_key)) != 0) {
-               printf("LM Key does not match expectations!\n");
-               printf("lm_key:\n");
-               dump_data(1, (const char *)lm_key, 8);
-               printf("expected:\n");
-               dump_data(1, (const char *)lm_hash, 8);
-               pass = False;
-       }
+       /* by changing the machine password twice we test the
+          credentials chaining fully, and we verify that the server
+          allows the password to be set to the same value twice in a
+          row (match win2k3) */
+       torture_comment(tctx, 
+               "Testing a second ServerPasswordSet on machine account\n");
+       torture_comment(tctx, 
+               "Changing machine account password to '%s' (same as previous run)\n", password);
 
-       if (break_which == NO_NT) {
-               char lm_key_expected[16];
-               memcpy(lm_key_expected, lm_hash, 8);
-               memset(lm_key_expected+8, '\0', 8);
-               if (memcmp(lm_key_expected, user_session_key, 
-                          16) != 0) {
-                       printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
-                       printf("user_session_key:\n");
-                       dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
-                       printf("expected:\n");
-                       dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
-                       pass = False;
-               }
-       } else {                
-               if (memcmp(session_key.data, user_session_key, 
-                          sizeof(user_session_key)) != 0) {
-                       printf("NT Session Key does not match expectations!\n");
-                       printf("user_session_key:\n");
-                       dump_data(1, (const char *)user_session_key, 16);
-                       printf("expected:\n");
-                       dump_data(1, (const char *)session_key.data, session_key.length);
-                       pass = False;
-               }
-       }
-        return pass;
-}
+       creds_client_authenticator(creds, &r.in.credential);
 
-/* 
- * Test LM authentication, no NT response supplied
- */
+       status = dcerpc_netr_ServerPasswordSet(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (2)");
 
-static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string) 
-{
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
+       }
 
-       return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
-}
+       cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
 
-/* 
- * Test the NTLM response only, no LM.
- */
+       torture_assert(tctx, 
+               test_SetupCredentials(p, tctx, machine_credentials, &creds), 
+               "ServerPasswordSet failed to actually change the password");
 
-static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
+       return true;
 }
 
-/* 
- * Test the NTLM response only, but in the LM field.
- */
-
-static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 
+/*
+  generate a random password for password change tests
+*/
+static DATA_BLOB netlogon_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
 {
-       BOOL pass = True;
-       NTSTATUS nt_status;
-       DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
-
-       uint8_t lm_key[8];
-       uint8_t lm_hash[16];
-       uint8_t user_session_key[16];
-       
-       ZERO_STRUCT(user_session_key);
-
-       SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
-
-       E_deshash(samlogon_state->password, lm_hash); 
-
-       nt_status = check_samlogon(samlogon_state,
-                                  BREAK_NONE,
-                                  &samlogon_state->chall,
-                                  &nt_response,
-                                  NULL,
-                                  lm_key, 
-                                  user_session_key,
-                                  error_string);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return False;
-       }
+       int i;
+       DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
+       generate_random_buffer(password.data, password.length);
 
-       if (memcmp(lm_hash, lm_key, 
-                  sizeof(lm_key)) != 0) {
-               printf("LM Key does not match expectations!\n");
-               printf("lm_key:\n");
-               dump_data(1, (const char *)lm_key, 8);
-               printf("expected:\n");
-               dump_data(1, (const char *)lm_hash, 8);
-               pass = False;
-       }
-       if (memcmp(lm_hash, user_session_key, 8) != 0) {
-               char lm_key_expected[16];
-               memcpy(lm_key_expected, lm_hash, 8);
-               memset(lm_key_expected+8, '\0', 8);
-               if (memcmp(lm_key_expected, user_session_key, 
-                          16) != 0) {
-                       printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
-                       printf("user_session_key:\n");
-                       dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
-                       printf("expected:\n");
-                       dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
-                       pass = False;
+       for (i=0; i < len; i++) {
+               if (((uint16_t *)password.data)[i] == 0) {
+                       ((uint16_t *)password.data)[i] = 1;
                }
        }
-        return pass;
-}
 
-/* 
- * Test the NTLM response only, but in the both the NT and LM fields.
- */
+       return password;
+}
 
-static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 
+/*
+  try a change password for our machine account
+*/
+static bool test_SetPassword2(struct torture_context *tctx, 
+                             struct dcerpc_pipe *p, 
+                             struct cli_credentials *machine_credentials)
 {
-       BOOL pass = True;
-       NTSTATUS nt_status;
-       DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
-       DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
-
-       char lm_key[8];
-       char lm_hash[16];
-       char user_session_key[16];
-       char nt_hash[16];
-       
-       ZERO_STRUCT(lm_key);
-       ZERO_STRUCT(user_session_key);
-
-       SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
-                    nt_response.data);
-       E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
-       SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 
-                          session_key.data);
-
-       E_deshash(samlogon_state->password, (uint8_t *)lm_hash); 
-
-       nt_status = check_samlogon(samlogon_state,
-                                  BREAK_NONE,
-                                  &samlogon_state->chall,
-                                  NULL, 
-                                  &nt_response,
-                                  lm_key, 
-                                  user_session_key,
-                                  error_string);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return False;
-       }
+       NTSTATUS status;
+       struct netr_ServerPasswordSet2 r;
+       const char *password;
+       DATA_BLOB new_random_pass;
+       struct creds_CredentialState *creds;
+       struct samr_CryptPassword password_buf;
+       struct samr_Password nt_hash;
 
-       if (memcmp(lm_hash, lm_key, 
-                  sizeof(lm_key)) != 0) {
-               printf("LM Key does not match expectations!\n");
-               printf("lm_key:\n");
-               dump_data(1, lm_key, 8);
-               printf("expected:\n");
-               dump_data(1, lm_hash, 8);
-               pass = False;
-       }
-       if (memcmp(session_key.data, user_session_key, 
-                  sizeof(user_session_key)) != 0) {
-               printf("NT Session Key does not match expectations!\n");
-               printf("user_session_key:\n");
-               dump_data(1, user_session_key, 16);
-               printf("expected:\n");
-               dump_data(1, (const char *)session_key.data, session_key.length);
-               pass = False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
+       r.in.secure_channel_type = SEC_CHAN_BDC;
+       r.in.computer_name = TEST_MACHINE_NAME;
 
-        return pass;
-}
+       password = generate_random_str(tctx, 8);
+       encode_pw_buffer(password_buf.data, password, STR_UNICODE);
+       creds_arcfour_crypt(creds, password_buf.data, 516);
 
-/* 
- * Test the NTLMv2 and LMv2 responses
- */
+       memcpy(r.in.new_password.data, password_buf.data, 512);
+       r.in.new_password.length = IVAL(password_buf.data, 512);
 
-static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
-{
-       BOOL pass = True;
-       NTSTATUS nt_status;
-       DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
-       DATA_BLOB lmv2_response = data_blob(NULL, 0);
-       DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
-       DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
+       torture_comment(tctx, "Testing ServerPasswordSet2 on machine account\n");
+       torture_comment(tctx, "Changing machine account password to '%s'\n", password);
 
-       uint8_t user_session_key[16];
+       creds_client_authenticator(creds, &r.in.credential);
 
-       ZERO_STRUCT(user_session_key);
-       
-       /* TODO - test with various domain cases, and without domain */
-       if (!SMBNTLMv2encrypt(samlogon_state->account_name, lp_workgroup(), 
-                             samlogon_state->password, &samlogon_state->chall,
-                             &names_blob,
-                             &lmv2_response, &ntlmv2_response, 
-                             &ntlmv2_session_key)) {
-               data_blob_free(&names_blob);
-               return False;
-       }
-       data_blob_free(&names_blob);
-
-       nt_status = check_samlogon(samlogon_state,
-                                  break_which,
-                                  &samlogon_state->chall,
-                                  &lmv2_response,
-                                  &ntlmv2_response,
-                                  NULL, 
-                                  user_session_key,
-                                  error_string);
-       
-       data_blob_free(&lmv2_response);
-       data_blob_free(&ntlmv2_response);
+       status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2");
 
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return break_which == BREAK_NT;
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
        }
 
-       if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, 
-                  sizeof(user_session_key)) != 0) {
-               printf("USER (NTLMv2) Session Key does not match expectations!\n");
-               printf("user_session_key:\n");
-               dump_data(1, (const char *)user_session_key, 16);
-               printf("expected:\n");
-               dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
-               pass = False;
-       }
-        return pass;
-}
+       cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
 
-/* 
- * Test the NTLMv2 and LMv2 responses
- */
+       if (!torture_setting_bool(tctx, "dangerous", false)) {
+               torture_comment(tctx, 
+                       "Not testing ability to set password to '', enable dangerous tests to perform this test\n");
+       } else {
+               /* by changing the machine password to ""
+                * we check if the server uses password restrictions
+                * for ServerPasswordSet2
+                * (win2k3 accepts "")
+                */
+               password = "";
+               encode_pw_buffer(password_buf.data, password, STR_UNICODE);
+               creds_arcfour_crypt(creds, password_buf.data, 516);
+               
+               memcpy(r.in.new_password.data, password_buf.data, 512);
+               r.in.new_password.length = IVAL(password_buf.data, 512);
+               
+               torture_comment(tctx, 
+                       "Testing ServerPasswordSet2 on machine account\n");
+               torture_comment(tctx, 
+                       "Changing machine account password to '%s'\n", password);
+               
+               creds_client_authenticator(creds, &r.in.credential);
+               
+               status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2");
+               
+               if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+                       torture_comment(tctx, "Credential chaining failed\n");
+               }
+               
+               cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
+       }
 
-static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
-}
+       torture_assert(tctx, test_SetupCredentials(p, tctx, machine_credentials, &creds), 
+               "ServerPasswordSet failed to actually change the password");
 
-/* 
- * Test the LMv2 response only
- */
+       /* now try a random password */
+       password = generate_random_str(tctx, 8);
+       encode_pw_buffer(password_buf.data, password, STR_UNICODE);
+       creds_arcfour_crypt(creds, password_buf.data, 516);
 
-static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
-}
+       memcpy(r.in.new_password.data, password_buf.data, 512);
+       r.in.new_password.length = IVAL(password_buf.data, 512);
 
-/* 
- * Test the NTLMv2 response only
- */
+       torture_comment(tctx, "Testing second ServerPasswordSet2 on machine account\n");
+       torture_comment(tctx, "Changing machine account password to '%s'\n", password);
 
-static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
-}
+       creds_client_authenticator(creds, &r.in.credential);
 
-static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
-}
+       status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet2 (2)");
 
-static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
-}
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
+       }
 
-static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
-}
+       /* by changing the machine password twice we test the
+          credentials chaining fully, and we verify that the server
+          allows the password to be set to the same value twice in a
+          row (match win2k3) */
+       torture_comment(tctx, 
+               "Testing a second ServerPasswordSet2 on machine account\n");
+       torture_comment(tctx, 
+               "Changing machine account password to '%s' (same as previous run)\n", password);
 
-static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
-}
+       creds_client_authenticator(creds, &r.in.credential);
 
-static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
-{
-       return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
-}
+       status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (3)");
 
-static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
-{
-       NTSTATUS nt_status;
-       DATA_BLOB nt_response = data_blob(NULL, 0);
-       DATA_BLOB lm_response = data_blob(NULL, 0);
-       char *password;
-       char *dospw;
-       smb_ucs2_t *unicodepw;
-
-       uint8_t user_session_key[16];
-       uint8_t lm_key[16];
-       static const uint8_t zeros[8];
-       DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
-
-       ZERO_STRUCT(user_session_key);
-       
-       if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw, 
-                             samlogon_state->password)) == -1) {
-               DEBUG(0, ("push_ucs2_allocate failed!\n"));
-               exit(1);
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
        }
 
-       nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, 
-                                      strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
+       cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
 
-       password = strdup_upper(samlogon_state->password);
+       torture_assert (tctx, 
+               test_SetupCredentials(p, tctx, machine_credentials, &creds), 
+               "ServerPasswordSet failed to actually change the password");
 
-       if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
-                                  CH_DOS, password,
-                                  strlen(password)+1, 
-                                  (const void**)&dospw)) == -1) {
-               DEBUG(0, ("push_ascii_allocate failed!\n"));
-               exit(1);
-       }
+       new_random_pass = netlogon_very_rand_pass(tctx, 128);
 
-       SAFE_FREE(password);
+       /* now try a random stream of bytes for a password */
+       set_pw_in_buffer(password_buf.data, &new_random_pass);
 
-       lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
+       creds_arcfour_crypt(creds, password_buf.data, 516);
 
-       nt_status = check_samlogon(samlogon_state,
-                                  break_which,
-                                  &chall,
-                                  &lm_response,
-                                  &nt_response,
-                                  lm_key, 
-                                  user_session_key,
-                                  error_string);
-       
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return break_which == BREAK_NT;
-       }
+       memcpy(r.in.new_password.data, password_buf.data, 512);
+       r.in.new_password.length = IVAL(password_buf.data, 512);
 
-       return True;
-}
+       torture_comment(tctx, 
+               "Testing a third ServerPasswordSet2 on machine account, with a compleatly random password\n");
 
-static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
-                                      char **error_string) {
-       return test_plaintext(samlogon_state, BREAK_NONE, error_string);
-}
+       creds_client_authenticator(creds, &r.in.credential);
 
-static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
-                                    char **error_string) {
-       return test_plaintext(samlogon_state, BREAK_LM, error_string);
-}
+       status = dcerpc_netr_ServerPasswordSet2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet (3)");
 
-static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
-                                    char **error_string) {
-       return test_plaintext(samlogon_state, BREAK_NT, error_string);
-}
+       if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
+               torture_comment(tctx, "Credential chaining failed\n");
+       }
 
-static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
-                                  char **error_string) {
-       return test_plaintext(samlogon_state, NO_LM, error_string);
-}
+       mdfour(nt_hash.hash, new_random_pass.data, new_random_pass.length);
 
-static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
-                                  char **error_string) {
-       return test_plaintext(samlogon_state, NO_NT, error_string);
-}
+       cli_credentials_set_password(machine_credentials, NULL, CRED_UNINITIALISED);
+       cli_credentials_set_nt_hash(machine_credentials, &nt_hash, CRED_SPECIFIED);
 
-/* 
-   Tests:
-   
-   - LM only
-   - NT and LM            
-   - NT
-   - NT in LM field
-   - NT in both fields
-   - NTLMv2
-   - NTLMv2 and LMv2
-   - LMv2
-   - plaintext tests (in challenge-response fields)
-  
-   check we get the correct session key in each case
-   check what values we get for the LM session key
-   
-*/
+       torture_assert (tctx, 
+               test_SetupCredentials(p, tctx, machine_credentials, &creds), 
+               "ServerPasswordSet failed to actually change the password");
 
-static const struct ntlm_tests {
-       BOOL (*fn)(struct samlogon_state *, char **);
-       const char *name;
-       BOOL expect_fail;
-} test_table[] = {
-       {test_lm, "LM", False},
-       {test_lm_ntlm, "LM and NTLM", False},
-       {test_ntlm, "NTLM", False},
-       {test_ntlm_in_lm, "NTLM in LM", False},
-       {test_ntlm_in_both, "NTLM in both", False},
-       {test_ntlmv2, "NTLMv2", False},
-       {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
-       {test_lmv2, "LMv2", False},
-       {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
-       {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
-       {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
-       {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
-       {test_plaintext_none_broken, "Plaintext", True},
-       {test_plaintext_lm_broken, "Plaintext LM broken", True},
-       {test_plaintext_nt_broken, "Plaintext NT broken", True},
-       {test_plaintext_nt_only, "Plaintext NT only", True},
-       {test_plaintext_lm_only, "Plaintext LM only", True},
-       {NULL, NULL}
-};
+       return true;
+}
 
-/*
-  try a netlogon SamLogon
-*/
-static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_GetPassword(struct torture_context *tctx,
+                            struct dcerpc_pipe *p,
+                            struct cli_credentials *machine_credentials)
 {
-       int i, j;
-       BOOL ret = True;
-       int validation_levels[] = {2,3,6};
-       struct samlogon_state samlogon_state;
-       
-       samlogon_state.mem_ctx = mem_ctx;
-       samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
-       samlogon_state.password = lp_parm_string(-1, "torture", "password");
-       samlogon_state.p = p;
-
-       samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
-
-       generate_random_buffer(samlogon_state.chall.data, 8);
+       struct netr_ServerPasswordGet r;
+       struct creds_CredentialState *creds;
+       struct netr_Authenticator credential;
+       NTSTATUS status;
+       struct netr_Authenticator return_authenticator;
+       struct samr_Password password;
 
-       if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
-               return False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
-               return False;
-       }
+       creds_client_authenticator(creds, &credential);
 
-       if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
-               return False;
-       }
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
+       r.in.secure_channel_type = SEC_CHAN_BDC;
+       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.credential = &credential;
+       r.out.return_authenticator = &return_authenticator;
+       r.out.password = &password;
 
-       samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
-       samlogon_state.r.in.credential = &samlogon_state.auth;
-       samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
-
-       for (i=0;i<ARRAY_SIZE(validation_levels);i++) {
-               samlogon_state.r.in.validation_level = validation_levels[i];
-               for (j=0; test_table[j].fn; j++) {
-                       char *error_string = NULL;
-                       printf("Testing SamLogon with '%s' at validation level %d\n", 
-                              test_table[j].name, validation_levels[i]);
-       
-                       if (!test_table[j].fn(&samlogon_state, &error_string)) {
-                               if (test_table[j].expect_fail) {
-                                       printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
-                               } else {
-                                       printf("Test %s failed: %s\n", test_table[j].name, error_string);
-                                       ret = False;
-                               }
-                               SAFE_FREE(error_string);
-                       }
-               }
-       }
+       status = dcerpc_netr_ServerPasswordGet(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerPasswordGet");
 
-       return ret;
+       return true;
 }
 
-
-/*
-  try a change password for our machine account
-*/
-static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_GetTrustPasswords(struct torture_context *tctx,
+                                  struct dcerpc_pipe *p,
+                                  struct cli_credentials *machine_credentials)
 {
+       struct netr_ServerTrustPasswordsGet r;
+       struct creds_CredentialState *creds;
+       struct netr_Authenticator credential;
        NTSTATUS status;
-       struct netr_ServerPasswordSet r;
-       const char *password;
-       struct creds_CredentialState creds;
+       struct netr_Authenticator return_authenticator;
+       struct samr_Password password, password2;
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               return False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
+       creds_client_authenticator(creds, &credential);
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
        r.in.secure_channel_type = SEC_CHAN_BDC;
        r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.credential = &credential;
+       r.out.return_authenticator = &return_authenticator;
+       r.out.password = &password;
+       r.out.password2 = &password2;
 
-       password = generate_random_str(mem_ctx, 8);
-       E_md4hash(password, r.in.new_password.hash);
-
-       creds_des_encrypt(&creds, &r.in.new_password);
+       status = dcerpc_netr_ServerTrustPasswordsGet(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "ServerTrustPasswordsGet");
 
-       printf("Testing ServerPasswordSet on machine account\n");
-       printf("Changing machine account password to '%s'\n", password);
+       return true;
+}
 
-       creds_client_authenticator(&creds, &r.in.credential);
+/*
+  try a netlogon SamLogon
+*/
+bool test_netlogon_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
+                             struct cli_credentials *credentials, 
+                             struct creds_CredentialState *creds)
+{
+       NTSTATUS status;
+       struct netr_LogonSamLogon r;
+       struct netr_Authenticator auth, auth2;
+       union netr_LogonLevel logon;
+       union netr_Validation validation;
+       uint8_t authoritative;
+       struct netr_NetworkInfo ninfo;
+       DATA_BLOB names_blob, chal, lm_resp, nt_resp;
+       int i;
+       int flags = CLI_CRED_NTLM_AUTH;
+       if (lp_client_lanman_auth(tctx->lp_ctx)) {
+               flags |= CLI_CRED_LANMAN_AUTH;
+       }
 
-       status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerPasswordSet - %s\n", nt_errstr(status));
-               return False;
+       if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
+               flags |= CLI_CRED_NTLMv2_AUTH;
        }
 
-       if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
-               printf("Credential chaining failed\n");
+       cli_credentials_get_ntlm_username_domain(cmdline_credentials, tctx, 
+                                                &ninfo.identity_info.account_name.string,
+                                                &ninfo.identity_info.domain_name.string);
+       
+       generate_random_buffer(ninfo.challenge, 
+                              sizeof(ninfo.challenge));
+       chal = data_blob_const(ninfo.challenge, 
+                              sizeof(ninfo.challenge));
+
+       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);
+       torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
+
+       ninfo.lm.data = lm_resp.data;
+       ninfo.lm.length = lm_resp.length;
+
+       ninfo.nt.data = nt_resp.data;
+       ninfo.nt.length = nt_resp.length;
+
+       ninfo.identity_info.parameter_control = 0;
+       ninfo.identity_info.logon_id_low = 0;
+       ninfo.identity_info.logon_id_high = 0;
+       ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
+
+       logon.network = &ninfo;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.computer_name = cli_credentials_get_workstation(credentials);
+       r.in.credential = &auth;
+       r.in.return_authenticator = &auth2;
+       r.in.logon_level = 2;
+       r.in.logon = &logon;
+       r.out.validation = &validation;
+       r.out.authoritative = &authoritative;
+
+       d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
+       
+       for (i=2;i<3;i++) {
+               ZERO_STRUCT(auth2);
+               creds_client_authenticator(creds, &auth);
+               
+               r.in.validation_level = i;
+               
+               status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
+               
+               torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
+                       "Credential chaining failed");
        }
 
-       /* by changing the machine password twice we test the
-          credentials chaining fully, and we verify that the server
-          allows the password to be set to the same value twice in a
-          row (match win2k3) */
-       printf("Testing a second ServerPasswordSet on machine account\n");
-       printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
+       r.in.credential = NULL;
 
-       creds_client_authenticator(&creds, &r.in.credential);
+       for (i=2;i<=3;i++) {
 
-       status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
-               return False;
-       }
+               r.in.validation_level = i;
 
-       if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
-               printf("Credential chaining failed\n");
-       }
+               torture_comment(tctx, "Testing SamLogon with validation level %d and a NULL credential\n", i);
 
-       machine_password = password;
+               status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
+               torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, 
+                       "LogonSamLogon expected INVALID_PARAMETER");
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               printf("ServerPasswordSet failed to actually change the password\n");
-               return False;
        }
 
-       return True;
+       return true;
 }
 
+/*
+  try a netlogon SamLogon
+*/
+static bool test_SamLogon(struct torture_context *tctx, 
+                         struct dcerpc_pipe *p,
+                         struct cli_credentials *credentials)
+{
+       struct creds_CredentialState *creds;
+
+       if (!test_SetupCredentials(p, tctx, credentials, &creds)) {
+               return false;
+       }
+
+       return test_netlogon_ops(p, tctx, credentials, creds);
+}
 
 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
 static uint64_t sequence_nums[3];
@@ -1010,458 +686,506 @@ static uint64_t sequence_nums[3];
 /*
   try a netlogon DatabaseSync
 */
-static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_DatabaseSync(struct torture_context *tctx, 
+                             struct dcerpc_pipe *p,
+                             struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_DatabaseSync r;
-       struct creds_CredentialState creds;
-       const uint32_t database_ids[] = {0, 1, 2}; 
+       struct creds_CredentialState *creds;
+       const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
        int i;
-       BOOL ret = True;
+       struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+       struct netr_Authenticator credential, return_authenticator;
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               return False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       ZERO_STRUCT(return_authenticator);
+
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computername = TEST_MACHINE_NAME;
        r.in.preferredmaximumlength = (uint32_t)-1;
-       ZERO_STRUCT(r.in.return_authenticator);
+       r.in.return_authenticator = &return_authenticator;
+       r.out.delta_enum_array = &delta_enum_array;
+       r.out.return_authenticator = &return_authenticator;
 
        for (i=0;i<ARRAY_SIZE(database_ids);i++) {
-               r.in.sync_context = 0;
+
+               uint32_t sync_context = 0;
+
                r.in.database_id = database_ids[i];
+               r.in.sync_context = &sync_context;
+               r.out.sync_context = &sync_context;
 
-               printf("Testing DatabaseSync of id %d\n", r.in.database_id);
+               torture_comment(tctx, "Testing DatabaseSync of id %d\n", r.in.database_id);
 
                do {
-                       creds_client_authenticator(&creds, &r.in.credential);
-
-                       status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
-                       if (!NT_STATUS_IS_OK(status) &&
-                           !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-                               printf("DatabaseSync - %s\n", nt_errstr(status));
-                               ret = False;
-                               break;
-                       }
+                       creds_client_authenticator(creds, &credential);
+
+                       r.in.credential = &credential;
 
-                       if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
-                               printf("Credential chaining failed\n");
+                       status = dcerpc_netr_DatabaseSync(p, tctx, &r);
+                       if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
+                           break;
+
+                       /* Native mode servers don't do this */
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+                               return true;
                        }
+                       torture_assert_ntstatus_ok(tctx, status, "DatabaseSync");
 
-                       r.in.sync_context = r.out.sync_context;
+                       if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
+                               torture_comment(tctx, "Credential chaining failed\n");
+                       }
 
-                       if (r.out.delta_enum_array &&
-                           r.out.delta_enum_array->num_deltas > 0 &&
-                           r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
-                           r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
+                       if (delta_enum_array &&
+                           delta_enum_array->num_deltas > 0 &&
+                           delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
+                           delta_enum_array->delta_enum[0].delta_union.domain) {
                                sequence_nums[r.in.database_id] = 
-                                       r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
-                               printf("\tsequence_nums[%d]=%llu\n",
+                                       delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
+                               torture_comment(tctx, "\tsequence_nums[%d]=%llu\n",
                                       r.in.database_id, 
-                                      sequence_nums[r.in.database_id]);
+                                      (unsigned long long)sequence_nums[r.in.database_id]);
                        }
                } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
        }
 
-       return ret;
+       return true;
 }
 
 
 /*
   try a netlogon DatabaseDeltas
 */
-static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_DatabaseDeltas(struct torture_context *tctx, 
+                               struct dcerpc_pipe *p,
+                               struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_DatabaseDeltas r;
-       struct creds_CredentialState creds;
+       struct creds_CredentialState *creds;
+       struct netr_Authenticator credential;
+       struct netr_Authenticator return_authenticator;
+       struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
        const uint32_t database_ids[] = {0, 1, 2}; 
        int i;
-       BOOL ret = True;
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               return False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computername = TEST_MACHINE_NAME;
        r.in.preferredmaximumlength = (uint32_t)-1;
        ZERO_STRUCT(r.in.return_authenticator);
+       r.out.return_authenticator = &return_authenticator;
+       r.out.delta_enum_array = &delta_enum_array;
 
        for (i=0;i<ARRAY_SIZE(database_ids);i++) {
                r.in.database_id = database_ids[i];
-               r.in.sequence_num = sequence_nums[r.in.database_id];
+               r.in.sequence_num = &sequence_nums[r.in.database_id];
 
-               if (r.in.sequence_num == 0) continue;
+               if (*r.in.sequence_num == 0) continue;
 
-               r.in.sequence_num -= 1;
+               *r.in.sequence_num -= 1;
 
-
-               printf("Testing DatabaseDeltas of id %d at %llu\n", 
-                      r.in.database_id, r.in.sequence_num);
+               torture_comment(tctx, "Testing DatabaseDeltas of id %d at %llu\n", 
+                      r.in.database_id, (unsigned long long)*r.in.sequence_num);
 
                do {
-                       creds_client_authenticator(&creds, &r.in.credential);
-
-                       status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
-                       if (!NT_STATUS_IS_OK(status) &&
-                           !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-                               printf("DatabaseDeltas - %s\n", nt_errstr(status));
-                               ret = False;
-                               break;
+                       creds_client_authenticator(creds, &credential);
+
+                       status = dcerpc_netr_DatabaseDeltas(p, tctx, &r);
+                       if (NT_STATUS_EQUAL(status, 
+                                            NT_STATUS_SYNCHRONIZATION_REQUIRED)) {
+                               torture_comment(tctx, "not considering %s to be an error\n",
+                                      nt_errstr(status));
+                               return true;
                        }
+                       if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) 
+                           break;
+
+                       torture_assert_ntstatus_ok(tctx, status, "DatabaseDeltas");
 
-                       if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
-                               printf("Credential chaining failed\n");
+                       if (!creds_client_check(creds, &return_authenticator.cred)) {
+                               torture_comment(tctx, "Credential chaining failed\n");
                        }
 
-                       r.in.sequence_num++;
+                       (*r.in.sequence_num)++;
                } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
        }
 
-       return ret;
+       return true;
 }
 
 
 /*
   try a netlogon AccountDeltas
 */
-static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_AccountDeltas(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p,
+                              struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_AccountDeltas r;
-       struct creds_CredentialState creds;
-       BOOL ret = True;
+       struct creds_CredentialState *creds;
+
+       struct netr_AccountBuffer buffer;
+       uint32_t count_returned = 0;
+       uint32_t total_entries = 0;
+       struct netr_UAS_INFO_0 recordid;
+       struct netr_Authenticator return_authenticator;
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               return False;
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       ZERO_STRUCT(return_authenticator);
+
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computername = TEST_MACHINE_NAME;
-       ZERO_STRUCT(r.in.return_authenticator);
-       creds_client_authenticator(&creds, &r.in.credential);
+       r.in.return_authenticator = &return_authenticator;
+       creds_client_authenticator(creds, &r.in.credential);
        ZERO_STRUCT(r.in.uas);
        r.in.count=10;
        r.in.level=0;
        r.in.buffersize=100;
-
-       printf("Testing AccountDeltas\n");
+       r.out.buffer = &buffer;
+       r.out.count_returned = &count_returned;
+       r.out.total_entries = &total_entries;
+       r.out.recordid = &recordid;
+       r.out.return_authenticator = &return_authenticator;
 
        /* w2k3 returns "NOT IMPLEMENTED" for this call */
-       status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
-               printf("AccountDeltas - %s\n", nt_errstr(status));
-               ret = False;
-       }
+       status = dcerpc_netr_AccountDeltas(p, tctx, &r);
+       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "AccountDeltas");
 
-       return ret;
+       return true;
 }
 
 /*
   try a netlogon AccountSync
 */
-static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_AccountSync(struct torture_context *tctx, struct dcerpc_pipe *p, 
+                            struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_AccountSync r;
-       struct creds_CredentialState creds;
-       BOOL ret = True;
+       struct creds_CredentialState *creds;
 
-       if (!test_SetupCredentials(p, mem_ctx, &creds)) {
-               return False;
+       struct netr_AccountBuffer buffer;
+       uint32_t count_returned = 0;
+       uint32_t total_entries = 0;
+       uint32_t next_reference = 0;
+       struct netr_UAS_INFO_0 recordid;
+       struct netr_Authenticator return_authenticator;
+
+       ZERO_STRUCT(recordid);
+       ZERO_STRUCT(return_authenticator);
+
+       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+               return false;
        }
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computername = TEST_MACHINE_NAME;
-       ZERO_STRUCT(r.in.return_authenticator);
-       creds_client_authenticator(&creds, &r.in.credential);
-       ZERO_STRUCT(r.in.recordid);
+       r.in.return_authenticator = &return_authenticator;
+       creds_client_authenticator(creds, &r.in.credential);
+       r.in.recordid = &recordid;
        r.in.reference=0;
        r.in.level=0;
        r.in.buffersize=100;
-
-       printf("Testing AccountSync\n");
+       r.out.buffer = &buffer;
+       r.out.count_returned = &count_returned;
+       r.out.total_entries = &total_entries;
+       r.out.next_reference = &next_reference;
+       r.out.recordid = &recordid;
+       r.out.return_authenticator = &return_authenticator;
 
        /* w2k3 returns "NOT IMPLEMENTED" for this call */
-       status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
-               printf("AccountSync - %s\n", nt_errstr(status));
-               ret = False;
-       }
+       status = dcerpc_netr_AccountSync(p, tctx, &r);
+       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "AccountSync");
 
-       return ret;
+       return true;
 }
 
 /*
   try a netlogon GetDcName
 */
-static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_GetDcName(struct torture_context *tctx, 
+                          struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_GetDcName r;
+       const char *dcname = NULL;
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.domainname = lp_workgroup();
-
-       printf("Testing GetDcName\n");
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.domainname = lp_workgroup(tctx->lp_ctx);
+       r.out.dcname = &dcname;
 
-       status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("GetDcName - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_GetDcName(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "GetDcName");
+       torture_assert_werr_ok(tctx, r.out.result, "GetDcName");
 
-       printf("\tDC is at '%s'\n", r.out.dcname);
+       torture_comment(tctx, "\tDC is at '%s'\n", dcname);
 
-       return True;
+       return true;
 }
 
 /*
   try a netlogon LogonControl 
 */
-static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_LogonControl(struct torture_context *tctx, 
+                             struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_LogonControl r;
-       BOOL ret = True;
+       union netr_CONTROL_QUERY_INFORMATION info;
        int i;
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.function_code = 1;
+       r.out.info = &info;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl level %d\n", i);
+               torture_comment(tctx, "Testing LogonControl level %d\n", i);
 
-               status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
-       return ret;
+       return true;
 }
 
 
 /*
   try a netlogon GetAnyDCName
 */
-static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_GetAnyDCName(struct torture_context *tctx, 
+                             struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_GetAnyDCName r;
+       const char *dcname = NULL;
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.domainname = lp_workgroup();
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.domainname = lp_workgroup(tctx->lp_ctx);
+       r.out.dcname = &dcname;
 
-       printf("Testing GetAnyDCName\n");
+       status = dcerpc_netr_GetAnyDCName(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "GetAnyDCName");
 
-       status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("GetAnyDCName - %s\n", nt_errstr(status));
-               return False;
+       if (dcname) {
+           torture_comment(tctx, "\tDC is at '%s'\n", dcname);
        }
 
-       if (r.out.dcname) {
-               printf("\tDC is at '%s'\n", r.out.dcname);
-       }
-
-       return True;
+       return true;
 }
 
 
 /*
   try a netlogon LogonControl2
 */
-static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_LogonControl2(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_LogonControl2 r;
-       BOOL ret = True;
+       union netr_CONTROL_DATA_INFORMATION data;
+       union netr_CONTROL_QUERY_INFORMATION query;
        int i;
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       data.domain = lp_workgroup(tctx->lp_ctx);
+
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 
        r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
-       r.in.data.domain = lp_workgroup();
+       r.in.data = &data;
+       r.out.query = &query;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2 level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
+       data.domain = lp_workgroup(tctx->lp_ctx);
+
        r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
-       r.in.data.domain = lp_workgroup();
+       r.in.data = &data;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2 level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
+       data.domain = lp_workgroup(tctx->lp_ctx);
+
        r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
-       r.in.data.domain = lp_workgroup();
+       r.in.data = &data;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2 level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
+       data.debug_level = ~0;
+
        r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
-       r.in.data.debug_level = ~0;
+       r.in.data = &data;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2 level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
-       return ret;
+       return true;
 }
 
 /*
   try a netlogon DatabaseSync2
 */
-static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_DatabaseSync2(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p,
+                              struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_DatabaseSync2 r;
-       struct creds_CredentialState creds;
+       struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+       struct netr_Authenticator return_authenticator, credential;
+
+       struct creds_CredentialState *creds;
        const uint32_t database_ids[] = {0, 1, 2}; 
        int i;
-       BOOL ret = True;
 
-       if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
-               return False;
+       if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_FLAGS, 
+                                   machine_credentials,
+                                   SEC_CHAN_BDC, &creds)) {
+               return false;
        }
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       ZERO_STRUCT(return_authenticator);
+
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computername = TEST_MACHINE_NAME;
        r.in.preferredmaximumlength = (uint32_t)-1;
-       ZERO_STRUCT(r.in.return_authenticator);
+       r.in.return_authenticator = &return_authenticator;
+       r.out.return_authenticator = &return_authenticator;
+       r.out.delta_enum_array = &delta_enum_array;
 
        for (i=0;i<ARRAY_SIZE(database_ids);i++) {
-               r.in.sync_context = 0;
+
+               uint32_t sync_context = 0;
+
                r.in.database_id = database_ids[i];
+               r.in.sync_context = &sync_context;
+               r.out.sync_context = &sync_context;
                r.in.restart_state = 0;
 
-               printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
+               torture_comment(tctx, "Testing DatabaseSync2 of id %d\n", r.in.database_id);
 
                do {
-                       creds_client_authenticator(&creds, &r.in.credential);
-
-                       status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
-                       if (!NT_STATUS_IS_OK(status) &&
-                           !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-                               printf("DatabaseSync2 - %s\n", nt_errstr(status));
-                               ret = False;
-                               break;
+                       creds_client_authenticator(creds, &credential);
+
+                       r.in.credential = &credential;
+
+                       status = dcerpc_netr_DatabaseSync2(p, tctx, &r);
+                       if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
+                           break;
+
+                       /* Native mode servers don't do this */
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+                               return true;
                        }
 
-                       if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
-                               printf("Credential chaining failed\n");
+                       torture_assert_ntstatus_ok(tctx, status, "DatabaseSync2");
+
+                       if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
+                               torture_comment(tctx, "Credential chaining failed\n");
                        }
 
-                       r.in.sync_context = r.out.sync_context;
                } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
        }
 
-       return ret;
+       return true;
 }
 
 
 /*
   try a netlogon LogonControl2Ex
 */
-static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_LogonControl2Ex(struct torture_context *tctx, 
+                                struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_LogonControl2Ex r;
-       BOOL ret = True;
+       union netr_CONTROL_QUERY_INFORMATION query;
        int i;
 
-       r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 
        r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
-       r.in.data.domain = lp_workgroup();
+       r.in.data.domain = lp_workgroup(tctx->lp_ctx);
+       r.out.query = &query;
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2Ex level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
        r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
-       r.in.data.domain = lp_workgroup();
+       r.in.data.domain = lp_workgroup(tctx->lp_ctx);
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2Ex level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
        r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
-       r.in.data.domain = lp_workgroup();
+       r.in.data.domain = lp_workgroup(tctx->lp_ctx);
 
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2Ex level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
        r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
@@ -1470,128 +1194,345 @@ static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        for (i=1;i<4;i++) {
                r.in.level = i;
 
-               printf("Testing LogonControl2Ex level %d function %d\n", 
+               torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
                       i, r.in.function_code);
 
-               status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LogonControl - %s\n", nt_errstr(status));
-                       ret = False;
-               }
+               status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "LogonControl");
        }
 
-       return ret;
+       return true;
 }
 
+static bool test_netr_DsRGetForestTrustInformation(struct torture_context *tctx, 
+                                                  struct dcerpc_pipe *p, const char *trusted_domain_name) 
+{
+       NTSTATUS status;
+       struct netr_DsRGetForestTrustInformation r;
+       struct lsa_ForestTrustInformation info, *info_ptr;
+
+       info_ptr = &info;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.trusted_domain_name = trusted_domain_name;
+       r.in.flags = 0;
+       r.out.forest_trust_info = &info_ptr;
+
+       torture_comment(tctx ,"Testing netr_DsRGetForestTrustInformation\n");
+
+       status = dcerpc_netr_DsRGetForestTrustInformation(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsRGetForestTrustInformation");
+       torture_assert_werr_ok(tctx, r.out.result, "DsRGetForestTrustInformation");
+
+       return true;
+}
 
 /*
   try a netlogon netr_DsrEnumerateDomainTrusts
 */
-static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+static bool test_DsrEnumerateDomainTrusts(struct torture_context *tctx, 
+                                         struct dcerpc_pipe *p)
 {
        NTSTATUS status;
        struct netr_DsrEnumerateDomainTrusts r;
+       struct netr_DomainTrustList trusts;
+       int i;
 
-       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.trust_flags = 0x3f;
+       r.out.trusts = &trusts;
+
+       status = dcerpc_netr_DsrEnumerateDomainTrusts(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsrEnumerateDomaintrusts");
+       torture_assert_werr_ok(tctx, r.out.result, "DsrEnumerateDomaintrusts");
 
-       printf("Testing netr_DsrEnumerateDomainTrusts\n");
+       /* when trusted_domain_name is NULL, netr_DsRGetForestTrustInformation
+        * will show non-forest trusts and all UPN suffixes of the own forest
+        * as LSA_FOREST_TRUST_TOP_LEVEL_NAME types */
 
-       status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
-               printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
-                      nt_errstr(status), win_errstr(r.out.result));
-               return False;
+       if (r.out.trusts->count) {
+               if (!test_netr_DsRGetForestTrustInformation(tctx, p, NULL)) {
+                       return false;
+               }
+       }
+
+       for (i=0; i<r.out.trusts->count; i++) {
+
+               /* get info for transitive forest trusts */
+
+               if (r.out.trusts->array[i].trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
+                       if (!test_netr_DsRGetForestTrustInformation(tctx, p, 
+                                                                   r.out.trusts->array[i].dns_name)) {
+                               return false;
+                       }
+               }
        }
 
-       return True;
+       return true;
 }
 
+static bool test_netr_NetrEnumerateTrustedDomains(struct torture_context *tctx,
+                                                 struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_NetrEnumerateTrustedDomains r;
+       struct netr_Blob trusted_domains_blob;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.out.trusted_domains_blob = &trusted_domains_blob;
+
+       status = dcerpc_netr_NetrEnumerateTrustedDomains(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_NetrEnumerateTrustedDomains");
+       torture_assert_werr_ok(tctx, r.out.result, "NetrEnumerateTrustedDomains");
+
+       return true;
+}
+
+static bool test_netr_NetrEnumerateTrustedDomainsEx(struct torture_context *tctx,
+                                                   struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_NetrEnumerateTrustedDomainsEx r;
+       struct netr_DomainTrustList dom_trust_list;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.out.dom_trust_list = &dom_trust_list;
+
+       status = dcerpc_netr_NetrEnumerateTrustedDomainsEx(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_NetrEnumerateTrustedDomainsEx");
+       torture_assert_werr_ok(tctx, r.out.result, "NetrEnumerateTrustedDomainsEx");
+
+       return true;
+}
+
+
+static bool test_netr_DsRGetSiteName(struct dcerpc_pipe *p, struct torture_context *tctx,
+                                    const char *computer_name, 
+                                    const char *expected_site) 
+{
+       NTSTATUS status;
+       struct netr_DsRGetSiteName r;
+       const char *site = NULL;
+
+       if (torture_setting_bool(tctx, "samba4", false))
+               torture_skip(tctx, "skipping DsRGetSiteName test against Samba4");
+
+       r.in.computer_name              = computer_name;
+       r.out.site                      = &site;
+       torture_comment(tctx, "Testing netr_DsRGetSiteName\n");
+
+       status = dcerpc_netr_DsRGetSiteName(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsRGetSiteName");
+       torture_assert_werr_ok(tctx, r.out.result, "DsRGetSiteName");
+       torture_assert_str_equal(tctx, expected_site, site, "netr_DsRGetSiteName");
+
+       r.in.computer_name              = talloc_asprintf(tctx, "\\\\%s", computer_name);
+       torture_comment(tctx, 
+                       "Testing netr_DsRGetSiteName with broken computer name: %s\n", r.in.computer_name);
+
+       status = dcerpc_netr_DsRGetSiteName(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsRGetSiteName");
+       torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_COMPUTERNAME, "netr_DsRGetSiteName");
+
+       return true;
+}
 
 /*
-  test an ADS style interactive domain login
+  try a netlogon netr_DsRGetDCName
 */
-static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                                 struct creds_CredentialState *creds)
+static bool test_netr_DsRGetDCName(struct torture_context *tctx, 
+                                  struct dcerpc_pipe *p)
 {
        NTSTATUS status;
-       struct netr_LogonSamLogonWithFlags r;
-       struct netr_Authenticator a, ra;
-       struct netr_PasswordInfo pinfo;
-       const char *plain_pass;
+       struct netr_DsRGetDCName r;
+       struct netr_DsRGetDCNameInfo *info = NULL;
+
+       r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
+       r.in.domain_guid        = NULL;
+       r.in.site_guid          = NULL;
+       r.in.flags              = DS_RETURN_DNS_NAME;
+       r.out.info              = &info;
+
+       status = dcerpc_netr_DsRGetDCName(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsRGetDCName");
+       torture_assert_werr_ok(tctx, r.out.result, "DsRGetDCName");
+       return test_netr_DsRGetSiteName(p, tctx, 
+                                      info->dc_unc,
+                                      info->dc_site_name);
+}
 
-       ZERO_STRUCT(r);
-       ZERO_STRUCT(ra);
+/*
+  try a netlogon netr_DsRGetDCNameEx
+*/
+static bool test_netr_DsRGetDCNameEx(struct torture_context *tctx, 
+                                    struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_DsRGetDCNameEx r;
+       struct netr_DsRGetDCNameInfo *info = NULL;
+
+       r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
+       r.in.domain_guid        = NULL;
+       r.in.site_name          = NULL;
+       r.in.flags              = DS_RETURN_DNS_NAME;
+       r.out.info              = &info;
+
+       status = dcerpc_netr_DsRGetDCNameEx(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx");
+       torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx");
+
+       return test_netr_DsRGetSiteName(p, tctx, info->dc_unc,
+                                       info->dc_site_name);
+}
 
-       creds_client_authenticator(creds, &a);
+/*
+  try a netlogon netr_DsRGetDCNameEx2
+*/
+static bool test_netr_DsRGetDCNameEx2(struct torture_context *tctx, 
+                                     struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_DsRGetDCNameEx2 r;
+       struct netr_DsRGetDCNameInfo *info = NULL;
+
+       r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.client_account     = NULL;
+       r.in.mask               = 0x00000000;
+       r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
+       r.in.domain_guid        = NULL;
+       r.in.site_name          = NULL;
+       r.in.flags              = DS_RETURN_DNS_NAME;
+       r.out.info              = &info;
+
+       torture_comment(tctx, "Testing netr_DsRGetDCNameEx2 without client account\n");
+
+       status = dcerpc_netr_DsRGetDCNameEx2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx2");
+       torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx2");
+
+       torture_comment(tctx, "Testing netr_DsRGetDCNameEx2 with client acount\n");
+       r.in.client_account     = TEST_MACHINE_NAME"$";
+       r.in.mask               = ACB_SVRTRUST;
+       r.in.flags              = DS_RETURN_FLAT_NAME;
+       r.out.info              = &info;
+
+       status = dcerpc_netr_DsRGetDCNameEx2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx2");
+       torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx2");
+       return test_netr_DsRGetSiteName(p, tctx, info->dc_unc,
+                                       info->dc_site_name);
+}
 
-       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.workstation = TEST_MACHINE_NAME;
-       r.in.credential = &a;
-       r.in.return_authenticator = &ra;
-       r.in.logon_level = 5;
-       r.in.logon.password = &pinfo;
-       r.in.validation_level = 6;
-       r.in.flags = 0;
+static bool test_netr_DsrGetDcSiteCoverageW(struct torture_context *tctx, 
+                                           struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_DsrGetDcSiteCoverageW r;
+       struct DcSitesCtr *ctr = NULL;
 
-       pinfo.identity_info.domain_name.string = lp_workgroup();
-       pinfo.identity_info.parameter_control = 0;
-       pinfo.identity_info.logon_id_low = 0;
-       pinfo.identity_info.logon_id_high = 0;
-       pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username");
-       pinfo.identity_info.workstation.string = TEST_MACHINE_NAME;
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.out.ctr = &ctr;
 
-       plain_pass = lp_parm_string(-1, "torture", "password");
+       status = dcerpc_netr_DsrGetDcSiteCoverageW(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "failed");
+       torture_assert_werr_ok(tctx, r.out.result, "failed");
 
-       E_deshash(plain_pass, pinfo.lmpassword.hash);
-       E_md4hash(plain_pass, pinfo.ntpassword.hash);
+       return true;
+}
 
-       creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
-       creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
+static bool test_netr_DsRAddressToSitenamesW(struct torture_context *tctx,
+                                            struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_DsRAddressToSitenamesW r;
+       struct netr_DsRAddress addr;
+       struct netr_DsRAddressToSitenamesWCtr *ctr;
 
-       printf("Testing netr_LogonSamLogonWithFlags\n");
+       ctr = talloc(tctx, struct netr_DsRAddressToSitenamesWCtr);
 
-       status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status));
-               exit(1);
-               return False;
-       }
+       addr.size = 16;
+       addr.buffer = talloc_zero_array(tctx, uint8_t, addr.size);
 
-       if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
-               printf("Credential chaining failed\n");
-               return False;
-       }
+       addr.buffer[0] = 2; /* AF_INET */
+       addr.buffer[4] = 127;
+       addr.buffer[5] = 0;
+       addr.buffer[6] = 0;
+       addr.buffer[7] = 1;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.count = 1;
+       r.in.addresses = talloc_zero_array(tctx, struct netr_DsRAddress, r.in.count);
+       r.in.addresses[0] = addr;
+       r.out.ctr = &ctr;
 
-       return True;
+       status = dcerpc_netr_DsRAddressToSitenamesW(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "failed");
+       torture_assert_werr_ok(tctx, r.out.result, "failed");
+
+       return true;
 }
 
+static bool test_netr_DsRAddressToSitenamesExW(struct torture_context *tctx,
+                                              struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct netr_DsRAddressToSitenamesExW r;
+       struct netr_DsRAddress addr;
+       struct netr_DsRAddressToSitenamesExWCtr *ctr;
+
+       ctr = talloc(tctx, struct netr_DsRAddressToSitenamesExWCtr);
+
+       addr.size = 16;
+       addr.buffer = talloc_zero_array(tctx, uint8_t, addr.size);
 
-static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+       addr.buffer[0] = 2; /* AF_INET */
+       addr.buffer[4] = 127;
+       addr.buffer[5] = 0;
+       addr.buffer[6] = 0;
+       addr.buffer[7] = 1;
+
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.count = 1;
+       r.in.addresses = talloc_zero_array(tctx, struct netr_DsRAddress, r.in.count);
+       r.in.addresses[0] = addr;
+       r.out.ctr = &ctr;
+
+       status = dcerpc_netr_DsRAddressToSitenamesExW(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "failed");
+       torture_assert_werr_ok(tctx, r.out.result, "failed");
+
+       return true;
+}
+
+static bool test_GetDomainInfo(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p,
+                              struct cli_credentials *machine_credentials)
 {
        NTSTATUS status;
        struct netr_LogonGetDomainInfo r;
        struct netr_DomainQuery1 q1;
        struct netr_Authenticator a;
-       struct creds_CredentialState creds;
+       struct creds_CredentialState *creds;
+       union netr_DomainInfo info;
 
-       if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
-               return False;
+       if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
+                                   machine_credentials, &creds)) {
+               return false;
        }
 
        ZERO_STRUCT(r);
 
-       creds_client_authenticator(&creds, &a);
+       creds_client_authenticator(creds, &a);
 
-       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        r.in.computer_name = TEST_MACHINE_NAME;
-       r.in.unknown1 = 512;
        r.in.level = 1;
        r.in.credential = &a;
-       r.out.credential = &a;
-
-       r.in.i1[0] = 0;
-       r.in.i1[1] = 0;
+       r.in.return_authenticator = &a;
+       r.out.return_authenticator = &a;
+       r.out.info = &info;
 
        r.in.query.query1 = &q1;
        ZERO_STRUCT(q1);
@@ -1604,119 +1545,232 @@ static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        q1.blob2.data = NULL;
        q1.product.string = "product string";
 
-       printf("Testing netr_LogonGetDomainInfo\n");
+       torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n");
 
-       status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
-               return False;
-       }
+       status = dcerpc_netr_LogonGetDomainInfo(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo");
+       torture_assert(tctx, creds_client_check(creds, &a.cred), "Credential chaining failed");
 
-       if (!creds_client_check(&creds, &a.cred)) {
-               printf("Credential chaining failed\n");
-               return False;
-       }
+       torture_comment(tctx, "Testing netr_LogonGetDomainInfo 2nd call\n");
+       creds_client_authenticator(creds, &a);
 
-       test_InteractiveLogin(p, mem_ctx, &creds);
+       status = dcerpc_netr_LogonGetDomainInfo(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo");
+       torture_assert(tctx, creds_client_check(creds, &a.cred), "Credential chaining failed");
 
-       return True;
+       return true;
 }
 
 
-BOOL torture_rpc_netlogon(int dummy)
+static void async_callback(struct rpc_request *req)
 {
-        NTSTATUS status;
-        struct dcerpc_pipe *p;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-       void *join_ctx;
-
-       mem_ctx = talloc_init("torture_rpc_netlogon");
-
-       join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
-                                      &machine_password);
-       if (!join_ctx) {
-               printf("Failed to join as BDC\n");
-               return False;
+       int *counter = (int *)req->async.private_data;
+       if (NT_STATUS_IS_OK(req->status)) {
+               (*counter)++;
        }
+}
 
-       status = torture_rpc_connection(&p, 
-                                       DCERPC_NETLOGON_NAME,
-                                       DCERPC_NETLOGON_UUID,
-                                       DCERPC_NETLOGON_VERSION);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
+static bool test_GetDomainInfo_async(struct torture_context *tctx, 
+                                    struct dcerpc_pipe *p,
+                                    struct cli_credentials *machine_credentials)
+{
+       NTSTATUS status;
+       struct netr_LogonGetDomainInfo r;
+       struct netr_DomainQuery1 q1;
+       struct netr_Authenticator a;
+#define ASYNC_COUNT 100
+       struct creds_CredentialState *creds;
+       struct creds_CredentialState *creds_async[ASYNC_COUNT];
+       struct rpc_request *req[ASYNC_COUNT];
+       int i;
+       int *async_counter = talloc(tctx, int);
+       union netr_DomainInfo info;
 
-       if (!test_LogonUasLogon(p, mem_ctx)) {
-               ret = False;
+       if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
+                                   machine_credentials, &creds)) {
+               return false;
        }
 
-       if (!test_LogonUasLogoff(p, mem_ctx)) {
-               ret = False;
-       }
+       ZERO_STRUCT(r);
+       r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.computer_name = TEST_MACHINE_NAME;
+       r.in.level = 1;
+       r.in.credential = &a;
+       r.in.return_authenticator = &a;
+       r.out.return_authenticator = &a;
+       r.out.info = &info;
 
-       if (!test_SetPassword(p, mem_ctx)) {
-               ret = False;
-       }
+       r.in.query.query1 = &q1;
+       ZERO_STRUCT(q1);
+       
+       /* this should really be the fully qualified name */
+       q1.workstation_domain = TEST_MACHINE_NAME;
+       q1.workstation_site = "Default-First-Site-Name";
+       q1.blob2.length = 0;
+       q1.blob2.size = 0;
+       q1.blob2.data = NULL;
+       q1.product.string = "product string";
 
-       if (!test_SamLogon(p, mem_ctx)) {
-               ret = False;
-       }
+       torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
 
-       if (!test_GetDomainInfo(p, mem_ctx)) {
-               ret = False;
-       }
+       *async_counter = 0;
 
-       if (!test_DatabaseSync(p, mem_ctx)) {
-               ret = False;
-       }
+       for (i=0;i<ASYNC_COUNT;i++) {
+               creds_client_authenticator(creds, &a);
 
-       if (!test_DatabaseDeltas(p, mem_ctx)) {
-               ret = False;
-       }
+               creds_async[i] = (struct creds_CredentialState *)talloc_memdup(creds, creds, sizeof(*creds));
+               req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, tctx, &r);
 
-       if (!test_AccountDeltas(p, mem_ctx)) {
-               ret = False;
-       }
+               req[i]->async.callback = async_callback;
+               req[i]->async.private_data = async_counter;
 
-       if (!test_AccountSync(p, mem_ctx)) {
-               ret = False;
+               /* even with this flush per request a w2k3 server seems to 
+                  clag with multiple outstanding requests. bleergh. */
+               torture_assert_int_equal(tctx, event_loop_once(dcerpc_event_context(p)), 0, 
+                                        "event_loop_once failed");
        }
 
-       if (!test_GetDcName(p, mem_ctx)) {
-               ret = False;
-       }
+       for (i=0;i<ASYNC_COUNT;i++) {
+               status = dcerpc_ndr_request_recv(req[i]);
 
-       if (!test_LogonControl(p, mem_ctx)) {
-               ret = False;
-       }
+               torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo_async");
+               torture_assert_ntstatus_ok(tctx, r.out.result, "netr_LogonGetDomainInfo_async"); 
 
-       if (!test_GetAnyDCName(p, mem_ctx)) {
-               ret = False;
+               torture_assert(tctx, creds_client_check(creds_async[i], &a.cred), 
+                       "Credential chaining failed at async");
        }
 
-       if (!test_LogonControl2(p, mem_ctx)) {
-               ret = False;
-       }
+       torture_comment(tctx, 
+                       "Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
 
-       if (!test_DatabaseSync2(p, mem_ctx)) {
-               ret = False;
-       }
+       torture_assert_int_equal(tctx, (*async_counter), ASYNC_COUNT, "int");
 
-       if (!test_LogonControl2Ex(p, mem_ctx)) {
-               ret = False;
-       }
+       return true;
+}
+
+static bool test_ManyGetDCName(struct torture_context *tctx, 
+                              struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p2;
+       struct lsa_ObjectAttribute attr;
+       struct lsa_QosInfo qos;
+       struct lsa_OpenPolicy2 o;
+       struct policy_handle lsa_handle;
+       struct lsa_DomainList domains;
+
+       struct lsa_EnumTrustDom t;
+       uint32_t resume_handle = 0;
+       struct netr_GetAnyDCName d;
+       const char *dcname = NULL;
+
+       int i;
 
-       if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
-               ret = False;
+       if (p->conn->transport.transport != NCACN_NP) {
+               return true;
        }
 
-       talloc_destroy(mem_ctx);
+       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");
+
+       status = dcerpc_bind_auth_none(p2, &ndr_table_lsarpc);
+       torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
+
+       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;
 
-       torture_rpc_close(p);
+       o.in.system_name = "\\";
+       o.in.attr = &attr;
+       o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       o.out.handle = &lsa_handle;
 
-       torture_leave_domain(join_ctx);
+       status = dcerpc_lsa_OpenPolicy2(p2, tctx, &o);
+       torture_assert_ntstatus_ok(tctx, status, "OpenPolicy2 failed");
 
-       return ret;
+       t.in.handle = &lsa_handle;
+       t.in.resume_handle = &resume_handle;
+       t.in.max_size = 1000;
+       t.out.domains = &domains;
+       t.out.resume_handle = &resume_handle;
+
+       status = dcerpc_lsa_EnumTrustDom(p2, tctx, &t);
+
+       if ((!NT_STATUS_IS_OK(status) &&
+            (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES))))
+               torture_fail(tctx, "Could not list domains");
+
+       talloc_free(p2);
+
+       d.in.logon_server = talloc_asprintf(tctx, "\\\\%s",
+                                           dcerpc_server_name(p));
+       d.out.dcname = &dcname;
+
+       for (i=0; i<domains.count * 4; i++) {
+               struct lsa_DomainInfo *info =
+                       &domains.domains[rand()%domains.count];
+
+               d.in.domainname = info->name.string;
+
+               status = dcerpc_netr_GetAnyDCName(p, tctx, &d);
+               torture_assert_ntstatus_ok(tctx, status, "GetAnyDCName");
+
+               torture_comment(tctx, "\tDC for domain %s is %s\n", info->name.string,
+                      dcname ? dcname : "unknown");
+       }
+
+       return true;
+}
+
+struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "NETLOGON");
+       struct torture_rpc_tcase *tcase;
+       struct torture_test *test;
+
+       tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "netlogon", 
+                                                 &ndr_table_netlogon, TEST_MACHINE_NAME);
+
+       torture_rpc_tcase_add_test(tcase, "LogonUasLogon", test_LogonUasLogon);
+       torture_rpc_tcase_add_test(tcase, "LogonUasLogoff", test_LogonUasLogoff);
+       torture_rpc_tcase_add_test_creds(tcase, "SamLogon", test_SamLogon);
+       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, "GetPassword", test_GetPassword);
+       torture_rpc_tcase_add_test_creds(tcase, "GetTrustPasswords", test_GetTrustPasswords);
+       torture_rpc_tcase_add_test_creds(tcase, "GetDomainInfo", test_GetDomainInfo);
+       torture_rpc_tcase_add_test_creds(tcase, "DatabaseSync", test_DatabaseSync);
+       torture_rpc_tcase_add_test_creds(tcase, "DatabaseDeltas", test_DatabaseDeltas);
+       torture_rpc_tcase_add_test_creds(tcase, "AccountDeltas", test_AccountDeltas);
+       torture_rpc_tcase_add_test_creds(tcase, "AccountSync", test_AccountSync);
+       torture_rpc_tcase_add_test(tcase, "GetDcName", test_GetDcName);
+       torture_rpc_tcase_add_test(tcase, "ManyGetDCName", test_ManyGetDCName);
+       torture_rpc_tcase_add_test(tcase, "LogonControl", test_LogonControl);
+       torture_rpc_tcase_add_test(tcase, "GetAnyDCName", test_GetAnyDCName);
+       torture_rpc_tcase_add_test(tcase, "LogonControl2", test_LogonControl2);
+       torture_rpc_tcase_add_test_creds(tcase, "DatabaseSync2", test_DatabaseSync2);
+       torture_rpc_tcase_add_test(tcase, "LogonControl2Ex", test_LogonControl2Ex);
+       torture_rpc_tcase_add_test(tcase, "DsrEnumerateDomainTrusts", test_DsrEnumerateDomainTrusts);
+       torture_rpc_tcase_add_test(tcase, "NetrEnumerateTrustedDomains", test_netr_NetrEnumerateTrustedDomains);
+       torture_rpc_tcase_add_test(tcase, "NetrEnumerateTrustedDomainsEx", test_netr_NetrEnumerateTrustedDomainsEx);
+       test = torture_rpc_tcase_add_test_creds(tcase, "GetDomainInfo_async", test_GetDomainInfo_async);
+       test->dangerous = true;
+       torture_rpc_tcase_add_test(tcase, "DsRGetDCName", test_netr_DsRGetDCName);
+       torture_rpc_tcase_add_test(tcase, "DsRGetDCNameEx", test_netr_DsRGetDCNameEx);
+       torture_rpc_tcase_add_test(tcase, "DsRGetDCNameEx2", test_netr_DsRGetDCNameEx2);
+       torture_rpc_tcase_add_test(tcase, "DsrGetDcSiteCoverageW", test_netr_DsrGetDcSiteCoverageW);
+       torture_rpc_tcase_add_test(tcase, "DsRAddressToSitenamesW", test_netr_DsRAddressToSitenamesW);
+       torture_rpc_tcase_add_test(tcase, "DsRAddressToSitenamesExW", test_netr_DsRAddressToSitenamesExW);
+
+       return suite;
 }