s4-smbtorture: allow test_SamLogon to test interactive samlogon in RPC-SAMR family...
[ira/wip.git] / source4 / torture / rpc / samr.c
index 9483ae2a9ad8e96da00238b2420b88a36686046f..3f2cf6b41ef95504ca680294c537352c5b9718f9 100644 (file)
@@ -1,20 +1,21 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    test suite for samr rpc operations
 
    Copyright (C) Andrew Tridgell 2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
-   
+   Copyright (C) Guenther Deschner 2008,2009
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "librpc/gen_ndr/ndr_netlogon.h"
 #include "librpc/gen_ndr/ndr_netlogon_c.h"
 #include "librpc/gen_ndr/ndr_samr_c.h"
+#include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "../lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
 #include "libcli/security/security.h"
 #include "torture/rpc/rpc.h"
 #include "param/param.h"
+#include "auth/gensec/gensec.h"
+#include "auth/gensec/gensec_proto.h"
+#include "../libcli/auth/schannel.h"
+#include "auth/gensec/schannel_state.h"
 
 #include <unistd.h>
 
@@ -45,20 +51,35 @@ enum torture_samr_choice {
        TORTURE_SAMR_PASSWORDS,
        TORTURE_SAMR_PASSWORDS_PWDLASTSET,
        TORTURE_SAMR_USER_ATTRIBUTES,
-       TORTURE_SAMR_OTHER
+       TORTURE_SAMR_USER_PRIVILEGES,
+       TORTURE_SAMR_OTHER,
+       TORTURE_SAMR_MANY_ACCOUNTS,
+       TORTURE_SAMR_MANY_GROUPS,
+       TORTURE_SAMR_MANY_ALIASES
 };
 
-static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+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_pipe *p,
+                              struct torture_context *tctx,
                               struct policy_handle *handle);
 
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
                                struct policy_handle *handle);
 
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                              struct policy_handle *handle);
+static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
+                               struct policy_handle *handle);
 
-static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                               const char *acct_name, 
+static bool test_ChangePassword(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
+                               const char *acct_name,
                                struct policy_handle *domain_handle, char **password);
 
 static void init_lsa_String(struct lsa_String *string, const char *s)
@@ -66,6 +87,11 @@ static void init_lsa_String(struct lsa_String *string, const char *s)
        string->string = s;
 }
 
+static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
+{
+       string->string = s;
+}
+
 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
 {
        string->length = length;
@@ -138,8 +164,8 @@ static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *
 }
 
 
-static bool test_QuerySecurity(struct dcerpc_pipe *p, 
-                              struct torture_context *tctx, 
+static bool test_QuerySecurity(struct dcerpc_pipe *p,
+                              struct torture_context *tctx,
                               struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -174,7 +200,7 @@ static bool test_QuerySecurity(struct dcerpc_pipe *p,
 }
 
 
-static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx, 
+static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
                             struct policy_handle *handle, uint32_t base_acct_flags,
                             const char *base_account_name)
 {
@@ -189,9 +215,12 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        const char *test_account_name;
 
        uint32_t user_extra_flags = 0;
-       if (base_acct_flags == ACB_NORMAL) {
-               /* When created, accounts are expired by default */
-               user_extra_flags = ACB_PW_EXPIRED;
+
+       if (!torture_setting_bool(tctx, "samba3", false)) {
+               if (base_acct_flags == ACB_NORMAL) {
+                       /* When created, accounts are expired by default */
+                       user_extra_flags = ACB_PW_EXPIRED;
+               }
        }
 
        s.in.user_handle = handle;
@@ -323,7 +352,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
 
        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", 
+       TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
                           SAMR_FIELD_COMMENT);
 
        test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
@@ -339,7 +368,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
        TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
        test_account_name = base_account_name;
-       TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name, 
+       TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
                           SAMR_FIELD_ACCOUNT_NAME);
 
        TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
@@ -349,7 +378,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        TEST_USERINFO_STRING(6, full_name,  8, full_name, "xx6-8 full_name", 0);
        TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
        TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
-       TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name", 
+       TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
                           SAMR_FIELD_FULL_NAME);
 
        TEST_USERINFO_STRING(6, full_name,  1, full_name, "", 0);
@@ -359,19 +388,19 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        TEST_USERINFO_STRING(6, full_name,  8, full_name, "", 0);
        TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
        TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
-       TEST_USERINFO_STRING(21, full_name, 21, full_name, "", 
+       TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
                           SAMR_FIELD_FULL_NAME);
 
        TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
        TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
        TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
-       TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script", 
+       TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
                           SAMR_FIELD_LOGON_SCRIPT);
 
        TEST_USERINFO_STRING(12, profile_path,  3, profile_path, "xx12-3 profile_path", 0);
        TEST_USERINFO_STRING(12, profile_path,  5, profile_path, "xx12-5 profile_path", 0);
        TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
-       TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path", 
+       TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
                           SAMR_FIELD_PROFILE_PATH);
 
        TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
@@ -389,23 +418,23 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
                             SAMR_FIELD_HOME_DRIVE);
        TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
                             SAMR_FIELD_HOME_DRIVE);
-       
+
        TEST_USERINFO_STRING(13, description,  1, description, "xx13-1 description", 0);
        TEST_USERINFO_STRING(13, description,  5, description, "xx13-5 description", 0);
        TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
-       TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description", 
+       TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
                           SAMR_FIELD_DESCRIPTION);
 
        TEST_USERINFO_STRING(14, workstations,  3, workstations, "14workstation3", 0);
        TEST_USERINFO_STRING(14, workstations,  5, workstations, "14workstation4", 0);
        TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
-       TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21", 
+       TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
                           SAMR_FIELD_WORKSTATIONS);
-       TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3", 
+       TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
                           SAMR_FIELD_WORKSTATIONS);
-       TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5", 
+       TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
                           SAMR_FIELD_WORKSTATIONS);
-       TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14", 
+       TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
                           SAMR_FIELD_WORKSTATIONS);
 
        TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
@@ -420,90 +449,111 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx
        TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
                           SAMR_FIELD_PARAMETERS);
 
-       TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
-       TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
-       TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__, 
-                         SAMR_FIELD_COUNTRY_CODE);
-       TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__, 
-                         SAMR_FIELD_COUNTRY_CODE);
-
-       TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
-       TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__, 
-                         SAMR_FIELD_CODE_PAGE);
-       TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__, 
-                         SAMR_FIELD_CODE_PAGE);
-
-       TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
-       TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
-       TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__, 
-                         SAMR_FIELD_ACCT_EXPIRY);
-       TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__, 
-                         SAMR_FIELD_ACCT_EXPIRY);
-       TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__, 
-                         SAMR_FIELD_ACCT_EXPIRY);
+       /* Samba 3 cannot store country_code and copy_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);
+               TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
+                                 SAMR_FIELD_COUNTRY_CODE);
+               TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
+                                 SAMR_FIELD_COUNTRY_CODE);
+
+               TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
+               TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
+                                 SAMR_FIELD_CODE_PAGE);
+               TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
+                                 SAMR_FIELD_CODE_PAGE);
+       }
+
+       if (!torture_setting_bool(tctx, "samba3", false)) {
+               TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
+               TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
+               TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
+                                 SAMR_FIELD_ACCT_EXPIRY);
+               TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
+                                 SAMR_FIELD_ACCT_EXPIRY);
+               TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
+                                 SAMR_FIELD_ACCT_EXPIRY);
+       } else {
+               /* Samba 3 can only store seconds / time_t in passdb - gd */
+               NTTIME nt;
+               unix_to_nt_time(&nt, time(NULL) + __LINE__);
+               TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
+               unix_to_nt_time(&nt, time(NULL) + __LINE__);
+               TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
+               unix_to_nt_time(&nt, time(NULL) + __LINE__);
+               TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+               unix_to_nt_time(&nt, time(NULL) + __LINE__);
+               TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+               unix_to_nt_time(&nt, time(NULL) + __LINE__);
+               TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+       }
 
        TEST_USERINFO_INT(4, logon_hours.bits[3],  3, logon_hours.bits[3], 1, 0);
        TEST_USERINFO_INT(4, logon_hours.bits[3],  5, logon_hours.bits[3], 2, 0);
        TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
-       TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4, 
+       TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
                          SAMR_FIELD_LOGON_HOURS);
 
