gensec: split GENSEC into mechanism-dependent and runtime functions
[samba.git] / source4 / torture / rpc / samr.c
index ae0c8c032f6c3b54684695591c389155c98eb2af..f7d6a93bb39f62bdc2e6cc21d79a43ea12c61315 100644 (file)
@@ -4,7 +4,7 @@
 
    Copyright (C) Andrew Tridgell 2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
-   Copyright (C) Guenther Deschner 2008,2009
+   Copyright (C) Guenther Deschner 2008-2010
 
    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
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "torture/torture.h"
+#include <tevent.h>
 #include "system/time.h"
 #include "librpc/gen_ndr/lsa.h"
 #include "librpc/gen_ndr/ndr_netlogon.h"
 #include "../lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
 #include "libcli/security/security.h"
-#include "torture/rpc/rpc.h"
+#include "torture/rpc/torture_rpc.h"
 #include "param/param.h"
+#include "auth/gensec/gensec.h"
+#include "auth/gensec/schannel.h"
+#include "auth/gensec/gensec_proto.h"
+#include "../libcli/auth/schannel.h"
 
 #include <unistd.h>
 
 enum torture_samr_choice {
        TORTURE_SAMR_PASSWORDS,
        TORTURE_SAMR_PASSWORDS_PWDLASTSET,
+       TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
+       TORTURE_SAMR_PASSWORDS_LOCKOUT,
        TORTURE_SAMR_USER_ATTRIBUTES,
        TORTURE_SAMR_USER_PRIVILEGES,
-       TORTURE_SAMR_OTHER
+       TORTURE_SAMR_OTHER,
+       TORTURE_SAMR_MANY_ACCOUNTS,
+       TORTURE_SAMR_MANY_GROUPS,
+       TORTURE_SAMR_MANY_ALIASES
 };
 
-static bool test_QueryUserInfo(struct dcerpc_pipe *p,
+struct torture_samr_context {
+       struct policy_handle handle;
+       struct cli_credentials *machine_credentials;
+       enum torture_samr_choice choice;
+       uint32_t num_objects_large_dc;
+};
+
+static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
                               struct torture_context *tctx,
                               struct policy_handle *handle);
 
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
                                struct torture_context *tctx,
                                struct policy_handle *handle);
 
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
                                struct torture_context *tctx,
                                struct policy_handle *handle);
 
@@ -85,25 +102,26 @@ static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s
        string->array = (uint16_t *)discard_const(s);
 }
 
-bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                  struct policy_handle *handle)
+bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
+                           struct torture_context *tctx,
+                           struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_Close r;
 
        r.in.handle = handle;
        r.out.handle = handle;
 
-       status = dcerpc_samr_Close(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "Close");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
+               "Close failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
 
        return true;
 }
 
-static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
-                      struct policy_handle *handle)
+static bool test_Shutdown(struct dcerpc_binding_handle *b,
+                         struct torture_context *tctx,
+                         struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_Shutdown r;
 
        if (!torture_setting_bool(tctx, "dangerous", false)) {
@@ -113,18 +131,19 @@ static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        r.in.connect_handle = handle;
 
-       torture_comment(tctx, "testing samr_Shutdown\n");
+       torture_comment(tctx, "Testing samr_Shutdown\n");
 
-       status = dcerpc_samr_Shutdown(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
+               "Shutdown failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
 
        return true;
 }
 
-static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
+                                struct torture_context *tctx,
                                 struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_SetDsrmPassword r;
        struct lsa_String string;
        struct samr_Password hash;
@@ -141,20 +160,20 @@ static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *
        r.in.unknown = 0;
        r.in.hash = &hash;
 
-       torture_comment(tctx, "testing samr_SetDsrmPassword\n");
+       torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
 
-       status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
+               "SetDsrmPassword failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
 
        return true;
 }
 
 
-static bool test_QuerySecurity(struct dcerpc_pipe *p,
+static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
                               struct torture_context *tctx,
                               struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QuerySecurity r;
        struct samr_SetSecurity s;
        struct sec_desc_buf *sdbuf = NULL;
@@ -163,8 +182,9 @@ static bool test_QuerySecurity(struct dcerpc_pipe *p,
        r.in.sec_info = 7;
        r.out.sdbuf = &sdbuf;
 
-       status = dcerpc_samr_QuerySecurity(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
+               "QuerySecurity failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
 
        torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
 
@@ -176,21 +196,22 @@ static bool test_QuerySecurity(struct dcerpc_pipe *p,
                torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
        }
 
-       status = dcerpc_samr_SetSecurity(p, tctx, &s);
-       torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
+               "SetSecurity failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
 
-       status = dcerpc_samr_QuerySecurity(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
+               "QuerySecurity failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
 
        return true;
 }
 
 
-static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
                             struct policy_handle *handle, uint32_t base_acct_flags,
                             const char *base_account_name)
 {
-       NTSTATUS status;
        struct samr_SetUserInfo s;
        struct samr_SetUserInfo2 s2;
        struct samr_QueryUserInfo q;
@@ -220,10 +241,11 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        q0 = q;
 
 #define TESTCALL(call, r) \
-               status = dcerpc_samr_ ##call(p, tctx, &r); \
-               if (!NT_STATUS_IS_OK(status)) { \
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
+                       #call " failed"); \
+               if (!NT_STATUS_IS_OK(r.out.result)) { \
                        torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
-                              r.in.level, nt_errstr(status), __location__); \
+                              r.in.level, nt_errstr(r.out.result), __location__); \
                        ret = false; \
                        break; \
                }
@@ -336,13 +358,10 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        q0.in.level = 12;
        do { TESTCALL(QueryUserInfo, q0) } while (0);
 
-       /* Samba 3 cannot store comment fields atm. - gd */
-       if (!torture_setting_bool(tctx, "samba3", false)) {
-               TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
-               TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
-               TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
-                                  SAMR_FIELD_COMMENT);
-       }
+       TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
+       TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
+       TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
+                          SAMR_FIELD_COMMENT);
 
        test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
        TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
@@ -438,7 +457,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
                           SAMR_FIELD_PARAMETERS);
 
-       /* Samba 3 cannot store country_code and copy_page atm. - gd */
+       /* Samba 3 cannot store country_code and code_page atm. - gd */
        if (!torture_setting_bool(tctx, "samba3", false)) {
                TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
                TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
@@ -562,8 +581,8 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
 */
 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
 {
-       size_t len = MAX(8, min_len) + (random() % 6);
-       char *s = generate_random_str(mem_ctx, len);
+       size_t len = MAX(8, min_len);
+       char *s = generate_random_password(mem_ctx, len, len+6);
        return s;
 }
 
@@ -598,7 +617,7 @@ static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
 */
 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
 {
-       char *s = generate_random_str(mem_ctx, len);
+       char *s = generate_random_password(mem_ctx, len, len);
        printf("Generated password '%s'\n", s);
        return s;
 }
@@ -612,14 +631,16 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
        bool ret = true;
        DATA_BLOB session_key;
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -633,7 +654,7 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -642,10 +663,11 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
 
        torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -664,6 +686,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
        union samr_UserInfo u;
        bool ret = true;
        DATA_BLOB session_key;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        char *newpass;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
@@ -671,8 +694,9 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -689,7 +713,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -698,10 +722,11 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -711,7 +736,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -722,10 +747,11 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
 
@@ -745,6 +771,7 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
        DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
        uint8_t confounder[16];
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct MD5Context ctx;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
@@ -752,8 +779,9 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        if (makeshort && policy_min_pw_len) {
@@ -771,7 +799,7 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -788,10 +816,11 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
 
        torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -805,10 +834,11 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
 
        torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -830,14 +860,16 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
        struct MD5Context ctx;
        uint8_t confounder[16];
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -854,7 +886,7 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -871,10 +903,11 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -888,10 +921,11 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
 
@@ -907,6 +941,7 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
        bool ret = true;
        DATA_BLOB session_key;
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
@@ -915,8 +950,9 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -935,7 +971,7 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -957,10 +993,11 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -979,6 +1016,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
        bool ret = true;
        DATA_BLOB session_key;
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
@@ -987,8 +1025,9 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -1020,7 +1059,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -1045,10 +1084,11 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
 
        torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -1059,11 +1099,11 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
 
                u.info21.nt_owf_password.length++;
 
-               status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                       printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
-                              s.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+                       "SetUserInfo failed");
+               if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
+                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+                              s.in.level, nt_errstr(s.out.result));
                        ret = false;
                }
        }
@@ -1072,11 +1112,11 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
 
                u.info21.lm_owf_password.length++;
 
-               status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                       printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
-                              s.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+                       "SetUserInfo failed");
+               if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
+                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+                              s.in.level, nt_errstr(s.out.result));
                        ret = false;
                }
        }
@@ -1104,6 +1144,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        struct MD5Context ctx;
        uint8_t confounder[16];
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
@@ -1113,8 +1154,9 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
@@ -1130,7 +1172,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        }
 
        if (fields_present & SAMR_FIELD_COMMENT) {
-               comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
+               comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
        }
 
        ZERO_STRUCT(u);
@@ -1203,7 +1245,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -1268,9 +1310,13 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        }
 
        if (use_setinfo2) {
-               status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
+                       "SetUserInfo2 failed");
+               status = s2.out.result;
        } else {
-               status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+                       "SetUserInfo failed");
+               status = s.out.result;
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -1297,7 +1343,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo%s level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
                       use_setinfo2 ? "2":"", level, nt_errstr(status));
                ret = false;
        } else {
@@ -1307,10 +1353,10 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
-                              struct policy_handle *handle)
+static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
+                             struct torture_context *tctx,
+                             struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_SetAliasInfo r;
        struct samr_QueryAliasInfo q;
        union samr_AliasInfo *info;
@@ -1332,13 +1378,14 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct
                    case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
                    case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
                                "Test Description, should test I18N as well"); break;
-                   case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
+                   case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
                }
 
-               status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("SetAliasInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
+                       "SetAliasInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
 
@@ -1346,10 +1393,11 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct
                q.in.level = levels[i];
                q.out.info = &info;
 
-               status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryAliasInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
+                       "QueryAliasInfo failed");
+               if (!NT_STATUS_IS_OK(q.out.result)) {
+                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(q.out.result));
                        ret = false;
                }
        }
@@ -1357,20 +1405,21 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct
        return ret;
 }
 
-static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
+                                 struct torture_context *tctx,
                                  struct policy_handle *user_handle)
 {
        struct samr_GetGroupsForUser r;
        struct samr_RidWithAttributeArray *rids = NULL;
-       NTSTATUS status;
 
-       torture_comment(tctx, "testing GetGroupsForUser\n");
+       torture_comment(tctx, "Testing GetGroupsForUser\n");
 
        r.in.user_handle = user_handle;
        r.out.rids = &rids;
 
-       status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
+               "GetGroupsForUser failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
 
        return true;
 
@@ -1379,43 +1428,47 @@ static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context
 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
                              struct lsa_String *domain_name)
 {
-       NTSTATUS status;
        struct samr_GetDomPwInfo r;
        struct samr_PwInfo info;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        r.in.domain_name = domain_name;
        r.out.info = &info;
 
        torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
 
-       status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
+               "GetDomPwInfo failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
 
        r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
 
-       status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
+               "GetDomPwInfo failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
 
        r.in.domain_name->string = "\\\\__NONAME__";
        torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
 
-       status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
+               "GetDomPwInfo failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
 
        r.in.domain_name->string = "\\\\Builtin";
        torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
 
-       status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
+               "GetDomPwInfo failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
 
        return true;
 }
 
-static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
+                              struct torture_context *tctx,
                               struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_GetUserPwInfo r;
        struct samr_PwInfo info;
 
@@ -1424,13 +1477,15 @@ static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tc
        r.in.user_handle = handle;
        r.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
+               "GetUserPwInfo failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
 
        return true;
 }
 
-static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
+static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
+                               struct torture_context *tctx,
                                struct policy_handle *domain_handle, const char *name,
                                uint32_t *rid)
 {
@@ -1446,58 +1501,73 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        n.in.names = sname;
        n.out.rids = &rids;
        n.out.types = &types;
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
-       if (NT_STATUS_IS_OK(status)) {
+       status = dcerpc_samr_LookupNames_r(b, tctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (NT_STATUS_IS_OK(n.out.result)) {
                *rid = n.out.rids->ids[0];
        } else {
-               return status;
+               return n.out.result;
        }
 
        init_lsa_String(&sname[1], "xxNONAMExx");
        n.in.num_names = 2;
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
-       if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
-               printf("LookupNames[2] failed - %s\n", nt_errstr(status));
-               if (NT_STATUS_IS_OK(status)) {
+       status = dcerpc_samr_LookupNames_r(b, tctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
+               torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
+               if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
-               return status;
+               return n.out.result;
        }
 
        n.in.num_names = 0;
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
+       status = dcerpc_samr_LookupNames_r(b, tctx, &n);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupNames[0] failed - %s\n", nt_errstr(status));
                return status;
        }
+       if (!NT_STATUS_IS_OK(n.out.result)) {
+               torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
+               return n.out.result;
+       }
 
        init_lsa_String(&sname[0], "xxNONAMExx");
        n.in.num_names = 1;
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-               printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
-               if (NT_STATUS_IS_OK(status)) {
+       status = dcerpc_samr_LookupNames_r(b, tctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
+               torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
+               if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
-               return status;
+               return n.out.result;
        }
 
        init_lsa_String(&sname[0], "xxNONAMExx");
        init_lsa_String(&sname[1], "xxNONAME2xx");
        n.in.num_names = 2;
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-               printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
-               if (NT_STATUS_IS_OK(status)) {
+       status = dcerpc_samr_LookupNames_r(b, tctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
+               torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
+               if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
-               return status;
+               return n.out.result;
        }
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
+static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
                                     struct torture_context *tctx,
                                     struct policy_handle *domain_handle,
                                     const char *name, struct policy_handle *user_handle)
@@ -1506,7 +1576,7 @@ static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
        struct samr_OpenUser r;
        uint32_t rid;
 
-       status = test_LookupName(p, tctx, domain_handle, name, &rid);
+       status = test_LookupName(b, tctx, domain_handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -1515,12 +1585,15 @@ static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.user_handle = user_handle;
-       status = dcerpc_samr_OpenUser(p, tctx, &r);
+       status = dcerpc_samr_OpenUser_r(b, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
+               return status;
+       }
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
        }
 
-       return status;
+       return r.out.result;
 }
 
 #if 0
@@ -1543,10 +1616,10 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
                return false;
        }
 
-       printf("Testing ChangePasswordUser for user 'testuser'\n");
+       torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
 
-       printf("old password: %s\n", oldpass);
-       printf("new password: %s\n", newpass);
+       torture_comment(tctx, "old password: %s\n", oldpass);
+       torture_comment(tctx, "new password: %s\n", newpass);
 
        E_md4hash(oldpass, old_nt_hash);
        E_md4hash(newpass, new_nt_hash);
@@ -1572,9 +1645,10 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1586,7 +1660,8 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
 }
 #endif
 
-static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
+                                   struct torture_context *tctx,
                                    const char *acct_name,
                                    struct policy_handle *handle, char **password)
 {
@@ -1605,15 +1680,16 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
 
-       status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
+       status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
        pwp.in.user_handle = &user_handle;
        pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
+               "GetUserPwInfo failed");
+       if (NT_STATUS_IS_OK(pwp.out.result)) {
                policy_min_pw_len = pwp.out.info->min_password_length;
        }
        newpass = samr_rand_pass(tctx, policy_min_pw_len);
@@ -1651,8 +1727,9 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
                "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
 
        /* Unbreak the LM hash */
@@ -1672,8 +1749,9 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
                "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
 
        /* Unbreak the NT hash */
@@ -1693,9 +1771,10 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        hash6.hash[0]++;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1716,9 +1795,10 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1746,12 +1826,13 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 0;
        r.in.lm_cross = NULL;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (NT_STATUS_IS_OK(r.out.result)) {
                changed = true;
                *password = newpass;
-       } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
-               printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
+       } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1784,12 +1865,13 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (NT_STATUS_IS_OK(r.out.result)) {
                changed = true;
                *password = newpass;
-       } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
-               printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
+       } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1822,11 +1904,12 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
-       } else  if (!NT_STATUS_IS_OK(status)) {
-               printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+               "ChangePasswordUser failed");
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
+       } else  if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                changed = true;
@@ -1846,17 +1929,18 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        r.in.lm_cross = &hash6;
 
        if (changed) {
-               status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-                       printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
-               } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-                       printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
+                       "ChangePasswordUser failed");
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+                       torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
+               } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+                       torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
                        ret = false;
                }
        }
 
 
-       if (!test_samr_handle_Close(p, tctx, &user_handle)) {
+       if (!test_samr_handle_Close(b, tctx, &user_handle)) {
                ret = false;
        }
 
@@ -1864,11 +1948,11 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
 }
 
 
-static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
+                                       struct torture_context *tctx,
                                        const char *acct_name,
                                        struct policy_handle *handle, char **password)
 {
-       NTSTATUS status;
        struct samr_OemChangePasswordUser2 r;
        bool ret = true;
        struct samr_Password lm_verifier;
@@ -1876,6 +1960,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        struct lsa_AsciiString server, account, account_bad;
        char *oldpass;
        char *newpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_lm_hash[16], new_lm_hash[16];
 
        struct samr_GetDomPwInfo dom_pw_info;
@@ -1895,8 +1980,9 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        oldpass = *password;
 
-       status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
-       if (NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
+               "GetDomPwInfo failed");
+       if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
                policy_min_pw_len = dom_pw_info.out.info->min_password_length;
        }
 
@@ -1920,12 +2006,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        /* Break the verification */
        lm_verifier.hash[0]++;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
+           && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1942,12 +2029,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        r.in.password = &lm_pass;
        r.in.hash = &lm_verifier;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
+           && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1959,12 +2047,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        r.in.password = &lm_pass;
        r.in.hash = NULL;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-               printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
+           && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1972,11 +2061,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        account_bad.string = TEST_ACCOUNT_NAME "XX";
        r.in.account = &account_bad;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-               printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1986,11 +2076,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        r.in.password = &lm_pass;
        r.in.hash = &lm_verifier;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2000,11 +2091,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        r.in.password = NULL;
        r.in.hash = &lm_verifier;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-               printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
-                       nt_errstr(status));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2020,11 +2112,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        r.in.password = &lm_pass;
        r.in.hash = &lm_verifier;
 
