lib/util: remove extra safe_string.h file
[samba.git] / source4 / torture / rpc / samr.c
index f7d6a93bb39f62bdc2e6cc21d79a43ea12c61315..5863a6d1ee6da45933f3f75c9789209c73ada356 100644 (file)
@@ -4,6 +4,7 @@
 
    Copyright (C) Andrew Tridgell 2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
+   Copyright (C) Jelmer Vernooij 2005-2007
    Copyright (C) Guenther Deschner 2008-2010
 
    This program is free software; you can redistribute it and/or modify
 #include "torture/torture.h"
 #include <tevent.h>
 #include "system/time.h"
+#include "system/network.h"
 #include "librpc/gen_ndr/lsa.h"
 #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 "lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
 #include "libcli/security/security.h"
 #include "torture/rpc/torture_rpc.h"
 #include "param/param.h"
 #include "auth/gensec/gensec.h"
-#include "auth/gensec/schannel.h"
 #include "auth/gensec/gensec_proto.h"
 #include "../libcli/auth/schannel.h"
+#include "torture/util.h"
+#include "source4/librpc/rpc/dcerpc.h"
+#include "source3/rpc_client/init_samr.h"
+#include "lib/crypto/gnutls_helpers.h"
 
-#include <unistd.h>
+#undef strcasecmp
 
 #define TEST_ACCOUNT_NAME "samrtorturetest"
 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
@@ -48,6 +53,9 @@
 #define TEST_MACHINENAME "samrtestmach$"
 #define TEST_DOMAINNAME "samrtestdom$"
 
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
 enum torture_samr_choice {
        TORTURE_SAMR_PASSWORDS,
        TORTURE_SAMR_PASSWORDS_PWDLASTSET,
@@ -244,35 +252,20 @@ static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_con
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
                        #call " failed"); \
                if (!NT_STATUS_IS_OK(r.out.result)) { \
-                       torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
+                       torture_result(tctx, TORTURE_FAIL, #call " level %u failed - %s (%s)\n", \
                               r.in.level, nt_errstr(r.out.result), __location__); \
                        ret = false; \
                        break; \
                }
 
 #define STRING_EQUAL(s1, s2, field) \
-               if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
-                       torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
-                              #field, s2, __location__); \
-                       ret = false; \
-                       break; \
-               }
+       torture_assert_str_equal(tctx, s1, s2, "Failed to set " #field)
 
 #define MEM_EQUAL(s1, s2, length, field) \
-               if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
-                       torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
-                              #field, (const char *)s2, __location__); \
-                       ret = false; \
-                       break; \
-               }
+       torture_assert_mem_equal(tctx, s1, s2, length, "Failed to set " #field)
 
 #define INT_EQUAL(i1, i2, field) \
-               if (i1 != i2) { \
-                       torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
-                              #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
-                       ret = false; \
-                       break; \
-               }
+       torture_assert_int_equal(tctx, i1, i2, "Failed to set " #field)
 
 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
                torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
@@ -364,19 +357,19 @@ static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_con
                           SAMR_FIELD_COMMENT);
 
        test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
-       TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
+       TEST_USERINFO_STRING(7, account_name,  1, account_name, test_account_name, 0);
        test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
-       TEST_USERINFO_STRING(7, account_name,  3, account_name, base_account_name, 0);
+       TEST_USERINFO_STRING(7, account_name,  3, account_name, test_account_name, 0);
        test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
-       TEST_USERINFO_STRING(7, account_name,  5, account_name, base_account_name, 0);
+       TEST_USERINFO_STRING(7, account_name,  5, account_name, test_account_name, 0);
        test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
-       TEST_USERINFO_STRING(7, account_name,  6, account_name, base_account_name, 0);
+       TEST_USERINFO_STRING(7, account_name,  6, account_name, test_account_name, 0);
        test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
-       TEST_USERINFO_STRING(7, account_name,  7, account_name, base_account_name, 0);
+       TEST_USERINFO_STRING(7, account_name,  7, account_name, test_account_name, 0);
        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_USERINFO_STRING(7, account_name, 21, account_name, test_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, test_account_name,
                           SAMR_FIELD_ACCOUNT_NAME);
 
        TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
@@ -538,26 +531,26 @@ static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_con
 
        /* 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),
-                             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),
-                             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),
-                             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),
-                             0);
+               /* 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),
+                                     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),
+                                     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),
+                                     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),
+                                     0);
        }
        TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
                              (base_acct_flags | ACB_DISABLED),
@@ -649,24 +642,31 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
        s.in.info = &u;
        s.in.level = 24;
 
-       encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
        u.info24.password_expired = 0;
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+       status = init_samr_CryptPassword(newpass,
+                                         &session_key,
+                                         &u.info24.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
 
        torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -709,48 +709,64 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
 
        u.info23.info.fields_present = fields_present;
 
-       encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
-
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
+       status = init_samr_CryptPassword(newpass,
+                                        &session_key,
+                                        &u.info23.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
 
        torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
                *password = newpass;
        }
 
-       encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
-
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
        /* This should break the key nicely */
-       session_key.length--;
-       arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
+       session_key.data[0]++;
+
+       status = init_samr_CryptPassword(newpass,
+                                        &session_key,
+                                        &u.info23.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
+
+       /* Reset the session key */
+       session_key.data[0]--;
 
        torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
@@ -768,14 +784,12 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
        union samr_UserInfo u;
        bool ret = true;
        DATA_BLOB session_key;
-       DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
-       uint8_t confounder[16];
        char *newpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
-       struct MD5Context ctx;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
+
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
@@ -794,32 +808,31 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
        s.in.info = &u;
        s.in.level = 26;
 
-       encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
        u.info26.password_expired = 0;
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       generate_random_buffer((uint8_t *)confounder, 16);
-
-       MD5Init(&ctx);
-       MD5Update(&ctx, confounder, 16);
-       MD5Update(&ctx, session_key.data, session_key.length);
-       MD5Final(confounded_session_key.data, &ctx);
-
-       arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
-       memcpy(&u.info26.password.data[516], confounder, 16);
+       status = init_samr_CryptPasswordEx(newpass,
+                                          &session_key,
+                                          &u.info26.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPasswordEx failed");
 
        torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -827,17 +840,27 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
        }
 
        /* This should break the key nicely */
-       confounded_session_key.data[0]++;
+       session_key.data[0]++;
+
+       status = init_samr_CryptPasswordEx(newpass,
+                                          &session_key,
+                                          &u.info26.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPasswordEx failed");
 
-       arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
-       memcpy(&u.info26.password.data[516], confounder, 16);
+       /* Reset the key */
+       session_key.data[0]--;
 
        torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -856,14 +879,12 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
        union samr_UserInfo u;
        bool ret = true;
        DATA_BLOB session_key;
-       DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
-       struct MD5Context ctx;
-       uint8_t confounder[16];
        char *newpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
+
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
@@ -882,31 +903,29 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
 
        u.info25.info.fields_present = fields_present;
 
-       encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
-
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       generate_random_buffer((uint8_t *)confounder, 16);
-
-       MD5Init(&ctx);
-       MD5Update(&ctx, confounder, 16);
-       MD5Update(&ctx, session_key.data, session_key.length);
-       MD5Final(confounded_session_key.data, &ctx);
-
-       arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
-       memcpy(&u.info25.password.data[516], confounder, 16);
+       status = init_samr_CryptPasswordEx(newpass,
+                                          &session_key,
+                                          &u.info25.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPasswordEx failed");
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -914,17 +933,27 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
        }
 
        /* This should break the key nicely */
-       confounded_session_key.data[0]++;
+       session_key.data[0]++;
+
+       status = init_samr_CryptPasswordEx(newpass,
+                                          &session_key,
+                                          &u.info25.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPasswordEx failed");
 
-       arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
-       memcpy(&u.info25.password.data[516], confounder, 16);
+       /* Reset the key */
+       session_key.data[0]--;
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       newpass, nt_errstr(s.out.result));
        if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
@@ -971,7 +1000,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)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -980,14 +1009,14 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
                DATA_BLOB in,out;
                in = data_blob_const(nt_hash, 16);
                out = data_blob_talloc_zero(tctx, 16);
-               sess_crypt_blob(&out, &in, &session_key, true);
+               sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                memcpy(u.info18.nt_pwd.hash, out.data, out.length);
        }
        {
                DATA_BLOB in,out;
                in = data_blob_const(lm_hash, 16);
                out = data_blob_talloc_zero(tctx, 16);
-               sess_crypt_blob(&out, &in, &session_key, true);
+               sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                memcpy(u.info18.lm_pwd.hash, out.data, out.length);
        }
 
@@ -996,7 +1025,7 @@ static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *t
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -1059,7 +1088,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)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
@@ -1069,7 +1098,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                in = data_blob_const(u.info21.lm_owf_password.array,
                                     u.info21.lm_owf_password.length);
                out = data_blob_talloc_zero(tctx, 16);
-               sess_crypt_blob(&out, &in, &session_key, true);
+               sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                u.info21.lm_owf_password.array = (uint16_t *)out.data;
        }
 
@@ -1078,7 +1107,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                in = data_blob_const(u.info21.nt_owf_password.array,
                                     u.info21.nt_owf_password.length);
                out = data_blob_talloc_zero(tctx, 16);