-       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
-                             (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ), 
-                             (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+                             (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ),
+                             (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
                              0);
-       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
-                             (base_acct_flags  | ACB_DISABLED), 
-                             (base_acct_flags  | ACB_DISABLED | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+                             (base_acct_flags  | ACB_DISABLED),
+                             (base_acct_flags  | ACB_DISABLED | user_extra_flags),
                              0);
-       
+
        /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
-                             (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
-                             (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+                             (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP),
+                             (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP),
                              0);
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ), 
-                             (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
+                             (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
                              0);
 
 
        /* The 'autolock' flag doesn't stick - check this */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK), 
-                             (base_acct_flags | ACB_DISABLED | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
+                             (base_acct_flags | ACB_DISABLED | user_extra_flags),
                              0);
 #if 0
        /* Removing the 'disabled' flag doesn't stick - check this */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags), 
-                             (base_acct_flags | ACB_DISABLED | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags),
+                             (base_acct_flags | ACB_DISABLED | user_extra_flags),
                              0);
 #endif
+
+       /* Samba3 cannot store these atm */
+       if (!torture_setting_bool(tctx, "samba3", false)) {
        /* The 'store plaintext' flag does stick */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED), 
-                             (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
+                             (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
                              0);
        /* The 'use DES' flag does stick */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY), 
-                             (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
+                             (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
                              0);
        /* The 'don't require kerberos pre-authentication flag does stick */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH), 
-                             (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
+                             (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
                              0);
        /* The 'no kerberos PAC required' flag sticks */
-       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD), 
-                             (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags), 
+       TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
+                             (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
                              0);
-
-       TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags, 
-                             (base_acct_flags | ACB_DISABLED), 
-                             (base_acct_flags | ACB_DISABLED | user_extra_flags), 
+       }
+       TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
+                             (base_acct_flags | ACB_DISABLED),
+                             (base_acct_flags | ACB_DISABLED | user_extra_flags),
                              SAMR_FIELD_ACCT_FLAGS);
 
 #if 0
@@ -594,7 +644,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;
        }
@@ -605,7 +655,7 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -650,7 +700,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;
        }
@@ -661,7 +711,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -672,7 +722,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;
        }
@@ -685,7 +735,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        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",
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        }
@@ -695,7 +745,7 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
 
 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
-                              struct policy_handle *handle, bool makeshort, 
+                              struct policy_handle *handle, bool makeshort,
                               char **password)
 {
        NTSTATUS status;
@@ -732,7 +782,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;
        }
@@ -751,7 +801,7 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -768,7 +818,7 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
 
        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",
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -815,7 +865,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;
        }
@@ -834,7 +884,7 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -851,7 +901,7 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        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",
+               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        }
@@ -896,7 +946,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;
        }
@@ -920,7 +970,7 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -981,7 +1031,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;
        }
@@ -1008,7 +1058,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        } else {
@@ -1023,7 +1073,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                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",
+                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
                               s.in.level, nt_errstr(status));
                        ret = false;
                }
@@ -1036,7 +1086,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                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",
+                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
                               s.in.level, nt_errstr(status));
                        ret = false;
                }
@@ -1164,7 +1214,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;
        }
@@ -1258,7 +1308,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 {
@@ -1293,12 +1343,12 @@ 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",
+                       torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -1309,7 +1359,7 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct
 
                status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryAliasInfo level %u failed - %s\n",
+                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -1418,7 +1468,7 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        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));              
+               torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(status));
                if (NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1428,7 +1478,7 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        n.in.num_names = 0;
        status = dcerpc_samr_LookupNames(p, tctx, &n);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupNames[0] failed - %s\n", nt_errstr(status));              
+               torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
                return status;
        }
 
@@ -1436,7 +1486,7 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        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));             
+               torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
                if (NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1448,7 +1498,7 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        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));            
+               torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
                if (NT_STATUS_IS_OK(status)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1458,7 +1508,8 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t
        return NT_STATUS_OK;
 }
 
-static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
+                                    struct torture_context *tctx,
                                     struct policy_handle *domain_handle,
                                     const char *name, struct policy_handle *user_handle)
 {
@@ -1466,7 +1517,7 @@ static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct samr_OpenUser r;
        uint32_t rid;
 
-       status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
+       status = test_LookupName(p, tctx, domain_handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -1475,16 +1526,17 @@ static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.user_handle = user_handle;
-       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+       status = dcerpc_samr_OpenUser(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
+               torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
        }
 
        return status;
 }
 
 #if 0
-static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
+                                  struct torture_context *tctx,
                                   struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -1497,15 +1549,15 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        uint8_t old_nt_hash[16], new_nt_hash[16];
        uint8_t old_lm_hash[16], new_lm_hash[16];
 
-       status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
+       status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
        if (!NT_STATUS_IS_OK(status)) {
                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);
@@ -1531,13 +1583,13 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.cross2_present = 1;
        r.in.lm_cross = &hash6;
 
-       status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
+       status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+       if (!test_samr_handle_Close(p, tctx, &user_handle)) {
                ret = false;
        }
 
@@ -1546,7 +1598,7 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 #endif
 
 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
-                                   const char *acct_name, 
+                                   const char *acct_name,
                                    struct policy_handle *handle, char **password)
 {
        NTSTATUS status;
@@ -1579,7 +1631,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
 
        torture_comment(tctx, "Testing ChangePasswordUser\n");
 
-       torture_assert(tctx, *password != NULL, 
+       torture_assert(tctx, *password != NULL,
                                   "Failing ChangePasswordUser as old password was NULL.  Previous test failed?");
 
        oldpass = *password;
@@ -1632,7 +1684,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        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_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
                "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
 
        /* Unbreak the NT hash */
@@ -1654,7 +1706,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
 
        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_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -1677,7 +1729,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
 
        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_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -1710,7 +1762,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
                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));
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -1748,7 +1800,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
                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));
+               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -1783,9 +1835,9 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
 
        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));
+               torture_comment(tctx, "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_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                changed = true;
@@ -1807,14 +1859,14 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex
        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));
+                       torture_comment(tctx, "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_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
                        ret = false;
                }
        }
 
-       
+
        if (!test_samr_handle_Close(p, tctx, &user_handle)) {
                ret = false;
        }
@@ -1849,7 +1901,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        torture_comment(tctx, "Testing OemChangePasswordUser2\n");
 
-       torture_assert(tctx, *password != NULL, 
+       torture_assert(tctx, *password != NULL,
                                   "Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?");
 
        oldpass = *password;
@@ -1883,7 +1935,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        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",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1905,7 +1957,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        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",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1922,7 +1974,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        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",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1934,7 +1986,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
 
        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",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1948,7 +2000,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
 
        if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
-               printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1962,7 +2014,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
        status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
 
        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",
+               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -1981,9 +2033,9 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co
 
        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));
+               torture_comment(tctx, "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_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                *password = newpass;
@@ -2019,7 +2071,7 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 
        torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
 
-       torture_assert(tctx, *password != NULL, 
+       torture_assert(tctx, *password != NULL,
                                   "Failing ChangePasswordUser2 as old password was NULL.  Previous test failed?");
        oldpass = *password;
 
@@ -2031,7 +2083,7 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
                }
 
                newpass = samr_rand_pass(tctx, policy_min_pw_len);
-       } 
+       }
 
        server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
        init_lsa_String(&account, acct_name);
@@ -2060,9 +2112,9 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 
        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));
+               torture_comment(tctx, "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_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                *password = newpass;
@@ -2072,7 +2124,7 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 }
 
 
-bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx, 
+bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
                              const char *account_string,
                              int policy_min_pw_len,
                              char **password,
@@ -2091,7 +2143,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        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");
 
@@ -2107,7 +2159,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                torture_comment(tctx, "Using password '%s'\n", newpass);
        }
 
-       torture_assert(tctx, *password != NULL, 
+       torture_assert(tctx, *password != NULL,
                                   "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
 
        oldpass = *password;
@@ -2127,7 +2179,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
        arcfour_crypt(nt_pass.data, old_nt_hash, 516);
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
-       
+
        /* Break the verification */
        nt_verifier.hash[0]++;
 
@@ -2145,11 +2197,11 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        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",
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
                        nt_errstr(status));
                ret = false;
        }
-       
+
        encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
        arcfour_crypt(lm_pass.data, old_nt_hash, 516);
        E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