-       status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
-       } else if (!NT_STATUS_IS_OK(status)) {
-               printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
+               "OemChangePasswordUser2 failed");
+
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
+       } else if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -2039,13 +2133,13 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
                                     char **password,
                                     char *newpass, bool allow_password_restriction)
 {
-       NTSTATUS status;
        struct samr_ChangePasswordUser2 r;
        bool ret = true;
        struct lsa_String server, account;
        struct samr_CryptPassword nt_pass, lm_pass;
        struct samr_Password nt_verifier, lm_verifier;
        char *oldpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_nt_hash[16], new_nt_hash[16];
        uint8_t old_lm_hash[16], new_lm_hash[16];
 
@@ -2066,8 +2160,9 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 
        if (!newpass) {
                int policy_min_pw_len = 0;
-               status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
-               if (NT_STATUS_IS_OK(status)) {
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
+                       "GetDomPwInfo failed");
+               if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
                        policy_min_pw_len = dom_pw_info.out.info->min_password_length;
                }
 
@@ -2099,11 +2194,13 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
        r.in.lm_password = &lm_pass;
        r.in.lm_verifier = &lm_verifier;
 
-       status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
-       if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
-       } else if (!NT_STATUS_IS_OK(status)) {
-               printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
+               "ChangePasswordUser2 failed");
+
+       if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
+       } else if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -2121,18 +2218,18 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                              NTTIME last_password_change,
                              bool handle_reject_reason)
 {
-       NTSTATUS status;
        struct samr_ChangePasswordUser3 r;
        bool ret = true;
        struct lsa_String server, account, account_bad;
        struct samr_CryptPassword nt_pass, lm_pass;
        struct samr_Password nt_verifier, lm_verifier;
        char *oldpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_nt_hash[16], new_nt_hash[16];
        uint8_t old_lm_hash[16], new_lm_hash[16];
        NTTIME t;
        struct samr_DomInfo1 *dominfo = NULL;
-       struct samr_ChangeReject *reject = NULL;
+       struct userPwdChangeFailureInformation *reject = NULL;
 
        torture_comment(tctx, "Testing ChangePasswordUser3\n");
 
@@ -2183,11 +2280,12 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        r.out.dominfo = &dominfo;
        r.out.reject = &reject;
 
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
-           (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
-               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
-                       nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
+           (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2214,11 +2312,12 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        r.out.dominfo = &dominfo;
        r.out.reject = &reject;
 
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
-           (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
-               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
-                       nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
+           (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2226,10 +2325,11 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
 
        r.in.account = &account_bad;
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
-                       nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
+                       nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2260,18 +2360,19 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
        unix_to_nt_time(&t, time(NULL));
 
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && dominfo
            && reject
            && handle_reject_reason
            && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
                if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
 
-                       if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
-                               printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
-                                       SAMR_REJECT_OTHER, reject->reason);
+                       if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
+                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                                       SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                                return false;
                        }
                }
@@ -2288,40 +2389,40 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
                           (last_password_change + dominfo->min_password_age > t)) {
 
-                       if (reject->reason != SAMR_REJECT_OTHER) {
-                               printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
-                                       SAMR_REJECT_OTHER, reject->reason);
+                       if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
+                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                                       SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                                return false;
                        }
 
                } else if ((dominfo->min_password_length > 0) &&
                           (strlen(newpass) < dominfo->min_password_length)) {
 
-                       if (reject->reason != SAMR_REJECT_TOO_SHORT) {
-                               printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
-                                       SAMR_REJECT_TOO_SHORT, reject->reason);
+                       if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
+                               torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
+                                       SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
                                return false;
                        }
 
                } else if ((dominfo->password_history_length > 0) &&
                            strequal(oldpass, newpass)) {
 
-                       if (reject->reason != SAMR_REJECT_IN_HISTORY) {
-                               printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
-                                       SAMR_REJECT_IN_HISTORY, reject->reason);
+                       if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
+                               torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
+                                       SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
                                return false;
                        }
                } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
 
-                       if (reject->reason != SAMR_REJECT_COMPLEXITY) {
-                               printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
-                                       SAMR_REJECT_COMPLEXITY, reject->reason);
+                       if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
+                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
+                                       SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
                                return false;
                        }
 
                }
 
-               if (reject->reason == SAMR_REJECT_TOO_SHORT) {
+               if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
                        /* retry with adjusted size */
                        return test_ChangePasswordUser3(p, tctx, account_string,
                                                        dominfo->min_password_length,
@@ -2329,16 +2430,17 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
                }
 
-       } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               if (reject && reject->reason != SAMR_REJECT_OTHER) {
-                       printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
-                              SAMR_REJECT_OTHER, reject->reason);
+       } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
+                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                              SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                        return false;
                }
                /* Perhaps the server has a 'min password age' set? */
 
        } else {
-               torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
+               torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
+
                *password = talloc_strdup(tctx, newpass);
        }
 
@@ -2366,10 +2468,11 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        DATA_BLOB new_random_pass;
        char *newpass;
        char *oldpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_nt_hash[16], new_nt_hash[16];
        NTTIME t;
        struct samr_DomInfo1 *dominfo = NULL;
-       struct samr_ChangeReject *reject = NULL;
+       struct userPwdChangeFailureInformation *reject = NULL;
 
        new_random_pass = samr_very_rand_pass(tctx, 128);
 
@@ -2392,7 +2495,7 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -2409,10 +2512,11 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
 
-       status = dcerpc_samr_SetUserInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
+               "SetUserInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
 
@@ -2441,18 +2545,19 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        unix_to_nt_time(&t, time(NULL));
 
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               if (reject && reject->reason != SAMR_REJECT_OTHER) {
-                       printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
-                              SAMR_REJECT_OTHER, reject->reason);
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
+                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                              SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                        return false;
                }
                /* Perhaps the server has a 'min password age' set? */
 
-       } else if (!NT_STATUS_IS_OK(status)) {
-               printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
+       } else if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2479,18 +2584,19 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        unix_to_nt_time(&t, time(NULL));
 
-       status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
+               "ChangePasswordUser3 failed");
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
-               if (reject && reject->reason != SAMR_REJECT_OTHER) {
-                       printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
-                              SAMR_REJECT_OTHER, reject->reason);
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
+                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                              SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                        return false;
                }
                /* Perhaps the server has a 'min password age' set? */
 
        } else {
-               torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
+               torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
                *password = talloc_strdup(tctx, newpass);
        }
 
@@ -2498,60 +2604,63 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 }
 
 
-static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                 struct policy_handle *alias_handle)
+static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *alias_handle)
 {
        struct samr_GetMembersInAlias r;
        struct lsa_SidArray sids;
-       NTSTATUS status;
 
        torture_comment(tctx, "Testing GetMembersInAlias\n");
 
        r.in.alias_handle = alias_handle;
        r.out.sids = &sids;
 
-       status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
+               "GetMembersInAlias failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
 
        return true;
 }
 
-static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
+                                 struct torture_context *tctx,
                                  struct policy_handle *alias_handle,
                                  const struct dom_sid *domain_sid)
 {
        struct samr_AddAliasMember r;
        struct samr_DeleteAliasMember d;
-       NTSTATUS status;
        struct dom_sid *sid;
 
        sid = dom_sid_add_rid(tctx, domain_sid, 512);
 
-       torture_comment(tctx, "testing AddAliasMember\n");
+       torture_comment(tctx, "Testing AddAliasMember\n");
        r.in.alias_handle = alias_handle;
        r.in.sid = sid;
 
-       status = dcerpc_samr_AddAliasMember(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
+               "AddAliasMember failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
 
        d.in.alias_handle = alias_handle;
        d.in.sid = sid;
 
-       status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
-       torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
+               "DeleteAliasMember failed");
+       torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
 
        return true;
 }
 
-static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
+                                          struct torture_context *tctx,
                                           struct policy_handle *alias_handle)
 {
        struct samr_AddMultipleMembersToAlias a;
        struct samr_RemoveMultipleMembersFromAlias r;
-       NTSTATUS status;
        struct lsa_SidArray sids;
 
-       torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
+       torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
        a.in.alias_handle = alias_handle;
        a.in.sids = &sids;
 
@@ -2562,47 +2671,101 @@ static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture
        sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
        sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
 
-       status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
-       torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
+               "AddMultipleMembersToAlias failed");
+       torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
 
 
-       torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
+       torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
        r.in.alias_handle = alias_handle;
        r.in.sids = &sids;
 
-       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
+               "RemoveMultipleMembersFromAlias failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
 
        /* strange! removing twice doesn't give any error */
-       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
+               "RemoveMultipleMembersFromAlias failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
 
        /* but removing an alias that isn't there does */
        sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
 
-       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
+               "RemoveMultipleMembersFromAlias failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
+
+       return true;
+}
+
+static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
+                                   struct torture_context *tctx,
+                                   struct policy_handle *domain_handle)
+{
+       struct samr_GetAliasMembership r;
+       struct lsa_SidArray sids;
+       struct samr_Ids rids;
+
+       torture_comment(tctx, "Testing GetAliasMembership\n");
+
+       r.in.domain_handle      = domain_handle;
+       r.in.sids               = &sids;
+       r.out.rids              = &rids;
+
+       sids.num_sids = 0;
+       sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
+               "GetAliasMembership failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "samr_GetAliasMembership failed");
+
+       torture_assert_int_equal(tctx, sids.num_sids, rids.count,
+               "protocol misbehaviour");
+
+       sids.num_sids = 1;
+       sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
+       sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
+               "samr_GetAliasMembership failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "samr_GetAliasMembership failed");
+
+#if 0
+       /* only true for w2k8 it seems
+        * win7, xp, w2k3 will return a 0 length array pointer */
+
+       if (rids.ids && (rids.count == 0)) {
+               torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
+       }
+#endif
+       if (!rids.ids && rids.count) {
+               torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
+       }
 
        return true;
 }
 
-static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                           struct policy_handle *user_handle)
+static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
+                                         struct torture_context *tctx,
+                                         struct policy_handle *user_handle)
 {
        struct samr_TestPrivateFunctionsUser r;
-       NTSTATUS status;
 
        torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
 
        r.in.user_handle = user_handle;
 
-       status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
+               "TestPrivateFunctionsUser failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
 
        return true;
 }
 
-static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
+static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
                                          struct torture_context *tctx,
                                          struct policy_handle *handle,
                                          bool use_info2,
@@ -2628,18 +2791,22 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
                        r2.in.user_handle = handle;
                        r2.in.level = levels[i];
                        r2.out.info = &info;
-                       status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
+                               "QueryUserInfo2 failed");
+                       status = r2.out.result;
 
                } else {
                        r.in.user_handle = handle;
                        r.in.level = levels[i];
                        r.out.info = &info;
-                       status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+                               "QueryUserInfo failed");
+                       status = r.out.result;
                }
 
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
-                       printf("QueryUserInfo%s level %u failed - %s\n",
+                       torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
                               use_info2 ? "2":"", levels[i], nt_errstr(status));
                        return false;
                }
@@ -2665,122 +2832,139 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
 
        *pwdlastset = pwdlastset21;
 
-       torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
+       torture_comment(tctx, "(pwdlastset: %llu)\n",
+                       (unsigned long long) *pwdlastset);
 
        return true;
 }
 
-static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
-                               struct cli_credentials *machine_credentials,
-                               struct cli_credentials *test_credentials,
-                               struct netlogon_creds_CredentialState *creds,
-                               NTSTATUS expected_result)
+static bool test_SamLogon(struct torture_context *tctx,
+                         struct dcerpc_pipe *p,
+                         struct cli_credentials *test_credentials,
+                         NTSTATUS expected_result,
+                         bool interactive)
 {
        NTSTATUS status;
-       struct netr_LogonSamLogon r;
-       struct netr_Authenticator auth, auth2;
+       struct netr_LogonSamLogonEx r;
        union netr_LogonLevel logon;
        union netr_Validation validation;
        uint8_t authoritative;
+       struct netr_IdentityInfo identity;
        struct netr_NetworkInfo ninfo;
+       struct netr_PasswordInfo pinfo;
        DATA_BLOB names_blob, chal, lm_resp, nt_resp;
        int flags = CLI_CRED_NTLM_AUTH;
+       uint32_t samlogon_flags = 0;
+       struct netlogon_creds_CredentialState *creds;
+       struct netr_Authenticator a;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
-       if (lp_client_lanman_auth(tctx->lp_ctx)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
+
+       if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
                flags |= CLI_CRED_LANMAN_AUTH;
        }
 
-       if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
+       if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
                flags |= CLI_CRED_NTLMv2_AUTH;
        }
 
        cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
-                                                &ninfo.identity_info.account_name.string,
-                                                &ninfo.identity_info.domain_name.string);
+                                                &identity.account_name.string,
+                                                &identity.domain_name.string);
 
-       generate_random_buffer(ninfo.challenge,
-                              sizeof(ninfo.challenge));
-       chal = data_blob_const(ninfo.challenge,
-                              sizeof(ninfo.challenge));
+       identity.parameter_control =
+               MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
+               MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
+       identity.logon_id_low = 0;
+       identity.logon_id_high = 0;
+       identity.workstation.string = cli_credentials_get_workstation(test_credentials);
 
-       names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
-                                               cli_credentials_get_domain(machine_credentials));
+       if (interactive) {
+               netlogon_creds_client_authenticator(creds, &a);
 
-       status = cli_credentials_get_ntlm_response(test_credentials, tctx,
-                                                  &flags,
-                                                  chal,
-                                                  names_blob,
-                                                  &lm_resp, &nt_resp,
-                                                  NULL, NULL);
-       torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
+               if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
+                       ZERO_STRUCT(pinfo.lmpassword.hash);
+               }
+               E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
 
-       ninfo.lm.data = lm_resp.data;
-       ninfo.lm.length = lm_resp.length;
+               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+                       netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
+                       netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
+               } else {
+                       netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
+                       netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
+               }
 
-       ninfo.nt.data = nt_resp.data;
-       ninfo.nt.length = nt_resp.length;
+               pinfo.identity_info = identity;
+               logon.password = &pinfo;
 
-       ninfo.identity_info.parameter_control =
-               MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
-               MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
-       ninfo.identity_info.logon_id_low = 0;
-       ninfo.identity_info.logon_id_high = 0;
-       ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
+               r.in.logon_level = NetlogonInteractiveInformation;
+       } else {
+               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(test_credentials),
+                                                       cli_credentials_get_domain(test_credentials));
+
+               status = cli_credentials_get_ntlm_response(test_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;
 
-       logon.network = &ninfo;
+               ninfo.nt.data = nt_resp.data;
+               ninfo.nt.length = nt_resp.length;
+
+               ninfo.identity_info = identity;
+               logon.network = &ninfo;
+
+               r.in.logon_level = NetlogonNetworkInformation;
+       }
 
        r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
-       r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
-       r.in.credential = &auth;
-       r.in.return_authenticator = &auth2;
-       r.in.logon_level = 2;
+       r.in.computer_name = cli_credentials_get_workstation(test_credentials);
        r.in.logon = &logon;
+       r.in.flags = &samlogon_flags;
+       r.out.flags = &samlogon_flags;
        r.out.validation = &validation;
        r.out.authoritative = &authoritative;
 
-       d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
-
-       ZERO_STRUCT(auth2);
-       netlogon_creds_client_authenticator(creds, &auth);
+       torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
 
-       r.in.validation_level = 2;
+       r.in.validation_level = 6;
 
-       status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
+       torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
+               "netr_LogonSamLogonEx failed");
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
+               r.in.validation_level = 3;
+               torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
+                       "netr_LogonSamLogonEx failed");
+       }
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
                return true;
        } else {
-               torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
        }
 
-       torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
-                       "Credential chaining failed");
-
        return true;
 }
 
-static bool test_SamLogon(struct torture_context *tctx,
-                         struct dcerpc_pipe *p,
-                         struct cli_credentials *machine_credentials,
-                         struct cli_credentials *test_credentials,
-                         NTSTATUS expected_result)
-{
-       struct netlogon_creds_CredentialState *creds;
-
-       if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
-               return false;
-       }
-
-       return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
-                                  creds, expected_result);
-}
-
 static bool test_SamLogon_with_creds(struct torture_context *tctx,
                                     struct dcerpc_pipe *p,
                                     struct cli_credentials *machine_creds,
                                     const char *acct_name,
-                                    char *password,
-                                    NTSTATUS expected_samlogon_result)
+                                    const char *password,
+                                    NTSTATUS expected_samlogon_result,
+                                    bool interactive)
 {
        bool ret = true;
        struct cli_credentials *test_credentials;
@@ -2788,20 +2972,19 @@ static bool test_SamLogon_with_creds(struct torture_context *tctx,
        test_credentials = cli_credentials_init(tctx);
 
        cli_credentials_set_workstation(test_credentials,
-                                       TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
+                                       cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
        cli_credentials_set_domain(test_credentials,
-                                  lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
+                                  cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
        cli_credentials_set_username(test_credentials,
                                     acct_name, CRED_SPECIFIED);
        cli_credentials_set_password(test_credentials,
                                     password, CRED_SPECIFIED);
-       cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
 
-       printf("testing samlogon as %s@%s password: %s\n",
-               acct_name, TEST_ACCOUNT_NAME_PWD, password);
+       torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
+               interactive ? "interactive" : "network", acct_name, password);
 
-       if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
-                          expected_samlogon_result)) {
+       if (!test_SamLogon(tctx, p, test_credentials,
+                           expected_samlogon_result, interactive)) {
                torture_warning(tctx, "new password did not work\n");
                ret = false;
        }
@@ -2827,6 +3010,7 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p,
 {
        const char *fields = NULL;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        switch (level) {
        case 21:
@@ -2853,7 +3037,7 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p,
                ret = false;
        }
 
-       if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
+       if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
                                           use_queryinfo2,
                                           pwdlastset)) {
                ret = false;
@@ -2867,13 +3051,37 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p,
                                      machine_creds,
                                      acct_name,
                                      *password,
-                                     expected_samlogon_result)) {
+                                     expected_samlogon_result,
+                                     false)) {
                ret = false;
        }
 
        return ret;
 }
 
+static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
+                                        struct cli_credentials *credentials,
+                                        struct dcerpc_pipe **p)
+{
+       struct dcerpc_binding *b;
+
+       torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
+               "failed to get rpc binding");
+
+       /* We have to use schannel, otherwise the SamLogonEx fails
+        * with INTERNAL_ERROR */
+
+       b->flags &= ~DCERPC_AUTH_OPTIONS;
+       b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
+
+       torture_assert_ntstatus_ok(tctx,
+               dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
+                                     credentials, tctx->ev, tctx->lp_ctx),
+               "failed to bind to netlogon");
+
+       return true;
+}
+
 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                        struct torture_context *tctx,
                                        uint32_t acct_flags,
@@ -2884,10 +3092,10 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
 {
        int s = 0, q = 0, f = 0, l = 0, z = 0;
        bool ret = true;
-       int delay = 500000;
+       int delay = 50000;
        bool set_levels[] = { false, true };
        bool query_levels[] = { false, true };
-       uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
+       uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
        uint32_t nonzeros[] = { 1, 24 };
        uint32_t fields_present[] = {
                0,
@@ -2903,28 +3111,30 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
                SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
        };
-       NTSTATUS status;
        struct dcerpc_pipe *np = NULL;
 
-       if (torture_setting_bool(tctx, "samba3", false)) {
-               delay = 1000000;
-               printf("Samba3 has second granularity, setting delay to: %d\n",
+       if (torture_setting_bool(tctx, "samba3", false) ||
+           torture_setting_bool(tctx, "samba4", false)) {
+               delay = 999999;
+               torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
                        delay);
        }
 
-       status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
-       if (!NT_STATUS_IS_OK(status)) {
-               return false;
-       }
+       torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
 
        /* set to 1 to enable testing for all possible opcode
           (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
           combinations */
 #if 0
+#define TEST_ALL_LEVELS 1
 #define TEST_SET_LEVELS 1
 #define TEST_QUERY_LEVELS 1
 #endif
+#ifdef TEST_ALL_LEVELS
        for (l=0; l<ARRAY_SIZE(levels); l++) {
+#else
+       for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
+#endif
        for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
        for (f=0; f<ARRAY_SIZE(fields_present); f++) {
 #ifdef TEST_SET_LEVELS
@@ -2970,7 +3180,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                            password,
                                            machine_credentials,
                                            query_levels[q],
-                                           &pwdlastset_old,
+                                           &pwdlastset_new,
                                            expected_samlogon_result)) {
                        ret = false;
                }
@@ -2995,11 +3205,12 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                        "been set\n");
                                break;
                        }