-               sess_crypt_blob(&out, &in, &session_key, true);
+               sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                u.info21.nt_owf_password.array = (uint16_t *)out.data;
        }
 
@@ -1087,7 +1116,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        } else {
@@ -1102,7 +1131,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                        "SetUserInfo failed");
                if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
-                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
                               s.in.level, nt_errstr(s.out.result));
                        ret = false;
                }
@@ -1115,7 +1144,7 @@ static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *t
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                        "SetUserInfo failed");
                if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
-                       torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
                               s.in.level, nt_errstr(s.out.result));
                        ret = false;
                }
@@ -1140,9 +1169,6 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        union samr_UserInfo u;
        bool ret = true;
        DATA_BLOB session_key;
-       DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
-       struct MD5Context ctx;
-       uint8_t confounder[16];
        char *newpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
@@ -1218,59 +1244,44 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
                u.info23.info.password_expired = password_expired;
                u.info23.info.comment.string = comment;
 
-               encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
-
                break;
        case 24:
                u.info24.password_expired = password_expired;
 
-               encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
-
                break;
        case 25:
                u.info25.info.fields_present = fields_present;
                u.info25.info.password_expired = password_expired;
                u.info25.info.comment.string = comment;
 
-               encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
-
                break;
        case 26:
                u.info26.password_expired = password_expired;
 
-               encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
-
                break;
        }
 
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       generate_random_buffer((uint8_t *)confounder, 16);
-
-       MD5Init(&ctx);
-       MD5Update(&ctx, confounder, 16);
-       MD5Update(&ctx, session_key.data, session_key.length);
-       MD5Final(confounded_session_key.data, &ctx);
-
        switch (level) {
        case 18:
                {
                        DATA_BLOB in,out;
                        in = data_blob_const(u.info18.nt_pwd.hash, 16);
                        out = data_blob_talloc_zero(tctx, 16);
-                       sess_crypt_blob(&out, &in, &session_key, true);
+                       sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                        memcpy(u.info18.nt_pwd.hash, out.data, out.length);
                }
                {
                        DATA_BLOB in,out;
                        in = data_blob_const(u.info18.lm_pwd.hash, 16);
                        out = data_blob_talloc_zero(tctx, 16);
-                       sess_crypt_blob(&out, &in, &session_key, true);
+                       sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                        memcpy(u.info18.lm_pwd.hash, out.data, out.length);
                }
 
@@ -1281,7 +1292,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
                        in = data_blob_const(u.info21.lm_owf_password.array,
                                             u.info21.lm_owf_password.length);
                        out = data_blob_talloc_zero(tctx, 16);
-                       sess_crypt_blob(&out, &in, &session_key, true);
+                       sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                        u.info21.lm_owf_password.array = (uint16_t *)out.data;
                }
                if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
@@ -1289,33 +1300,57 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
                        in = data_blob_const(u.info21.nt_owf_password.array,
                                             u.info21.nt_owf_password.length);
                        out = data_blob_talloc_zero(tctx, 16);
-                       sess_crypt_blob(&out, &in, &session_key, true);
+                       sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
                        u.info21.nt_owf_password.array = (uint16_t *)out.data;
                }
                break;
        case 23:
-               arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
+               status = init_samr_CryptPassword(newpass,
+                                                &session_key,
+                                                &u.info23.password);
+               torture_assert_ntstatus_ok(tctx,
+                                          status,
+                                          "init_samr_CryptPassword failed");
                break;
        case 24:
-               arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+               status = init_samr_CryptPassword(newpass,
+                                                &session_key,
+                                                &u.info24.password);
+               torture_assert_ntstatus_ok(tctx,
+                                          status,
+                                          "init_samr_CryptPassword failed");
                break;
        case 25:
-               arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
-               memcpy(&u.info25.password.data[516], confounder, 16);
+               status = init_samr_CryptPasswordEx(newpass,
+                                                  &session_key,
+                                                  &u.info25.password);
+               torture_assert_ntstatus_ok(tctx,
+                                          status,
+                                          "init_samr_CryptPasswordEx failed");
                break;
        case 26:
-               arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
-               memcpy(&u.info26.password.data[516], confounder, 16);
+               status = init_samr_CryptPasswordEx(newpass,
+                                                  &session_key,
+                                                  &u.info26.password);
+               torture_assert_ntstatus_ok(tctx,
+                                          status,
+                                          "init_samr_CryptPasswordEx failed");
                break;
        }
 
        if (use_setinfo2) {
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
                        "SetUserInfo2 failed");
-               status = s2.out.result;
+               torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                               __location__, __FUNCTION__,
+                               newpass, nt_errstr(s2.out.result));
+                       status = s2.out.result;
        } else {
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                        "SetUserInfo failed");
+               torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
+                               __location__, __FUNCTION__,
+                               newpass, nt_errstr(s.out.result));
                status = s.out.result;
        }
 
@@ -1343,7 +1378,7 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo%s level %u failed - %s\n",
                       use_setinfo2 ? "2":"", level, nt_errstr(status));
                ret = false;
        } else {
@@ -1384,7 +1419,7 @@ static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
                        "SetAliasInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "SetAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -1396,7 +1431,7 @@ static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
                        "QueryAliasInfo failed");
                if (!NT_STATUS_IS_OK(q.out.result)) {
-                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(q.out.result));
                        ret = false;
                }
@@ -1518,7 +1553,7 @@ static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
                return status;
        }
        if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
-               torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
+               torture_result(tctx, TORTURE_FAIL, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
                if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1531,7 +1566,7 @@ static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
                return status;
        }
        if (!NT_STATUS_IS_OK(n.out.result)) {
-               torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
+               torture_result(tctx, TORTURE_FAIL, "LookupNames[0] failed - %s\n", nt_errstr(status));
                return n.out.result;
        }
 
@@ -1542,7 +1577,7 @@ static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
                return status;
        }
        if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
-               torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
+               torture_result(tctx, TORTURE_FAIL, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
                if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1557,7 +1592,7 @@ static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
                return status;
        }
        if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
-               torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
+               torture_result(tctx, TORTURE_FAIL, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
                if (NT_STATUS_IS_OK(n.out.result)) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -1590,7 +1625,7 @@ static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
                return status;
        }
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
        }
 
        return r.out.result;
@@ -1648,7 +1683,7 @@ static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1715,8 +1750,8 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        r.in.user_handle = &user_handle;
        r.in.lm_present = 1;
-       /* Break the LM hash */
-       hash1.hash[0]++;
+       /* Break the NT hash */
+       hash3.hash[0]++;
        r.in.old_lm_crypted = &hash1;
        r.in.new_lm_crypted = &hash2;
        r.in.nt_present = 1;
@@ -1729,18 +1764,29 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
-       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
-               "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
-       /* Unbreak the LM hash */
-       hash1.hash[0]--;
+       /* Do not proceed if this call has been removed */
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
+               torture_skip(tctx, "ValidatePassword not supported by server\n");
+       }
+
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
+                       "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
+       }
+
+       /* Unbreak the NT hash */
+       hash3.hash[0]--;
 
        r.in.user_handle = &user_handle;
        r.in.lm_present = 1;
        r.in.old_lm_crypted = &hash1;
        r.in.new_lm_crypted = &hash2;
-       /* Break the NT hash */
-       hash3.hash[0]--;
+       /* Break the LM hash */
+       hash1.hash[0]--;
        r.in.nt_present = 1;
        r.in.old_nt_crypted = &hash3;
        r.in.new_nt_crypted = &hash4;
@@ -1751,8 +1797,13 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
-       torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
-               "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
+                       "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
+       }
 
        /* Unbreak the NT hash */
        hash3.hash[0]--;
@@ -1773,8 +1824,13 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
-       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
+           !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
+       {
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1797,8 +1853,13 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
-       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
+       if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
+           !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
+       {
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1828,11 +1889,14 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (NT_STATUS_IS_OK(r.out.result)) {
                changed = true;
                *password = newpass;
        } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1867,11 +1931,14 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (NT_STATUS_IS_OK(r.out.result)) {
                changed = true;
                *password = newpass;
        } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -1906,10 +1973,13 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                "ChangePasswordUser failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
        } else  if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                changed = true;
@@ -1931,10 +2001,13 @@ static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
        if (changed) {
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
                        "ChangePasswordUser failed");
+               torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                               __location__, __FUNCTION__,
+                               oldpass, newpass, nt_errstr(r.out.result));
                if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                        torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
                } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-                       torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
                        ret = false;
                }
        }
@@ -1962,6 +2035,11 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
        char *newpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_lm_hash[16], new_lm_hash[16];
+       gnutls_cipher_hd_t cipher_hnd = NULL;
+       gnutls_datum_t session_key = {
+               .data = old_lm_hash,
+               .size = 16
+       };
 
        struct samr_GetDomPwInfo dom_pw_info;
        struct samr_PwInfo info;
@@ -1995,7 +2073,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
        E_deshash(newpass, new_lm_hash);
 
        encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
-       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &session_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
+       gnutls_cipher_deinit(cipher_hnd);
        E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 
        r.in.server = &server;
@@ -2008,10 +2092,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2019,7 +2106,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
        encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
        /* Break the old password */
        old_lm_hash[0]++;