@@ -2161,7 +2213,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        /* Unbreak it again */
        old_nt_hash[0]--;
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
-       
+
        r.in.server = &server;
        r.in.account = &account;
        r.in.nt_password = &nt_pass;
@@ -2176,18 +2228,18 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        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",
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
                        nt_errstr(status));
                ret = false;
        }
-       
+
        /* This shouldn't be a valid name */
        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",
+               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
                        nt_errstr(status));
                ret = false;
        }
@@ -2228,16 +2280,16 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
            && (!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;
                        }
                }
 
                /* We tested the order of precendence which is as follows:
-               
-               * pwd min_age 
+
+               * pwd min_age
                * pwd length
                * pwd complexity
                * pwd history
@@ -2247,56 +2299,56 @@ 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, 
+                       return test_ChangePasswordUser3(p, tctx, account_string,
                                                        dominfo->min_password_length,
-                                                       password, NULL, 0, false); 
+                                                       password, NULL, 0, false);
 
                }
 
        } 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);
+               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 { 
+       } else {
                torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
                *password = talloc_strdup(tctx, newpass);
        }
@@ -2306,7 +2358,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
                                    const char *account_string,
-                                   struct policy_handle *handle, 
+                                   struct policy_handle *handle,
                                    char **password)
 {
        NTSTATUS status;
@@ -2328,11 +2380,11 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        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);
 
-       torture_assert(tctx, *password != NULL, 
+       torture_assert(tctx, *password != NULL,
                                   "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
 
        oldpass = *password;
@@ -2351,7 +2403,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;
        }
@@ -2370,7 +2422,7 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        status = dcerpc_samr_SetUserInfo(p, tctx, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u failed - %s\n",
+               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(status));
                ret = false;
        }
@@ -2403,18 +2455,18 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
 
        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 (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));
+               torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(status));
                ret = false;
        }
-       
+
        newpass = samr_rand_pass(tctx, 128);
 
        mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
@@ -2441,9 +2493,9 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
 
        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 (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? */
@@ -2545,6 +2597,56 @@ static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture
        return true;
 }
 
+static bool test_GetAliasMembership(struct dcerpc_pipe *p,
+                                   struct torture_context *tctx,
+                                   struct policy_handle *domain_handle)
+{
+       struct samr_GetAliasMembership r;
+       struct lsa_SidArray sids;
+       struct samr_Ids rids;
+       NTSTATUS status;
+
+       torture_comment(tctx, "Testing GetAliasMembership\n");
+
+       if (torture_setting_bool(tctx, "samba4", false)) {
+               torture_skip(tctx, "skipping GetAliasMembership against s4");
+       }
+
+       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);
+
+       status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+               "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");
+
+       status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+               "samr_GetAliasMembership failed");
+
+#if 0
+       /* only true for w2k8 it seems
+        * win7, xp, w2k3 will return a 0 length array pointer */
+
+       torture_assert(tctx, (rids.ids && !rids.count),
+               "samr_GetAliasMembership protocol misbehaviour");
+#endif
+       torture_assert(tctx, (!rids.ids && rids.count),
+               "samr_GetAliasMembership protocol misbehaviour");
+
+       return true;
+}
+
 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                                            struct policy_handle *user_handle)
 {
@@ -2598,7 +2700,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
 
                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;
                }
@@ -2629,21 +2731,27 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
        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;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
 
        if (lp_client_lanman_auth(tctx->lp_ctx)) {
                flags |= CLI_CRED_LANMAN_AUTH;
@@ -2654,92 +2762,99 @@ static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *t
        }
 
        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));
 
-       logon.network = &ninfo;
+               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;
+
+               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);
+       torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
 
-       ZERO_STRUCT(auth2);
-       netlogon_creds_client_authenticator(creds, &auth);
+       r.in.validation_level = 6;
 
-       r.in.validation_level = 2;
-
-       status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
+       status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+               r.in.validation_level = 3;
+               status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
+       }
        if (!NT_STATUS_IS_OK(status)) {
-               torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
+               torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
                return true;
        } else {
-               torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
+               torture_assert_ntstatus_ok(tctx, status, "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)
+                                    NTSTATUS expected_samlogon_result,
+                                    bool interactive)
 {
        bool ret = true;
        struct cli_credentials *test_credentials;
@@ -2747,20 +2862,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;
        }
@@ -2826,7 +2940,8 @@ static bool test_SetPassword_level(struct dcerpc_pipe *p,
                                      machine_creds,
                                      acct_name,
                                      *password,
-                                     expected_samlogon_result)) {
+                                     expected_samlogon_result,
+                                     false)) {
                ret = false;
        }
 
@@ -2842,11 +2957,12 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                                        struct cli_credentials *machine_credentials)
 {
        int s = 0, q = 0, f = 0, l = 0, z = 0;
+       struct dcerpc_binding *b;
        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,
@@ -2866,24 +2982,46 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
        struct dcerpc_pipe *np = NULL;
 
        if (torture_setting_bool(tctx, "samba3", false)) {
-               delay = 1000000;
-               printf("Samba3 has second granularity, setting delay to: %d\n",
+               delay = 999999;
+               torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
                        delay);
        }
 
-       status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
+       status = torture_rpc_binding(tctx, &b);
        if (!NT_STATUS_IS_OK(status)) {
-               return false;
+               ret = false;
+               return ret;
+       }
+
+       /* 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;
+
+       status = dcerpc_pipe_connect_b(tctx, &np, b,
+                                      &ndr_table_netlogon,
+                                      machine_credentials, tctx->ev, tctx->lp_ctx);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               torture_warning(tctx, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
+               ret = false;
+               return ret;
        }
 
        /* 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
@@ -3231,14 +3369,313 @@ 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)
+{
+       NTSTATUS status;
+       bool ret = true;
+
+       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;
+
+               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");
+       }
+
+       {
+               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;
+
+               status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status,
+                       "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;
+               r.in.resume_handle = &resume_handle;
+               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,
+                       "Failed to enum accounts");
+
+               for (i=0; i < lsa_sid_array.num_sids; i++) {
+                       if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
+                               found_sid = true;
+                       }
+               }
+
+               torture_assert(tctx, found_sid,
+                       "failed to list privileged account");
+       }
+
+       {
+               struct lsa_EnumAccountRights r;
+               struct lsa_RightSet user_rights;
+
+               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,
+                       "Failed to enum rights for account");
+
+               if (user_rights.count < 1) {
+                       torture_warning(tctx, "failed to find newly added rights");
+                       return false;
+               }
+       }
+
+       {
+               struct lsa_OpenAccount r;
+
+               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,
+                       "Failed to open lsa account");
+       }
+
+       {
+               struct lsa_GetSystemAccessAccount r;
+               uint32_t access_mask;
+
+               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,
+                       "Failed to get lsa system access account");
+       }
+
+       {
+               struct lsa_Close r;
+
+               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,
+                       "Failed to close lsa");
+       }
+
+       {
+               struct samr_DeleteUser r;
+
+               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");
+       }
+
+       {
+               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;
+               r.in.resume_handle = &resume_handle;
+               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,
+                       "Failed to enum accounts");
+
+               for (i=0; i < lsa_sid_array.num_sids; i++) {
+                       if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
+                               found_sid = true;
+                       }
+               }
+
+               torture_assert(tctx, found_sid,
+                       "failed to list privileged account");
+       }
+
+       {
+               struct lsa_EnumAccountRights r;
+               struct lsa_RightSet user_rights;
+
+               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,
+                       "Failed to enum rights for account");
+
+               if (user_rights.count < 1) {
+                       torture_warning(tctx, "failed to find newly added rights");
+                       return false;
+               }
+       }
+
+       {
+               struct lsa_OpenAccount r;
+
+               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,
+                       "Failed to open lsa account");
+       }
+
+       {
+               struct lsa_GetSystemAccessAccount r;
+               uint32_t access_mask;
+
+               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,
+                       "Failed to get lsa system access account");
+       }
+
+       {
+               struct lsa_DeleteObject r;
+
+               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,
+                       "Failed to delete object");
+       }
+
+       {
+               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;
+               r.in.resume_handle = &resume_handle;
+               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,
+                       "Failed to enum accounts");
+
+               for (i=0; i < lsa_sid_array.num_sids; i++) {
+                       if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
+                               found_sid = true;
+                       }
+               }
+
+               torture_assert(tctx, !found_sid,
+                       "should not have listed privileged account");
+       }
+
+       {
+               struct lsa_EnumAccountRights r;
+               struct lsa_RightSet user_rights;
+
+               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,
+                       "Failed to enum rights for account");
+       }
+
        return ret;
 }
 
-static bool test_user_ops(struct dcerpc_pipe *p, 
+static bool test_user_ops(struct dcerpc_pipe *p,
                          struct torture_context *tctx,
-                         struct policy_handle *user_handle, 
-                         struct policy_handle *domain_handle, 
-                         uint32_t base_acct_flags, 
+                         struct policy_handle *user_handle,
+                         struct policy_handle *domain_handle,
+                         const struct dom_sid *domain_sid,
+                         uint32_t base_acct_flags,
                          const char *base_acct_name, enum torture_samr_choice which_ops,
                          struct cli_credentials *machine_credentials)
 {
@@ -3256,7 +3693,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
                0
        };
-       
+
        status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                ret = false;
@@ -3279,7 +3716,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
                                      base_acct_name)) {
                        ret = false;
-               }       
+               }
 
                if (!test_GetUserPwInfo(p, tctx, user_handle)) {
                        ret = false;
@@ -3297,11 +3734,11 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
                        char simple_pass[9];
                        char *v = generate_random_str(tctx, 1);
-                       
+
                        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)) {
@@ -3331,35 +3768,35 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                for (i = 0; password_fields[i]; i++) {
                        if (!test_SetUserPass_23(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;
                        }
-               }               
+               }
 
                for (i = 0; password_fields[i]; i++) {
                        if (!test_SetUserPass_25(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;
                        }
-               }               
+               }
 
                if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
                        ret = false;
-               }       
+               }
 
                if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
                        ret = false;
-               }       
+               }
 
                if (torture_setting_bool(tctx, "samba4", false)) {
-                       printf("skipping Set Password level 18 and 21 against Samba4\n");
+                       torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
                } else {
 
                        if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
@@ -3392,22 +3829,25 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                q.in.user_handle = user_handle;
                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", 
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
                               q.in.level, nt_errstr(status));
                        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, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                       info->info5.acct_flags,
                                       expected_flags);
-                               ret = false;
+                               /* FIXME: GD */
+                               if (!torture_setting_bool(tctx, "samba3", false)) {
+                                       ret = false;
+                               }
                        }
                        if (info->info5.rid != rid) {
-                               printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
+                               torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
                                       info->info5.rid, rid);
 
                        }