+                       break;
                default:
                        if (pwdlastset_new != 0) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected pwdLastSet 0 but got %lld\n",
-                                       pwdlastset_old);
+                                       "expected pwdLastSet 0 but got %llu\n",
+                                       (unsigned long long) pwdlastset_old);
                                ret = false;
                        }
                        break;
@@ -3017,15 +3228,10 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                ret = false;
                        }
                        break;
-               default:
-                       if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
-                           (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
-                               ret = false;
-                       }
-                       break;
                }
 
+               pwdlastset_old = pwdlastset_new;
+
                usleep(delay);
 
                /* set #2 */
@@ -3055,7 +3261,6 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                case 21:
                case 23:
                case 25:
-
                        /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
                         * password has been changed, old and new pwdlastset
                         * need to be the same value */
@@ -3068,19 +3273,22 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                        pwdlastset_new, "pwdlastset must be equal");
                                break;
                        }
+                       break;
                default:
                        if (pwdlastset_old >= pwdlastset_new) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
-                                       pwdlastset_old, pwdlastset_new);
+                                       "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
+                                       (unsigned long long) pwdlastset_old,
+                                       (unsigned long long) pwdlastset_new);
                                ret = false;
                        }
                        if (pwdlastset_new == 0) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected non-0 pwdlastset, got: %lld\n",
-                                       pwdlastset_new);
+                                       "expected non-0 pwdlastset, got: %llu\n",
+                                       (unsigned long long) pwdlastset_new);
                                ret = false;
                        }
+                       break;
                }
 
                switch (levels[l]) {
@@ -3095,13 +3303,6 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                ret = false;
                        }
                        break;
-               default:
-                       if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
-                           (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
-                               ret = false;
-                       }
-                       break;
                }
 
                pwdlastset_old = pwdlastset_new;
@@ -3136,31 +3337,54 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                case 23:
                case 25:
 
-                       /* if no password has been changed, old and new pwdlastset
+                       /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
+                        * password has been changed, old and new pwdlastset
                         * need to be the same value */
 
-                       if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+                       if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
+                           !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
                        {
                                torture_assert_int_equal(tctx, pwdlastset_old,
                                        pwdlastset_new, "pwdlastset must be equal");
                                break;
                        }
+                       break;
                default:
                        if (pwdlastset_old >= pwdlastset_new) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
-                                       pwdlastset_old, pwdlastset_new);
+                                       "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
+                                       (unsigned long long) pwdlastset_old,
+                                       (unsigned long long) pwdlastset_new);
                                ret = false;
                        }
                        if (pwdlastset_new == 0) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected non-0 pwdlastset, got: %lld\n",
-                                       pwdlastset_new);
+                                       "expected non-0 pwdlastset, got: %llu\n",
+                                       (unsigned long long) pwdlastset_new);
+                               ret = false;
+                       }
+                       break;
+               }
+
+               switch (levels[l]) {
+               case 21:
+               case 23:
+               case 25:
+                       if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+                            (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
+                            (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
+                            (pwdlastset_old >= pwdlastset_new)) {
+                               torture_warning(tctx, "pwdlastset not increasing\n");
                                ret = false;
                        }
+                       break;
                }
 
+               pwdlastset_old = pwdlastset_new;
+
+               usleep(delay);
+
                /* set #3 */
 
                /* set a password and force password change (pwdlastset 0) by
@@ -3209,19 +3433,12 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                        pwdlastset_new, "pwdlastset must be equal");
                                break;
                        }
+                       break;
                default:
-
-                       if (pwdlastset_old == pwdlastset_new) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
-                                       pwdlastset_old, pwdlastset_new);
-                               ret = false;
-                       }
-
                        if (pwdlastset_new != 0) {
                                torture_warning(tctx, "pwdLastSet test failed: "
-                                       "expected pwdLastSet 0, got %lld\n",
-                                       pwdlastset_old);
+                                       "expected pwdLastSet 0, got %llu\n",
+                                       (unsigned long long) pwdlastset_old);
                                ret = false;
                        }
                        break;
@@ -3239,13 +3456,6 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                ret = false;
                        }
                        break;
-               default:
-                       if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
-                           (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
-                               ret = false;
-                       }
-                       break;
                }
 
                /* if the level we are testing does not have a fields_present
@@ -3272,72 +3482,840 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
 #undef TEST_SET_LEVELS
 #undef TEST_QUERY_LEVELS
 
+       talloc_free(np);
+
        return ret;
 }
 
-static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
-                                      struct dcerpc_pipe *lp,
-                                      struct torture_context *tctx,
-                                      struct policy_handle *domain_handle,
-                                      struct policy_handle *lsa_handle,
-                                      struct policy_handle *user_handle,
-                                      const struct dom_sid *domain_sid,
-                                      uint32_t rid,
-                                      struct cli_credentials *machine_credentials)
+static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
+                                          struct torture_context *tctx,
+                                          struct policy_handle *handle,
+                                          uint32_t *badpwdcount)
 {
-       NTSTATUS status;
-       bool ret = true;
+       union samr_UserInfo *info;
+       struct samr_QueryUserInfo r;
 
-       struct policy_handle lsa_acct_handle;
-       struct dom_sid *user_sid;
+       r.in.user_handle = handle;
+       r.in.level = 3;
+       r.out.info = &info;
 
-       user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
+       torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
 
-       {
-               struct lsa_EnumAccountRights r;
-               struct lsa_RightSet rights;
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+               "failed to query userinfo");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query userinfo");
 
-               printf("Testing LSA EnumAccountRights\n");
+       *badpwdcount = info->info3.bad_password_count;
 
-               r.in.handle = lsa_handle;
-               r.in.sid = user_sid;
-               r.out.rights = &rights;
+       torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
 
-               status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
-               torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
-                       "Expected enum rights for account to fail");
-       }
+       return true;
+}
 
-       {
-               struct lsa_RightSet rights;
-               struct lsa_StringLarge names[2];
-               struct lsa_AddAccountRights r;
+static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
+                                       struct torture_context *tctx,
+                                       struct policy_handle *user_handle,
+                                       uint32_t acct_flags)
+{
+       struct samr_SetUserInfo r;
+       union samr_UserInfo user_info;
 
-               printf("Testing LSA AddAccountRights\n");
+       torture_comment(tctx, "Testing SetUserInfo level 16\n");
 
-               init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
-               init_lsa_StringLarge(&names[1], NULL);
+       user_info.info16.acct_flags = acct_flags;
 
-               rights.count = 1;
-               rights.names = names;
+       r.in.user_handle = user_handle;
+       r.in.level = 16;
+       r.in.info = &user_info;
 
-               r.in.handle = lsa_handle;
-               r.in.sid = user_sid;
-               r.in.rights = &rights;
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
+               "failed to set account flags");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to set account flags");
 
-               status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
-                       "Failed to add privileges");
-       }
+       return true;
+}
 
-       {
-               struct lsa_EnumAccounts r;
-               uint32_t resume_handle = 0;
-               struct lsa_SidArray lsa_sid_array;
-               int i;
-               bool found_sid = false;
+static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *user_handle,
+                                  uint32_t acct_flags,
+                                  char **password)
+{
+       struct dcerpc_binding_handle *b = p->binding_handle;
+
+       torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
+               "failed to set password");
+
+       torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
+
+       torture_assert(tctx,
+                      test_SetUserInfo_acct_flags(b, tctx, user_handle,
+                                                  acct_flags & ~ACB_DISABLED),
+                      "failed to enable user");
+
+       torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
+               "failed to set password");
+
+       return true;
+}
+
+static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
+                              struct torture_context *tctx,
+                              struct policy_handle *domain_handle,
+                              enum samr_DomainInfoClass level,
+                              union samr_DomainInfo *info)
+{
+       struct samr_SetDomainInfo r;
+
+       r.in.domain_handle = domain_handle;
+       r.in.level = level;
+       r.in.info = info;
+
+       torture_assert_ntstatus_ok(tctx,
+                                  dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
+                                  "failed to set domain info");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+                                  "failed to set domain info");
+
+       return true;
+}
+
+static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
+                                       struct torture_context *tctx,
+                                       struct policy_handle *domain_handle,
+                                       enum samr_DomainInfoClass level,
+                                       union samr_DomainInfo *info,
+                                       NTSTATUS expected)
+{
+       struct samr_SetDomainInfo r;
+
+       r.in.domain_handle = domain_handle;
+       r.in.level = level;
+       r.in.info = info;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
+               "SetDomainInfo failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
+
+       return true;
+}
 
-               printf("Testing LSA EnumAccounts\n");
+static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
+                                       struct torture_context *tctx,
+                                       struct policy_handle *domain_handle,
+                                       enum samr_DomainInfoClass level,
+                                       union samr_DomainInfo **q_info)
+{
+       struct samr_QueryDomainInfo2 r;
+
+       r.in.domain_handle = domain_handle;
+       r.in.level = level;
+       r.out.info = q_info;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
+               "failed to query domain info");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query domain info");
+
+       return true;
+}
+
+static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
+                                     struct dcerpc_pipe *np,
+                                     struct torture_context *tctx,
+                                     uint32_t acct_flags,
+                                     const char *acct_name,
+                                     struct policy_handle *domain_handle,
+                                     struct policy_handle *user_handle,
+                                     char **password,
+                                     struct cli_credentials *machine_credentials,
+                                     const char *comment,
+                                     bool disable,
+                                     bool interactive,
+                                     NTSTATUS expected_success_status,
+                                     struct samr_DomInfo1 *info1,
+                                     struct samr_DomInfo12 *info12)
+{
+       union samr_DomainInfo info;
+       char **passwords;
+       int i;
+       uint32_t badpwdcount, tmp;
+       uint32_t password_history_length = 12;
+       uint32_t lockout_threshold = 15;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+
+       torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
+
+       torture_assert(tctx, password_history_length < lockout_threshold,
+               "password history length needs to be smaller than account lockout threshold for this test");
+
+
+       /* set policies */
+
+       info.info1 = *info1;
+       info.info1.password_history_length = password_history_length;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainPasswordInformation, &info),
+                      "failed to set password history length");
+
+       info.info12 = *info12;
+       info.info12.lockout_threshold = lockout_threshold;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &info),
+                      "failed to set lockout threshold");
+
+       /* reset bad pwd count */
+
+       torture_assert(tctx,
+               test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
+
+
+       /* enable or disable account */
+       if (disable) {
+               torture_assert(tctx,
+                              test_SetUserInfo_acct_flags(b, tctx, user_handle,
+                                               acct_flags | ACB_DISABLED),
+                              "failed to disable user");
+       } else {
+               torture_assert(tctx,
+                              test_SetUserInfo_acct_flags(b, tctx, user_handle,
+                                               acct_flags & ~ACB_DISABLED),
+                              "failed to enable user");
+       }
+
+
+       /* setup password history */
+
+       passwords = talloc_array(tctx, char *, password_history_length);
+
+       for (i=0; i < password_history_length; i++) {
+
+               torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
+                       "failed to set password");
+               passwords[i] = talloc_strdup(tctx, *password);
+
+               if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                             acct_name, passwords[i],
+                                             expected_success_status, interactive)) {
+                       torture_fail(tctx, "failed to auth with latest password");
+               }
+
+               torture_assert(tctx,
+                       test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+
+               torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
+       }
+
+
+       /* test with wrong password */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                     acct_name, "random_crap",
+                                     NT_STATUS_WRONG_PASSWORD, interactive)) {
+               torture_fail(tctx, "succeeded to authenticate with wrong password");
+       }
+
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+
+       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+
+
+       /* test with latest good password */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
+                                     passwords[password_history_length-1],
+                                     expected_success_status, interactive)) {
+               torture_fail(tctx, "succeeded to authenticate with wrong password");
+       }
+
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+
+       if (disable) {
+               torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+       } else {
+               /* only enabled accounts get the bad pwd count reset upon
+                * successful logon */
+               torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
+       }
+
+       tmp = badpwdcount;
+
+
+       /* test password history */
+
+       for (i=0; i < password_history_length; i++) {
+
+               torture_comment(tctx, "Testing bad password count behavior with "
+                                     "password #%d of #%d\n", i, password_history_length);
+
+               /* - network samlogon will succeed auth and not
+                *   increase badpwdcount for 2 last entries
+                * - interactive samlogon only for the last one */
+
+               if (i == password_history_length - 1 ||
+                   (i == password_history_length - 2 && !interactive)) {
+
+                       if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                                     acct_name, passwords[i],
+                                                     expected_success_status, interactive)) {
+                               torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
+                       }
+
+                       torture_assert(tctx,
+                               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+
+                       if (disable) {
+                               /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
+                               torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
+                       } else {
+                               /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
+                               torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
+                       }
+
+                       tmp = badpwdcount;
+
+                       continue;
+               }
+
+               if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                             acct_name, passwords[i],
+                                             NT_STATUS_WRONG_PASSWORD, interactive)) {
+                       torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
+               }
+
+               torture_assert(tctx,
+                       test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+
+               /* - network samlogon will fail auth but not increase
+                *   badpwdcount for 3rd last entry
+                * - interactive samlogon for 3rd and 2nd last entry */
+
+               if (i == password_history_length - 3 ||
+                   (i == password_history_length - 2 && interactive)) {
+                       /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
+                       torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
+               } else {
+                       /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
+                       torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
+               }
+
+               tmp = badpwdcount;
+       }
+
+       return true;
+}
+
+static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
+                                          struct torture_context *tctx,
+                                          uint32_t acct_flags,
+                                          const char *acct_name,
+                                          struct policy_handle *domain_handle,
+                                          struct policy_handle *user_handle,
+                                          char **password,
+                                          struct cli_credentials *machine_credentials)
+{
+       union samr_DomainInfo *q_info, s_info;
+       struct samr_DomInfo1 info1, _info1;
+       struct samr_DomInfo12 info12, _info12;
+       bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *np;
+       int i;
+
+       struct {
+               const char *comment;
+               bool disabled;
+               bool interactive;
+               NTSTATUS expected_success_status;
+       } creds[] = {
+               {
+                       .comment                = "network logon (disabled account)",
+                       .disabled               = true,
+                       .interactive            = false,
+                       .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
+               },
+               {
+                       .comment                = "network logon (enabled account)",
+                       .disabled               = false,
+                       .interactive            = false,
+                       .expected_success_status= NT_STATUS_OK
+               },
+               {
+                       .comment                = "interactive logon (disabled account)",
+                       .disabled               = true,
+                       .interactive            = true,
+                       .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
+               },
+               {
+                       .comment                = "interactive logon (enabled account)",
+                       .disabled               = false,
+                       .interactive            = true,
+                       .expected_success_status= NT_STATUS_OK
+               },
+       };
+
+       torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
+
+       /* backup old policies */
+
+       torture_assert(tctx,
+               test_QueryDomainInfo2_level(b, tctx, domain_handle,
+                                           DomainPasswordInformation, &q_info),
+               "failed to query domain info level 1");
+
+       info1 = q_info->info1;
+       _info1 = info1;
+
+       torture_assert(tctx,
+               test_QueryDomainInfo2_level(b, tctx, domain_handle,
+                                           DomainLockoutInformation, &q_info),
+               "failed to query domain info level 12");
+
+       info12 = q_info->info12;
+       _info12 = info12;
+
+       /* run tests */
+
+       for (i=0; i < ARRAY_SIZE(creds); i++) {
+
+               /* skip trust tests for now */
+               if (acct_flags & ACB_WSTRUST ||
+                   acct_flags & ACB_SVRTRUST ||
+                   acct_flags & ACB_DOMTRUST) {
+                       continue;
+               }
+
+               ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
+                                                domain_handle, user_handle, password,
+                                                machine_credentials,
+                                                creds[i].comment,
+                                                creds[i].disabled,
+                                                creds[i].interactive,
+                                                creds[i].expected_success_status,
+                                                &_info1, &_info12);
+               if (!ret) {
+                       torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
+               } else {
+                       torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
+               }
+       }
+
+       /* restore policies */
+
+       s_info.info1 = info1;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainPasswordInformation, &s_info),
+                      "failed to set password information");
+
+       s_info.info12 = info12;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &s_info),
+                      "failed to set lockout information");
+
+       return ret;
+}
+
+static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
+                                         struct torture_context *tctx,
+                                         struct policy_handle *handle,
+                                         uint32_t *acct_flags)
+{
+       union samr_UserInfo *info;
+       struct samr_QueryUserInfo r;
+
+       r.in.user_handle = handle;
+       r.in.level = 16;
+       r.out.info = &info;
+
+       torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+               "failed to query userinfo");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query userinfo");
+
+       *acct_flags = info->info16.acct_flags;
+
+       torture_comment(tctx, "  (acct_flags: 0x%08x)\n", *acct_flags);
+
+       return true;
+}
+
+static bool test_Password_lockout(struct dcerpc_pipe *p,
+                                 struct dcerpc_pipe *np,
+                                 struct torture_context *tctx,
+                                 uint32_t acct_flags,
+                                 const char *acct_name,
+                                 struct policy_handle *domain_handle,
+                                 struct policy_handle *user_handle,
+                                 char **password,
+                                 struct cli_credentials *machine_credentials,
+                                 const char *comment,
+                                 bool disable,
+                                 bool interactive,
+                                 NTSTATUS expected_success_status,
+                                 struct samr_DomInfo1 *info1,
+                                 struct samr_DomInfo12 *info12)
+{
+       union samr_DomainInfo info;
+       uint32_t badpwdcount;
+       uint32_t password_history_length = 1;
+       uint64_t lockout_threshold = 1;
+       uint32_t lockout_seconds = 5;
+       uint64_t delta_time_factor = 10 * 1000 * 1000;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+
+       torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
+
+       /* set policies */
+
+       info.info1 = *info1;
+
+       torture_comment(tctx, "setting password history length.\n");
+       info.info1.password_history_length = password_history_length;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainPasswordInformation, &info),
+                      "failed to set password history length");
+
+       info.info12 = *info12;
+       info.info12.lockout_threshold = lockout_threshold;
+
+       /* set lockout duration < lockout window: should fail */
+       info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
+       info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
+
+       torture_assert(tctx,
+               test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
+                                           DomainLockoutInformation, &info,
+                                           NT_STATUS_INVALID_PARAMETER),
+               "setting lockout duration < lockout window gave unexpected result");
+
+       info.info12.lockout_duration = 0;
+       info.info12.lockout_window = 0;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &info),
+                      "failed to set lockout window and duration to 0");
+
+
+       /* set lockout duration of 5 seconds */
+       info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
+       info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &info),
+                      "failed to set lockout window and duration to 5 seconds");
+
+       /* reset bad pwd count */
+
+       torture_assert(tctx,
+               test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
+
+
+       /* enable or disable account */
+
+       if (disable) {
+               torture_assert(tctx,
+                              test_SetUserInfo_acct_flags(b, tctx, user_handle,
+                                               acct_flags | ACB_DISABLED),
+                              "failed to disable user");
+       } else {
+               torture_assert(tctx,
+                              test_SetUserInfo_acct_flags(b, tctx, user_handle,
+                                               acct_flags & ~ACB_DISABLED),
+                              "failed to enable user");
+       }
+
+
+       /* test logon with right password */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                     acct_name, *password,
+                                     expected_success_status, interactive)) {
+               torture_fail(tctx, "failed to auth with latest password");
+       }
+
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+       torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
+
+
+       /* test with wrong password ==> lockout */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                     acct_name, "random_crap",
+                                     NT_STATUS_WRONG_PASSWORD, interactive)) {
+               torture_fail(tctx, "succeeded to authenticate with wrong password");
+       }
+
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+
+       torture_assert(tctx,
+               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
+       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
+                                "expected account to be locked");
+
+
+       /* test with good password */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
+                                    *password,
+                                    NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
+       {
+               torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
+       }
+
+       /* bad pwd count should not get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+
+       /* curiously, windows does _not_ set the autlock flag */
+       torture_assert(tctx,
+               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
+       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
+                                "expected account to be locked");
+
+
+       /* with bad password */
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
+                                     acct_name, "random_crap2",
+                                     NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
+       {
+               torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
+       }
+
+       /* bad pwd count should not get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
+       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+
+       /* curiously, windows does _not_ set the autlock flag */
+       torture_assert(tctx,
+               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
+       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
+                                "expected account to be locked");
+
+
+       /* let lockout duration expire ==> unlock */
+
+       torture_comment(tctx, "let lockout duration expire...\n");
+       sleep(lockout_seconds + 1);
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
+                                    *password,
+                                    expected_success_status, interactive))
+       {
+               torture_fail(tctx, "failed to authenticate after lockout expired");
+       }
+
+       torture_assert(tctx,
+               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
+       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
+                                "expected account not to be locked");
+
+       return true;
+}
+
+static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
+                                      struct torture_context *tctx,
+                                      uint32_t acct_flags,
+                                      const char *acct_name,
+                                      struct policy_handle *domain_handle,
+                                      struct policy_handle *user_handle,
+                                      char **password,
+                                      struct cli_credentials *machine_credentials)
+{
+       union samr_DomainInfo *q_info, s_info;
+       struct samr_DomInfo1 info1, _info1;
+       struct samr_DomInfo12 info12, _info12;
+       bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_pipe *np;
+       int i;
+
+       struct {
+               const char *comment;
+               bool disabled;
+               bool interactive;
+               NTSTATUS expected_success_status;
+       } creds[] = {
+               {
+                       .comment                = "network logon (disabled account)",
+                       .disabled               = true,
+                       .interactive            = false,
+                       .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
+               },
+               {
+                       .comment                = "network logon (enabled account)",
+                       .disabled               = false,
+                       .interactive            = false,
+                       .expected_success_status= NT_STATUS_OK
+               },
+               {
+                       .comment                = "interactive logon (disabled account)",
+                       .disabled               = true,
+                       .interactive            = true,
+                       .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
+               },
+               {
+                       .comment                = "interactive logon (enabled account)",
+                       .disabled               = false,
+                       .interactive            = true,
+                       .expected_success_status= NT_STATUS_OK
+               },
+       };
+
+       torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
+
+       /* backup old policies */
+
+       torture_assert(tctx,
+               test_QueryDomainInfo2_level(b, tctx, domain_handle,
+                                           DomainPasswordInformation, &q_info),
+               "failed to query domain info level 1");
+
+       info1 = q_info->info1;
+       _info1 = info1;
+
+       torture_assert(tctx,
+               test_QueryDomainInfo2_level(b, tctx, domain_handle,
+                                           DomainLockoutInformation, &q_info),
+               "failed to query domain info level 12");
+
+       info12 = q_info->info12;
+       _info12 = info12;
+
+       /* run tests */
+
+       for (i=0; i < ARRAY_SIZE(creds); i++) {
+
+               /* skip trust tests for now */
+               if (acct_flags & ACB_WSTRUST ||
+                   acct_flags & ACB_SVRTRUST ||
+                   acct_flags & ACB_DOMTRUST) {
+                       continue;
+               }
+
+               ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
+                                            domain_handle, user_handle, password,
+                                            machine_credentials,
+                                            creds[i].comment,
+                                            creds[i].disabled,
+                                            creds[i].interactive,
+                                            creds[i].expected_success_status,
+                                            &_info1, &_info12);
+               if (!ret) {
+                       torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
+               } else {
+                       torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
+               }
+       }
+
+       /* restore policies */
+
+       s_info.info1 = info1;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainPasswordInformation, &s_info),
+                      "failed to set password information");
+
+       s_info.info12 = info12;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &s_info),
+                      "failed to set lockout information");
+
+       return ret;
+}
+
+static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
+                                      struct dcerpc_pipe *lp,
+                                      struct torture_context *tctx,
+                                      struct policy_handle *domain_handle,
+                                      struct policy_handle *lsa_handle,
+                                      struct policy_handle *user_handle,
+                                      const struct dom_sid *domain_sid,
+                                      uint32_t rid,
+                                      struct cli_credentials *machine_credentials)
+{
+       bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct dcerpc_binding_handle *lb = lp->binding_handle;
+
+       struct policy_handle lsa_acct_handle;
+       struct dom_sid *user_sid;
+
+       user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
+
+       {
+               struct lsa_EnumAccountRights r;
+               struct lsa_RightSet rights;
+
+               torture_comment(tctx, "Testing LSA EnumAccountRights\n");
+
+               r.in.handle = lsa_handle;
+               r.in.sid = user_sid;
+               r.out.rights = &rights;
+
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
+                       "lsa_EnumAccountRights failed");
+               torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+                       "Expected enum rights for account to fail");
+       }
+
+       {
+               struct lsa_RightSet rights;
+               struct lsa_StringLarge names[2];
+               struct lsa_AddAccountRights r;
+
+               torture_comment(tctx, "Testing LSA AddAccountRights\n");
+
+               init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
+               init_lsa_StringLarge(&names[1], NULL);
+
+               rights.count = 1;
+               rights.names = names;
+
+               r.in.handle = lsa_handle;
+               r.in.sid = user_sid;
+               r.in.rights = &rights;
+
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
+                       "lsa_AddAccountRights failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "Failed to add privileges");
+       }
+
+       {
+               struct lsa_EnumAccounts r;
+               uint32_t resume_handle = 0;
+               struct lsa_SidArray lsa_sid_array;
+               int i;
+               bool found_sid = false;
+
+               torture_comment(tctx, "Testing LSA EnumAccounts\n");
 
                r.in.handle = lsa_handle;
                r.in.num_entries = 0x1000;
@@ -3345,8 +4323,9 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                r.out.sids = &lsa_sid_array;
                r.out.resume_handle = &resume_handle;
 
-               status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
+                       "lsa_EnumAccounts failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum accounts");
 
                for (i=0; i < lsa_sid_array.num_sids; i++) {
@@ -3363,14 +4342,15 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                struct lsa_EnumAccountRights r;
                struct lsa_RightSet user_rights;
 
-               printf("Testing LSA EnumAccountRights\n");
+               torture_comment(tctx, "Testing LSA EnumAccountRights\n");
 
                r.in.handle = lsa_handle;
                r.in.sid = user_sid;
                r.out.rights = &user_rights;
 
-               status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
+                       "lsa_EnumAccountRights failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum rights for account");
 
                if (user_rights.count < 1) {
@@ -3382,15 +4362,16 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
        {
                struct lsa_OpenAccount r;
 
-               printf("Testing LSA OpenAccount\n");
+               torture_comment(tctx, "Testing LSA OpenAccount\n");
 
                r.in.handle = lsa_handle;
                r.in.sid = user_sid;
                r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
                r.out.acct_handle = &lsa_acct_handle;
 
-               status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
+                       "lsa_OpenAccount failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to open lsa account");
        }
 
