lib/util: remove extra safe_string.h file
[samba.git] / source4 / torture / rpc / samr.c
index 5bf758e2fb27f7888b0d720057854cd3a4568078..5863a6d1ee6da45933f3f75c9789209c73ada356 100644 (file)
@@ -42,6 +42,9 @@
 #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"
@@ -1006,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);
        }
 
@@ -1095,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;
        }
 
@@ -1104,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;
        }
 
@@ -1271,14 +1274,14 @@ static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
                        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);
                }
 
@@ -1289,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) {
@@ -1297,7 +1300,7 @@ 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;
@@ -2126,7 +2129,7 @@ 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;
        }
@@ -2267,6 +2270,12 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte
        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;
        dom_pw_info.out.info = &info;
@@ -2298,7 +2307,16 @@ 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);
 
        status = init_samr_CryptPassword(newpass,
@@ -2351,6 +2369,11 @@ static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct tort
        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;
@@ -2387,7 +2410,16 @@ 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);
 
        crypt_status = init_samr_CryptPassword(newpass,
@@ -2443,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");
 
@@ -2471,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 */
@@ -2505,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;
@@ -2535,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;
        }
@@ -2561,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;
@@ -2691,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];
-       gnutls_hash_hd_t hash_hnd;
 
        bool ret = true;
        struct lsa_String server, account;
@@ -2704,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);
 
@@ -2727,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",
@@ -2734,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));
 
-       gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
-       gnutls_hash(hash_hnd, confounder, 16);
-       gnutls_hash(hash_hnd, session_key.data, session_key.length);
-       gnutls_hash_deinit(hash_hnd, confounded_session_key.data);
+       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");
 
@@ -2766,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;
@@ -2807,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;