@@ -3433,21 +3873,52 @@ static bool test_user_ops(struct dcerpc_pipe *p,
 
                break;
 
-       case TORTURE_SAMR_OTHER:
-               /* We just need the account to exist */
-               break;
-       }
-       return ret;
-}
+       case TORTURE_SAMR_USER_PRIVILEGES: {
 
-static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
-                          struct policy_handle *alias_handle,
-                          const struct dom_sid *domain_sid)
+               struct dcerpc_pipe *lp;
+               struct policy_handle *lsa_handle;
+
+               status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
+               torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
+
+               if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
+                       ret = false;
+               }
+
+               if (!test_DeleteUser_with_privs(p, lp, tctx,
+                                               domain_handle, lsa_handle, user_handle,
+                                               domain_sid, rid,
+                                               machine_credentials)) {
+                       ret = false;
+               }
+
+               if (!test_lsa_Close(lp, tctx, lsa_handle)) {
+                       ret = false;
+               }
+
+               if (!ret) {
+                       torture_warning(tctx, "privileged user delete test failed\n");
+               }
+
+               break;
+       }
+       case TORTURE_SAMR_OTHER:
+               /* We just need the account to exist */
+               break;
+       }
+       return ret;
+}
+
+static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
+                          struct policy_handle *alias_handle,
+                          const struct dom_sid *domain_sid)
 {
        bool ret = true;
 
-       if (!test_QuerySecurity(p, tctx, alias_handle)) {
-               ret = false;
+       if (!torture_setting_bool(tctx, "samba3", false)) {
+               if (!test_QuerySecurity(p, tctx, alias_handle)) {
+                       ret = false;
+               }
        }
 
        if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
@@ -3462,8 +3933,9 @@ static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
                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;
        }
 
@@ -3491,7 +3963,8 @@ static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
        return true;
 }
 
-bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+bool test_DeleteUser_byname(struct dcerpc_pipe *p,
+                           struct torture_context *tctx,
                            struct policy_handle *handle, const char *name)
 {
        NTSTATUS status;
@@ -3499,19 +3972,19 @@ bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct policy_handle user_handle;
        uint32_t rid;
 
-       status = test_LookupName(p, mem_ctx, handle, name, &rid);
+       status = test_LookupName(p, tctx, handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
-       status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
+       status = test_OpenUser_byname(p, 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, mem_ctx, &d);
+       status = dcerpc_samr_DeleteUser(p, tctx, &d);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3519,12 +3992,13 @@ bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, TALLOC_CTX *mem_ctx, 
+static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
+                                   struct torture_context *tctx,
                                    struct policy_handle *handle, const char *name)
 {
        NTSTATUS status;
@@ -3533,7 +4007,7 @@ static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct policy_handle group_handle;
        uint32_t rid;
 
-       status = test_LookupName(p, mem_ctx, handle, name, &rid);
+       status = test_LookupName(p, tctx, handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3542,14 +4016,14 @@ static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.group_handle = &group_handle;
-       status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
+       status = dcerpc_samr_OpenGroup(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
        d.in.group_handle = &group_handle;
        d.out.group_handle = &group_handle;
-       status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
+       status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3557,13 +4031,15 @@ static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, TALLOC_CTX *mem_ctx,
-                                  struct policy_handle *domain_handle, const char *name)
+static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
+                                   struct torture_context *tctx,
+                                   struct policy_handle *domain_handle,
+                                   const char *name)
 {
        NTSTATUS status;
        struct samr_OpenAlias r;
@@ -3571,9 +4047,9 @@ static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct policy_handle alias_handle;
        uint32_t rid;
 
-       printf("testing DeleteAlias_byname\n");
+       torture_comment(tctx, "testing DeleteAlias_byname\n");
 
-       status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
+       status = test_LookupName(p, tctx, domain_handle, name, &rid);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3582,14 +4058,14 @@ static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.alias_handle = &alias_handle;
-       status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
+       status = dcerpc_samr_OpenAlias(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
 
        d.in.alias_handle = &alias_handle;
        d.out.alias_handle = &alias_handle;
-       status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
+       status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
        }
@@ -3597,24 +4073,26 @@ static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, TALLOC_CTX *mem_ctx,
-                                    struct policy_handle *alias_handle)
+static bool test_DeleteAlias(struct dcerpc_pipe *p,
+                            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, mem_ctx, &d);
+       status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("DeleteAlias failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -3622,9 +4100,11 @@ static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
-                           struct policy_handle *domain_handle, 
-                            struct policy_handle *alias_handle, 
-                            const struct dom_sid *domain_sid)
+                            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;
@@ -3632,23 +4112,23 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx
        uint32_t rid;
        bool ret = true;
 
-       init_lsa_String(&name, TEST_ALIASNAME);
+       init_lsa_String(&name, alias_name);
        r.in.domain_handle = domain_handle;
        r.in.alias_name = &name;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        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);
 
        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);
+                       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, 
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
                               nt_errstr(status));
                        return false;
                }
@@ -3662,10 +4142,14 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               printf("CreateAlias failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
                return false;
        }
 
+       if (!test_alias) {
+               return ret;
+       }
+
        if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
                ret = false;
        }
@@ -3673,7 +4157,8 @@ static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx
        return ret;
 }
 
-static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_ChangePassword(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
                                const char *acct_name,
                                struct policy_handle *domain_handle, char **password)
 {
@@ -3683,32 +4168,32 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return false;
        }
 
-       if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
+       if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
                ret = false;
        }
 
-       if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
+       if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
                ret = false;
        }
 
-       if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
+       if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
                ret = false;
        }
 
        /* test what happens when setting the old password again */