@@ -3398,39 +4379,43 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                struct lsa_GetSystemAccessAccount r;
                uint32_t access_mask;
 
-               printf("Testing LSA GetSystemAccessAccount\n");
+               torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
 
                r.in.handle = &lsa_acct_handle;
                r.out.access_mask = &access_mask;
 
-               status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
+                       "lsa_GetSystemAccessAccount failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to get lsa system access account");
        }
 
        {
                struct lsa_Close r;
 
-               printf("Testing LSA Close\n");
+               torture_comment(tctx, "Testing LSA Close\n");
 
                r.in.handle = &lsa_acct_handle;
                r.out.handle = &lsa_acct_handle;
 
-               status = dcerpc_lsa_Close(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
+                       "lsa_Close failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to close lsa");
        }
 
        {
                struct samr_DeleteUser r;
 
-               printf("Testing SAMR DeleteUser\n");
+               torture_comment(tctx, "Testing SAMR DeleteUser\n");
 
                r.in.user_handle = user_handle;
                r.out.user_handle = user_handle;
 
-               status = dcerpc_samr_DeleteUser(p, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
+                       "DeleteUser failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "DeleteUser failed");
        }
 
        {
@@ -3440,7 +4425,7 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                int i;
                bool found_sid = false;
 
-               printf("Testing LSA EnumAccounts\n");
+               torture_comment(tctx, "Testing LSA EnumAccounts\n");
 
                r.in.handle = lsa_handle;
                r.in.num_entries = 0x1000;
@@ -3448,8 +4433,9 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                r.out.sids = &lsa_sid_array;
                r.out.resume_handle = &resume_handle;
 
-               status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
+                       "lsa_EnumAccounts failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum accounts");
 
                for (i=0; i < lsa_sid_array.num_sids; i++) {
@@ -3466,14 +4452,15 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                struct lsa_EnumAccountRights r;
                struct lsa_RightSet user_rights;
 
-               printf("Testing LSA EnumAccountRights\n");
+               torture_comment(tctx, "Testing LSA EnumAccountRights\n");
 
                r.in.handle = lsa_handle;
                r.in.sid = user_sid;
                r.out.rights = &user_rights;
 
-               status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
+                       "lsa_EnumAccountRights failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum rights for account");
 
                if (user_rights.count < 1) {
@@ -3485,15 +4472,16 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
        {
                struct lsa_OpenAccount r;
 
-               printf("Testing LSA OpenAccount\n");
+               torture_comment(tctx, "Testing LSA OpenAccount\n");
 
                r.in.handle = lsa_handle;
                r.in.sid = user_sid;
                r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
                r.out.acct_handle = &lsa_acct_handle;
 
-               status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
+                       "lsa_OpenAccount failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to open lsa account");
        }
 
@@ -3501,26 +4489,28 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                struct lsa_GetSystemAccessAccount r;
                uint32_t access_mask;
 
-               printf("Testing LSA GetSystemAccessAccount\n");
+               torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
 
                r.in.handle = &lsa_acct_handle;
                r.out.access_mask = &access_mask;
 
-               status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
+                       "lsa_GetSystemAccessAccount failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to get lsa system access account");
        }
 
        {
                struct lsa_DeleteObject r;
 
-               printf("Testing LSA DeleteObject\n");
+               torture_comment(tctx, "Testing LSA DeleteObject\n");
 
                r.in.handle = &lsa_acct_handle;
                r.out.handle = &lsa_acct_handle;
 
-               status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
+                       "lsa_DeleteObject failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to delete object");
        }
 
@@ -3531,7 +4521,7 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                int i;
                bool found_sid = false;
 
-               printf("Testing LSA EnumAccounts\n");
+               torture_comment(tctx, "Testing LSA EnumAccounts\n");
 
                r.in.handle = lsa_handle;
                r.in.num_entries = 0x1000;
@@ -3539,8 +4529,9 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                r.out.sids = &lsa_sid_array;
                r.out.resume_handle = &resume_handle;
 
-               status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
-               torture_assert_ntstatus_ok(tctx, status,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
+                       "lsa_EnumAccounts failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum accounts");
 
                for (i=0; i < lsa_sid_array.num_sids; i++) {
@@ -3557,14 +4548,15 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                struct lsa_EnumAccountRights r;
                struct lsa_RightSet user_rights;
 
-               printf("Testing LSA EnumAccountRights\n");
+               torture_comment(tctx, "Testing LSA EnumAccountRights\n");
 
                r.in.handle = lsa_handle;
                r.in.sid = user_sid;
                r.out.rights = &user_rights;
 
-               status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
-               torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
+                       "lsa_EnumAccountRights failed");
+               torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
                        "Failed to enum rights for account");
        }
 
@@ -3584,6 +4576,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
        struct samr_QueryUserInfo q;
        union samr_UserInfo *info;
        NTSTATUS status;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        bool ret = true;
        int i;
@@ -3595,35 +4588,35 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                0
        };
 
-       status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
+       status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                ret = false;
        }
 
        switch (which_ops) {
        case TORTURE_SAMR_USER_ATTRIBUTES:
-               if (!test_QuerySecurity(p, tctx, user_handle)) {
+               if (!test_QuerySecurity(b, tctx, user_handle)) {
                        ret = false;
                }
 
-               if (!test_QueryUserInfo(p, tctx, user_handle)) {
+               if (!test_QueryUserInfo(b, tctx, user_handle)) {
                        ret = false;
                }
 
-               if (!test_QueryUserInfo2(p, tctx, user_handle)) {
+               if (!test_QueryUserInfo2(b, tctx, user_handle)) {
                        ret = false;
                }
 
-               if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
+               if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
                                      base_acct_name)) {
                        ret = false;
                }
 
-               if (!test_GetUserPwInfo(p, tctx, user_handle)) {
+               if (!test_GetUserPwInfo(b, tctx, user_handle)) {
                        ret = false;
                }
 
-               if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
+               if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
                        ret = false;
                }
 
@@ -3639,7 +4632,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                        ZERO_STRUCT(simple_pass);
                        memset(simple_pass, *v, sizeof(simple_pass) - 1);
 
-                       printf("Testing machine account password policy rules\n");
+                       torture_comment(tctx, "Testing machine account password policy rules\n");
 
                        /* Workstation trust accounts don't seem to need to honour password quality policy */
                        if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
@@ -3696,34 +4689,29 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                        ret = false;
                }
 
-               if (torture_setting_bool(tctx, "samba4", false)) {
-                       printf("skipping Set Password level 18 and 21 against Samba4\n");
-               } else {
+               if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
+                       ret = false;
+               }
 
-                       if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
-                               ret = false;
+               if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
+                       ret = false;
+               }
+
+               for (i = 0; password_fields[i]; i++) {
+
+                       if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
+                               /* we need to skip as that would break
+                                * the ChangePasswordUser3 verify */
+                               continue;
                        }
 
-                       if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
+                       if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
                                ret = false;
                        }
 
-                       for (i = 0; password_fields[i]; i++) {
-
-                               if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
-                                       /* we need to skip as that would break
-                                        * the ChangePasswordUser3 verify */
-                                       continue;
-                               }
-
-                               if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
-                                       ret = false;
-                               }
-
-                               /* check it was set right */
-                               if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
-                                       ret = false;
-                               }
+                       /* check it was set right */
+                       if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
+                               ret = false;
                        }
                }
 
@@ -3731,15 +4719,16 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                q.in.level = 5;
                q.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo level %u failed - %s\n",
-                              q.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
+                       "QueryUserInfo failed");
+               if (!NT_STATUS_IS_OK(q.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                              q.in.level, nt_errstr(q.out.result));
                        ret = false;
                } else {
                        uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
                        if ((info->info5.acct_flags) != expected_flags) {
-                               printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                               torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                       info->info5.acct_flags,
                                       expected_flags);
                                /* FIXME: GD */
@@ -3748,7 +4737,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                                }
                        }
                        if (info->info5.rid != rid) {
-                               printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
+                               torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
                                       info->info5.rid, rid);
 
                        }
@@ -3774,15 +4763,56 @@ static bool test_user_ops(struct dcerpc_pipe *p,
 
                break;
 
+       case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
+
+               /* test bad pwd count change behaviour */
+               if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
+                                                   base_acct_name,
+                                                   domain_handle,
+                                                   user_handle, &password,
+                                                   machine_credentials)) {
+                       ret = false;
+               }
+
+               if (ret == true) {
+                       torture_comment(tctx, "badPwdCount test succeeded\n");
+               } else {
+                       torture_warning(tctx, "badPwdCount test failed\n");
+               }
+
+               break;
+
+       case TORTURE_SAMR_PASSWORDS_LOCKOUT:
+
+               if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
+                                               base_acct_name,
+                                               domain_handle,
+                                               user_handle, &password,
+                                               machine_credentials))
+               {
+                       ret = false;
+               }
+
+               if (ret == true) {
+                       torture_comment(tctx, "lockout test succeeded\n");
+               } else {
+                       torture_warning(tctx, "lockout test failed\n");
+               }
+
+               break;
+
+
        case TORTURE_SAMR_USER_PRIVILEGES: {
 
                struct dcerpc_pipe *lp;
                struct policy_handle *lsa_handle;
+               struct dcerpc_binding_handle *lb;
 
                status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
                torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
+               lb = lp->binding_handle;
 
-               if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
+               if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
                        ret = false;
                }
 
@@ -3793,7 +4823,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                        ret = false;
                }
 
-               if (!test_lsa_Close(lp, tctx, lsa_handle)) {
+               if (!test_lsa_Close(lb, tctx, lsa_handle)) {
                        ret = false;
                }
 
@@ -3804,42 +4834,47 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                break;
        }
        case TORTURE_SAMR_OTHER:
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+       case TORTURE_SAMR_MANY_GROUPS:
+       case TORTURE_SAMR_MANY_ALIASES:
                /* We just need the account to exist */
                break;
        }
        return ret;
 }
 
-static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_alias_ops(struct dcerpc_binding_handle *b,
+                          struct torture_context *tctx,
                           struct policy_handle *alias_handle,
                           const struct dom_sid *domain_sid)
 {
        bool ret = true;
 
        if (!torture_setting_bool(tctx, "samba3", false)) {
-               if (!test_QuerySecurity(p, tctx, alias_handle)) {
+               if (!test_QuerySecurity(b, tctx, alias_handle)) {
                        ret = false;
                }
        }
 
-       if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
+       if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
                ret = false;
        }
 
-       if (!test_SetAliasInfo(p, tctx, alias_handle)) {
+       if (!test_SetAliasInfo(b, tctx, alias_handle)) {
                ret = false;
        }
 
-       if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
+       if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
                ret = false;
        }
 
-       if (torture_setting_bool(tctx, "samba4", false)) {
-               printf("skipping MultipleMembers Alias tests against Samba4\n");
+       if (torture_setting_bool(tctx, "samba3", false) ||
+           torture_setting_bool(tctx, "samba4", false)) {
+               torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
                return ret;
        }
 
-       if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
+       if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
                ret = false;
        }
 
@@ -3847,23 +4882,24 @@ static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
 }
 
 
-static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                    struct policy_handle *user_handle)
+static bool test_DeleteUser(struct dcerpc_binding_handle *b,
+                           struct torture_context *tctx,
+                           struct policy_handle *user_handle)
 {
        struct samr_DeleteUser d;
-       NTSTATUS status;
        torture_comment(tctx, "Testing DeleteUser\n");
 
        d.in.user_handle = user_handle;
        d.out.user_handle = user_handle;
 
-       status = dcerpc_samr_DeleteUser(p, tctx, &d);
-       torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
+               "DeleteUser failed");
+       torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
 
        return true;
 }
 