-       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &session_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
+       gnutls_cipher_deinit(cipher_hnd);
        /* unbreak it for the next operation */
        old_lm_hash[0]--;
        E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
@@ -2031,16 +2123,24 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrypted password - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
 
        encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
-       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &session_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
+       gnutls_cipher_deinit(cipher_hnd);
 
        r.in.server = &server;
        r.in.account = &account;
@@ -2049,10 +2149,13 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2063,9 +2166,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2078,9 +2184,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2093,9 +2202,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2104,7 +2216,12 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
        E_deshash(newpass, new_lm_hash);
 
        encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
-       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &session_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
+       gnutls_cipher_deinit(cipher_hnd);
        E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 
        r.in.server = &server;
@@ -2114,11 +2231,14 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
                "OemChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
        } else if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -2142,11 +2262,19 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
        struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_nt_hash[16], new_nt_hash[16];
        uint8_t old_lm_hash[16], new_lm_hash[16];
-
+       DATA_BLOB old_nt_hash_blob
+               = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
        struct samr_GetDomPwInfo dom_pw_info;
        struct samr_PwInfo info;
 
        struct lsa_String domain_name;
+       NTSTATUS status;
+
+       gnutls_cipher_hd_t cipher_hnd = NULL;
+       gnutls_datum_t old_lm_key = {
+               .data = old_lm_hash,
+               .size = sizeof(old_lm_hash),
+       };
 
        domain_name.string = "";
        dom_pw_info.in.domain_name = &domain_name;
@@ -2179,11 +2307,25 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
        E_deshash(newpass, new_lm_hash);
 
        encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
-       arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &old_lm_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd,
+                             lm_pass.data,
+                             516);
+       gnutls_cipher_deinit(cipher_hnd);
+
        E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
 
-       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
+
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        r.in.server = &server;
@@ -2196,11 +2338,14 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
                "ChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
        } else if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        } else {
                *password = newpass;
@@ -2210,6 +2355,106 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
 }
 
 
+static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct torture_context *tctx,
+                                             const char *acct_name,
+                                             const char *password, NTSTATUS status)
+{
+       struct samr_ChangePasswordUser2 r;
+       struct lsa_String server, account;
+       struct samr_CryptPassword nt_pass, lm_pass;
+       struct samr_Password nt_verifier, lm_verifier;
+       const char *oldpass;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       uint8_t old_nt_hash[16], new_nt_hash[16];
+       uint8_t old_lm_hash[16], new_lm_hash[16];
+       DATA_BLOB old_nt_hash_blob
+               = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
+       gnutls_cipher_hd_t cipher_hnd = NULL;
+       gnutls_datum_t old_lm_key = {
+               .data = old_lm_hash,
+               .size = sizeof(old_lm_hash),
+       };
+
+       struct samr_GetDomPwInfo dom_pw_info;
+       struct samr_PwInfo info;
+
+       struct lsa_String domain_name;
+       NTSTATUS crypt_status;
+
+       char *newpass;
+       int policy_min_pw_len = 0;
+
+       domain_name.string = "";
+       dom_pw_info.in.domain_name = &domain_name;
+       dom_pw_info.out.info = &info;
+
+       torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
+
+       oldpass = password;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
+                                  "GetDomPwInfo failed");
+       if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
+               policy_min_pw_len = dom_pw_info.out.info->min_password_length;
+       }
+
+       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);
+
+       E_md4hash(oldpass, old_nt_hash);
+       E_md4hash(newpass, new_nt_hash);
+
+       E_deshash(oldpass, old_lm_hash);
+       E_deshash(newpass, new_lm_hash);
+
+       encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
+
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &old_lm_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd,
+                             lm_pass.data,
+                             516);
+       gnutls_cipher_deinit(cipher_hnd);
+
+       E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
+
+       crypt_status = init_samr_CryptPassword(newpass,
+                                              &old_nt_hash_blob,
+                                              &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  crypt_status,
+                                  "init_samr_CryptPassword failed");
+
+       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;
+       r.in.nt_verifier = &nt_verifier;
+       r.in.lm_change = 1;
+       r.in.lm_password = &lm_pass;
+       r.in.lm_verifier = &lm_verifier;
+
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
+               "ChangePasswordUser2 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
+
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
+               torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
+       } else {
+               torture_assert_ntstatus_equal(tctx, r.out.result, status, "ChangePasswordUser2 returned unexpected value");
+       }
+
+       return true;
+}
+
+
 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
                              const char *account_string,
                              int policy_min_pw_len,
@@ -2230,6 +2475,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        NTTIME t;
        struct samr_DomInfo1 *dominfo = NULL;
        struct userPwdChangeFailureInformation *reject = NULL;
+       DATA_BLOB old_nt_hash_blob = data_blob_const(old_nt_hash, 16);
+       NTSTATUS status;
 
        torture_comment(tctx, "Testing ChangePasswordUser3\n");
 
@@ -2258,12 +2505,45 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        E_deshash(oldpass, old_lm_hash);
        E_deshash(newpass, new_lm_hash);
 
-       encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(lm_pass.data, old_nt_hash, 516);
+       /*
+        * The new plaintext password is encrypted using RC4 with the
+        * old NT password hash (directly, with no confounder).  The
+        * password is at the end of the random padded buffer,
+        * offering a little protection.
+        *
+        * This is almost certainly wrong, it should be the old LM
+        * hash, it was switched in an unrelated commit
+        * 579c13da43d5b40ac6d6c1436399fbc1d8dfd054 in 2004.
+        */
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &lm_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
+       /*
+        * Now we prepare a DES cross-hash of the old LM and new NT
+        * passwords to link the two buffers
+        */
        E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
 
-       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+       /*
+        * The new plaintext password is also encrypted using RC4 with
+        * the old NT password hash (directly, with no confounder).
+        * The password is at the end of the random padded buffer,
+        * offering a little protection.
+        */
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
+       /*
+        * Another DES based cross-hash
+        */
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        /* Break the verification */
@@ -2282,23 +2562,38 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
            (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
-               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
 
-       encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(lm_pass.data, old_nt_hash, 516);
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &lm_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
        E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
 
-       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
-       /* Break the NT hash */
+       /* Break the NT Hash */
        old_nt_hash[0]++;
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
        /* Unbreak it again */
        old_nt_hash[0]--;
+
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        r.in.server = &server;
@@ -2314,9 +2609,12 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
            (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
-               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrypted password - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2327,8 +2625,11 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        r.in.account = &account_bad;
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
                        nt_errstr(r.out.result));
                ret = false;
        }
@@ -2339,12 +2640,22 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
        E_deshash(oldpass, old_lm_hash);
        E_deshash(newpass, new_lm_hash);
 
-       encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(lm_pass.data, old_nt_hash, 516);
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &lm_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
        E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
 
-       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword");
+
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        r.in.server = &server;
@@ -2362,6 +2673,18 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
+
+       torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
+                       "last_password_change[%s], dominfo->min_password_age[%lld]\n",
+                       __location__,
+                       (dominfo == NULL)? "NULL" : "present",
+                       reject ? "true" : "false",
+                       handle_reject_reason ? "true" : "false",
+                       null_nttime(last_password_change) ? "null" : "not null",
+                       dominfo ? (long long)dominfo->min_password_age : (long long)0);
 
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && dominfo
@@ -2371,7 +2694,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
 
                        if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
-                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
                                        SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                                return false;
                        }
@@ -2386,11 +2709,11 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
                Guenther */
 
-               if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
-                          (last_password_change + dominfo->min_password_age > t)) {
+               if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
+                          (last_password_change - dominfo->min_password_age > t)) {
 
                        if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
-                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
                                        SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                                return false;
                        }
@@ -2399,7 +2722,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                           (strlen(newpass) < dominfo->min_password_length)) {
 
                        if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
-                               torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
                                        SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
                                return false;
                        }
@@ -2408,14 +2731,14 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                            strequal(oldpass, newpass)) {
 
                        if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
-                               torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "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->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
-                               torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
                                        SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
                                return false;
                        }
@@ -2432,7 +2755,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
 
        } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
-                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                       torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
                               SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                        return false;
                }
@@ -2457,9 +2780,6 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        struct samr_SetUserInfo s;
        union samr_UserInfo u;
        DATA_BLOB session_key;
-       DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
-       uint8_t confounder[16];
-       struct MD5Context ctx;
 
        bool ret = true;
        struct lsa_String server, account;
@@ -2470,9 +2790,22 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        char *oldpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
        uint8_t old_nt_hash[16], new_nt_hash[16];
+       DATA_BLOB old_nt_hash_blob
+               = data_blob_const(old_nt_hash,
+                                 sizeof(old_nt_hash));
        NTTIME t;
        struct samr_DomInfo1 *dominfo = NULL;
        struct userPwdChangeFailureInformation *reject = NULL;
+       gnutls_cipher_hd_t cipher_hnd = NULL;
+       uint8_t _confounder[16] = {0};
+       DATA_BLOB confounder
+               = data_blob_const(_confounder,
+                                 sizeof(_confounder));
+       DATA_BLOB pw_data;
+       gnutls_datum_t old_nt_key = {
+               .data = old_nt_hash,
+               .size = sizeof(old_nt_hash),
+       };
 
        new_random_pass = samr_very_rand_pass(tctx, 128);
 