-       if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
+       if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
                ret = false;
        }
 
        {
                char simple_pass[9];
-               char *v = generate_random_str(mem_ctx, 1);
+               char *v = generate_random_str(tctx, 1);
 
                ZERO_STRUCT(simple_pass);
                memset(simple_pass, *v, sizeof(simple_pass) - 1);
 
                /* test what happens when picking a simple password */
-               if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
+               if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
                        ret = false;
                }
        }
@@ -3729,8 +4214,8 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                r.in.level = 1;
                r.out.info = &info;
 
-               printf("testing samr_QueryDomainInfo level 1\n");
-               status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
+               torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
+               status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
                        return false;
                }
@@ -3749,24 +4234,24 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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, mem_ctx, &s);
+               torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
+               status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
                if (!NT_STATUS_IS_OK(status)) {
                        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, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
+               if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
                        ret = false;
                }
 
                s.in.info->info1.min_password_length = len_old;
                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, mem_ctx, &s);
+
+               torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
+               status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
                if (!NT_STATUS_IS_OK(status)) {
                        return false;
                }
@@ -3784,14 +4269,14 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                n.in.domain_handle = domain_handle;
                n.in.num_names = 1;
-               n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
-               n.in.names[0].string = acct_name; 
+               n.in.names = talloc_array(tctx, struct lsa_String, 1);
+               n.in.names[0].string = acct_name;
                n.out.rids = &rids;
                n.out.types = &types;
 
-               status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+               status = dcerpc_samr_LookupNames(p, tctx, &n);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("LookupNames failed - %s\n", nt_errstr(status));
+                       torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
                        return false;
                }
 
@@ -3800,9 +4285,9 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                r.in.rid = n.out.rids->ids[0];
                r.out.user_handle = &user_handle;
 
-               status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+               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_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
                        return false;
                }
 
@@ -3810,15 +4295,15 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                q.in.level = 5;
                q.out.info = &info;
 
-               status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+               status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo failed - %s\n", nt_errstr(status));
+                       torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
                        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, mem_ctx, acct_name, 0, password, NULL, 
+               if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
                                              info->info5.last_password_change, true)) {
                        ret = false;
                }
@@ -3826,11 +4311,11 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        /* we change passwords twice - this has the effect of verifying
           they were changed correctly for the final call */
-       if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
+       if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
                ret = false;
        }
 
-       if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
+       if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
                ret = false;
        }
 
@@ -3838,11 +4323,13 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
-                           struct policy_handle *domain_handle, 
+                           struct policy_handle *domain_handle,
+                           const char *user_name,
                            struct policy_handle *user_handle_out,
-                           struct dom_sid *domain_sid, 
+                           struct dom_sid *domain_sid,
                            enum torture_samr_choice which_ops,
-                           struct cli_credentials *machine_credentials)
+                           struct cli_credentials *machine_credentials,
+                           bool test_user)
 {
 
        TALLOC_CTX *user_ctx;
@@ -3861,7 +4348,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        struct policy_handle user_handle;
        user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
-       init_lsa_String(&name, TEST_ACCOUNT_NAME);
+       init_lsa_String(&name, user_name);
 
        r.in.domain_handle = domain_handle;
        r.in.account_name = &name;
@@ -3869,16 +4356,16 @@ 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);
 
        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);
+                       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, 
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
                               nt_errstr(status));
                        return false;
                }
@@ -3891,54 +4378,64 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                }
                status = dcerpc_samr_CreateUser(p, user_ctx, &r);
        }
+
        if (!NT_STATUS_IS_OK(status)) {
                talloc_free(user_ctx);
-               printf("CreateUser failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
                return false;
-       } else {
+       }
+
+       if (!test_user) {
+               if (user_handle_out) {
+                       *user_handle_out = user_handle;
+               }
+               return ret;
+       }
+
+       {
                q.in.user_handle = &user_handle;
                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", 
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
                               q.in.level, nt_errstr(status));
                        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, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                       info->info16.acct_flags,
                                       acct_flags);
                                ret = false;
                        }
                }
-               
-               if (!test_user_ops(p, tctx, &user_handle, domain_handle, 
-                                  acct_flags, name.string, which_ops,
+
+               if (!test_user_ops(p, tctx, &user_handle, domain_handle,
+                                  domain_sid, acct_flags, name.string, which_ops,
                                   machine_credentials)) {
                        ret = false;
                }
-               
+
                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_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
                                ret = false;
                        }
                }
-               
+
        }
 
        talloc_free(user_ctx);
-       
+
        return ret;
 }
 
@@ -3974,7 +4471,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 },
@@ -3996,17 +4493,17 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                r.out.user_handle = &user_handle;
                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);
-               
+
                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);
+                               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, 
+                               torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
                                       nt_errstr(status));
                                ret = false;
                                continue;
@@ -4023,19 +4520,19 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
 
                }
                if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
-                       printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n", 
+                       torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
                               nt_errstr(status), nt_errstr(account_types[i].nt_status));
                        ret = false;
                }
-               
+
                if (NT_STATUS_IS_OK(status)) {
                        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", 
+                               torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
                                       q.in.level, nt_errstr(status));
                                ret = false;
                        } else {
@@ -4044,51 +4541,53 @@ 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, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                               info->info5.acct_flags,
                                               expected_flags);
                                        ret = false;
-                               } 
+                               }
                                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, "QuerUserInfo 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, "QuerUserInfo 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, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_USERS, info->info5.primary_gid);
                                                ret = false;
                                        }
                                        break;
                                }
                        }
-               
-                       if (!test_user_ops(p, tctx, &user_handle, domain_handle, 
-                                          acct_flags, name.string, which_ops,
+
+                       if (!test_user_ops(p, tctx, &user_handle, domain_handle,
+                                          domain_sid, acct_flags, name.string, which_ops,
                                           machine_credentials)) {
                                ret = false;
                        }
 
-                       printf("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));
-                               ret = false;
+                       if (!policy_handle_empty(&user_handle)) {
+                               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)) {
+                                       torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
+                                       ret = false;
+                               }
                        }
                }
                talloc_free(user_ctx);
@@ -4097,7 +4596,8 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
        return ret;
 }
 
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
                                struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4108,15 +4608,15 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+               status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryAliasInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -4125,7 +4625,8 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
                                struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4136,15 +4637,15 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+               status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryGroupInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -4153,7 +4654,8 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryGroupMember(struct dcerpc_pipe *p,
+                                 struct torture_context *tctx,
                                  struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4161,14 +4663,14 @@ static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct samr_RidTypeArray *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, mem_ctx, &r);
+       status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -4176,7 +4678,8 @@ static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 
-static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_SetGroupInfo(struct dcerpc_pipe *p,
+                             struct torture_context *tctx,
                              struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4189,27 +4692,27 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+               status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryGroupInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        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];
                s.in.info = *r.out.info;
 
 #if 0
-               /* disabled this, as it changes the name only from the point of view of samr, 
+               /* disabled this, as it changes the name only from the point of view of samr,
                   but leaves the name from the point of view of w2k3 internals (and ldap). This means
                   the name is still reserved, so creating the old name fails, but deleting by the old name
                   also fails */
@@ -4222,17 +4725,17 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        init_lsa_String(&s.in.info->description, "test description");
                }
 