-bool test_DeleteUser_byname(struct dcerpc_pipe *p,
+bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
                            struct torture_context *tctx,
                            struct policy_handle *handle, const char *name)
 {
@@ -3872,32 +4908,34 @@ bool test_DeleteUser_byname(struct dcerpc_pipe *p,
        struct policy_handle user_handle;
        uint32_t rid;
 
-       status = test_LookupName(p, tctx, handle, name, &rid);
+       status = test_LookupName(b, tctx, handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
-       status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
+       status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
        d.in.user_handle = &user_handle;
        d.out.user_handle = &user_handle;
-       status = dcerpc_samr_DeleteUser(p, tctx, &d);
-       if (!NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
+               "DeleteUser failed");
+       if (!NT_STATUS_IS_OK(d.out.result)) {
+               status = d.out.result;
                goto failed;
        }
 
        return true;
 
 failed:
-       printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
 
-static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
+static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
                                    struct torture_context *tctx,
                                    struct policy_handle *handle, const char *name)
 {
@@ -3907,7 +4945,7 @@ static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
        struct policy_handle group_handle;
        uint32_t rid;
 
-       status = test_LookupName(p, tctx, handle, name, &rid);
+       status = test_LookupName(b, tctx, handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3916,27 +4954,31 @@ static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.group_handle = &group_handle;
-       status = dcerpc_samr_OpenGroup(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
+               "OpenGroup failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               status = r.out.result;
                goto failed;
        }
 
        d.in.group_handle = &group_handle;
        d.out.group_handle = &group_handle;
-       status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
-       if (!NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
+               "DeleteDomainGroup failed");
+       if (!NT_STATUS_IS_OK(d.out.result)) {
+               status = d.out.result;
                goto failed;
        }
 
        return true;
 
 failed:
-       printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
 
-static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
+static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
                                    struct torture_context *tctx,
                                    struct policy_handle *domain_handle,
                                    const char *name)
@@ -3947,9 +4989,9 @@ static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
        struct policy_handle alias_handle;
        uint32_t rid;
 
-       printf("testing DeleteAlias_byname\n");
+       torture_comment(tctx, "Testing DeleteAlias_byname\n");
 
-       status = test_LookupName(p, tctx, domain_handle, name, &rid);
+       status = test_LookupName(b, tctx, domain_handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3958,54 +5000,59 @@ static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.alias_handle = &alias_handle;
-       status = dcerpc_samr_OpenAlias(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
+               "OpenAlias failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               status = r.out.result;
                goto failed;
        }
 
        d.in.alias_handle = &alias_handle;
        d.out.alias_handle = &alias_handle;
-       status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
-       if (!NT_STATUS_IS_OK(status)) {
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
+               "DeleteDomAlias failed");
+       if (!NT_STATUS_IS_OK(d.out.result)) {
+               status = d.out.result;
                goto failed;
        }
 
        return true;
 
 failed:
-       printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
-static bool test_DeleteAlias(struct dcerpc_pipe *p,
+static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
                             struct torture_context *tctx,
                             struct policy_handle *alias_handle)
 {
        struct samr_DeleteDomAlias d;
-       NTSTATUS status;
        bool ret = true;
-       printf("Testing DeleteAlias\n");
+
+       torture_comment(tctx, "Testing DeleteAlias\n");
 
        d.in.alias_handle = alias_handle;
        d.out.alias_handle = alias_handle;
 
-       status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("DeleteAlias failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
+               "DeleteDomAlias failed");
+       if (!NT_STATUS_IS_OK(d.out.result)) {
+               torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
                ret = false;
        }
 
        return ret;
 }
 
-static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_CreateAlias(struct dcerpc_binding_handle *b,
+                            struct torture_context *tctx,
                             struct policy_handle *domain_handle,
                             const char *alias_name,
                             struct policy_handle *alias_handle,
                             const struct dom_sid *domain_sid,
                             bool test_alias)
 {
-       NTSTATUS status;
        struct samr_CreateDomAlias r;
        struct lsa_String name;
        uint32_t rid;
@@ -4018,30 +5065,32 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx
        r.out.alias_handle = alias_handle;
        r.out.rid = &rid;
 
-       printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
+       torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
 
-       status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
+               "CreateDomAlias failed");
 
        if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-                       printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
+                       torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
                        return true;
                } else {
-                       printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
-                              nt_errstr(status));
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
+                              nt_errstr(r.out.result));
                        return false;
                }
        }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
-               if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
+               if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
                        return false;
                }
-               status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
+                       "CreateDomAlias failed");
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("CreateAlias failed - %s\n", nt_errstr(status));
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -4049,7 +5098,7 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx
                return ret;
        }
 
-       if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
+       if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
                ret = false;
        }
 
@@ -4062,12 +5111,13 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                                struct policy_handle *domain_handle, char **password)
 {
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        if (!*password) {
                return false;
        }
 
-       if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
+       if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
                ret = false;
        }
 
@@ -4105,7 +5155,6 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                uint16_t len_old, len;
                uint32_t pwd_prop_old;
                int64_t min_pwd_age_old;
-               NTSTATUS status;
 
                len = 5;
 
@@ -4113,9 +5162,10 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                r.in.level = 1;
                r.out.info = &info;
 
-               printf("testing samr_QueryDomainInfo level 1\n");
-               status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
+               torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
+                       "QueryDomainInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
                        return false;
                }
 
@@ -4133,13 +5183,14 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                min_pwd_age_old = s.in.info->info1.min_password_age;
                s.in.info->info1.min_password_age = 0;
 
-               printf("testing samr_SetDomainInfo level 1\n");
-               status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
-               if (!NT_STATUS_IS_OK(status)) {
+               torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
+                       "SetDomainInfo failed");
+               if (!NT_STATUS_IS_OK(s.out.result)) {
                        return false;
                }
 
-               printf("calling test_ChangePasswordUser3 with too short password\n");
+               torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
 
                if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
                        ret = false;
@@ -4149,16 +5200,16 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                s.in.info->info1.password_properties = pwd_prop_old;
                s.in.info->info1.min_password_age = min_pwd_age_old;
 
-               printf("testing samr_SetDomainInfo level 1\n");
-               status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
-               if (!NT_STATUS_IS_OK(status)) {
+               torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
+                       "SetDomainInfo failed");
+               if (!NT_STATUS_IS_OK(s.out.result)) {
                        return false;
                }
 
        }
 
        {
-               NTSTATUS status;
                struct samr_OpenUser r;
                struct samr_QueryUserInfo q;
                union samr_UserInfo *info;
@@ -4173,9 +5224,10 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                n.out.rids = &rids;
                n.out.types = &types;
 
-               status = dcerpc_samr_LookupNames(p, tctx, &n);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("LookupNames failed - %s\n", nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
+                       "LookupNames failed");
+               if (!NT_STATUS_IS_OK(n.out.result)) {
+                       torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
                        return false;
                }
 
@@ -4184,9 +5236,10 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                r.in.rid = n.out.rids->ids[0];
                r.out.user_handle = &user_handle;
 
-               status = dcerpc_samr_OpenUser(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
+                       "OpenUser failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
                        return false;
                }
 
@@ -4194,13 +5247,14 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                q.in.level = 5;
                q.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo failed - %s\n", nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
+                       "QueryUserInfo failed");
+               if (!NT_STATUS_IS_OK(q.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
                        return false;
                }
 
-               printf("calling test_ChangePasswordUser3 with too early password change\n");
+               torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
 
                if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
                                              info->info5.last_password_change, true)) {
@@ -4233,7 +5287,6 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        TALLOC_CTX *user_ctx;
 
-       NTSTATUS status;
        struct samr_CreateUser r;
        struct samr_QueryUserInfo q;
        union samr_UserInfo *info;
@@ -4244,6 +5297,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
        const uint32_t acct_flags = ACB_NORMAL;
        struct lsa_String name;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        struct policy_handle user_handle;
        user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
@@ -4255,32 +5309,34 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
        r.out.user_handle = &user_handle;
        r.out.rid = &rid;
 
-       printf("Testing CreateUser(%s)\n", r.in.account_name->string);
+       torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
 
-       status = dcerpc_samr_CreateUser(p, user_ctx, &r);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
+               "CreateUser failed");
 
        if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                       printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
+                       torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
                        return true;
                } else {
-                       printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
-                              nt_errstr(status));
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+                              nt_errstr(r.out.result));
                        return false;
                }
        }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
-               if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
+               if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
                        talloc_free(user_ctx);
                        return false;
                }
-               status = dcerpc_samr_CreateUser(p, user_ctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
+                       "CreateUser failed");
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
+       if (!NT_STATUS_IS_OK(r.out.result)) {
                talloc_free(user_ctx);
-               printf("CreateUser failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -4296,14 +5352,15 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                q.in.level = 16;
                q.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo level %u failed - %s\n",
-                              q.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
+                       "QueryUserInfo failed");
+               if (!NT_STATUS_IS_OK(q.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                              q.in.level, nt_errstr(q.out.result));
                        ret = false;
                } else {
                        if ((info->info16.acct_flags & acct_flags) != acct_flags) {
-                               printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                               torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                       info->info16.acct_flags,
                                       acct_flags);
                                ret = false;
@@ -4319,14 +5376,15 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                if (user_handle_out) {
                        *user_handle_out = user_handle;
                } else {
-                       printf("Testing DeleteUser (createuser test)\n");
+                       torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
 
                        d.in.user_handle = &user_handle;
                        d.out.user_handle = &user_handle;
 
-                       status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("DeleteUser failed - %s\n", nt_errstr(status));
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
+                               "DeleteUser failed");
+                       if (!NT_STATUS_IS_OK(d.out.result)) {
+                               torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
                                ret = false;
                        }
                }
@@ -4345,7 +5403,6 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                             enum torture_samr_choice which_ops,
                             struct cli_credentials *machine_credentials)
 {
-       NTSTATUS status;
        struct samr_CreateUser2 r;
        struct samr_QueryUserInfo q;
        union samr_UserInfo *info;
@@ -4355,6 +5412,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
        struct lsa_String name;
        bool ret = true;
        int i;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        struct {
                uint32_t acct_flags;
@@ -4370,7 +5428,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
                { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
                { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
-               { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
+               { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
                { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
                { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
                { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
@@ -4393,46 +5451,49 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                r.out.access_granted = &access_granted;
                r.out.rid = &rid;
 
-               printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
+               torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
 
-               status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
+                       "CreateUser2 failed");
 
                if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
-                       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
-                               printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
+                       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
+                               torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
                                continue;
                        } else {
-                               printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
-                                      nt_errstr(status));
+                               torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+                                      nt_errstr(r.out.result));
                                ret = false;
                                continue;
                        }
                }
 
-               if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
-                       if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
+                       if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
                                talloc_free(user_ctx);
                                ret = false;
                                continue;
                        }
-                       status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
+                               "CreateUser2 failed");
 
                }
-               if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
-                       printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
-                              nt_errstr(status), nt_errstr(account_types[i].nt_status));
+               if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
+                       torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
+                              nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
                        ret = false;
                }
 
-               if (NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_IS_OK(r.out.result)) {
                        q.in.user_handle = &user_handle;
                        q.in.level = 5;
                        q.out.info = &info;
 
-                       status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("QueryUserInfo level %u failed - %s\n",
-                                      q.in.level, nt_errstr(status));
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
+                               "QueryUserInfo failed");
+                       if (!NT_STATUS_IS_OK(q.out.result)) {
+                               torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                                      q.in.level, nt_errstr(q.out.result));
                                ret = false;
                        } else {
                                uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
@@ -4440,7 +5501,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                        expected_flags |= ACB_PW_EXPIRED;
                                }
                                if ((info->info5.acct_flags) != expected_flags) {
-                                       printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                                       torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                               info->info5.acct_flags,
                                               expected_flags);
                                        ret = false;
@@ -4448,21 +5509,21 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                switch (acct_flags) {
                                case ACB_SVRTRUST:
                                        if (info->info5.primary_gid != DOMAIN_RID_DCS) {
-                                               printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
+                                               torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_DCS, info->info5.primary_gid);
                                                ret = false;
                                        }
                                        break;
                                case ACB_WSTRUST:
                                        if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
-                                               printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
+                                               torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
                                                ret = false;
                                        }
                                        break;
                                case ACB_NORMAL:
                                        if (info->info5.primary_gid != DOMAIN_RID_USERS) {
-                                               printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
+                                               torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_USERS, info->info5.primary_gid);
                                                ret = false;
                                        }
@@ -4477,14 +5538,15 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                        }
 
                        if (!policy_handle_empty(&user_handle)) {
-                               printf("Testing DeleteUser (createuser2 test)\n");
+                               torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
 
                                d.in.user_handle = &user_handle;
                                d.out.user_handle = &user_handle;
 
-                               status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       printf("DeleteUser failed - %s\n", nt_errstr(status));
+                               torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
+                                       "DeleteUser failed");
+                               if (!NT_STATUS_IS_OK(d.out.result)) {
+                                       torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
                                        ret = false;
                                }
                        }
@@ -4495,11 +5557,10 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
        return ret;
 }
 
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
                                struct torture_context *tctx,
                                struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryAliasInfo r;
        union samr_AliasInfo *info;
        uint16_t levels[] = {1, 2, 3};
@@ -4507,16 +5568,17 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryAliasInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
 
                r.in.alias_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryAliasInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
+                       "QueryAliasInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -4524,11 +5586,10 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
+static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
                                struct torture_context *tctx,
                                struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryGroupInfo r;
        union samr_GroupInfo *info;
        uint16_t levels[] = {1, 2, 3, 4, 5};
@@ -4536,16 +5597,17 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryGroupInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
 
                r.in.group_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryGroupInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
+                       "QueryGroupInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -4553,23 +5615,23 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryGroupMember(struct dcerpc_pipe *p,
+static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
                                  struct torture_context *tctx,
                                  struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryGroupMember r;
-       struct samr_RidTypeArray *rids = NULL;
+       struct samr_RidAttrArray *rids = NULL;
        bool ret = true;
 
-       printf("Testing QueryGroupMember\n");
+       torture_comment(tctx, "Testing QueryGroupMember\n");
 
        r.in.group_handle = handle;
        r.out.rids = &rids;
 
-       status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
+               "QueryGroupMember failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -4577,11 +5639,10 @@ static bool test_QueryGroupMember(struct dcerpc_pipe *p,
 }
 
 
-static bool test_SetGroupInfo(struct dcerpc_pipe *p,
+static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
                              struct torture_context *tctx,
                              struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryGroupInfo r;
        union samr_GroupInfo *info;
        struct samr_SetGroupInfo s;
@@ -4591,20 +5652,21 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p,
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryGroupInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
 
                r.in.group_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryGroupInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
+                       "QueryGroupInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
 
-               printf("Testing SetGroupInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
 
                s.in.group_handle = handle;
                s.in.level = levels[i];
@@ -4624,18 +5686,19 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p,
                        init_lsa_String(&s.in.info->description, "test description");
                }
 
-               status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
+                       "SetGroupInfo failed");
                if (set_ok[i]) {
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("SetGroupInfo level %u failed - %s\n",
-                                      r.in.level, nt_errstr(status));
+                       if (!NT_STATUS_IS_OK(s.out.result)) {
+                               torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
+                                      r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
                } else {
-                       if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
-                               printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
-                                      r.in.level, nt_errstr(status));
+                       if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
+                               torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+                                      r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
@@ -4645,11 +5708,10 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryUserInfo(struct dcerpc_pipe *p,
+static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
                               struct torture_context *tctx,
                               struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryUserInfo r;
        union samr_UserInfo *info;
        uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
@@ -4658,16 +5720,17 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p,
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryUserInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
 
                r.in.user_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+                       "QueryUserInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -4675,11 +5738,10 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
                                struct torture_context *tctx,
                                struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryUserInfo2 r;
        union samr_UserInfo *info;
        uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
@@ -4688,16 +5750,17 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryUserInfo2 level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
 
                r.in.user_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo2 level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
+                       "QueryUserInfo2 failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -4705,102 +5768,102 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_OpenUser(struct dcerpc_pipe *p,
+static bool test_OpenUser(struct dcerpc_binding_handle *b,
                          struct torture_context *tctx,
                          struct policy_handle *handle, uint32_t rid)
 {
-       NTSTATUS status;
        struct samr_OpenUser r;
        struct policy_handle user_handle;
        bool ret = true;
 
-       printf("Testing OpenUser(%u)\n", rid);
+       torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
 
        r.in.domain_handle = handle;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.user_handle = &user_handle;
 
-       status = dcerpc_samr_OpenUser(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
+               "OpenUser failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
-       if (!test_QuerySecurity(p, tctx, &user_handle)) {
+       if (!test_QuerySecurity(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_QueryUserInfo(p, tctx, &user_handle)) {
+       if (!test_QueryUserInfo(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
+       if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
+       if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
+       if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, tctx, &user_handle)) {
+       if (!test_samr_handle_Close(b, tctx, &user_handle)) {
                ret = false;
        }
 
        return ret;
 }
 
-static bool test_OpenGroup(struct dcerpc_pipe *p,
+static bool test_OpenGroup(struct dcerpc_binding_handle *b,
                           struct torture_context *tctx,
                           struct policy_handle *handle, uint32_t rid)
 {
-       NTSTATUS status;
        struct samr_OpenGroup r;
        struct policy_handle group_handle;
        bool ret = true;
 
-       printf("Testing OpenGroup(%u)\n", rid);
+       torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
 
        r.in.domain_handle = handle;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.group_handle = &group_handle;
 
-       status = dcerpc_samr_OpenGroup(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
+               "OpenGroup failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
        if (!torture_setting_bool(tctx, "samba3", false)) {
-               if (!test_QuerySecurity(p, tctx, &group_handle)) {
+               if (!test_QuerySecurity(b, tctx, &group_handle)) {
                        ret = false;
                }
        }
 
-       if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
+       if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
                ret = false;
        }
 
-       if (!test_QueryGroupMember(p, tctx, &group_handle)) {
+       if (!test_QueryGroupMember(b, tctx, &group_handle)) {
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, tctx, &group_handle)) {
+       if (!test_samr_handle_Close(b, tctx, &group_handle)) {
                ret = false;
        }
 
        return ret;
 }
 
-static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_OpenAlias(struct dcerpc_binding_handle *b,
+                          struct torture_context *tctx,
                           struct policy_handle *handle, uint32_t rid)
 {
-       NTSTATUS status;
        struct samr_OpenAlias r;
        struct policy_handle alias_handle;
        bool ret = true;
@@ -4812,38 +5875,39 @@ static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
        r.in.rid = rid;
        r.out.alias_handle = &alias_handle;
 
-       status = dcerpc_samr_OpenAlias(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
+               "OpenAlias failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
        if (!torture_setting_bool(tctx, "samba3", false)) {
-               if (!test_QuerySecurity(p, tctx, &alias_handle)) {
+               if (!test_QuerySecurity(b, tctx, &alias_handle)) {
                        ret = false;
                }
        }
 
-       if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
+       if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
                ret = false;
        }
 
-       if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
+       if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
+       if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
                ret = false;
        }
 
        return ret;
 }
 
-static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool check_mask(struct dcerpc_binding_handle *b,
+                      struct torture_context *tctx,
                       struct policy_handle *handle, uint32_t rid,
                       uint32_t acct_flag_mask)
 {
-       NTSTATUS status;
        struct samr_OpenUser r;
        struct samr_QueryUserInfo q;
        union samr_UserInfo *info;
@@ -4857,9 +5921,10 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
        r.in.rid = rid;
        r.out.user_handle = &user_handle;
 
-       status = dcerpc_samr_OpenUser(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
+               "OpenUser failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
@@ -4867,30 +5932,31 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
        q.in.level = 16;
        q.out.info = &info;
 
-       status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("QueryUserInfo level 16 failed - %s\n",
-                      nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
+               "QueryUserInfo failed");
+       if (!NT_STATUS_IS_OK(q.out.result)) {
+               torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
+                      nt_errstr(q.out.result));
                ret = false;
        } else {
                if ((acct_flag_mask & info->info16.acct_flags) == 0) {
-                       printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
+                       torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
                               acct_flag_mask, info->info16.acct_flags, rid);
                        ret = false;
                }
        }
 
-       if (!test_samr_handle_Close(p, tctx, &user_handle)) {
+       if (!test_samr_handle_Close(b, tctx, &user_handle)) {
                ret = false;
        }
 
        return ret;
 }
 
-static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                struct policy_handle *handle)
+static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
+                                    struct torture_context *tctx,
+                                    struct policy_handle *handle)
 {
-       NTSTATUS status = STATUS_MORE_ENTRIES;
        struct samr_EnumDomainUsers r;
        uint32_t mask, resume_handle=0;
        int i, mask_idx;
@@ -4907,7 +5973,7 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
                            ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
                            ACB_PWNOEXP, 0};
 
-       printf("Testing EnumDomainUsers\n");
+       torture_comment(tctx, "Testing EnumDomainUsers\n");
 
        for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
                r.in.domain_handle = handle;
@@ -4918,10 +5984,11 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
                r.out.num_entries = &num_entries;
                r.out.sam = &sam;
 
-               status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
-               if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
-                   !NT_STATUS_IS_OK(status)) {
-                       printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
+                       "EnumDomainUsers failed");
+               if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
+                   !NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
                        return false;
                }
 
@@ -4933,16 +6000,16 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
 
                for (i=0;i<sam->count;i++) {
                        if (mask) {
-                               if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
+                               if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
                                        ret = false;
                                }
-                       } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
+                       } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
                                ret = false;
                        }
                }
        }
 
-       printf("Testing LookupNames\n");
+       torture_comment(tctx, "Testing LookupNames\n");
        n.in.domain_handle = handle;
        n.in.num_names = sam->count;
        n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
@@ -4951,14 +6018,15 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
        for (i=0;i<sam->count;i++) {
                n.in.names[i].string = sam->entries[i].name.string;
        }
-       status = dcerpc_samr_LookupNames(p, tctx, &n);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupNames failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
+               "LookupNames failed");
+       if (!NT_STATUS_IS_OK(n.out.result)) {
+               torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
                ret = false;
        }
 
 
-       printf("Testing LookupRids\n");
+       torture_comment(tctx, "Testing LookupRids\n");
        lr.in.domain_handle = handle;
        lr.in.num_rids = sam->count;
        lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
@@ -4967,8 +6035,9 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
        for (i=0;i<sam->count;i++) {
                lr.in.rids[i] = sam->entries[i].idx;
        }
-       status = dcerpc_samr_LookupRids(p, tctx, &lr);
-       torture_assert_ntstatus_ok(tctx, status, "LookupRids");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
+               "LookupRids failed");
+       torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
 
        return ret;
 }