@@ -2493,29 +2826,34 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        set_pw_in_buffer(u.info25.password.data, &new_random_pass);
 
+       pw_data = data_blob_const(u.info25.password.data, 516);
+
        status = dcerpc_fetch_session_key(p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
                return false;
        }
 
-       generate_random_buffer((uint8_t *)confounder, 16);
+       generate_random_buffer(_confounder,
+                              sizeof(_confounder));
 
-       MD5Init(&ctx);
-       MD5Update(&ctx, confounder, 16);
-       MD5Update(&ctx, session_key.data, session_key.length);
-       MD5Final(confounded_session_key.data, &ctx);
+       samba_gnutls_arcfour_confounded_md5(&confounder,
+                                           &session_key,
+                                           &pw_data,
+                                           SAMBA_GNUTLS_ENCRYPT);
 
-       arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
-       memcpy(&u.info25.password.data[516], confounder, 16);
+       memcpy(&u.info25.password.data[516], _confounder, sizeof(_confounder));
 
        torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
                "SetUserInfo failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, "RANDOM", nt_errstr(s.out.result));
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                ret = false;
        }
@@ -2529,7 +2867,16 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
        mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
 
        set_pw_in_buffer(nt_pass.data, &new_random_pass);
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+
+       gnutls_cipher_init(&cipher_hnd,
+                          GNUTLS_CIPHER_ARCFOUR_128,
+                          &old_nt_key,
+                          NULL);
+       gnutls_cipher_encrypt(cipher_hnd,
+                             nt_pass.data,
+                             516);
+       gnutls_cipher_deinit(cipher_hnd);
+
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        r.in.server = &server;
@@ -2547,17 +2894,20 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, "RANDOM", nt_errstr(r.out.result));
 
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
-                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                       torture_result(tctx, TORTURE_FAIL, "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(r.out.result)) {
-               torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -2567,8 +2917,13 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        E_md4hash(newpass, new_nt_hash);
 
-       encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
-       arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+       status = init_samr_CryptPassword(newpass,
+                                        &old_nt_hash_blob,
+                                        &nt_pass);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
+
        E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 
        r.in.server = &server;
@@ -2586,10 +2941,13 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
 
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
                "ChangePasswordUser3 failed");
+       torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
+                       __location__, __FUNCTION__,
+                       oldpass, newpass, nt_errstr(r.out.result));
 
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
                if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
-                       torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
+                       torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
                               SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
                        return false;
                }
@@ -2774,7 +3132,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
        NTSTATUS status;
        uint16_t levels[] = { /* 3, */ 5, 21 };
        int i;
-       NTTIME pwdlastset3 = 0;
+       /* NTTIME pwdlastset3 = 0; */
        NTTIME pwdlastset5 = 0;
        NTTIME pwdlastset21 = 0;
 
@@ -2806,14 +3164,14 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
 
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
-                       torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
                               use_info2 ? "2":"", levels[i], nt_errstr(status));
                        return false;
                }
 
                switch (levels[i]) {
                case 3:
-                       pwdlastset3 = info->info3.last_password_change;
+                       /* pwdlastset3 = info->info3.last_password_change; */
                        break;
                case 5:
                        pwdlastset5 = info->info5.last_password_change;
@@ -2840,6 +3198,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
 
 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,
                          bool interactive)
@@ -2859,7 +3218,7 @@ static bool test_SamLogon(struct torture_context *tctx,
        struct netr_Authenticator a;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
-       torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
+       torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
 
        if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
                flags |= CLI_CRED_LANMAN_AUTH;
@@ -2876,8 +3235,7 @@ static bool test_SamLogon(struct torture_context *tctx,
        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.logon_id = 0;
        identity.workstation.string = cli_credentials_get_workstation(test_credentials);
 
        if (interactive) {
@@ -2888,7 +3246,10 @@ static bool test_SamLogon(struct torture_context *tctx,
                }
                E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
 
-               if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+               if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+                       netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
+                       netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
+               } else 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 {
@@ -2912,6 +3273,7 @@ static bool test_SamLogon(struct torture_context *tctx,
                status = cli_credentials_get_ntlm_response(test_credentials, tctx,
                                                           &flags,
                                                           chal,
+                                                          NULL, /* server_timestamp */
                                                           names_blob,
                                                           &lm_resp, &nt_resp,
                                                           NULL, NULL);
@@ -2983,9 +3345,9 @@ static bool test_SamLogon_with_creds(struct torture_context *tctx,
        torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
                interactive ? "interactive" : "network", acct_name, password);
 
-       if (!test_SamLogon(tctx, p, test_credentials,
+       if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
                            expected_samlogon_result, interactive)) {
-               torture_warning(tctx, "new password did not work\n");
+               torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
                ret = false;
        }
 
@@ -3064,6 +3426,7 @@ static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
                                         struct dcerpc_pipe **p)
 {
        struct dcerpc_binding *b;
+       NTSTATUS status;
 
        torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
                "failed to get rpc binding");
@@ -3071,8 +3434,12 @@ static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
        /* 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_binding_set_flags(b,
+                                         DCERPC_SCHANNEL |
+                                         DCERPC_SIGN | DCERPC_SEAL |
+                                         DCERPC_SCHANNEL_AUTO,
+                                         DCERPC_AUTH_OPTIONS);
+       torture_assert_ntstatus_ok(tctx, status, "set flags");
 
        torture_assert_ntstatus_ok(tctx,
                dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
@@ -3208,7 +3575,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                        break;
                default:
                        if (pwdlastset_new != 0) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected pwdLastSet 0 but got %llu\n",
                                        (unsigned long long) pwdlastset_old);
                                ret = false;
@@ -3224,7 +3591,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                             (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
                             (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
                             (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
+                               torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
                                ret = false;
                        }
                        break;
@@ -3276,14 +3643,14 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                        break;
                default:
                        if (pwdlastset_old >= pwdlastset_new) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
                                        (unsigned long long) pwdlastset_old,
                                        (unsigned long long) pwdlastset_new);
                                ret = false;
                        }
                        if (pwdlastset_new == 0) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected non-0 pwdlastset, got: %llu\n",
                                        (unsigned long long) pwdlastset_new);
                                ret = false;
@@ -3299,7 +3666,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                             (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
                             (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
                             (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
+                               torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
                                ret = false;
                        }
                        break;
@@ -3352,14 +3719,14 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                        break;
                default:
                        if (pwdlastset_old >= pwdlastset_new) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
                                        (unsigned long long) pwdlastset_old,
                                        (unsigned long long) pwdlastset_new);
                                ret = false;
                        }
                        if (pwdlastset_new == 0) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected non-0 pwdlastset, got: %llu\n",
                                        (unsigned long long) pwdlastset_new);
                                ret = false;
@@ -3375,7 +3742,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                             (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
                             (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
                             (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
+                               torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
                                ret = false;
                        }
                        break;
@@ -3436,7 +3803,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                        break;
                default:
                        if (pwdlastset_new != 0) {
-                               torture_warning(tctx, "pwdLastSet test failed: "
+                               torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
                                        "expected pwdLastSet 0, got %llu\n",
                                        (unsigned long long) pwdlastset_old);
                                ret = false;
@@ -3452,7 +3819,7 @@ static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
                             (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
                             (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
                             (pwdlastset_old >= pwdlastset_new)) {
-                               torture_warning(tctx, "pwdlastset not increasing\n");
+                               torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
                                ret = false;
                        }
                        break;
@@ -3644,8 +4011,14 @@ static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
        uint32_t badpwdcount, tmp;
        uint32_t password_history_length = 12;
        uint32_t lockout_threshold = 15;
+       uint32_t lockout_seconds = 5;
+       uint64_t delta_time_factor = 10 * 1000 * 1000;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
+       if (torture_setting_bool(tctx, "samba3", false)) {
+               lockout_seconds = 60;
+       }
+
        torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
 
        torture_assert(tctx, password_history_length < lockout_threshold,
@@ -3656,15 +4029,20 @@ static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
 
        info.info1 = *info1;
        info.info1.password_history_length = password_history_length;
+       info.info1.min_password_age = 0;
 
        torture_assert(tctx,
                       test_SetDomainInfo(b, tctx, domain_handle,
                                          DomainPasswordInformation, &info),
-                      "failed to set password history length");
+                      "failed to set password history length and min passwd age");
 
        info.info12 = *info12;
        info.info12.lockout_threshold = lockout_threshold;
 
+       /* set lockout duration of 5 seconds */
+       info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
+       info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
+
        torture_assert(tctx,
                       test_SetDomainInfo(b, tctx, domain_handle,
                                          DomainLockoutInformation, &info),
@@ -3766,7 +4144,9 @@ static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
                        if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
                                                      acct_name, passwords[i],
                                                      expected_success_status, interactive)) {
-                               torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
+                               torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
+                                                                  nt_errstr(expected_success_status),
+                                                                  interactive ? "interactive" : "network", i, password_history_length));
                        }
 
                        torture_assert(tctx,
@@ -3893,16 +4273,16 @@ static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
                        continue;
                }
 
