diff options
Diffstat (limited to 'source4/torture/rap/sam.c')
-rw-r--r-- | source4/torture/rap/sam.c | 376 |
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; +} |