@@ -4979,12 +6048,11 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
                                       struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_EnumDomainUsers r;
        uint32_t resume_handle=0;
        int i;
 #define ASYNC_COUNT 100
-       struct rpc_request *req[ASYNC_COUNT];
+       struct tevent_req *req[ASYNC_COUNT];
 
        if (!torture_setting_bool(tctx, "dangerous", false)) {
                torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
@@ -4999,16 +6067,14 @@ static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_con
        r.out.resume_handle = &resume_handle;
 
        for (i=0;i<ASYNC_COUNT;i++) {
-               req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
+               req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
        }
 
        for (i=0;i<ASYNC_COUNT;i++) {
-               status = dcerpc_ndr_request_recv(req[i]);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("EnumDomainUsers[%d] failed - %s\n",
-                              i, nt_errstr(status));
-                       return false;
-               }
+               tevent_req_poll(req[i], tctx->ev);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
+                       talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
+                              i, nt_errstr(r.out.result)));
        }
 
        torture_comment(tctx, "%d async requests OK\n", i);
@@ -5016,19 +6082,19 @@ static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_con
        return true;
 }
 
-static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
-                                 struct torture_context *tctx,
-                                 struct policy_handle *handle)
+static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
+                                     struct torture_context *tctx,
+                                     struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_EnumDomainGroups r;
        uint32_t resume_handle=0;
        struct samr_SamArray *sam = NULL;
        uint32_t num_entries = 0;
        int i;
        bool ret = true;
+       bool universal_group_found = false;
 
-       printf("Testing EnumDomainGroups\n");
+       torture_comment(tctx, "Testing EnumDomainGroups\n");
 
        r.in.domain_handle = handle;
        r.in.resume_handle = &resume_handle;
@@ -5037,9 +6103,10 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
        r.out.num_entries = &num_entries;
        r.out.sam = &sam;
 
-       status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
+               "EnumDomainGroups failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -5047,8 +6114,22 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
                return false;
        }
 
-       for (i=0;i<sam->count;i++) {
-               if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
+       for (i=0;i<sam->count;i++) {
+               if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
+                       ret = false;
+               }
+               if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
+                                                "Enterprise Admins") == 0)) {
+                       universal_group_found = true;
+               }
+       }
+
+       /* when we are running this on s4 we should get back at least the
+        * "Enterprise Admins" universal group. If we don't get a group entry
+        * at all we probably are performing the test on the builtin domain.
+        * So ignore this case. */
+       if (torture_setting_bool(tctx, "samba4", false)) {
+               if ((sam->count > 0) && (!universal_group_found)) {
                        ret = false;
                }
        }
@@ -5056,11 +6137,10 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
-                                  struct torture_context *tctx,
-                                  struct policy_handle *handle)
+static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
+                                      struct torture_context *tctx,
+                                      struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_EnumDomainAliases r;
        uint32_t resume_handle=0;
        struct samr_SamArray *sam = NULL;
@@ -5068,7 +6148,7 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
        int i;
        bool ret = true;
 
-       printf("Testing EnumDomainAliases\n");
+       torture_comment(tctx, "Testing EnumDomainAliases\n");
 
        r.in.domain_handle = handle;
        r.in.resume_handle = &resume_handle;
@@ -5077,9 +6157,10 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
        r.out.num_entries = &num_entries;
        r.out.resume_handle = &resume_handle;
 
-       status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
+               "EnumDomainAliases failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -5088,7 +6169,7 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
        }
 
        for (i=0;i<sam->count;i++) {
-               if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
+               if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
                        ret = false;
                }
        }
@@ -5096,11 +6177,10 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
+static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
                                            struct torture_context *tctx,
                                            struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_GetDisplayEnumerationIndex r;
        bool ret = true;
        uint16_t levels[] = {1, 2, 3, 4, 5};
@@ -5110,7 +6190,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
        int i;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
+               torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
 
                init_lsa_String(&name, TEST_ACCOUNT_NAME);
 
@@ -5119,23 +6199,25 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
                r.in.name = &name;
                r.out.idx = &idx;
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
+                       "GetDisplayEnumerationIndex failed");
 
                if (ok_lvl[i] &&
-                   !NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
-                       printf("GetDisplayEnumerationIndex level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+                   !NT_STATUS_IS_OK(r.out.result) &&
+                   !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
+                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
 
                init_lsa_String(&name, "zzzzzzzz");
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
+                       "GetDisplayEnumerationIndex failed");
 
-               if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
-                       printf("GetDisplayEnumerationIndex level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
+                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -5143,11 +6225,10 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
+static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
                                             struct torture_context *tctx,
                                             struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_GetDisplayEnumerationIndex2 r;
        bool ret = true;
        uint16_t levels[] = {1, 2, 3, 4, 5};
@@ -5157,7 +6238,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
        int i;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
+               torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
 
                init_lsa_String(&name, TEST_ACCOUNT_NAME);
 
@@ -5166,21 +6247,23 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
                r.in.name = &name;
                r.out.idx = &idx;
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
+                       "GetDisplayEnumerationIndex2 failed");
                if (ok_lvl[i] &&
-                   !NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
-                       printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+                   !NT_STATUS_IS_OK(r.out.result) &&
+                   !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
+                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
 
                init_lsa_String(&name, "zzzzzzzz");
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
-               if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
-                       printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
+                       "GetDisplayEnumerationIndex2 failed");
+               if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
+                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -5192,18 +6275,18 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
        if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
                /* odd, but valid */                                            \
        } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
-                       printf("%s mismatch for %s: %s != %s (%s)\n", \
+                       torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
                               #s1, user.string,  s1.string, s2.string, __location__);   \
                        ret = false; \
        }
 #define INT_EQUAL_QUERY(s1, s2, user)          \
                if (s1 != s2) { \
-                       printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
+                       torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
                               #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
                        ret = false; \
                }
 
-static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
+static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
                                       struct torture_context *tctx,
                                       struct samr_QueryDisplayInfo *querydisplayinfo,
                                       bool *seen_testuser)
@@ -5213,7 +6296,6 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
        union samr_UserInfo *info;
        struct policy_handle user_handle;
        int i, ret = true;
-       NTSTATUS status;
        r.in.domain_handle = querydisplayinfo->in.domain_handle;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        for (i = 0; ; i++) {
@@ -5243,9 +6325,10 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
                switch (querydisplayinfo->in.level) {
                case 1:
                case 2:
-                       status = dcerpc_samr_OpenUser(p, tctx, &r);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
+                               "OpenUser failed");
+                       if (!NT_STATUS_IS_OK(r.out.result)) {
+                               torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
                                return false;
                        }
                }
@@ -5253,9 +6336,10 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
                q.in.user_handle = &user_handle;
                q.in.level = 21;
                q.out.info = &info;
-               status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
+                       "QueryUserInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
                        return false;
                }
 
@@ -5287,12 +6371,12 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
                                        info->info21.acct_flags, info->info21.account_name);
 
                        if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
-                               printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
+                               torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
                                       info->info21.account_name.string);
                        }
 
                        if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
-                               printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
+                               torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
                                       info->info21.account_name.string,
                                       querydisplayinfo->out.info->info2.entries[i].acct_flags,
                                       info->info21.acct_flags);
@@ -5302,18 +6386,17 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
                        break;
                }
 
-               if (!test_samr_handle_Close(p, tctx, &user_handle)) {
+               if (!test_samr_handle_Close(b, tctx, &user_handle)) {
                        return false;
                }
        }
        return ret;
 }
 
-static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
+static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                                  struct torture_context *tctx,
                                  struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDisplayInfo r;
        struct samr_QueryDomainInfo dom_info;
        union samr_DomainInfo *info = NULL;
@@ -5327,11 +6410,11 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
 
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryDisplayInfo level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
 
                r.in.start_idx = 0;
-               status = STATUS_MORE_ENTRIES;
-               while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+               r.out.result = STATUS_MORE_ENTRIES;
+               while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
                        r.in.domain_handle = handle;
                        r.in.level = levels[i];
                        r.in.max_entries = 2;
@@ -5340,21 +6423,22 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
                        r.out.returned_size = &returned_size;
                        r.out.info = &disp_info;
 
-                       status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
-                       if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
-                               printf("QueryDisplayInfo level %u failed - %s\n",
-                                      levels[i], nt_errstr(status));
+                       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
+                               "QueryDisplayInfo failed");
+                       if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
+                               torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
+                                      levels[i], nt_errstr(r.out.result));
                                ret = false;
                        }
                        switch (r.in.level) {
                        case 1:
-                               if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
+                               if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
                                        ret = false;
                                }
                                r.in.start_idx += r.out.info->info1.count;
                                break;
                        case 2:
-                               if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
+                               if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
                                        ret = false;
                                }
                                r.in.start_idx += r.out.info->info2.count;
@@ -5375,39 +6459,52 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
                dom_info.out.info = &info;
 
                /* Check number of users returned is correct */
-               status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n",
-                              r.in.level, nt_errstr(status));
-                               ret = false;
-                               break;
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
+                       "QueryDomainInfo failed");
+               if (!NT_STATUS_IS_OK(dom_info.out.result)) {
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                              r.in.level, nt_errstr(dom_info.out.result));
+                       ret = false;
+                       break;
                }
                switch (r.in.level) {
                case 1:
                case 4:
                        if (info->general.num_users < r.in.start_idx) {
-                               printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
-                                      r.in.start_idx, info->general.num_groups,
-                                      info->general.domain_name.string);
-                               ret = false;
+                               /* On AD deployments this numbers don't match
+                                * since QueryDisplayInfo returns universal and
+                                * global groups, QueryDomainInfo only global
+                                * ones. */
+                               if (torture_setting_bool(tctx, "samba3", false)) {
+                                       torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
+                                              r.in.start_idx, info->general.num_groups,
+                                              info->general.domain_name.string);
+                                       ret = false;
+                               }
                        }
                        if (!seen_testuser) {
                                struct policy_handle user_handle;
-                               if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
-                                       printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
+                               if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
+                                       torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
                                               info->general.domain_name.string);
                                        ret = false;
-                                       test_samr_handle_Close(p, tctx, &user_handle);
+                                       test_samr_handle_Close(b, tctx, &user_handle);
                                }
                        }
                        break;
                case 3:
                case 5:
                        if (info->general.num_groups != r.in.start_idx) {
-                               printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
-                                      r.in.start_idx, info->general.num_groups,
-                                      info->general.domain_name.string);
-                               ret = false;
+                               /* On AD deployments this numbers don't match
+                                * since QueryDisplayInfo returns universal and
+                                * global groups, QueryDomainInfo only global
+                                * ones. */
+                               if (torture_setting_bool(tctx, "samba3", false)) {
+                                       torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
+                                              r.in.start_idx, info->general.num_groups,
+                                              info->general.domain_name.string);
+                                       ret = false;
+                               }
                        }
 
                        break;
@@ -5418,11 +6515,10 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
+static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
                                   struct torture_context *tctx,
                                   struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDisplayInfo2 r;
        bool ret = true;
        uint16_t levels[] = {1, 2, 3, 4, 5};
@@ -5432,7 +6528,7 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
        union samr_DispInfo info;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
 
                r.in.domain_handle = handle;
                r.in.level = levels[i];
@@ -5443,10 +6539,11 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
                r.out.returned_size = &returned_size;
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo2 level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
+                       "QueryDisplayInfo2 failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -5454,10 +6551,10 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                 struct policy_handle *handle)
+static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDisplayInfo3 r;
        bool ret = true;
        uint16_t levels[] = {1, 2, 3, 4, 5};
@@ -5478,10 +6575,11 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context
                r.out.returned_size = &returned_size;
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo3 level %u failed - %s\n",
-                              levels[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
+                       "QueryDisplayInfo3 failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
+                              levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -5490,18 +6588,17 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context
 }
 
 
-static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
+static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
                                           struct torture_context *tctx,
                                           struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDisplayInfo r;
        bool ret = true;
        uint32_t total_size;
        uint32_t returned_size;
        union samr_DispInfo info;
 
-       printf("Testing QueryDisplayInfo continuation\n");
+       torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
 
        r.in.domain_handle = handle;
        r.in.level = 1;
@@ -5513,34 +6610,35 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
        r.out.info = &info;
 
        do {
-               status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
-               if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
+                       "QueryDisplayInfo failed");
+               if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
                        if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
-                               printf("expected idx %d but got %d\n",
+                               torture_warning(tctx, "expected idx %d but got %d\n",
                                       r.in.start_idx + 1,
                                       r.out.info->info1.entries[0].idx);
                                break;
                        }
                }
-               if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
-                   !NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo level %u failed - %s\n",
-                              r.in.level, nt_errstr(status));
+               if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
+                   !NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
+                              r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        break;
                }
                r.in.start_idx++;
-       } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
-                 NT_STATUS_IS_OK(status)) &&
+       } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
+                 NT_STATUS_IS_OK(r.out.result)) &&
                 *r.out.returned_size != 0);
 
        return ret;
 }
 
-static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
+                                struct torture_context *tctx,
                                 struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDomainInfo r;
        union samr_DomainInfo *info = NULL;
        struct samr_SetDomainInfo s;
@@ -5548,6 +6646,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
        uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
        int i;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
        const char *domain_comment = talloc_asprintf(tctx,
                                  "Tortured by Samba4 RPC-SAMR: %s",
                                  timestring(tctx, time(NULL)));
@@ -5557,10 +6656,11 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
        s.in.info = talloc(tctx, union samr_DomainInfo);
 
        s.in.info->oem.oem_information.string = domain_comment;
-       status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetDomainInfo level %u (set comment) failed - %s\n",
-                      s.in.level, nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
+               "SetDomainInfo failed");
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
+                      s.in.level, nt_errstr(s.out.result));
                return false;
        }
 
@@ -5571,10 +6671,11 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n",
-                              r.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
+                       "QueryDomainInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                              r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
                }
@@ -5582,40 +6683,48 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
                switch (levels[i]) {
                case 2:
                        if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
-                               printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+                               torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
                                       levels[i], info->general.oem_information.string, domain_comment);
-                               ret = false;
+                               if (!torture_setting_bool(tctx, "samba3", false)) {
+                                       ret = false;
+                               }
                        }
                        if (!info->general.primary.string) {
-                               printf("QueryDomainInfo level %u returned no PDC name\n",
+                               torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
                                       levels[i]);
                                ret = false;
                        } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
                                if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
-                                       printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
-                                              levels[i], info->general.primary.string, dcerpc_server_name(p));
+                                       if (torture_setting_bool(tctx, "samba3", false)) {
+                                               torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
+                                                      levels[i], info->general.primary.string, dcerpc_server_name(p));
+                                       }
                                }
                        }
                        break;
                case 4:
                        if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
-                               printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+                               torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
                                       levels[i], info->oem.oem_information.string, domain_comment);
-                               ret = false;
+                               if (!torture_setting_bool(tctx, "samba3", false)) {
+                                       ret = false;
+                               }
                        }
                        break;
                case 6:
                        if (!info->info6.primary.string) {
-                               printf("QueryDomainInfo level %u returned no PDC name\n",
+                               torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
                                       levels[i]);
                                ret = false;
                        }
                        break;
                case 11:
                        if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
-                               printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
+                               torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
                                       levels[i], info->general2.general.oem_information.string, domain_comment);
-                               ret = false;
+                               if (!torture_setting_bool(tctx, "samba3", false)) {
+                                       ret = false;
+                               }
                        }
                        break;
                }
@@ -5626,27 +6735,29 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
                s.in.level = levels[i];
                s.in.info = info;
 
-               status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
+                       "SetDomainInfo failed");
                if (set_ok[i]) {
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("SetDomainInfo level %u failed - %s\n",
-                                      r.in.level, nt_errstr(status));
+                       if (!NT_STATUS_IS_OK(s.out.result)) {
+                               torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
+                                      r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
                } else {
-                       if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
-                               printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
-                                      r.in.level, nt_errstr(status));
+                       if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
+                               torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+                                      r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
                }
 
-               status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n",
-                              r.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
+                       "QueryDomainInfo failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                              r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
                }
@@ -5656,10 +6767,10 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
 }
 
 
-static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
+                                 struct torture_context *tctx,
                                  struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_QueryDomainInfo2 r;
        union samr_DomainInfo *info = NULL;
        uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
@@ -5667,16 +6778,17 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context
        bool ret = true;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
+               torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
 
                r.in.domain_handle = handle;
                r.in.level = levels[i];
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo2 level %u failed - %s\n",
-                              r.in.level, nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
+                       "QueryDomainInfo2 failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
+                              r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
                }
