summaryrefslogtreecommitdiffstats
path: root/source4/torture/rap/sam.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/rap/sam.c')
-rw-r--r--source4/torture/rap/sam.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/source4/torture/rap/sam.c b/source4/torture/rap/sam.c
new file mode 100644
index 0000000..3c13849
--- /dev/null
+++ b/source4/torture/rap/sam.c
@@ -0,0 +1,376 @@
+/*
+ Unix SMB/CIFS implementation.
+ test suite for RAP sam operations
+
+ Copyright (C) Guenther Deschner 2010-2011
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/libcli.h"
+#include "torture/torture.h"
+#include "torture/util.h"
+#include "torture/smbtorture.h"
+#include "torture/util.h"
+#include "libcli/rap/rap.h"
+#include "torture/rap/proto.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "torture/rpc/torture_rpc.h"
+
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+#define TEST_RAP_USER "torture_rap_user"
+
+static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
+{
+ size_t len = MAX(8, min_len);
+ char *s = generate_random_password(mem_ctx, len, len+6);
+ printf("Generated password '%s'\n", s);
+ return s;
+}
+
+static bool test_userpasswordset2_args(struct torture_context *tctx,
+ struct smbcli_state *cli,
+ const char *username,
+ const char **password)
+{
+ struct rap_NetUserPasswordSet2 r;
+ char *newpass = samr_rand_pass(tctx, 8);
+
+ ZERO_STRUCT(r);
+
+ r.in.UserName = username;
+
+ memcpy(r.in.OldPassword, *password, MIN(strlen(*password), 16));
+ memcpy(r.in.NewPassword, newpass, MIN(strlen(newpass), 16));
+ r.in.EncryptedPassword = 0;
+ r.in.RealPasswordLength = strlen(newpass);
+
+ torture_comment(tctx, "Testing rap_NetUserPasswordSet2(%s)\n", r.in.UserName);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuserpasswordset2(cli->tree, tctx, &r),
+ "smbcli_rap_netuserpasswordset2 failed");
+ if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
+ torture_warning(tctx, "RAP NetUserPasswordSet2 gave: %s\n",
+ win_errstr(W_ERROR(r.out.status)));
+ } else {
+ *password = newpass;
+ }
+
+ return true;
+}
+
+static bool test_userpasswordset2_crypt_args(struct torture_context *tctx,
+ struct smbcli_state *cli,
+ const char *username,
+ const char **password)
+{
+ struct rap_NetUserPasswordSet2 r;
+ char *newpass = samr_rand_pass(tctx, 8);
+
+ r.in.UserName = username;
+
+ E_deshash(*password, r.in.OldPassword);
+ E_deshash(newpass, r.in.NewPassword);
+
+ r.in.RealPasswordLength = strlen(newpass);
+ r.in.EncryptedPassword = 1;
+
+ torture_comment(tctx, "Testing rap_NetUserPasswordSet2(%s)\n", r.in.UserName);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuserpasswordset2(cli->tree, tctx, &r),
+ "smbcli_rap_netuserpasswordset2 failed");
+ if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
+ torture_warning(tctx, "RAP NetUserPasswordSet2 gave: %s\n",
+ win_errstr(W_ERROR(r.out.status)));
+ } else {
+ *password = newpass;
+ }
+
+ return true;
+}
+
+static bool test_userpasswordset2(struct torture_context *tctx,
+ struct smbcli_state *cli)
+{
+ struct test_join *join_ctx;
+ const char *password;
+ bool ret = true;
+
+ join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
+ torture_setting_string(tctx, "workgroup", NULL),
+ ACB_NORMAL,
+ &password, 14);
+ if (join_ctx == NULL) {
+ torture_fail(tctx, "failed to create user\n");
+ }
+
+ ret &= test_userpasswordset2_args(tctx, cli, TEST_RAP_USER, &password);
+ ret &= test_userpasswordset2_crypt_args(tctx, cli, TEST_RAP_USER, &password);
+
+ torture_leave_domain(tctx, join_ctx);
+
+ return ret;
+}
+
+static bool test_oemchangepassword_args(struct torture_context *tctx,
+ struct smbcli_state *cli,
+ const char *username,
+ const char **password)
+{
+ struct rap_NetOEMChangePassword r;
+
+ const char *oldpass = *password;
+ char *newpass = samr_rand_pass(tctx, 9);
+ uint8_t old_pw_hash[16];
+ uint8_t new_pw_hash[16];
+ gnutls_cipher_hd_t cipher_hnd = NULL;
+ gnutls_datum_t pw_key = {
+ .data = old_pw_hash,
+ .size = sizeof(old_pw_hash),
+ };
+
+ r.in.UserName = username;
+
+ E_deshash(oldpass, old_pw_hash);
+ E_deshash(newpass, new_pw_hash);
+
+ encode_pw_buffer(r.in.crypt_password, newpass, STR_ASCII);
+
+ gnutls_cipher_init(&cipher_hnd,
+ GNUTLS_CIPHER_ARCFOUR_128,
+ &pw_key,
+ NULL);
+ gnutls_cipher_encrypt(cipher_hnd,
+ r.in.crypt_password,
+ 516);
+ gnutls_cipher_deinit(cipher_hnd);
+ E_old_pw_hash(new_pw_hash, old_pw_hash, r.in.password_hash);
+
+ torture_comment(tctx, "Testing rap_NetOEMChangePassword(%s)\n", r.in.UserName);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netoemchangepassword(cli->tree, tctx, &r),
+ "smbcli_rap_netoemchangepassword failed");
+ if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
+ torture_warning(tctx, "RAP NetOEMChangePassword gave: %s\n",
+ win_errstr(W_ERROR(r.out.status)));
+ } else {
+ *password = newpass;
+ }
+
+ return true;
+}
+
+static bool test_oemchangepassword(struct torture_context *tctx,
+ struct smbcli_state *cli)
+{
+
+ struct test_join *join_ctx;
+ const char *password;
+ bool ret;
+
+ join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
+ torture_setting_string(tctx, "workgroup", NULL),
+ ACB_NORMAL,
+ &password, 14);
+ if (join_ctx == NULL) {
+ torture_fail(tctx, "failed to create user\n");
+ }
+
+ ret = test_oemchangepassword_args(tctx, cli, TEST_RAP_USER, &password);
+
+ torture_leave_domain(tctx, join_ctx);
+
+ return ret;
+}
+
+static bool test_usergetinfo_byname(struct torture_context *tctx,
+ struct smbcli_state *cli,
+ const char *UserName)
+{
+ struct rap_NetUserGetInfo r;
+ int i;
+ uint16_t levels[] = { 0, 1, 2, 10, 11 };
+
+ for (i=0; i < ARRAY_SIZE(levels); i++) {
+
+ r.in.UserName = UserName;
+ r.in.level = levels[i];
+ r.in.bufsize = 8192;
+
+ torture_comment(tctx,
+ "Testing rap_NetUserGetInfo(%s) level %d\n", r.in.UserName, r.in.level);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netusergetinfo(cli->tree, tctx, &r),
+ "smbcli_rap_netusergetinfo failed");
+ torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
+ "smbcli_rap_netusergetinfo failed");
+ }
+
+ return true;
+}
+
+static bool test_usergetinfo(struct torture_context *tctx,
+ struct smbcli_state *cli)
+{
+
+ struct test_join *join_ctx;
+ const char *password;
+ bool ret;
+
+ join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
+ torture_setting_string(tctx, "workgroup", NULL),
+ ACB_NORMAL,
+ &password, 14);
+ if (join_ctx == NULL) {
+ torture_fail(tctx, "failed to create user\n");
+ }
+
+ ret = test_usergetinfo_byname(tctx, cli, TEST_RAP_USER);
+
+ torture_leave_domain(tctx, join_ctx);
+
+ return ret;
+}
+
+static bool test_useradd(struct torture_context *tctx,
+ struct smbcli_state *cli)
+{
+
+ struct rap_NetUserAdd r;
+ struct rap_NetUserInfo1 info1;
+ int i;
+ uint16_t levels[] = { 1 };
+ const char *username = TEST_RAP_USER;
+
+ for (i=0; i < ARRAY_SIZE(levels); i++) {
+
+ const char *pwd;
+
+ pwd = generate_random_password(tctx, 9, 16);
+
+ r.in.level = levels[i];
+ r.in.bufsize = 0xffff;
+ r.in.pwdlength = strlen(pwd);
+ r.in.unknown = 0;
+
+ switch (r.in.level) {
+ case 1:
+ ZERO_STRUCT(info1);
+
+ info1.Name = username;
+ memcpy(info1.Password, pwd, MIN(strlen(pwd), 16));
+ info1.Priv = USER_PRIV_USER;
+ info1.Flags = 0x21;
+ info1.HomeDir = "home_dir";
+ info1.Comment = "comment";
+ info1.ScriptPath = "logon_script";
+
+ r.in.info.info1 = info1;
+ break;
+ }
+
+ torture_comment(tctx,
+ "Testing rap_NetUserAdd(%s) level %d\n", username, r.in.level);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuseradd(cli->tree, tctx, &r),
+ "smbcli_rap_netuseradd failed");
+ torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
+ "smbcli_rap_netuseradd failed");
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuseradd(cli->tree, tctx, &r),
+ "2nd smbcli_rap_netuseradd failed");
+ torture_assert_werr_equal(tctx, W_ERROR(r.out.status), WERR_NERR_USEREXISTS,
+ "2nd smbcli_rap_netuseradd failed");
+
+ {
+ struct rap_NetUserDelete d;
+
+ d.in.UserName = username;
+
+ smbcli_rap_netuserdelete(cli->tree, tctx, &d);
+ }
+ }
+
+ return true;
+}
+
+static bool test_userdelete(struct torture_context *tctx,
+ struct smbcli_state *cli)
+{
+
+ struct rap_NetUserDelete r;
+
+ {
+ struct rap_NetUserAdd a;
+ const char *pwd;
+
+ ZERO_STRUCT(a.in.info.info1);
+
+ pwd = generate_random_password(tctx, 9, 16);
+
+ a.in.level = 1;
+ a.in.bufsize = 0xffff;
+ a.in.pwdlength = strlen(pwd);
+ a.in.unknown = 0;
+ a.in.info.info1.Name = TEST_RAP_USER;
+ a.in.info.info1.Priv = USER_PRIV_USER;
+
+ memcpy(a.in.info.info1.Password, pwd, MIN(strlen(pwd), 16));
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuseradd(cli->tree, tctx, &a),
+ "smbcli_rap_netuseradd failed");
+ }
+
+ r.in.UserName = TEST_RAP_USER;
+
+ torture_comment(tctx,
+ "Testing rap_NetUserDelete(%s)\n", r.in.UserName);
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuserdelete(cli->tree, tctx, &r),
+ "smbcli_rap_netuserdelete failed");
+ torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
+ "smbcli_rap_netuserdelete failed");
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_rap_netuserdelete(cli->tree, tctx, &r),
+ "2nd smbcli_rap_netuserdelete failed");
+ torture_assert_werr_equal(tctx, W_ERROR(r.out.status), WERR_NERR_USERNOTFOUND,
+ "2nd smbcli_rap_netuserdelete failed");
+
+ return true;
+}
+
+struct torture_suite *torture_rap_sam(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "sam");
+
+ torture_suite_add_1smb_test(suite, "userpasswordset2", test_userpasswordset2);
+ torture_suite_add_1smb_test(suite, "oemchangepassword", test_oemchangepassword);
+ torture_suite_add_1smb_test(suite, "usergetinfo", test_usergetinfo);
+ torture_suite_add_1smb_test(suite, "useradd", test_useradd);
+ torture_suite_add_1smb_test(suite, "userdelete", test_userdelete);
+
+ return suite;
+}