lib/util: remove extra safe_string.h file
[samba.git] / source4 / torture / rpc / samr.c
index 92861f4c8aaaba4f17fa4e060619fe25a75db7c9..5863a6d1ee6da45933f3f75c9789209c73ada356 100644 (file)
@@ -31,7 +31,7 @@
 #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 "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"
+
+#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,
@@ -634,7 +642,6 @@ 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);
@@ -644,7 +651,12 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx
                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");
 
@@ -697,8 +709,6 @@ 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_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
@@ -706,7 +716,12 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
                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");
 
@@ -723,8 +738,6 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
                *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_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
@@ -733,8 +746,17 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t
        }
 
        /* 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");
 
@@ -762,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;
-       MD5_CTX ctx;
        struct samr_GetUserPwInfo pwp;
        struct samr_PwInfo info;
        int policy_min_pw_len = 0;
+
        pwp.in.user_handle = handle;
        pwp.out.info = &info;
 
@@ -788,7 +808,6 @@ 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);
@@ -798,15 +817,12 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc
                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");
 
@@ -824,10 +840,17 @@ 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");
 
@@ -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);
-       MD5_CTX 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,8 +903,6 @@ 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_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
@@ -891,15 +910,12 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t
                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");
 
@@ -917,10 +933,17 @@ 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");
 
@@ -986,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);
        }
 
@@ -1075,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;
        }
 
@@ -1084,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;
        }
 
@@ -1146,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);
-       MD5_CTX ctx;
-       uint8_t confounder[16];
        char *newpass;
        struct dcerpc_binding_handle *b = p->binding_handle;
        struct samr_GetUserPwInfo pwp;
@@ -1224,28 +1244,20 @@ 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;
        }
 
@@ -1256,27 +1268,20 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
                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);
                }
 
@@ -1287,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) {
@@ -1295,23 +1300,41 @@ 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;
        }
 
@@ -2012,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;
@@ -2045,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;
@@ -2072,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);
@@ -2090,13 +2129,18 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
 
        if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
            && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
-               torture_result(tctx, TORTURE_FAIL, "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;
@@ -2172,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;
@@ -2213,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;
@@ -2250,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;
@@ -2296,11 +2367,20 @@ static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct tort
        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;
 
@@ -2330,11 +2410,25 @@ static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct tort
        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);
+       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;
@@ -2381,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");
 
@@ -2409,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 */
@@ -2443,16 +2572,28 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                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;
@@ -2473,7 +2614,7 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct
                        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_result(tctx, TORTURE_FAIL, "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;
        }
@@ -2499,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;
@@ -2629,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];
-       MD5_CTX ctx;
 
        bool ret = true;
        struct lsa_String server, account;
@@ -2642,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);
 
@@ -2665,6 +2826,8 @@ 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_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
@@ -2672,15 +2835,15 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex
                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");
 
@@ -2704,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;
@@ -2745,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;
@@ -3058,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) {