-               ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
-                                                domain_handle, user_handle, password,
-                                                machine_credentials,
-                                                creds[i].comment,
-                                                creds[i].disabled,
-                                                creds[i].interactive,
-                                                creds[i].expected_success_status,
-                                                &_info1, &_info12);
-               if (!ret) {
-                       torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
+               if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
+                                              domain_handle, user_handle, password,
+                                              machine_credentials,
+                                              creds[i].comment,
+                                              creds[i].disabled,
+                                              creds[i].interactive,
+                                              creds[i].expected_success_status,
+                                              &_info1, &_info12)) {
+                       torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
+                       ret = false;
                } else {
                        torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
                }
@@ -3927,28 +4307,95 @@ static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
        return ret;
 }
 
-static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
-                                         struct torture_context *tctx,
-                                         struct policy_handle *handle,
-                                         uint32_t *acct_flags)
+static bool test_QueryUserInfo_lockout(struct dcerpc_binding_handle *b,
+                                      struct torture_context *tctx,
+                                      struct policy_handle *domain_handle,
+                                      const char *acct_name,
+                                      uint16_t raw_bad_password_count,
+                                      uint16_t effective_bad_password_count,
+                                      uint32_t effective_acb_lockout)
 {
-       union samr_UserInfo *info;
+       struct policy_handle user_handle;
+       union samr_UserInfo *i;
        struct samr_QueryUserInfo r;
 
-       r.in.user_handle = handle;
-       r.in.level = 16;
-       r.out.info = &info;
+       NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       r.in.user_handle = &user_handle;
+       r.in.level = 3;
+       r.out.info = &i;
+       torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+               "failed to query userinfo");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query userinfo");
+       torture_comment(tctx, "  (acct_flags: 0x%08x) (raw_bad_pwd_count: %u)\n",
+                       i->info3.acct_flags, i->info3.bad_password_count);
+       torture_assert_int_equal(tctx, i->info3.bad_password_count,
+                                raw_bad_password_count,
+                                "raw badpwdcount");
+       torture_assert_int_equal(tctx, i->info3.acct_flags & ACB_AUTOLOCK,
+                                effective_acb_lockout,
+                                "effective acb_lockout");
+       TALLOC_FREE(i);
 
+       r.in.user_handle = &user_handle;
+       r.in.level = 5;
+       r.out.info = &i;
        torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+               "failed to query userinfo");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query userinfo");
+       torture_comment(tctx, "  (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
+                       i->info5.acct_flags, i->info5.bad_password_count);
+       torture_assert_int_equal(tctx, i->info5.bad_password_count,
+                                effective_bad_password_count,
+                                "effective badpwdcount");
+       torture_assert_int_equal(tctx, i->info5.acct_flags & ACB_AUTOLOCK,
+                                effective_acb_lockout,
+                                "effective acb_lockout");
+       TALLOC_FREE(i);
 
+       r.in.user_handle = &user_handle;
+       r.in.level = 16;
+       r.out.info = &i;
+       torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
                "failed to query userinfo");
        torture_assert_ntstatus_ok(tctx, r.out.result,
                "failed to query userinfo");
+       torture_comment(tctx, "  (acct_flags: 0x%08x)\n",
+                       i->info16.acct_flags);
+       torture_assert_int_equal(tctx, i->info16.acct_flags & ACB_AUTOLOCK,
+                                effective_acb_lockout,
+                                "effective acb_lockout");
+       TALLOC_FREE(i);
 
-       *acct_flags = info->info16.acct_flags;
+       r.in.user_handle = &user_handle;
+       r.in.level = 21;
+       r.out.info = &i;
+       torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
+       torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
+               "failed to query userinfo");
+       torture_assert_ntstatus_ok(tctx, r.out.result,
+               "failed to query userinfo");
+       torture_comment(tctx, "  (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
+                       i->info21.acct_flags, i->info21.bad_password_count);
+       torture_assert_int_equal(tctx, i->info21.bad_password_count,
+                                effective_bad_password_count,
+                                "effective badpwdcount");
+       torture_assert_int_equal(tctx, i->info21.acct_flags & ACB_AUTOLOCK,
+                                effective_acb_lockout,
+                                "effective acb_lockout");
+       TALLOC_FREE(i);
 
-       torture_comment(tctx, "  (acct_flags: 0x%08x)\n", *acct_flags);
+       if (!test_samr_handle_Close(b, tctx, &user_handle)) {
+               return false;
+       }
 
        return true;
 }
@@ -3965,27 +4412,33 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
                                  const char *comment,
                                  bool disable,
                                  bool interactive,
+                                 uint32_t password_history_length,
                                  NTSTATUS expected_success_status,
                                  struct samr_DomInfo1 *info1,
                                  struct samr_DomInfo12 *info12)
 {
        union samr_DomainInfo info;
-       uint32_t badpwdcount;
-       uint32_t password_history_length = 1;
        uint64_t lockout_threshold = 1;
        uint32_t lockout_seconds = 5;
        uint64_t delta_time_factor = 10 * 1000 * 1000;
        struct dcerpc_binding_handle *b = p->binding_handle;
 
+       if (torture_setting_bool(tctx, "samba3", false)) {
+               lockout_seconds = 60;
+       }
+
        torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
 
        /* set policies */
 
        info.info1 = *info1;
 
-       torture_comment(tctx, "setting password history length.\n");
+       torture_comment(tctx, "setting password history length to %d.\n", password_history_length);
        info.info1.password_history_length = password_history_length;
 
+       torture_comment(tctx, "setting min password again.\n");
+       info.info1.min_password_age = 0;
+
        torture_assert(tctx,
                       test_SetDomainInfo(b, tctx, domain_handle,
                                          DomainPasswordInformation, &info),
@@ -4052,9 +4505,9 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
        }
 
        torture_assert(tctx,
-               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
-       torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
-
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       0, 0, 0),
+               "expected account to not be locked");
 
        /* test with wrong password ==> lockout */
 
@@ -4064,15 +4517,14 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
                torture_fail(tctx, "succeeded to authenticate with wrong password");
        }
 
+       /*
+        * curiously, windows does _not_ return fresh values of
+        * effective bad_password_count and ACB_AUTOLOCK.
+        */
        torture_assert(tctx,
-               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
-       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
-
-       torture_assert(tctx,
-               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
-       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
-                                "expected account to be locked");
-
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to not be locked");
 
        /* test with good password */
 
@@ -4085,15 +4537,30 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
 
        /* bad pwd count should not get updated */
        torture_assert(tctx,
-               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
-       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
 
-       /* curiously, windows does _not_ set the autlock flag */
        torture_assert(tctx,
-               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
-       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
-                                "expected account to be locked");
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password,
+                                                        NT_STATUS_ACCOUNT_LOCKED_OUT),
+                      "got wrong status from ChangePasswordUser2");
 
+       /* bad pwd count should not get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
+                      "got wrong status from ChangePasswordUser2");
+
+       /* bad pwd count should not get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
 
        /* with bad password */
 
@@ -4106,21 +4573,76 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
 
        /* bad pwd count should not get updated */
        torture_assert(tctx,
-               test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
-       torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
+
+       /* let lockout duration expire ==> unlock */
+
+       torture_comment(tctx, "let lockout duration expire...\n");
+       sleep(lockout_seconds + 1);
+
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 0, 0),
+               "expected account to not be locked");
+
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
+                                    *password,
+                                    expected_success_status, interactive))
+       {
+               torture_fail(tctx, "failed to authenticate after lockout expired");
+       }
+
+       if (NT_STATUS_IS_OK(expected_success_status)) {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               0, 0, 0),
+                       "expected account to not be locked");
+       } else {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               1, 0, 0),
+                       "expected account to not be locked");
+       }
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
+                      "got wrong status from ChangePasswordUser2");
+
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
+                      "got wrong status from ChangePasswordUser2");
+
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
 
-       /* curiously, windows does _not_ set the autlock flag */
        torture_assert(tctx,
-               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
-       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
-                                "expected account to be locked");
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
+                      "got wrong status from ChangePasswordUser2");
 
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, ACB_AUTOLOCK),
+               "expected account to be locked");
 
        /* let lockout duration expire ==> unlock */
 
        torture_comment(tctx, "let lockout duration expire...\n");
        sleep(lockout_seconds + 1);
 
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 0, 0),
+               "expected account to not be locked");
+
        if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
                                     *password,
                                     expected_success_status, interactive))
@@ -4128,10 +4650,116 @@ static bool test_Password_lockout(struct dcerpc_pipe *p,
                torture_fail(tctx, "failed to authenticate after lockout expired");
        }
 