@@ -5687,7 +6799,9 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context
 
 /* Test whether querydispinfo level 5 and enumdomgroups return the same
    set of group names. */
-static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_GroupList(struct dcerpc_binding_handle *b,
+                          struct torture_context *tctx,
+                          struct dom_sid *domain_sid,
                           struct policy_handle *handle)
 {
        struct samr_EnumDomainGroups q1;
@@ -5705,6 +6819,9 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
        int num_names = 0;
        const char **names = NULL;
 
+       bool builtin_domain = dom_sid_compare(domain_sid,
+                                             &global_sid_Builtin) == 0;
+
        torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
 
        q1.in.domain_handle = handle;
@@ -5716,7 +6833,9 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = STATUS_MORE_ENTRIES;
        while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-               status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
+                       "EnumDomainGroups failed");
+               status = q1.out.result;
 
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
@@ -5733,6 +6852,11 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
 
+       if (builtin_domain) {
+               torture_assert(tctx, num_names == 0,
+                              "EnumDomainGroups shouldn't return any group in the builtin domain!");
+       }
+
        q2.in.domain_handle = handle;
        q2.in.level = 5;
        q2.in.start_idx = 0;
@@ -5744,8 +6868,9 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = STATUS_MORE_ENTRIES;
        while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
-               status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
-
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
+                       "QueryDisplayInfo failed");
+               status = q2.out.result;
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
                        break;
@@ -5764,8 +6889,8 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
                                }
                        }
 
-                       if (!found) {
-                               printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
+                       if ((!found) && (!builtin_domain)) {
+                               torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
                                       name);
                                ret = false;
                        }
@@ -5774,14 +6899,19 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               printf("QueryDisplayInfo level 5 failed - %s\n",
+               torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
                       nt_errstr(status));
                ret = false;
        }
 
+       if (builtin_domain) {
+               torture_assert(tctx, q2.in.start_idx != 0,
+                              "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
+       }
+
        for (i=0; i<num_names; i++) {
                if (names[i] != NULL) {
-                       printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
+                       torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
                               names[i]);
                        ret = false;
                }
@@ -5790,46 +6920,48 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
        return ret;
 }
 
-static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
+                                  struct torture_context *tctx,
                                   struct policy_handle *group_handle)
 {
        struct samr_DeleteDomainGroup d;
-       NTSTATUS status;
 
        torture_comment(tctx, "Testing DeleteDomainGroup\n");
 
        d.in.group_handle = group_handle;
        d.out.group_handle = group_handle;
 
-       status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
-       torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
+               "DeleteDomainGroup failed");
+       torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
 
        return true;
 }
 
-static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
+                                           struct torture_context *tctx,
                                            struct policy_handle *domain_handle)
 {
        struct samr_TestPrivateFunctionsDomain r;
-       NTSTATUS status;
        bool ret = true;
 
        torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
 
        r.in.domain_handle = domain_handle;
 
-       status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
+               "TestPrivateFunctionsDomain failed");
+       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
 
        return ret;
 }
 
-static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_RidToSid(struct dcerpc_binding_handle *b,
+                         struct torture_context *tctx,
                          struct dom_sid *domain_sid,
                          struct policy_handle *domain_handle)
 {
        struct samr_RidToSid r;
-       NTSTATUS status;
        bool ret = true;
        struct dom_sid *calc_sid, *out_sid;
        int rids[] = { 0, 42, 512, 10200 };
@@ -5843,15 +6975,16 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
                r.in.rid = rids[i];
                r.out.sid = &out_sid;
 
-               status = dcerpc_samr_RidToSid(p, tctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
+                       "RidToSid failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
                        ret = false;
                } else {
                        calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
 
                        if (!dom_sid_equal(calc_sid, out_sid)) {
-                               printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
+                               torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
                                       dom_sid_string(tctx, out_sid),
                                       dom_sid_string(tctx, calc_sid));
                                ret = false;
@@ -5862,20 +6995,24 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
        return ret;
 }
 
-static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
+                                      struct torture_context *tctx,
                                       struct policy_handle *domain_handle)
 {
        struct samr_GetBootKeyInformation r;
-       NTSTATUS status;
        bool ret = true;
        uint32_t unknown = 0;
+       NTSTATUS status;
 
        torture_comment(tctx, "Testing GetBootKeyInformation\n");
 
        r.in.domain_handle = domain_handle;
        r.out.unknown = &unknown;
 
-       status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
+       status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
+       if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
+               status = r.out.result;
+       }
        if (!NT_STATUS_IS_OK(status)) {
                /* w2k3 seems to fail this sometimes and pass it sometimes */
                torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
@@ -5884,7 +7021,8 @@ static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_con
        return ret;
 }
 
-static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
+                               struct torture_context *tctx,
                                struct policy_handle *domain_handle,
                                struct policy_handle *group_handle)
 {
@@ -5892,34 +7030,39 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
        struct samr_AddGroupMember r;
        struct samr_DeleteGroupMember d;
        struct samr_QueryGroupMember q;
-       struct samr_RidTypeArray *rids = NULL;
+       struct samr_RidAttrArray *rids = NULL;
        struct samr_SetMemberAttributesOfGroup s;
        uint32_t rid;
+       bool found_member = false;
+       int i;
 
-       status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
+       status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
        torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
 
        r.in.group_handle = group_handle;
        r.in.rid = rid;
        r.in.flags = 0; /* ??? */
 
-       torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
+       torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
 
        d.in.group_handle = group_handle;
        d.in.rid = rid;
 
-       status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
-       torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
+               "DeleteGroupMember failed");
+       torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
 
-       status = dcerpc_samr_AddGroupMember(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
+               "AddGroupMember failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
 
-       status = dcerpc_samr_AddGroupMember(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
+               "AddGroupMember failed");
+       torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
 
        if (torture_setting_bool(tctx, "samba4", false) ||
            torture_setting_bool(tctx, "samba3", false)) {
-               torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
+               torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
        } else {
                /* this one is quite strange. I am using random inputs in the
                   hope of triggering an error that might give us a clue */
@@ -5928,27 +7071,56 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
                s.in.unknown1 = random();
                s.in.unknown2 = random();
 
-               status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
-               torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
+                       "SetMemberAttributesOfGroup failed");
+               torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
        }
 
        q.in.group_handle = group_handle;
        q.out.rids = &rids;
 
-       status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
-       torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
+               "QueryGroupMember failed");
+       torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
+       torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
+
+       for (i=0; i < rids->count; i++) {
+               if (rids->rids[i] == rid) {
+                       found_member = true;
+               }
+       }
+
+       torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
+               "DeleteGroupMember failed");
+       torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
 
-       status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
-       torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
+       rids = NULL;
+       found_member = false;
 
-       status = dcerpc_samr_AddGroupMember(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
+               "QueryGroupMember failed");
+       torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
+       torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
+
+       for (i=0; i < rids->count; i++) {
+               if (rids->rids[i] == rid) {
+                       found_member = true;
+               }
+       }
+
+       torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
+               "AddGroupMember failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
 
        return true;
 }
 
 
-static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
+static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
                                   struct torture_context *tctx,
                                   struct policy_handle *domain_handle,
                                   const char *group_name,
@@ -5956,107 +7128,473 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
                                   struct dom_sid *domain_sid,
                                   bool test_group)
 {
-       NTSTATUS status;
-       struct samr_CreateDomainGroup r;
-       uint32_t rid;
-       struct lsa_String name;
-       bool ret = true;
+       struct samr_CreateDomainGroup r;
+       uint32_t rid;
+       struct lsa_String name;
+       bool ret = true;
+
+       init_lsa_String(&name, group_name);
+
+       r.in.domain_handle = domain_handle;
+       r.in.name = &name;
+       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       r.out.group_handle = group_handle;
+       r.out.rid = &rid;
+
+       torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
+               "CreateDomainGroup failed");
+
+       if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
+               if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
+                       torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
+                       return true;
+               } else {
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
+                              nt_errstr(r.out.result));
+                       return false;
+               }
+       }
+
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
+               if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
+                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
+                              nt_errstr(r.out.result));
+                       return false;
+               }
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
+                       "CreateDomainGroup failed");
+       }
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
+               if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
+
+                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
+                              nt_errstr(r.out.result));
+                       return false;
+               }
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
+                       "CreateDomainGroup failed");
+       }
+       torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
+
+       if (!test_group) {
+               return ret;
+       }
+
+       if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
+               torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
+               ret = false;
+       }
+
+       if (!test_SetGroupInfo(b, tctx, group_handle)) {
+               ret = false;
+       }
+
+       return ret;
+}
+
+
+/*
+  its not totally clear what this does. It seems to accept any sid you like.
+*/
+static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
+                                              struct torture_context *tctx,
+                                              struct policy_handle *domain_handle)
+{
+       struct samr_RemoveMemberFromForeignDomain r;
+
+       r.in.domain_handle = domain_handle;
+       r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
+               "RemoveMemberFromForeignDomain failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
+
+       return true;
+}
+
+static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
+                                struct torture_context *tctx,
+                                struct policy_handle *domain_handle,
+                                uint32_t *total_num_entries_p)
+{
+       NTSTATUS status;
+       struct samr_EnumDomainUsers r;
+       uint32_t resume_handle = 0;
+       uint32_t num_entries = 0;
+       uint32_t total_num_entries = 0;
+       struct samr_SamArray *sam;
+
+       r.in.domain_handle = domain_handle;
+       r.in.acct_flags = 0;
+       r.in.max_size = (uint32_t)-1;
+       r.in.resume_handle = &resume_handle;
+
+       r.out.sam = &sam;
+       r.out.num_entries = &num_entries;
+       r.out.resume_handle = &resume_handle;
+
+       torture_comment(tctx, "Testing EnumDomainUsers\n");
+
+       do {
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
+                       "EnumDomainUsers failed");
+               if (NT_STATUS_IS_ERR(r.out.result)) {
+                       torture_assert_ntstatus_ok(tctx, r.out.result,
+                               "failed to enumerate users");
+               }
+               status = r.out.result;
+
+               total_num_entries += num_entries;
+       } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+
+       if (total_num_entries_p) {
+               *total_num_entries_p = total_num_entries;
+       }
+
+       return true;
+}
+
+static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
+                                 struct torture_context *tctx,
+                                 struct policy_handle *domain_handle,
+                                 uint32_t *total_num_entries_p)
+{
+       NTSTATUS status;
+       struct samr_EnumDomainGroups r;
+       uint32_t resume_handle = 0;
+       uint32_t num_entries = 0;
+       uint32_t total_num_entries = 0;
+       struct samr_SamArray *sam;
+
+       r.in.domain_handle = domain_handle;
+       r.in.max_size = (uint32_t)-1;
+       r.in.resume_handle = &resume_handle;
+
+       r.out.sam = &sam;
+       r.out.num_entries = &num_entries;
+       r.out.resume_handle = &resume_handle;
+
+       torture_comment(tctx, "Testing EnumDomainGroups\n");
+
+       do {
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
+                       "EnumDomainGroups failed");
+               if (NT_STATUS_IS_ERR(r.out.result)) {
+                       torture_assert_ntstatus_ok(tctx, r.out.result,
+                               "failed to enumerate groups");
+               }
+               status = r.out.result;
+
+               total_num_entries += num_entries;
+       } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+
+       if (total_num_entries_p) {
+               *total_num_entries_p = total_num_entries;
+       }
+
+       return true;
+}
+
+static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *domain_handle,
+                                  uint32_t *total_num_entries_p)
+{
+       NTSTATUS status;
+       struct samr_EnumDomainAliases r;
+       uint32_t resume_handle = 0;
+       uint32_t num_entries = 0;
+       uint32_t total_num_entries = 0;
+       struct samr_SamArray *sam;
+
+       r.in.domain_handle = domain_handle;
+       r.in.max_size = (uint32_t)-1;
+       r.in.resume_handle = &resume_handle;
+
+       r.out.sam = &sam;
+       r.out.num_entries = &num_entries;
+       r.out.resume_handle = &resume_handle;
+
+       torture_comment(tctx, "Testing EnumDomainAliases\n");
+
+       do {
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
+                       "EnumDomainAliases failed");
+               if (NT_STATUS_IS_ERR(r.out.result)) {
+                       torture_assert_ntstatus_ok(tctx, r.out.result,
+                               "failed to enumerate aliases");
+               }
+               status = r.out.result;
+
+               total_num_entries += num_entries;
+       } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+
+       if (total_num_entries_p) {
+               *total_num_entries_p = total_num_entries;
+       }
+
+       return true;
+}
+
+static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
+                                       struct torture_context *tctx,
+                                       struct policy_handle *handle,
+                                       uint16_t level,
+                                       uint32_t *total_num_entries_p)
+{
+       NTSTATUS status;
+       struct samr_QueryDisplayInfo r;
+       uint32_t total_num_entries = 0;
+
+       r.in.domain_handle = handle;
+       r.in.level = level;
+       r.in.start_idx = 0;
+       r.in.max_entries = (uint32_t)-1;
+       r.in.buf_size = (uint32_t)-1;
+
+       torture_comment(tctx, "Testing QueryDisplayInfo\n");
+
+       do {
+               uint32_t total_size;
+               uint32_t returned_size;
+               union samr_DispInfo info;
+
+               r.out.total_size = &total_size;
+               r.out.returned_size = &returned_size;
+               r.out.info = &info;
+
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
+                       "failed to query displayinfo");
+               if (NT_STATUS_IS_ERR(r.out.result)) {
+                       torture_assert_ntstatus_ok(tctx, r.out.result,
+                               "failed to query displayinfo");
+               }
+               status = r.out.result;
+
+               if (*r.out.returned_size == 0) {
+                       break;
+               }
+
+               switch (r.in.level) {
+               case 1:
+                       total_num_entries += info.info1.count;
+                       r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
+                       break;
+               case 2:
+                       total_num_entries += info.info2.count;
+                       r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
+                       break;
+               case 3:
+                       total_num_entries += info.info3.count;
+                       r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
+                       break;
+               case 4:
+                       total_num_entries += info.info4.count;
+                       r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
+                       break;
+               case 5:
+                       total_num_entries += info.info5.count;
+                       r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
+                       break;
+               default:
+                       return false;
+               }
+
+       } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+
+       if (total_num_entries_p) {
+               *total_num_entries_p = total_num_entries;
+       }
+
+       return true;
+}
+
+static bool test_ManyObjects(struct dcerpc_pipe *p,
+                            struct torture_context *tctx,
+                            struct policy_handle *domain_handle,
+                            struct dom_sid *domain_sid,
+                            struct torture_samr_context *ctx)
+{
+       uint32_t num_total = ctx->num_objects_large_dc;
+       uint32_t num_enum = 0;
+       uint32_t num_disp = 0;
+       uint32_t num_created = 0;
+       uint32_t num_anounced = 0;
+       uint32_t i;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
-       init_lsa_String(&name, group_name);
+       struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
 
-       r.in.domain_handle = domain_handle;
-       r.in.name = &name;
-       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       r.out.group_handle = group_handle;
-       r.out.rid = &rid;
+       /* query */
 
-       printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
+       {
+               struct samr_QueryDomainInfo2 r;
+               union samr_DomainInfo *info;
+               r.in.domain_handle = domain_handle;
+               r.in.level = 2;
+               r.out.info = &info;
 
-       status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
+                       "QueryDomainInfo2 failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "failed to query domain info");
 
-       if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-                       torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
-                       return true;
-               } else {
-                       printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
-                              nt_errstr(status));
+               switch (ctx->choice) {
+               case TORTURE_SAMR_MANY_ACCOUNTS:
+                       num_anounced = info->general.num_users;
+                       break;
+               case TORTURE_SAMR_MANY_GROUPS:
+                       num_anounced = info->general.num_groups;
+                       break;
+               case TORTURE_SAMR_MANY_ALIASES:
+                       num_anounced = info->general.num_aliases;
+                       break;
+               default:
                        return false;
                }
        }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
-               if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
-                       printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
-                              nt_errstr(status));
-                       return false;
-               }
-               status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
-       }
-       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
-               if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
+       /* create */
+
+       for (i=0; i < num_total; i++) {
 
-                       printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
-                              nt_errstr(status));
+               const char *name = NULL;
+
+               switch (ctx->choice) {
+               case TORTURE_SAMR_MANY_ACCOUNTS:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
+                       torture_assert(tctx,
+                               test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
+                               "failed to create user");
+                       break;
+               case TORTURE_SAMR_MANY_GROUPS:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
+                       torture_assert(tctx,
+                               test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
+                               "failed to create group");
+                       break;
+               case TORTURE_SAMR_MANY_ALIASES:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
+                       torture_assert(tctx,
+                               test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
+                               "failed to create alias");
+                       break;
+               default:
                        return false;
                }
-               status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
+               if (!policy_handle_empty(&handles[i])) {
+                       num_created++;
+               }
        }
-       torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
 
-       if (!test_group) {
-               return ret;
-       }
+       /* enum */
 
-       if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
-               printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
-               ret = false;
+       switch (ctx->choice) {
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+               torture_assert(tctx,
+                       test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
+                       "failed to enum users");
+               break;
+       case TORTURE_SAMR_MANY_GROUPS:
+               torture_assert(tctx,
+                       test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
+                       "failed to enum groups");
+               break;
+       case TORTURE_SAMR_MANY_ALIASES:
+               torture_assert(tctx,
+                       test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
+                       "failed to enum aliases");
+               break;
+       default:
+               return false;
        }
 
-       if (!test_SetGroupInfo(p, tctx, group_handle)) {
-               ret = false;
+       /* dispinfo */
+
+       switch (ctx->choice) {
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+               torture_assert(tctx,
+                       test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
+                       "failed to query display info");
+               break;
+       case TORTURE_SAMR_MANY_GROUPS:
+               torture_assert(tctx,
+                       test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
+                       "failed to query display info");
+               break;
+       case TORTURE_SAMR_MANY_ALIASES:
+               /* no aliases in dispinfo */
+               break;
+       default:
+               return false;
        }
 
-       return ret;
-}
+       /* close or delete */
 
+       for (i=0; i < num_total; i++) {
 
-/*
-  its not totally clear what this does. It seems to accept any sid you like.
-*/
-static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
-                                              struct torture_context *tctx,
-                                              struct policy_handle *domain_handle)
-{
-       NTSTATUS status;
-       struct samr_RemoveMemberFromForeignDomain r;
+               if (policy_handle_empty(&handles[i])) {
+                       continue;
+               }
 
-       r.in.domain_handle = domain_handle;
-       r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
+               if (torture_setting_bool(tctx, "samba3", false)) {
+                       torture_assert(tctx,
+                               test_samr_handle_Close(b, tctx, &handles[i]),
+                               "failed to close handle");
+               } else {
+                       switch (ctx->choice) {
+                       case TORTURE_SAMR_MANY_ACCOUNTS:
+                               torture_assert(tctx,
+                                       test_DeleteUser(b, tctx, &handles[i]),
+                                       "failed to delete user");
+                               break;
+                       case TORTURE_SAMR_MANY_GROUPS:
+                               torture_assert(tctx,
+                                       test_DeleteDomainGroup(b, tctx, &handles[i]),
+                                       "failed to delete group");
+                               break;
+                       case TORTURE_SAMR_MANY_ALIASES:
+                               torture_assert(tctx,
+                                       test_DeleteAlias(b, tctx, &handles[i]),
+                                       "failed to delete alias");
+                               break;
+                       default:
+                               return false;
+                       }
+               }
+       }
 