-               status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
+               status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
                if (set_ok[i]) {
                        if (!NT_STATUS_IS_OK(status)) {
-                               printf("SetGroupInfo level %u failed - %s\n", 
+                               torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
                                       r.in.level, nt_errstr(status));
                                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", 
+                               torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
                                       r.in.level, nt_errstr(status));
                                ret = false;
                                continue;
@@ -4243,7 +4746,8 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryUserInfo(struct dcerpc_pipe *p,
+                              struct torture_context *tctx,
                               struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4255,15 +4759,15 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+               status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -4272,7 +4776,8 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+                               struct torture_context *tctx,
                                struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4284,15 +4789,15 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+               status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryUserInfo2 level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
@@ -4301,7 +4806,8 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_OpenUser(struct dcerpc_pipe *p,
+                         struct torture_context *tctx,
                          struct policy_handle *handle, uint32_t rid)
 {
        NTSTATUS status;
@@ -4309,47 +4815,48 @@ static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+       status = dcerpc_samr_OpenUser(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
+               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
                return false;
        }
 
-       if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
+       if (!test_QuerySecurity(p, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
+       if (!test_QueryUserInfo(p, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
+       if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
+       if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
+       if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+       if (!test_samr_handle_Close(p, tctx, &user_handle)) {
                ret = false;
        }
 
        return ret;
 }
 
-static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_OpenGroup(struct dcerpc_pipe *p,
+                          struct torture_context *tctx,
                           struct policy_handle *handle, uint32_t rid)
 {
        NTSTATUS status;
@@ -4357,32 +4864,34 @@ static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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, mem_ctx, &r);
+       status = dcerpc_samr_OpenGroup(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
+               torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
                return false;
        }
 
-       if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
-               ret = false;
+       if (!torture_setting_bool(tctx, "samba3", false)) {
+               if (!test_QuerySecurity(p, tctx, &group_handle)) {
+                       ret = false;
+               }
        }
 
-       if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
+       if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
                ret = false;
        }
 
-       if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
+       if (!test_QueryGroupMember(p, tctx, &group_handle)) {
                ret = false;
        }
 
-       if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
+       if (!test_samr_handle_Close(p, tctx, &group_handle)) {
                ret = false;
        }
 
@@ -4406,12 +4915,14 @@ static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = dcerpc_samr_OpenAlias(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
+               torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
                return false;
        }
 
-       if (!test_QuerySecurity(p, tctx, &alias_handle)) {
-               ret = false;
+       if (!torture_setting_bool(tctx, "samba3", false)) {
+               if (!test_QuerySecurity(p, tctx, &alias_handle)) {
+                       ret = false;
+               }
        }
 
        if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
@@ -4430,7 +4941,7 @@ static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
 }
 
 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
-                      struct policy_handle *handle, uint32_t rid, 
+                      struct policy_handle *handle, uint32_t rid,
                       uint32_t acct_flag_mask)
 {
        NTSTATUS status;
@@ -4449,27 +4960,27 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = dcerpc_samr_OpenUser(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
+               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
                return false;
        }
 
        q.in.user_handle = &user_handle;
        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", 
+               torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
                       nt_errstr(status));
                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)) {
                ret = false;
        }
@@ -4477,8 +4988,9 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
        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_pipe *p,
+                                    struct torture_context *tctx,
+                                    struct policy_handle *handle)
 {
        NTSTATUS status = STATUS_MORE_ENTRIES;
        struct samr_EnumDomainUsers r;
@@ -4492,12 +5004,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
        struct samr_SamArray *sam = NULL;
        uint32_t num_entries = 0;
 
-       uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST, 
-                           ACB_DISABLED, ACB_NORMAL | ACB_DISABLED, 
-                           ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST, 
+       uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
+                           ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
+                           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;
@@ -4509,12 +5021,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
                r.out.sam = &sam;
 
                status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
-               if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&  
+               if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
                    !NT_STATUS_IS_OK(status)) {
-                       printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
+                       torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
                        return false;
                }
-       
+
                torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
 
                if (sam->count == 0) {
@@ -4532,7 +5044,7 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
                }
        }
 
-       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);
@@ -4543,12 +5055,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
        }
        status = dcerpc_samr_LookupNames(p, tctx, &n);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupNames failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
                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);
@@ -4560,13 +5072,13 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *
        status = dcerpc_samr_LookupRids(p, tctx, &lr);
        torture_assert_ntstatus_ok(tctx, status, "LookupRids");
 
-       return ret;     
+       return ret;
 }
 
 /*
   try blasting the server with a bunch of sync requests
 */
-static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx, 
+static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
                                       struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4595,19 +5107,20 @@ static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_con
        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", 
+                       torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
                               i, nt_errstr(status));
                        return false;
                }
        }
-       
+
        torture_comment(tctx, "%d async requests OK\n", i);
 
        return true;
 }
 
-static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                                 struct policy_handle *handle)
+static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
+                                     struct torture_context *tctx,
+                                     struct policy_handle *handle)
 {
        NTSTATUS status;
        struct samr_EnumDomainGroups r;
@@ -4617,7 +5130,7 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        int i;
        bool ret = true;
 
-       printf("Testing EnumDomainGroups\n");
+       torture_comment(tctx, "Testing EnumDomainGroups\n");
 
        r.in.domain_handle = handle;
        r.in.resume_handle = &resume_handle;
@@ -4626,18 +5139,18 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.out.num_entries = &num_entries;
        r.out.sam = &sam;
 
-       status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
+       status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
                return false;
        }
-       
+
        if (!sam) {
                return false;
        }
 
        for (i=0;i<sam->count;i++) {
-               if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
+               if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
                        ret = false;
                }
        }
@@ -4645,8 +5158,9 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
-static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                                  struct policy_handle *handle)
+static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
+                                      struct torture_context *tctx,
+                                      struct policy_handle *handle)
 {
        NTSTATUS status;
        struct samr_EnumDomainAliases r;
@@ -4656,7 +5170,7 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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;
@@ -4665,26 +5179,27 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.out.num_entries = &num_entries;
        r.out.resume_handle = &resume_handle;
 
-       status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
+       status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
                return false;
        }
-       
+
        if (!sam) {
                return false;
        }
 
        for (i=0;i<sam->count;i++) {
-               if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
+               if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
                        ret = false;
                }
        }
 
-       return ret;     
+       return ret;
 }
 
-static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
+                                           struct torture_context *tctx,
                                            struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4697,7 +5212,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m
        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);
 
@@ -4706,31 +5221,32 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m
                r.in.name = &name;
                r.out.idx = &idx;
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
+               status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
 
-               if (ok_lvl[i] && 
+               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", 
+                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
 
                init_lsa_String(&name, "zzzzzzzz");
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
-               
+               status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
+
                if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
-                       printf("GetDisplayEnumerationIndex level %u failed - %s\n", 
+                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
        }
-       
-       return ret;     
+
+       return ret;
 }
 
-static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
+                                            struct torture_context *tctx,
                                             struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4743,7 +5259,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *
        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);
 
@@ -4752,46 +5268,47 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *
                r.in.name = &name;
                r.out.idx = &idx;
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
-               if (ok_lvl[i] && 
-                   !NT_STATUS_IS_OK(status) && 
+               status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
+               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", 
+                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
 
                init_lsa_String(&name, "zzzzzzzz");
 
-               status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
+               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", 
+                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
        }
-       
-       return ret;     
+
+       return ret;
 }
 
 #define STRING_EQUAL_QUERY(s1, s2, user)                                       \
        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, TALLOC_CTX *mem_ctx, 
+static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
+                                      struct torture_context *tctx,
                                       struct samr_QueryDisplayInfo *querydisplayinfo,
-                                      bool *seen_testuser) 
+                                      bool *seen_testuser)
 {
        struct samr_OpenUser r;
        struct samr_QueryUserInfo q;
@@ -4822,28 +5339,28 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
                        /* Not interested in validating just the account name */
                        return true;
                }
-                       
+
                r.out.user_handle = &user_handle;
-               
+
                switch (querydisplayinfo->in.level) {
                case 1:
                case 2:
-                       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+                       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_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
                                return false;
                        }
                }
-               
+
                q.in.user_handle = &user_handle;
                q.in.level = 21;
                q.out.info = &info;
-               status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+               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_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
                        return false;
                }
-               
+
                switch (querydisplayinfo->in.level) {
                case 1:
                        if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
@@ -4859,7 +5376,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
                                        info->info21.rid, info->info21.account_name);
                        INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
                                        info->info21.acct_flags, info->info21.account_name);
-                       
+
                        break;
                case 2:
                        STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
@@ -4870,31 +5387,32 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
                                        info->info21.rid, info->info21.account_name);
                        INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
                                        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);
                                return false;
                        }
-                       
+
                        break;
                }
-               
-               if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+
+               if (!test_samr_handle_Close(p, tctx, &user_handle)) {
                        return false;
                }
        }
        return ret;
 }
 
-static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
+                                 struct torture_context *tctx,
                                  struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -4911,7 +5429,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
 
        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;
@@ -4923,22 +5441,22 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        r.out.total_size = &total_size;
                        r.out.returned_size = &returned_size;
                        r.out.info = &disp_info;
-                       
-                       status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
+
+                       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", 
+                               torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
                                       levels[i], nt_errstr(status));
                                ret = false;
                        }
                        switch (r.in.level) {
                        case 1:
-                               if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
+                               if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
                                        ret = false;
                                }
                                r.in.start_idx += r.out.info->info1.count;
                                break;
                        case 2:
-                               if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
+                               if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
                                        ret = false;
                                }
                                r.in.start_idx += r.out.info->info2.count;
@@ -4959,9 +5477,9 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                dom_info.out.info = &info;
 
                /* Check number of users returned is correct */
-               status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
+               status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(status));
                                ret = false;
                                break;
@@ -4970,40 +5488,41 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                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",
+                               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, mem_ctx, 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(p, 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, mem_ctx, &user_handle);
+                                       test_samr_handle_Close(p, 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",
+                               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;
                }
 
        }
-       
-       return ret;     
+
+       return ret;
 }
 
-static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                                 struct policy_handle *handle)
+static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *handle)
 {
        NTSTATUS status;
        struct samr_QueryDisplayInfo2 r;
@@ -5015,7 +5534,7 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        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];
@@ -5026,15 +5545,15 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                r.out.returned_size = &returned_size;
                r.out.info = &info;
 
-               status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
+               status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo2 level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
        }
-       
-       return ret;     
+
+       return ret;
 }
 
 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
@@ -5063,17 +5582,18 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context
 
                status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo3 level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
                               levels[i], nt_errstr(status));
                        ret = false;
                }
        }
-       
-       return ret;     
+
+       return ret;
 }
 
 
-static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
+                                          struct torture_context *tctx,
                                           struct policy_handle *handle)
 {
        NTSTATUS status;
@@ -5083,7 +5603,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
        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;
@@ -5095,10 +5615,10 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
        r.out.info = &info;
 
        do {
-               status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
+               status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
                if (NT_STATUS_IS_OK(status) && *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;
@@ -5106,7 +5626,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
                }
                if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
                    !NT_STATUS_IS_OK(status)) {
-                       printf("QueryDisplayInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(status));
                        ret = false;
                        break;
@@ -5115,8 +5635,8 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me
        } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
                  NT_STATUS_IS_OK(status)) &&
                 *r.out.returned_size != 0);
-       
-       return ret;     
+
+       return ret;
 }
 
 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
@@ -5130,19 +5650,19 @@ 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;
-       const char *domain_comment = talloc_asprintf(tctx, 
-                                 "Tortured by Samba4 RPC-SAMR: %s", 
+       const char *domain_comment = talloc_asprintf(tctx,
+                                 "Tortured by Samba4 RPC-SAMR: %s",
                                  timestring(tctx, time(NULL)));
 
        s.in.domain_handle = handle;
        s.in.level = 4;
        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", 
-                      r.in.level, nt_errstr(status));
+               torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
+                      s.in.level, nt_errstr(status));
                return false;
        }
 
@@ -5155,7 +5675,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
 
                status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(status));
                        ret = false;
                        continue;
@@ -5164,40 +5684,46 @@ 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",
+                                       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;
                }
@@ -5211,14 +5737,14 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
                status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
                if (set_ok[i]) {
                        if (!NT_STATUS_IS_OK(status)) {
-                               printf("SetDomainInfo level %u failed - %s\n", 
+                               torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
                                       r.in.level, nt_errstr(status));
                                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", 
+                               torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
                                       r.in.level, nt_errstr(status));
                                ret = false;
                                continue;
@@ -5227,14 +5753,14 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *
 
                status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(status));
                        ret = false;
                        continue;
                }
        }
 
-       return ret;     
+       return ret;
 }
 
 
@@ -5249,7 +5775,7 @@ 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];
@@ -5257,14 +5783,14 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context
 
                status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("QueryDomainInfo2 level %u failed - %s\n", 
+                       torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
                               r.in.level, nt_errstr(status));
                        ret = false;
                        continue;
                }
        }
 
-       return true;    
+       return true;
 }
 
 /* Test whether querydispinfo level 5 and enumdomgroups return the same
@@ -5312,7 +5838,7 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
        }
 
        torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
-       
+
        torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
 
        q2.in.domain_handle = handle;
@@ -5347,7 +5873,7 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
                        }
 
                        if (!found) {
-                               printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
+                               torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
                                       name);
                                ret = false;
                        }
@@ -5356,14 +5882,14 @@ 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;
        }
 
        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;
                }
@@ -5401,7 +5927,7 @@ static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct tortur
        r.in.domain_handle = domain_handle;
 
        status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
-       torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
+       torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
 
        return ret;
 }
@@ -5419,21 +5945,21 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        for (i=0;i<ARRAY_SIZE(rids);i++) {
                torture_comment(tctx, "Testing RidToSid\n");
-               
+
                calc_sid = dom_sid_dup(tctx, domain_sid);
                r.in.domain_handle = domain_handle;
                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_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
                        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;
@@ -5466,7 +5992,7 @@ 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_pipe *p, struct torture_context *tctx,
                                struct policy_handle *domain_handle,
                                struct policy_handle *group_handle)
 {
@@ -5477,6 +6003,8 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
        struct samr_RidTypeArray *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);
        torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
@@ -5485,7 +6013,7 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
        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;
@@ -5499,8 +6027,9 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
        status = dcerpc_samr_AddGroupMember(p, tctx, &r);
        torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
 
-       if (torture_setting_bool(tctx, "samba4", false)) {
-               torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
+       if (torture_setting_bool(tctx, "samba4", false) ||
+           torture_setting_bool(tctx, "samba3", false)) {
+               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 */
@@ -5518,10 +6047,34 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
 
        status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
        torture_assert_ntstatus_ok(tctx, status, "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");
 
        status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
        torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
 
+       rids = NULL;
+       found_member = false;
+
+       status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
+       torture_assert_ntstatus_ok(tctx, status, "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");
+
        status = dcerpc_samr_AddGroupMember(p, tctx, &r);
        torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
 
@@ -5529,11 +6082,13 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t
 }
 
 
-static bool test_CreateDomainGroup(struct dcerpc_pipe *p, 
-                                                                  struct torture_context *tctx, 
-                                  struct policy_handle *domain_handle, 
+static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
+                                  struct torture_context *tctx,
+                                  struct policy_handle *domain_handle,
+                                  const char *group_name,
                                   struct policy_handle *group_handle,
-                                  struct dom_sid *domain_sid)
+                                  struct dom_sid *domain_sid,
+                                  bool test_group)
 {
        NTSTATUS status;
        struct samr_CreateDomainGroup r;
@@ -5541,7 +6096,7 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
        struct lsa_String name;
        bool ret = true;
 
-       init_lsa_String(&name, TEST_GROUPNAME);
+       init_lsa_String(&name, group_name);
 
        r.in.domain_handle = domain_handle;
        r.in.name = &name;
@@ -5549,7 +6104,7 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
        r.out.group_handle = group_handle;
        r.out.rid = &rid;
 
-       printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
+       torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
 
        status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
 
@@ -5558,7 +6113,7 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
                        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, 
+                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
                               nt_errstr(status));
                        return false;
                }
@@ -5566,7 +6121,7 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
 
        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, 
+                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
                               nt_errstr(status));
                        return false;
                }
@@ -5574,8 +6129,8 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
        }
        if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
                if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
-                       
-                       printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string, 
+
+                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
                               nt_errstr(status));
                        return false;
                }
@@ -5583,8 +6138,12 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
        }
        torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
 
+       if (!test_group) {
+               return ret;
+       }
+
        if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
-               printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
                ret = false;
        }
 
@@ -5599,7 +6158,7 @@ static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
 /*
   its not totally clear what this does. It seems to accept any sid you like.
 */
-static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p, 
+static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
                                               struct torture_context *tctx,
                                               struct policy_handle *domain_handle)
 {
@@ -5615,15 +6174,345 @@ static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
        return true;
 }
 