+       if (NT_STATUS_IS_OK(expected_success_status)) {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               0, 0, 0),
+                       "expected account to not be locked");
+       } else {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               1, 0, 0),
+                       "expected account to not be locked");
+       }
+
+       /* Testing ChangePasswordUser behaviour with 3 attempts */
+       info.info12.lockout_threshold = 3;
+
+       torture_assert(tctx,
+                      test_SetDomainInfo(b, tctx, domain_handle,
+                                         DomainLockoutInformation, &info),
+                      "failed to set lockout threshold to 3");
+
+       if (NT_STATUS_IS_OK(expected_success_status)) {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               0, 0, 0),
+                       "expected account to not be locked");
+       } else {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               1, 0, 0),
+                       "expected account to not be locked");
+       }
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
+                      "got wrong status from ChangePasswordUser2");
+
+       /* bad pwd count will get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       1, 1, 0),
+               "expected account to not be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
+                      "got wrong status from ChangePasswordUser2");
+
+       /* bad pwd count will get updated */
        torture_assert(tctx,
-               test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
-       torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
-                                "expected account not to be locked");
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       2, 2, 0),
+               "expected account to not be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
+                      "got wrong status from ChangePasswordUser2");
+
+       /* bad pwd count should get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       3, 3, ACB_AUTOLOCK),
+               "expected account to be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
+                      "got wrong status from ChangePasswordUser2");
+
+       /* bad pwd count should not get updated */
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       3, 3, ACB_AUTOLOCK),
+               "expected account to be locked");
+
+       /* let lockout duration expire ==> unlock */
+
+       torture_comment(tctx, "let lockout duration expire...\n");
+       sleep(lockout_seconds + 1);
+
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       3, 0, 0),
+               "expected account to not be locked");
+
+       torture_assert(tctx,
+                      test_ChangePasswordUser2(p, tctx, acct_name, password, NULL, false),
+                      "got wrong status from ChangePasswordUser2");
+
+       torture_assert(tctx,
+               test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                       3, 0, 0),
+               "expected account to not be locked");
+
+       /* Used to reset the badPwdCount for the other tests */
+       if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
+                                     *password,
+                                     expected_success_status, interactive))
+       {
+               torture_fail(tctx, "failed to authenticate after lockout expired");
+       }
+
+       if (NT_STATUS_IS_OK(expected_success_status)) {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               0, 0, 0),
+                       "expected account to not be locked");
+       } else {
+               torture_assert(tctx,
+                       test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
+                               3, 0, 0),
+                       "expected account to not be locked");
+       }
 
        return true;
 }
@@ -4157,6 +4785,7 @@ static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
                const char *comment;
                bool disabled;
                bool interactive;
+               uint32_t password_history_length;
                NTSTATUS expected_success_status;
        } creds[] = {
                {
@@ -4171,6 +4800,13 @@ static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
                        .interactive            = false,
                        .expected_success_status= NT_STATUS_OK
                },
+               {
+                       .comment                = "network logon (enabled account, history len = 1)",
+                       .disabled               = false,
+                       .interactive            = false,
+                       .expected_success_status= NT_STATUS_OK,
+                       .password_history_length = 1
+               },
                {
                        .comment                = "interactive logon (disabled account)",
                        .disabled               = true,
@@ -4183,6 +4819,13 @@ static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
                        .interactive            = true,
                        .expected_success_status= NT_STATUS_OK
                },
+               {
+                       .comment                = "interactive logon (enabled account, history len = 1)",
+                       .disabled               = false,
+                       .interactive            = true,
+                       .expected_success_status= NT_STATUS_OK,
+                       .password_history_length = 1
+               },
        };
 
        torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
@@ -4208,7 +4851,7 @@ static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
        /* run tests */
 
        for (i=0; i < ARRAY_SIZE(creds); i++) {
-
+               bool test_passed;
                /* skip trust tests for now */
                if (acct_flags & ACB_WSTRUST ||
                    acct_flags & ACB_SVRTRUST ||
@@ -4216,16 +4859,19 @@ static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
                        continue;
                }
 
-               ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
+               test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
                                             domain_handle, user_handle, password,
                                             machine_credentials,
                                             creds[i].comment,
                                             creds[i].disabled,
                                             creds[i].interactive,
+                                            creds[i].password_history_length,
                                             creds[i].expected_success_status,
                                             &_info1, &_info12);
-               if (!ret) {
-                       torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
+               ret &= test_passed;
+               if (!test_passed) {
+                       torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
+                       break;
                } else {
                        torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
                }
@@ -4308,6 +4954,41 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                        "Failed to add privileges");
        }
 
+       {
+               struct lsa_RightSet rights;
+               struct lsa_StringLarge names[2];
+               struct lsa_AddAccountRights r;
+
+               torture_comment(tctx, "Testing LSA AddAccountRights 1\n");
+
+               init_lsa_StringLarge(&names[0], "SeInteractiveLogonRight");
+               init_lsa_StringLarge(&names[1], NULL);
+
+               rights.count = 1;
+               rights.names = names;
+
+               r.in.handle = lsa_handle;
+               r.in.sid = user_sid;
+               r.in.rights = &rights;
+
+               torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
+                       "lsa_AddAccountRights 1 failed");
+
+               if (torture_setting_bool(tctx, "nt4_dc", false)) {
+                       /*
+                        * The NT4 DC doesn't implement Rights.
+                        */
+                       torture_assert_ntstatus_equal(tctx, r.out.result,
+                               NT_STATUS_NO_SUCH_PRIVILEGE,
+                               "Add rights failed with incorrect error");
+               } else {
+                       torture_assert_ntstatus_ok(tctx, r.out.result,
+                               "Failed to add rights");
+
+               }
+       }
+
+
        {
                struct lsa_EnumAccounts r;
                uint32_t resume_handle = 0;
@@ -4341,6 +5022,14 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
        {
                struct lsa_EnumAccountRights r;
                struct lsa_RightSet user_rights;
+               uint32_t expected_count = 2;
+
+               if (torture_setting_bool(tctx, "nt4_dc", false)) {
+                       /*
+                        * NT4 DC doesn't store rights.
+                        */
+                       expected_count = 1;
+               }
 
                torture_comment(tctx, "Testing LSA EnumAccountRights\n");
 
@@ -4353,8 +5042,8 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, r.out.result,
                        "Failed to enum rights for account");
 
-               if (user_rights.count < 1) {
-                       torture_warning(tctx, "failed to find newly added rights");
+               if (user_rights.count < expected_count) {
+                       torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
                        return false;
                }
        }
@@ -4464,7 +5153,7 @@ static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
                        "Failed to enum rights for account");
 
                if (user_rights.count < 1) {
-                       torture_warning(tctx, "failed to find newly added rights");
+                       torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
                        return false;
                }
        }
@@ -4722,22 +5411,22 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
                        "QueryUserInfo failed");
                if (!NT_STATUS_IS_OK(q.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
                               q.in.level, nt_errstr(q.out.result));
                        ret = false;
                } else {
                        uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
                        if ((info->info5.acct_flags) != expected_flags) {
-                               torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
-                                      info->info5.acct_flags,
-                                      expected_flags);
                                /* FIXME: GD */
                                if (!torture_setting_bool(tctx, "samba3", false)) {
+                                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                                                     info->info5.acct_flags,
+                                                     expected_flags);
                                        ret = false;
                                }
                        }
                        if (info->info5.rid != rid) {
-                               torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
                                       info->info5.rid, rid);
 
                        }
@@ -4748,57 +5437,32 @@ static bool test_user_ops(struct dcerpc_pipe *p,
        case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
 
                /* test last password change timestamp behaviour */
-               if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
-                                                base_acct_name,
-                                                user_handle, &password,
-                                                machine_credentials)) {
-                       ret = false;
-               }
-
-               if (ret == true) {
-                       torture_comment(tctx, "pwdLastSet test succeeded\n");
-               } else {
-                       torture_warning(tctx, "pwdLastSet test failed\n");
-               }
-
+               torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
+                                                                base_acct_name,
+                                                                user_handle, &password,
+                                                                machine_credentials),
+                              "pwdLastSet test failed\n");
                break;
 
        case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
 
                /* test bad pwd count change behaviour */
-               if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
-                                                   base_acct_name,
-                                                   domain_handle,
-                                                   user_handle, &password,
-                                                   machine_credentials)) {
-                       ret = false;
-               }
-
-               if (ret == true) {
-                       torture_comment(tctx, "badPwdCount test succeeded\n");
-               } else {
-                       torture_warning(tctx, "badPwdCount test failed\n");
-               }
-
+               torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
+                                                                   base_acct_name,
+                                                                   domain_handle,
+                                                                   user_handle, &password,
+                                                                   machine_credentials),
+                              "badPwdCount test failed\n");
                break;
 
        case TORTURE_SAMR_PASSWORDS_LOCKOUT:
 
-               if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
-                                               base_acct_name,
-                                               domain_handle,
-                                               user_handle, &password,
-                                               machine_credentials))
-               {
-                       ret = false;
-               }
-
-               if (ret == true) {
-                       torture_comment(tctx, "lockout test succeeded\n");
-               } else {
-                       torture_warning(tctx, "lockout test failed\n");
-               }
-
+               torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
+                                                               base_acct_name,
+                                                               domain_handle,
+                                                               user_handle, &password,
+                                                               machine_credentials),
+                              "Lockout test failed");
                break;
 
 
@@ -4828,7 +5492,7 @@ static bool test_user_ops(struct dcerpc_pipe *p,
                }
 
                if (!ret) {
-                       torture_warning(tctx, "privileged user delete test failed\n");
+                       torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
                }
 
                break;
@@ -4930,7 +5594,7 @@ bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
        return true;
 
 failed:
-       torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
@@ -4973,7 +5637,7 @@ static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
        return true;
 
 failed:
-       torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
@@ -5019,7 +5683,7 @@ static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
        return true;
 
 failed:
-       torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
+       torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
        return false;
 }
 
@@ -5038,7 +5702,7 @@ static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
                "DeleteDomAlias failed");
        if (!NT_STATUS_IS_OK(d.out.result)) {
-               torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
+               torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
                ret = false;
        }
 