-       status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
+       talloc_free(handles);
 
-       return true;
-}
+       if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
+               torture_comment(tctx,
+                               "unexpected number of results (%u) returned in enum call, expected %u\n",
+                               num_enum, num_anounced + num_created);
 
+               torture_comment(tctx,
+                               "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
+                               num_disp, num_anounced + num_created);
+       }
 
+       return true;
+}
 
-static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_Connect(struct dcerpc_binding_handle *b,
+                        struct torture_context *tctx,
                         struct policy_handle *handle);
 
 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
-                           struct policy_handle *handle, struct dom_sid *sid,
-                           enum torture_samr_choice which_ops,
-                           struct cli_credentials *machine_credentials)
+                           struct torture_samr_context *ctx, struct dom_sid *sid)
 {
-       NTSTATUS status;
        struct samr_OpenDomain r;
        struct policy_handle domain_handle;
        struct policy_handle alias_handle;
        struct policy_handle user_handle;
        struct policy_handle group_handle;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        ZERO_STRUCT(alias_handle);
        ZERO_STRUCT(user_handle);
@@ -6065,72 +7603,92 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
 
-       r.in.connect_handle = handle;
+       r.in.connect_handle = &ctx->handle;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.sid = sid;
        r.out.domain_handle = &domain_handle;
 
-       status = dcerpc_samr_OpenDomain(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
+               "OpenDomain failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
 
        /* run the domain tests with the main handle closed - this tests
           the servers reference counting */
-       ret &= test_samr_handle_Close(p, tctx, handle);
+       torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
 
-       switch (which_ops) {
-       case TORTURE_SAMR_USER_ATTRIBUTES:
-       case TORTURE_SAMR_USER_PRIVILEGES:
+       switch (ctx->choice) {
        case TORTURE_SAMR_PASSWORDS:
+       case TORTURE_SAMR_USER_PRIVILEGES:
+               if (!torture_setting_bool(tctx, "samba3", false)) {
+                       ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
+               }
+               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
+               if (!ret) {
+                       torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
+               }
+               break;
+       case TORTURE_SAMR_USER_ATTRIBUTES:
                if (!torture_setting_bool(tctx, "samba3", false)) {
-                       ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
+                       ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
                }
-               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
+               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
                /* This test needs 'complex' users to validate */
-               ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
+               ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
                if (!ret) {
-                       printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
+                       torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
+       case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
+       case TORTURE_SAMR_PASSWORDS_LOCKOUT:
                if (!torture_setting_bool(tctx, "samba3", false)) {
-                       ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
+                       ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
                }
-               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, machine_credentials, true);
+               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
                if (!ret) {
-                       printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
+                       torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
+               }
+               break;
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+       case TORTURE_SAMR_MANY_GROUPS:
+       case TORTURE_SAMR_MANY_ALIASES:
+               ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
+               if (!ret) {
+                       torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_OTHER:
-               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
+               ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
                if (!ret) {
-                       printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
+                       torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
                }
                if (!torture_setting_bool(tctx, "samba3", false)) {
-                       ret &= test_QuerySecurity(p, tctx, &domain_handle);
+                       ret &= test_QuerySecurity(b, tctx, &domain_handle);
                }
-               ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
-               ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
-               ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
+               ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
+               ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
+               ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
+               ret &= test_GetAliasMembership(b, tctx, &domain_handle);
                ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
-               ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
-               ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
+               ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
+               ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
                ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
-               ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
-               ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
-               ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
-               ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
-               ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
+               ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
+               ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
+               ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
+               ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
+               ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
 
                if (torture_setting_bool(tctx, "samba4", false)) {
                        torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
                } else {
-                       ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
-                       ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
+                       ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
+                       ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
                }
-               ret &= test_GroupList(p, tctx, &domain_handle);
-               ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
-               ret &= test_RidToSid(p, tctx, sid, &domain_handle);
-               ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
+               ret &= test_GroupList(b, tctx, sid, &domain_handle);
+               ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
+               ret &= test_RidToSid(b, tctx, sid, &domain_handle);
+               ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
                if (!ret) {
                        torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
@@ -6138,74 +7696,74 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
        }
 
        if (!policy_handle_empty(&user_handle) &&
-           !test_DeleteUser(p, tctx, &user_handle)) {
+           !test_DeleteUser(b, tctx, &user_handle)) {
                ret = false;
        }
 
        if (!policy_handle_empty(&alias_handle) &&
-           !test_DeleteAlias(p, tctx, &alias_handle)) {
+           !test_DeleteAlias(b, tctx, &alias_handle)) {
                ret = false;
        }
 
        if (!policy_handle_empty(&group_handle) &&
-           !test_DeleteDomainGroup(p, tctx, &group_handle)) {
+           !test_DeleteDomainGroup(b, tctx, &group_handle)) {
                ret = false;
        }
 
-       ret &= test_samr_handle_Close(p, tctx, &domain_handle);
+       torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
 
+       torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
        /* reconnect the main handle */
-       ret &= test_Connect(p, tctx, handle);
 
        if (!ret) {
-               printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
+               torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
        }
 
        return ret;
 }
 
 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
-                             struct policy_handle *handle, const char *domain,
-                             enum torture_samr_choice which_ops,
-                             struct cli_credentials *machine_credentials)
+                             struct torture_samr_context *ctx, const char *domain)
 {
-       NTSTATUS status;
        struct samr_LookupDomain r;
        struct dom_sid2 *sid = NULL;
        struct lsa_String n1;
        struct lsa_String n2;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
        torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
 
        /* check for correct error codes */
-       r.in.connect_handle = handle;
+       r.in.connect_handle = &ctx->handle;
        r.in.domain_name = &n2;
        r.out.sid = &sid;
        n2.string = NULL;
 
-       status = dcerpc_samr_LookupDomain(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
+               "LookupDomain failed");
+       torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
 
        init_lsa_String(&n2, "xxNODOMAINxx");
 
-       status = dcerpc_samr_LookupDomain(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
+               "LookupDomain failed");
+       torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
 
-       r.in.connect_handle = handle;
+       r.in.connect_handle = &ctx->handle;
 
        init_lsa_String(&n1, domain);
        r.in.domain_name = &n1;
 
-       status = dcerpc_samr_LookupDomain(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
+               "LookupDomain failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
 
        if (!test_GetDomPwInfo(p, tctx, &n1)) {
                ret = false;
        }
 
-       if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
-                            machine_credentials)) {
+       if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
                ret = false;
        }
 
@@ -6214,50 +7772,50 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
 
 
 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
-                            struct policy_handle *handle, enum torture_samr_choice which_ops,
-                            struct cli_credentials *machine_credentials)
+                            struct torture_samr_context *ctx)
 {
-       NTSTATUS status;
        struct samr_EnumDomains r;
        uint32_t resume_handle = 0;
        uint32_t num_entries = 0;
        struct samr_SamArray *sam = NULL;
        int i;
        bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
 
-       r.in.connect_handle = handle;
+       r.in.connect_handle = &ctx->handle;
        r.in.resume_handle = &resume_handle;
        r.in.buf_size = (uint32_t)-1;
        r.out.resume_handle = &resume_handle;
        r.out.num_entries = &num_entries;
        r.out.sam = &sam;
 
-       status = dcerpc_samr_EnumDomains(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
+               "EnumDomains failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
 
        if (!*r.out.sam) {
                return false;
        }
 
        for (i=0;i<sam->count;i++) {
-               if (!test_LookupDomain(p, tctx, handle,
-                                      sam->entries[i].name.string, which_ops,
-                                      machine_credentials)) {
+               if (!test_LookupDomain(p, tctx, ctx,
+                                      sam->entries[i].name.string)) {
                        ret = false;
                }
        }
 
-       status = dcerpc_samr_EnumDomains(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
+               "EnumDomains failed");
+       torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
 
        return ret;
 }
 
 
-static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_Connect(struct dcerpc_binding_handle *b,
+                        struct torture_context *tctx,
                         struct policy_handle *handle)
 {
-       NTSTATUS status;
        struct samr_Connect r;
        struct samr_Connect2 r2;
        struct samr_Connect3 r3;
@@ -6268,78 +7826,82 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
        uint32_t level_out = 0;
        bool ret = true, got_handle = false;
 
-       torture_comment(tctx, "testing samr_Connect\n");
+       torture_comment(tctx, "Testing samr_Connect\n");
 
        r.in.system_name = 0;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.out.connect_handle = &h;
 
-       status = dcerpc_samr_Connect(p, tctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
+               "Connect failed");
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                got_handle = true;
                *handle = h;
        }
 
-       torture_comment(tctx, "testing samr_Connect2\n");
+       torture_comment(tctx, "Testing samr_Connect2\n");
 
        r2.in.system_name = NULL;
        r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r2.out.connect_handle = &h;
 
-       status = dcerpc_samr_Connect2(p, tctx, &r2);
-       if (!NT_STATUS_IS_OK(status)) {
-               torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
+               "Connect2 failed");
+       if (!NT_STATUS_IS_OK(r2.out.result)) {
+               torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
                ret = false;
        } else {
                if (got_handle) {
-                       test_samr_handle_Close(p, tctx, handle);
+                       test_samr_handle_Close(b, tctx, handle);
                }
                got_handle = true;
                *handle = h;
        }
 
-       torture_comment(tctx, "testing samr_Connect3\n");
+       torture_comment(tctx, "Testing samr_Connect3\n");
 
        r3.in.system_name = NULL;
        r3.in.unknown = 0;
        r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r3.out.connect_handle = &h;
 
-       status = dcerpc_samr_Connect3(p, tctx, &r3);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect3 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
+               "Connect3 failed");
+       if (!NT_STATUS_IS_OK(r3.out.result)) {
+               torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
                ret = false;
        } else {
                if (got_handle) {
-                       test_samr_handle_Close(p, tctx, handle);
+                       test_samr_handle_Close(b, tctx, handle);
                }
                got_handle = true;
                *handle = h;
        }
 
-       torture_comment(tctx, "testing samr_Connect4\n");
+       torture_comment(tctx, "Testing samr_Connect4\n");
 
        r4.in.system_name = "";
        r4.in.client_version = 0;
        r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r4.out.connect_handle = &h;
 
-       status = dcerpc_samr_Connect4(p, tctx, &r4);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect4 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
+               "Connect4 failed");
+       if (!NT_STATUS_IS_OK(r4.out.result)) {
+               torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
                ret = false;
        } else {
                if (got_handle) {
-                       test_samr_handle_Close(p, tctx, handle);
+                       test_samr_handle_Close(b, tctx, handle);
                }
                got_handle = true;
                *handle = h;
        }
 
-       torture_comment(tctx, "testing samr_Connect5\n");
+       torture_comment(tctx, "Testing samr_Connect5\n");
 
        info.info1.client_version = 0;
        info.info1.unknown2 = 0;
@@ -6352,13 +7914,14 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
        r5.out.info_out = &info;
        r5.out.connect_handle = &h;
 
-       status = dcerpc_samr_Connect5(p, tctx, &r5);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect5 failed - %s\n", nt_errstr(status));
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
+               "Connect5 failed");
+       if (!NT_STATUS_IS_OK(r5.out.result)) {
+               torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
                ret = false;
        } else {
                if (got_handle) {
-                       test_samr_handle_Close(p, tctx, handle);
+                       test_samr_handle_Close(b, tctx, handle);
                }
                got_handle = true;
                *handle = h;
@@ -6368,31 +7931,77 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
 }
 
 
+static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
+                                      struct torture_context *tctx)
+{
+       struct samr_ValidatePassword r;
+       union samr_ValidatePasswordReq req;
+       union samr_ValidatePasswordRep *repp = NULL;
+       NTSTATUS status;
+       const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
+       int i;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+
+       torture_comment(tctx, "Testing samr_ValidatePassword\n");
+
+       ZERO_STRUCT(r);
+       r.in.level = NetValidatePasswordReset;
+       r.in.req = &req;
+       r.out.rep = &repp;
+
+       ZERO_STRUCT(req);
+       req.req3.account.string = "non-existant-account-aklsdji";
+
+       for (i=0; passwords[i]; i++) {
+               req.req3.password.string = passwords[i];
+
+               status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
+                       torture_skip(tctx, "ValidatePassword not supported by server\n");
+               }
+               torture_assert_ntstatus_ok(tctx, status,
+                                          "samr_ValidatePassword failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                                          "samr_ValidatePassword failed");
+               torture_comment(tctx, "Server %s password '%s' with code %i\n",
+                               repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
+                               req.req3.password.string, repp->ctr3.status);
+       }
+
+       return true;
+}
+
 bool torture_rpc_samr(struct torture_context *torture)
 {
        NTSTATUS status;
        struct dcerpc_pipe *p;
        bool ret = true;
-       struct policy_handle handle;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx->choice = TORTURE_SAMR_OTHER;
+
+       ret &= test_Connect(b, torture, &ctx->handle);
 
        if (!torture_setting_bool(torture, "samba3", false)) {
-               ret &= test_QuerySecurity(p, torture, &handle);
+               ret &= test_QuerySecurity(b, torture, &ctx->handle);
        }
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
+       ret &= test_EnumDomains(p, torture, ctx);
 
-       ret &= test_SetDsrmPassword(p, torture, &handle);
+       ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
 
-       ret &= test_Shutdown(p, torture, &handle);
+       ret &= test_Shutdown(b, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
        return ret;
 }
@@ -6403,26 +8012,32 @@ bool torture_rpc_samr_users(struct torture_context *torture)
        NTSTATUS status;
        struct dcerpc_pipe *p;
        bool ret = true;
-       struct policy_handle handle;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
 
-       ret &= test_Connect(p, torture, &handle);
+       ret &= test_Connect(b, torture, &ctx->handle);
 
        if (!torture_setting_bool(torture, "samba3", false)) {
-               ret &= test_QuerySecurity(p, torture, &handle);
+               ret &= test_QuerySecurity(b, torture, &ctx->handle);
        }
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
+       ret &= test_EnumDomains(p, torture, ctx);
 
-       ret &= test_SetDsrmPassword(p, torture, &handle);
+       ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
 
-       ret &= test_Shutdown(p, torture, &handle);
+       ret &= test_Shutdown(b, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
        return ret;
 }
@@ -6433,18 +8048,26 @@ bool torture_rpc_samr_passwords(struct torture_context *torture)
        NTSTATUS status;
        struct dcerpc_pipe *p;
        bool ret = true;
-       struct policy_handle handle;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_PASSWORDS;
+
+       ret &= test_Connect(b, torture, &ctx->handle);
 
-       ret &= test_Connect(p, torture, &handle);
+       ret &= test_EnumDomains(p, torture, ctx);
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_samr_ValidatePassword(p, torture);
 
        return ret;
 }
@@ -6456,30 +8079,35 @@ static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
        NTSTATUS status;
        struct dcerpc_pipe *p;
        bool ret = true;
-       struct policy_handle handle;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
+       ctx->machine_credentials = machine_credentials;
 
-       ret &= test_EnumDomains(p, torture, &handle,
-                               TORTURE_SAMR_PASSWORDS_PWDLASTSET,
-                               machine_credentials);
+       ret &= test_Connect(b, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
        return ret;
 }
 
 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
 {
-       struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
        struct torture_rpc_tcase *tcase;
 
-       tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
+       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
                                                          &ndr_table_samr,
                                                          TEST_ACCOUNT_NAME_PWD);
 
@@ -6496,30 +8124,35 @@ static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context
        NTSTATUS status;
        struct dcerpc_pipe *p;
        bool ret = true;
-       struct policy_handle handle;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
+       b = p->binding_handle;
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx = talloc_zero(torture, struct torture_samr_context);
 
-       ret &= test_EnumDomains(p, torture, &handle,
-                               TORTURE_SAMR_USER_PRIVILEGES,
-                               machine_credentials);
+       ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
+       ctx->machine_credentials = machine_credentials;
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
        return ret;
 }
 
 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
 {
-       struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
        struct torture_rpc_tcase *tcase;
 
-       tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
+       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
                                                          &ndr_table_samr,
                                                          TEST_ACCOUNT_NAME_PWD);
 
@@ -6528,3 +8161,206 @@ struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
 
        return suite;
 }
+
+static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
+                                          struct dcerpc_pipe *p2,
+                                          void *data)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct torture_samr_context *ctx =
+               talloc_get_type_abort(data, struct torture_samr_context);
+       struct dcerpc_binding_handle *b;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       b = p->binding_handle;
+
+       ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
+       ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
+                                                       ctx->num_objects_large_dc);
+
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
+
+       return ret;
+}
+
+static bool torture_rpc_samr_many_groups(struct torture_context *torture,
+                                        struct dcerpc_pipe *p2,
+                                        void *data)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct torture_samr_context *ctx =
+               talloc_get_type_abort(data, struct torture_samr_context);
+       struct dcerpc_binding_handle *b;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       b = p->binding_handle;
+
+       ctx->choice = TORTURE_SAMR_MANY_GROUPS;
+       ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
+                                                       ctx->num_objects_large_dc);
+
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
+
+       return ret;
+}
+
+static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
+                                         struct dcerpc_pipe *p2,
+                                         void *data)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct torture_samr_context *ctx =
+               talloc_get_type_abort(data, struct torture_samr_context);
+       struct dcerpc_binding_handle *b;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       b = p->binding_handle;
+
+       ctx->choice = TORTURE_SAMR_MANY_ALIASES;
+       ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
+                                                       ctx->num_objects_large_dc);
+
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
+
+       return ret;
+}
+
+struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
+       struct torture_rpc_tcase *tcase;
+       struct torture_samr_context *ctx;
+
+       tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
+
+       ctx = talloc_zero(suite, struct torture_samr_context);
+       ctx->num_objects_large_dc = 150;
+
+       torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
+                                     torture_rpc_samr_many_aliases, ctx);
+       torture_rpc_tcase_add_test_ex(tcase, "many_groups",
+                                     torture_rpc_samr_many_groups, ctx);
+       torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
+                                     torture_rpc_samr_many_accounts, ctx);
+
+       return suite;
+}
+
+static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
+                                        struct dcerpc_pipe *p2,
+                                        struct cli_credentials *machine_credentials)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
+       ctx->machine_credentials = machine_credentials;
+
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
+
+       return ret;
+}
+
+struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
+       struct torture_rpc_tcase *tcase;
+
+       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
+                                                         &ndr_table_samr,
+                                                         TEST_ACCOUNT_NAME_PWD);
+
+       torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
+                                        torture_rpc_samr_badpwdcount);
+
+       return suite;
+}
+
+static bool torture_rpc_samr_lockout(struct torture_context *torture,
+                                    struct dcerpc_pipe *p2,
+                                    struct cli_credentials *machine_credentials)
+{
+       NTSTATUS status;
+       struct dcerpc_pipe *p;
+       bool ret = true;
+       struct torture_samr_context *ctx;
+       struct dcerpc_binding_handle *b;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       b = p->binding_handle;
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
+       ctx->machine_credentials = machine_credentials;
+
+       ret &= test_Connect(b, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(b, torture, &ctx->handle);
+
+       return ret;
+}
+
+struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
+       struct torture_rpc_tcase *tcase;
+
+       tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
+                                                         &ndr_table_samr,
+                                                         TEST_ACCOUNT_NAME_PWD);
+
+       torture_rpc_tcase_add_test_creds(tcase, "lockout",
+                                        torture_rpc_samr_lockout);
+
+       return suite;
+}
+
+