+static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
+                                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 {
+               status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
+               if (NT_STATUS_IS_ERR(status)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               "failed to enumerate users");
+               }
+
+               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_pipe *p,
+                                 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 {
+               status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
+               if (NT_STATUS_IS_ERR(status)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               "failed to enumerate groups");
+               }
+
+               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_pipe *p,
+                                  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 {
+               status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
+               if (NT_STATUS_IS_ERR(status)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               "failed to enumerate aliases");
+               }
+
+               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_pipe *p,
+                                       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;
+
+               status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
+               if (NT_STATUS_IS_ERR(status)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               "failed to query displayinfo");
+               }
+
+               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;
+       bool ret = true;
+       NTSTATUS status;
+       uint32_t i;
+
+       struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
+
+       /* query */
+
+       {
+               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_QueryDomainInfo2(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status,
+                       "failed to query domain info");
+
+               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;
+               }
+       }
+
+       /* create */
+
+       for (i=0; i < num_total; i++) {
+
+               const char *name = NULL;
+
+               switch (ctx->choice) {
+               case TORTURE_SAMR_MANY_ACCOUNTS:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
+                       ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
+                       break;
+               case TORTURE_SAMR_MANY_GROUPS:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
+                       ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
+                       break;
+               case TORTURE_SAMR_MANY_ALIASES:
+                       name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
+                       ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
+                       break;
+               default:
+                       return false;
+               }
+               if (!policy_handle_empty(&handles[i])) {
+                       num_created++;
+               }
+       }
+
+       /* enum */
+
+       switch (ctx->choice) {
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+               ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
+               break;
+       case TORTURE_SAMR_MANY_GROUPS:
+               ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
+               break;
+       case TORTURE_SAMR_MANY_ALIASES:
+               ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
+               break;
+       default:
+               return false;
+       }
+
+       /* dispinfo */
+
+       switch (ctx->choice) {
+       case TORTURE_SAMR_MANY_ACCOUNTS:
+               ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
+               break;
+       case TORTURE_SAMR_MANY_GROUPS:
+               ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
+               break;
+       case TORTURE_SAMR_MANY_ALIASES:
+               /* no aliases in dispinfo */
+               break;
+       default:
+               return false;
+       }
+
+       /* close or delete */
+
+       for (i=0; i < num_total; i++) {
+
+               if (policy_handle_empty(&handles[i])) {
+                       continue;
+               }
+
+               if (torture_setting_bool(tctx, "samba3", false)) {
+                       ret &= test_samr_handle_Close(p, tctx, &handles[i]);
+               } else {
+                       switch (ctx->choice) {
+                       case TORTURE_SAMR_MANY_ACCOUNTS:
+                               ret &= test_DeleteUser(p, tctx, &handles[i]);
+                               break;
+                       case TORTURE_SAMR_MANY_GROUPS:
+                               ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
+                               break;
+                       case TORTURE_SAMR_MANY_ALIASES:
+                               ret &= test_DeleteAlias(p, tctx, &handles[i]);
+                               break;
+                       default:
+                               return false;
+                       }
+               }
+       }
+
+       talloc_free(handles);
+
+       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 ret;
+}
 
 static bool test_Connect(struct dcerpc_pipe *p, 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)
+static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
+                           struct torture_samr_context *ctx, struct dom_sid *sid)
 {
        NTSTATUS status;
        struct samr_OpenDomain r;
@@ -5640,7 +6529,7 @@ 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;
@@ -5650,47 +6539,69 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        /* 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(p, tctx, &ctx->handle), "Failed to close SAMR handle");
 
-       switch (which_ops) {
-       case TORTURE_SAMR_USER_ATTRIBUTES:
+       switch (ctx->choice) {
        case TORTURE_SAMR_PASSWORDS:
-               ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
-               ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
+       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, ctx->choice, NULL);
+               }
+               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);
                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:
                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, &user_handle, sid, which_ops, machine_credentials);
+               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 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, &user_handle, sid, which_ops, NULL);
+               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(p, tctx, &domain_handle);
                ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
-               ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
-               ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
+               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_GetAliasMembership(p, 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_EnumDomainUsers_all(p, 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_EnumDomainGroups_all(p, tctx, &domain_handle);
+               ret &= test_EnumDomainAliases_all(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);
-               
+
                if (torture_setting_bool(tctx, "samba4", false)) {
                        torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
                } else {
@@ -5722,22 +6633,20 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
                ret = false;
        }
 
-       ret &= test_samr_handle_Close(p, tctx, &domain_handle);
+       torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
 
+       torture_assert(tctx, test_Connect(p, 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;
@@ -5749,7 +6658,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
        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;
@@ -5762,7 +6671,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
        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");
 
-       r.in.connect_handle = handle;
+       r.in.connect_handle = &ctx->handle;
 
        init_lsa_String(&n1, domain);
        r.in.domain_name = &n1;
@@ -5774,8 +6683,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct
                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;
        }
 
@@ -5784,8 +6692,7 @@ 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;
@@ -5795,7 +6702,7 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx
        int i;
        bool ret = true;
 
-       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;
@@ -5810,9 +6717,8 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx
        }
 
        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;
                }
        }
@@ -5880,7 +6786,7 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = dcerpc_samr_Connect3(p, tctx, &r3);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect3 failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                if (got_handle) {
@@ -5899,7 +6805,7 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = dcerpc_samr_Connect4(p, tctx, &r4);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect4 failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                if (got_handle) {
@@ -5924,7 +6830,7 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        status = dcerpc_samr_Connect5(p, tctx, &r5);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("Connect5 failed - %s\n", nt_errstr(status));
+               torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
                ret = false;
        } else {
                if (got_handle) {
@@ -5938,29 +6844,66 @@ 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;
+
+       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(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
+               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;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_OTHER;
 
-       ret &= test_QuerySecurity(p, torture, &handle);
+       ret &= test_Connect(p, torture, &ctx->handle);
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
+       if (!torture_setting_bool(torture, "samba3", false)) {
+               ret &= test_QuerySecurity(p, torture, &ctx->handle);
+       }
+
+       ret &= test_EnumDomains(p, torture, ctx);
 
-       ret &= test_SetDsrmPassword(p, torture, &handle);
+       ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
 
-       ret &= test_Shutdown(p, torture, &handle);
+       ret &= test_Shutdown(p, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_samr_handle_Close(p, torture, &ctx->handle);
 
        return ret;
 }
@@ -5971,24 +6914,30 @@ 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;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx = talloc_zero(torture, struct torture_samr_context);
 
-       ret &= test_QuerySecurity(p, torture, &handle);
+       ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
+       ret &= test_Connect(p, torture, &ctx->handle);
 
-       ret &= test_SetDsrmPassword(p, torture, &handle);
+       if (!torture_setting_bool(torture, "samba3", false)) {
+               ret &= test_QuerySecurity(p, torture, &ctx->handle);
+       }
 
-       ret &= test_Shutdown(p, torture, &handle);
+       ret &= test_EnumDomains(p, torture, ctx);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
+
+       ret &= test_Shutdown(p, torture, &ctx->handle);
+
+       ret &= test_samr_handle_Close(p, torture, &ctx->handle);
 
        return ret;
 }
@@ -5999,18 +6948,24 @@ 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;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_PASSWORDS;
 
-       ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
+       ret &= test_Connect(p, torture, &ctx->handle);
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, torture, &ctx->handle);
+
+       ret &= test_samr_ValidatePassword(p, torture);
 
        return ret;
 }
@@ -6022,20 +6977,23 @@ 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;
 
        status = torture_rpc_connection(torture, &p, &ndr_table_samr);
        if (!NT_STATUS_IS_OK(status)) {
                return false;
        }
 
-       ret &= test_Connect(p, torture, &handle);
+       ctx = talloc_zero(torture, struct torture_samr_context);
 
-       ret &= test_EnumDomains(p, torture, &handle,
-                               TORTURE_SAMR_PASSWORDS_PWDLASTSET,
-                               machine_credentials);
+       ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
+       ctx->machine_credentials = machine_credentials;
 
-       ret &= test_samr_handle_Close(p, torture, &handle);
+       ret &= test_Connect(p, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, torture, &ctx->handle);
 
        return ret;
 }
@@ -6045,7 +7003,7 @@ 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_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);
 
@@ -6054,3 +7012,151 @@ struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
 
        return suite;
 }
+
+static bool torture_rpc_samr_users_privileges_delete_user(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;
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       ctx = talloc_zero(torture, struct torture_samr_context);
+
+       ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
+       ctx->machine_credentials = machine_credentials;
+
+       ret &= test_Connect(p, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, 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_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, "delete_privileged_user",
+                                        torture_rpc_samr_users_privileges_delete_user);
+
+       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);
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       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(p, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, 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);
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       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(p, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, 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);
+
+       status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       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(p, torture, &ctx->handle);
+
+       ret &= test_EnumDomains(p, torture, ctx);
+
+       ret &= test_samr_handle_Close(p, 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;
+}