@@ -5075,7 +5739,7 @@ static bool test_CreateAlias(struct dcerpc_binding_handle *b,
                        torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
                        return true;
                } else {
-                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
+                       torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
                               nt_errstr(r.out.result));
                        return false;
                }
@@ -5090,7 +5754,7 @@ static bool test_CreateAlias(struct dcerpc_binding_handle *b,
        }
 
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -5227,7 +5891,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
                        "LookupNames failed");
                if (!NT_STATUS_IS_OK(n.out.result)) {
-                       torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
                        return false;
                }
 
@@ -5239,7 +5903,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
                        "OpenUser failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
                        return false;
                }
 
@@ -5250,7 +5914,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
                        "QueryUserInfo failed");
                if (!NT_STATUS_IS_OK(q.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
                        return false;
                }
 
@@ -5319,7 +5983,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                        torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
                        return true;
                } else {
-                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+                       torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
                               nt_errstr(r.out.result));
                        return false;
                }
@@ -5336,7 +6000,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
 
        if (!NT_STATUS_IS_OK(r.out.result)) {
                talloc_free(user_ctx);
-               torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -5355,12 +6019,12 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
                        "QueryUserInfo failed");
                if (!NT_STATUS_IS_OK(q.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
                               q.in.level, nt_errstr(q.out.result));
                        ret = false;
                } else {
                        if ((info->info16.acct_flags & acct_flags) != acct_flags) {
-                               torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                       info->info16.acct_flags,
                                       acct_flags);
                                ret = false;
@@ -5384,7 +6048,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
                        torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
                                "DeleteUser failed");
                        if (!NT_STATUS_IS_OK(d.out.result)) {
-                               torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
+                               torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
                                ret = false;
                        }
                }
@@ -5461,7 +6125,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
                                continue;
                        } else {
-                               torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+                               torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
                                       nt_errstr(r.out.result));
                                ret = false;
                                continue;
@@ -5479,7 +6143,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
 
                }
                if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
-                       torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
+                       torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
                               nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
                        ret = false;
                }
@@ -5492,7 +6156,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                        torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
                                "QueryUserInfo failed");
                        if (!NT_STATUS_IS_OK(q.out.result)) {
-                               torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
                                       q.in.level, nt_errstr(q.out.result));
                                ret = false;
                        } else {
@@ -5501,7 +6165,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                        expected_flags |= ACB_PW_EXPIRED;
                                }
                                if ((info->info5.acct_flags) != expected_flags) {
-                                       torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
+                                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
                                               info->info5.acct_flags,
                                               expected_flags);
                                        ret = false;
@@ -5509,21 +6173,21 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                switch (acct_flags) {
                                case ACB_SVRTRUST:
                                        if (info->info5.primary_gid != DOMAIN_RID_DCS) {
-                                               torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
+                                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_DCS, info->info5.primary_gid);
                                                ret = false;
                                        }
                                        break;
                                case ACB_WSTRUST:
                                        if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
-                                               torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
+                                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
                                                ret = false;
                                        }
                                        break;
                                case ACB_NORMAL:
                                        if (info->info5.primary_gid != DOMAIN_RID_USERS) {
-                                               torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
+                                               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
                                                       DOMAIN_RID_USERS, info->info5.primary_gid);
                                                ret = false;
                                        }
@@ -5537,7 +6201,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                ret = false;
                        }
 
-                       if (!policy_handle_empty(&user_handle)) {
+                       if (!ndr_policy_handle_empty(&user_handle)) {
                                torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
 
                                d.in.user_handle = &user_handle;
@@ -5546,7 +6210,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx
                                torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
                                        "DeleteUser failed");
                                if (!NT_STATUS_IS_OK(d.out.result)) {
-                                       torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
+                                       torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
                                        ret = false;
                                }
                        }
@@ -5577,7 +6241,7 @@ static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
                        "QueryAliasInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -5606,7 +6270,7 @@ static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
                        "QueryGroupInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -5631,7 +6295,7 @@ static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
                "QueryGroupMember failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -5661,7 +6325,7 @@ static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
                        "QueryGroupInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -5690,14 +6354,14 @@ static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
                        "SetGroupInfo failed");
                if (set_ok[i]) {
                        if (!NT_STATUS_IS_OK(s.out.result)) {
-                               torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
+                               torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
                                       r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
                } else {
                        if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
-                               torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+                               torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
                                       r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
@@ -5729,7 +6393,7 @@ static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
                        "QueryUserInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -5759,7 +6423,7 @@ static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
                        "QueryUserInfo2 failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -5786,7 +6450,7 @@ static bool test_OpenUser(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
                "OpenUser failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
@@ -5835,7 +6499,7 @@ static bool test_OpenGroup(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
                "OpenGroup failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
@@ -5878,7 +6542,7 @@ static bool test_OpenAlias(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
                "OpenAlias failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
@@ -5924,7 +6588,7 @@ static bool check_mask(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
                "OpenUser failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
                return false;
        }
 
@@ -5935,12 +6599,12 @@ static bool check_mask(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
                "QueryUserInfo failed");
        if (!NT_STATUS_IS_OK(q.out.result)) {
-               torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
                       nt_errstr(q.out.result));
                ret = false;
        } else {
                if ((acct_flag_mask & info->info16.acct_flags) == 0) {
-                       torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
+                       torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
                               acct_flag_mask, info->info16.acct_flags, rid);
                        ret = false;
                }
@@ -5988,7 +6652,7 @@ static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
                        "EnumDomainUsers failed");
                if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
                    !NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
                        return false;
                }
 
@@ -6021,7 +6685,7 @@ static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
                "LookupNames failed");
        if (!NT_STATUS_IS_OK(n.out.result)) {
-               torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
+               torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
                ret = false;
        }
 
@@ -6106,7 +6770,7 @@ static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
                "EnumDomainGroups failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -6160,7 +6824,7 @@ static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
                "EnumDomainAliases failed");
        if (!NT_STATUS_IS_OK(r.out.result)) {
-               torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
                return false;
        }
 
@@ -6205,7 +6869,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
                if (ok_lvl[i] &&
                    !NT_STATUS_IS_OK(r.out.result) &&
                    !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
-                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6216,7 +6880,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
                        "GetDisplayEnumerationIndex failed");
 
                if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
-                       torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6252,7 +6916,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
                if (ok_lvl[i] &&
                    !NT_STATUS_IS_OK(r.out.result) &&
                    !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
-                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6262,7 +6926,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
                        "GetDisplayEnumerationIndex2 failed");
                if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
-                       torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6275,13 +6939,13 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
        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)) { \
-                       torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
+                       torture_result(tctx, TORTURE_FAIL, "%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) { \
-                       torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
+                       torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
                               #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
                        ret = false; \
                }
@@ -6328,7 +6992,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
                        torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
                                "OpenUser failed");
                        if (!NT_STATUS_IS_OK(r.out.result)) {
-                               torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
+                               torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
                                return false;
                        }
                }
@@ -6339,7 +7003,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
                        "QueryUserInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
                        return false;
                }
 
@@ -6371,12 +7035,12 @@ static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
                                        info->info21.acct_flags, info->info21.account_name);
 
                        if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
-                               torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
+                               torture_result(tctx, TORTURE_FAIL, "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))) {
-                               torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
+                               torture_result(tctx, TORTURE_FAIL, "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);
@@ -6426,7 +7090,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                        torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
                                "QueryDisplayInfo failed");
                        if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
-                               torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
                                       levels[i], nt_errstr(r.out.result));
                                ret = false;
                        }
@@ -6462,7 +7126,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
                        "QueryDomainInfo failed");
                if (!NT_STATUS_IS_OK(dom_info.out.result)) {
-                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(dom_info.out.result));
                        ret = false;
                        break;
@@ -6476,7 +7140,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                                 * global groups, QueryDomainInfo only global
                                 * ones. */
                                if (torture_setting_bool(tctx, "samba3", false)) {
-                                       torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
+                                       torture_result(tctx, TORTURE_FAIL, "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;
@@ -6485,7 +7149,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                        if (!seen_testuser) {
                                struct policy_handle user_handle;
                                if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
-                                       torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
+                                       torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
                                               info->general.domain_name.string);
                                        ret = false;
                                        test_samr_handle_Close(b, tctx, &user_handle);
@@ -6500,7 +7164,7 @@ static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
                                 * global groups, QueryDomainInfo only global
                                 * ones. */
                                if (torture_setting_bool(tctx, "samba3", false)) {
-                                       torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
+                                       torture_result(tctx, TORTURE_FAIL, "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;
@@ -6542,7 +7206,7 @@ static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
                        "QueryDisplayInfo2 failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6578,7 +7242,7 @@ static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
                        "QueryDisplayInfo3 failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
                               levels[i], nt_errstr(r.out.result));
                        ret = false;
                }
@@ -6614,7 +7278,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
                        "QueryDisplayInfo failed");
                if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
                        if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
-                               torture_warning(tctx, "expected idx %d but got %d\n",
+                               torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
                                       r.in.start_idx + 1,
                                       r.out.info->info1.entries[0].idx);
                                break;
@@ -6622,7 +7286,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
                }
                if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
                    !NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        break;
@@ -6659,7 +7323,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
                "SetDomainInfo failed");
        if (!NT_STATUS_IS_OK(s.out.result)) {
-               torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
                       s.in.level, nt_errstr(s.out.result));
                return false;
        }
@@ -6674,7 +7338,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
                        "QueryDomainInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
@@ -6683,20 +7347,20 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                switch (levels[i]) {
                case 2:
                        if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
-                               torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
                                       levels[i], info->general.oem_information.string, domain_comment);
                                if (!torture_setting_bool(tctx, "samba3", false)) {
                                        ret = false;
                                }
                        }
                        if (!info->general.primary.string) {
-                               torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
+                               torture_result(tctx, TORTURE_FAIL, "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) {
                                        if (torture_setting_bool(tctx, "samba3", false)) {
-                                               torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
+                                               torture_result(tctx, TORTURE_FAIL, "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));
                                        }
                                }
@@ -6704,7 +7368,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                        break;
                case 4:
                        if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
-                               torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
                                       levels[i], info->oem.oem_information.string, domain_comment);
                                if (!torture_setting_bool(tctx, "samba3", false)) {
                                        ret = false;
@@ -6713,14 +7377,14 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                        break;
                case 6:
                        if (!info->info6.primary.string) {
-                               torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
+                               torture_result(tctx, TORTURE_FAIL, "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) {
-                               torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
                                       levels[i], info->general2.general.oem_information.string, domain_comment);
                                if (!torture_setting_bool(tctx, "samba3", false)) {
                                        ret = false;
@@ -6739,14 +7403,14 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                        "SetDomainInfo failed");
                if (set_ok[i]) {
                        if (!NT_STATUS_IS_OK(s.out.result)) {
-                               torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
+                               torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
                                       r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
                        }
                } else {
                        if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
-                               torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+                               torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
                                       r.in.level, nt_errstr(s.out.result));
                                ret = false;
                                continue;
@@ -6756,7 +7420,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
                        "QueryDomainInfo failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
                               r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
@@ -6787,14 +7451,14 @@ static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
                        "QueryDomainInfo2 failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
+                       torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
                               r.in.level, nt_errstr(r.out.result));
                        ret = false;
                        continue;
                }
        }
 
-       return true;
+       return ret;
 }
 
 /* Test whether querydispinfo level 5 and enumdomgroups return the same
@@ -6816,7 +7480,7 @@ static bool test_GroupList(struct dcerpc_binding_handle *b,
        uint32_t returned_size;
        union samr_DispInfo info;
 
-       int num_names = 0;
+       size_t num_names = 0;
        const char **names = NULL;
 
        bool builtin_domain = dom_sid_compare(domain_sid,
@@ -6890,7 +7554,7 @@ static bool test_GroupList(struct dcerpc_binding_handle *b,
                        }
 
                        if ((!found) && (!builtin_domain)) {
-                               torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
+                               torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
                                       name);
                                ret = false;
                        }
@@ -6899,7 +7563,7 @@ static bool test_GroupList(struct dcerpc_binding_handle *b,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
+               torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
                       nt_errstr(status));
                ret = false;
        }
@@ -6911,7 +7575,7 @@ static bool test_GroupList(struct dcerpc_binding_handle *b,
 
        for (i=0; i<num_names; i++) {
                if (names[i] != NULL) {
-                       torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
+                       torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
                               names[i]);
                        ret = false;
                }
@@ -6978,13 +7642,13 @@ static bool test_RidToSid(struct dcerpc_binding_handle *b,
                torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
                        "RidToSid failed");
                if (!NT_STATUS_IS_OK(r.out.result)) {
-                       torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
+                       torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
                        ret = false;
                } else {
                        calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
 
                        if (!dom_sid_equal(calc_sid, out_sid)) {
-                               torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
+                               torture_result(tctx, TORTURE_FAIL, "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;
@@ -7151,7 +7815,7 @@ static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
                        torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
                        return true;
                } else {
-                       torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
+                       torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
                               nt_errstr(r.out.result));
                        return false;
                }
@@ -7159,7 +7823,7 @@ static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
 
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
                if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
-                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
+                       torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
                               nt_errstr(r.out.result));
                        return false;
                }
@@ -7169,7 +7833,7 @@ static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
        if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
                if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
 
-                       torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
+                       torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
                               nt_errstr(r.out.result));
                        return false;
                }
@@ -7183,7 +7847,7 @@ static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
        }
 
        if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
-               torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
+               torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
                ret = false;
        }
 
@@ -7484,7 +8148,7 @@ static bool test_ManyObjects(struct dcerpc_pipe *p,
                default:
                        return false;
                }
-               if (!policy_handle_empty(&handles[i])) {
+               if (!ndr_policy_handle_empty(&handles[i])) {
                        num_created++;
                }
        }
@@ -7535,7 +8199,7 @@ static bool test_ManyObjects(struct dcerpc_pipe *p,
 
        for (i=0; i < num_total; i++) {
 
-               if (policy_handle_empty(&handles[i])) {
+               if (ndr_policy_handle_empty(&handles[i])) {
                        continue;
                }
 
@@ -7624,7 +8288,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
                }
                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));
+                       torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_USER_ATTRIBUTES:
@@ -7635,7 +8299,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
                /* This test needs 'complex' users to validate */
                ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
                if (!ret) {
-                       torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
+                       torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
@@ -7646,7 +8310,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
                }
                ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
                if (!ret) {
-                       torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
+                       torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_MANY_ACCOUNTS:
@@ -7654,13 +8318,13 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
        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));
+                       torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
                }
                break;
        case TORTURE_SAMR_OTHER:
                ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
                if (!ret) {
-                       torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
+                       torture_result(tctx, TORTURE_FAIL, "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(b, tctx, &domain_handle);
@@ -7695,17 +8359,17 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
                break;
        }
 
-       if (!policy_handle_empty(&user_handle) &&
+       if (!ndr_policy_handle_empty(&user_handle) &&
            !test_DeleteUser(b, tctx, &user_handle)) {
                ret = false;
        }
 
-       if (!policy_handle_empty(&alias_handle) &&
+       if (!ndr_policy_handle_empty(&alias_handle) &&
            !test_DeleteAlias(b, tctx, &alias_handle)) {
                ret = false;
        }
 
-       if (!policy_handle_empty(&group_handle) &&
+       if (!ndr_policy_handle_empty(&group_handle) &&
            !test_DeleteDomainGroup(b, tctx, &group_handle)) {
                ret = false;
        }
@@ -7716,7 +8380,7 @@ static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
        /* reconnect the main handle */
 
        if (!ret) {
-               torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
+               torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
        }
 
        return ret;
@@ -7828,7 +8492,7 @@ static bool test_Connect(struct dcerpc_binding_handle *b,
 
        torture_comment(tctx, "Testing samr_Connect\n");
 
-       r.in.system_name = 0;
+       r.in.system_name = NULL;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.out.connect_handle = &h;
 
@@ -7871,7 +8535,7 @@ static bool test_Connect(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
                "Connect3 failed");
        if (!NT_STATUS_IS_OK(r3.out.result)) {
-               torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
+               torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
                ret = false;
        } else {
                if (got_handle) {
@@ -7891,7 +8555,7 @@ static bool test_Connect(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
                "Connect4 failed");
        if (!NT_STATUS_IS_OK(r4.out.result)) {
-               torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
+               torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
                ret = false;
        } else {
                if (got_handle) {
@@ -7917,7 +8581,7 @@ static bool test_Connect(struct dcerpc_binding_handle *b,
        torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
                "Connect5 failed");
        if (!NT_STATUS_IS_OK(r5.out.result)) {
-               torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
+               torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
                ret = false;
        } else {
                if (got_handle) {
@@ -7931,8 +8595,8 @@ static bool test_Connect(struct dcerpc_binding_handle *b,
 }
 
 
-static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
-                                      struct torture_context *tctx)
+static bool test_samr_ValidatePassword(struct torture_context *tctx,
+                                      struct dcerpc_pipe *p)
 {
        struct samr_ValidatePassword r;
        union samr_ValidatePasswordReq req;
@@ -7944,13 +8608,17 @@ static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
 
        torture_comment(tctx, "Testing samr_ValidatePassword\n");
 
+       if (p->conn->transport.transport != NCACN_IP_TCP) {
+               torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\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";
+       req.req3.account.string = "non-existent-account-aklsdji";
 
        for (i=0; passwords[i]; i++) {
                req.req3.password.string = passwords[i];
@@ -8067,8 +8735,6 @@ bool torture_rpc_samr_passwords(struct torture_context *torture)
 
        ret &= test_samr_handle_Close(b, torture, &ctx->handle);
 
-       ret &= test_samr_ValidatePassword(p, torture);
-
        return ret;
 }
 
@@ -8363,4 +9029,15 @@ struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
        return suite;
 }
 
+struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
+       struct torture_rpc_tcase *tcase;
+
+       tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
+                                                 &ndr_table_samr);
+       torture_rpc_tcase_add_test(tcase, "validate",
+                                  test_samr_ValidatePassword);
 
+       return suite;
+}