-/*
+/*
Unix SMB/CIFS implementation.
test suite for samr rpc operations
Copyright (C) Andrew Tridgell 2003
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
-
+
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 "torture/torture.h"
#include "system/time.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 "../lib/crypto/crypto.h"
#include "libcli/auth/libcli_auth.h"
#include "libcli/security/security.h"
#include "torture/rpc/rpc.h"
+#include "param/param.h"
+
+#include <unistd.h>
#define TEST_ACCOUNT_NAME "samrtorturetest"
+#define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
#define TEST_ALIASNAME "samrtorturetestalias"
#define TEST_GROUPNAME "samrtorturetestgroup"
#define TEST_MACHINENAME "samrtestmach$"
enum torture_samr_choice {
TORTURE_SAMR_PASSWORDS,
+ TORTURE_SAMR_PASSWORDS_PWDLASTSET,
TORTURE_SAMR_USER_ATTRIBUTES,
TORTURE_SAMR_OTHER
};
-static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryUserInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle);
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle);
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *handle);
+static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle);
-static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- const char *acct_name,
+static bool test_ChangePassword(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ const char *acct_name,
struct policy_handle *domain_handle, char **password);
static void init_lsa_String(struct lsa_String *string, const char *s)
}
-static bool test_QuerySecurity(struct dcerpc_pipe *p,
- struct torture_context *tctx,
+static bool test_QuerySecurity(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
}
-static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle, uint32_t base_acct_flags,
const char *base_account_name)
{
const char *test_account_name;
uint32_t user_extra_flags = 0;
- if (base_acct_flags == ACB_NORMAL) {
- /* When created, accounts are expired by default */
- user_extra_flags = ACB_PW_EXPIRED;
+
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ if (base_acct_flags == ACB_NORMAL) {
+ /* When created, accounts are expired by default */
+ user_extra_flags = ACB_PW_EXPIRED;
+ }
}
s.in.user_handle = handle;
q0.in.level = 12;
do { TESTCALL(QueryUserInfo, q0) } while (0);
- TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
- TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
- TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
- SAMR_FIELD_COMMENT);
+ /* Samba 3 cannot store comment fields atm. - gd */
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
+ TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
+ TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
+ 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_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
TEST_USERINFO_STRING(7, account_name, 21, account_name, base_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, base_account_name,
SAMR_FIELD_ACCOUNT_NAME);
TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
- TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
+ TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
SAMR_FIELD_FULL_NAME);
TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
- TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
+ TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
SAMR_FIELD_FULL_NAME);
TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
- TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
+ TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
SAMR_FIELD_LOGON_SCRIPT);
TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
- TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
+ TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
SAMR_FIELD_PROFILE_PATH);
TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
SAMR_FIELD_HOME_DRIVE);
TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
SAMR_FIELD_HOME_DRIVE);
-
+
TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
- TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
+ TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
SAMR_FIELD_DESCRIPTION);
TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
- TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
+ TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
SAMR_FIELD_WORKSTATIONS);
- TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
+ TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
SAMR_FIELD_WORKSTATIONS);
- TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
+ TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
SAMR_FIELD_WORKSTATIONS);
- TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
+ TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
SAMR_FIELD_WORKSTATIONS);
TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
SAMR_FIELD_PARAMETERS);
TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
SAMR_FIELD_PARAMETERS);
+ /* also empty user parameters are allowed */
+ TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
+ TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
+ SAMR_FIELD_PARAMETERS);
+ TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
+ SAMR_FIELD_PARAMETERS);
- TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
- TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
- TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
- SAMR_FIELD_COUNTRY_CODE);
- TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
- SAMR_FIELD_COUNTRY_CODE);
-
- TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
- TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
- SAMR_FIELD_CODE_PAGE);
- TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
- SAMR_FIELD_CODE_PAGE);
-
- TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
- TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
- TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
- SAMR_FIELD_ACCT_EXPIRY);
- TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
- SAMR_FIELD_ACCT_EXPIRY);
- TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
- SAMR_FIELD_ACCT_EXPIRY);
+ /* Samba 3 cannot store country_code and copy_page atm. - gd */
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
+ TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
+ TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
+ SAMR_FIELD_COUNTRY_CODE);
+ TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
+ SAMR_FIELD_COUNTRY_CODE);
+
+ TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
+ TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
+ SAMR_FIELD_CODE_PAGE);
+ TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
+ SAMR_FIELD_CODE_PAGE);
+ }
+
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
+ TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
+ TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
+ SAMR_FIELD_ACCT_EXPIRY);
+ TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
+ SAMR_FIELD_ACCT_EXPIRY);
+ TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
+ SAMR_FIELD_ACCT_EXPIRY);
+ } else {
+ /* Samba 3 can only store seconds / time_t in passdb - gd */
+ NTTIME nt;
+ unix_to_nt_time(&nt, time(NULL) + __LINE__);
+ TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
+ unix_to_nt_time(&nt, time(NULL) + __LINE__);
+ TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
+ unix_to_nt_time(&nt, time(NULL) + __LINE__);
+ TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+ unix_to_nt_time(&nt, time(NULL) + __LINE__);
+ TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+ unix_to_nt_time(&nt, time(NULL) + __LINE__);
+ TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
+ }
TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
- TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
+ TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
SAMR_FIELD_LOGON_HOURS);
- TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
- (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
- (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+ (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
+ (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
0);
- TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
- (base_acct_flags | ACB_DISABLED),
- (base_acct_flags | ACB_DISABLED | user_extra_flags),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+ (base_acct_flags | ACB_DISABLED),
+ (base_acct_flags | ACB_DISABLED | user_extra_flags),
0);
-
+
/* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
- TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
- (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
- (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
+ (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
+ (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
0);
- TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
- (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
- (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+ (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
+ (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
0);
/* The 'autolock' flag doesn't stick - check this */
- TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
- (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
- (base_acct_flags | ACB_DISABLED | user_extra_flags),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+ (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
+ (base_acct_flags | ACB_DISABLED | user_extra_flags),
0);
#if 0
/* Removing the 'disabled' flag doesn't stick - check this */
- TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
- (base_acct_flags),
- (base_acct_flags | ACB_DISABLED | user_extra_flags),
+ TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
+ (base_acct_flags),
+ (base_acct_flags | ACB_DISABLED | user_extra_flags),
0);
#endif
+
+ /* 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),
+ 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),
+ 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),
+ 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),
+ 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),
- (base_acct_flags | ACB_DISABLED | user_extra_flags),
+ }
+ TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
+ (base_acct_flags | ACB_DISABLED),
+ (base_acct_flags | ACB_DISABLED | user_extra_flags),
SAMR_FIELD_ACCT_FLAGS);
#if 0
/*
generate a random password for password change tests
*/
-static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
+static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
{
size_t len = MAX(8, min_len) + (random() % 6);
char *s = generate_random_str(mem_ctx, len);
+ return s;
+}
+
+static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
+{
+ char *s = samr_rand_pass_silent(mem_ctx, min_len);
printf("Generated password '%s'\n", s);
return s;
+
}
/*
s.in.level = 24;
encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
- /* w2k3 ignores this length */
- u.info24.pw_len = strlen_m(newpass) * 2;
+ u.info24.password_expired = 0;
status = dcerpc_fetch_session_key(p, &session_key);
if (!NT_STATUS_IS_OK(status)) {
static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *handle, bool makeshort,
+ struct policy_handle *handle, bool makeshort,
char **password)
{
NTSTATUS status;
s.in.level = 26;
encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
- u.info26.pw_len = strlen(newpass);
+ u.info26.password_expired = 0;
status = dcerpc_fetch_session_key(p, &session_key);
if (!NT_STATUS_IS_OK(status)) {
return ret;
}
+static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
+ struct policy_handle *handle, char **password)
+{
+ NTSTATUS status;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ bool ret = true;
+ DATA_BLOB session_key;
+ char *newpass;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
+ int policy_min_pw_len = 0;
+ uint8_t lm_hash[16], nt_hash[16];
+
+ pwp.in.user_handle = handle;
+ pwp.out.info = &info;
+
+ status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ }
+ newpass = samr_rand_pass(tctx, policy_min_pw_len);
+
+ s.in.user_handle = handle;
+ s.in.info = &u;
+ s.in.level = 18;
+
+ ZERO_STRUCT(u);
+
+ u.info18.nt_pwd_active = true;
+ u.info18.lm_pwd_active = true;
+
+ E_md4hash(newpass, nt_hash);
+ E_deshash(newpass, lm_hash);
+
+ status = dcerpc_fetch_session_key(p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ return false;
+ }
+
+ {
+ 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);
+ 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);
+ memcpy(u.info18.lm_pwd.hash, out.data, out.length);
+ }
+
+ torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
+
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u failed - %s\n",
+ s.in.level, nt_errstr(status));
+ ret = false;
+ } else {
+ *password = newpass;
+ }
+
+ return ret;
+}
+
+static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
+ struct policy_handle *handle, uint32_t fields_present,
+ char **password)
+{
+ NTSTATUS status;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ bool ret = true;
+ DATA_BLOB session_key;
+ char *newpass;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
+ int policy_min_pw_len = 0;
+ uint8_t lm_hash[16], nt_hash[16];
+
+ pwp.in.user_handle = handle;
+ pwp.out.info = &info;
+
+ status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ }
+ newpass = samr_rand_pass(tctx, policy_min_pw_len);
+
+ s.in.user_handle = handle;
+ s.in.info = &u;
+ s.in.level = 21;
+
+ E_md4hash(newpass, nt_hash);
+ E_deshash(newpass, lm_hash);
+
+ ZERO_STRUCT(u);
+
+ u.info21.fields_present = fields_present;
+
+ if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ u.info21.lm_owf_password.length = 16;
+ u.info21.lm_owf_password.size = 16;
+ u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
+ u.info21.lm_password_set = true;
+ }
+
+ if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+ u.info21.nt_owf_password.length = 16;
+ u.info21.nt_owf_password.size = 16;
+ u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
+ u.info21.nt_password_set = true;
+ }
+
+ status = dcerpc_fetch_session_key(p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ return false;
+ }
+
+ if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ DATA_BLOB in,out;
+ 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);
+ u.info21.lm_owf_password.array = (uint16_t *)out.data;
+ }
+
+ if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+ DATA_BLOB in,out;
+ 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);
+ u.info21.nt_owf_password.array = (uint16_t *)out.data;
+ }
+
+ torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
+
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u failed - %s\n",
+ s.in.level, nt_errstr(status));
+ ret = false;
+ } else {
+ *password = newpass;
+ }
+
+ /* try invalid length */
+ if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+
+ u.info21.nt_owf_password.length++;
+
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+ s.in.level, nt_errstr(status));
+ ret = false;
+ }
+ }
+
+ if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+
+ u.info21.lm_owf_password.length++;
+
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
+ s.in.level, nt_errstr(status));
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ uint16_t level,
+ uint32_t fields_present,
+ char **password, uint8_t password_expired,
+ bool use_setinfo2,
+ bool *matched_expected_error)
+{
+ NTSTATUS status;
+ NTSTATUS expected_error = NT_STATUS_OK;
+ struct samr_SetUserInfo s;
+ struct samr_SetUserInfo2 s2;
+ 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 samr_GetUserPwInfo pwp;
+ struct samr_PwInfo info;
+ int policy_min_pw_len = 0;
+ const char *comment = NULL;
+ uint8_t lm_hash[16], nt_hash[16];
+
+ pwp.in.user_handle = handle;
+ pwp.out.info = &info;
+
+ status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info->min_password_length;
+ }
+ newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
+
+ if (use_setinfo2) {
+ s2.in.user_handle = handle;
+ s2.in.info = &u;
+ s2.in.level = level;
+ } else {
+ s.in.user_handle = handle;
+ s.in.info = &u;
+ s.in.level = level;
+ }
+
+ if (fields_present & SAMR_FIELD_COMMENT) {
+ comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
+ }
+
+ ZERO_STRUCT(u);
+
+ switch (level) {
+ case 18:
+ E_md4hash(newpass, nt_hash);
+ E_deshash(newpass, lm_hash);
+
+ u.info18.nt_pwd_active = true;
+ u.info18.lm_pwd_active = true;
+ u.info18.password_expired = password_expired;
+
+ memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
+ memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
+
+ break;
+ case 21:
+ E_md4hash(newpass, nt_hash);
+ E_deshash(newpass, lm_hash);
+
+ u.info21.fields_present = fields_present;
+ u.info21.password_expired = password_expired;
+ u.info21.comment.string = comment;
+
+ if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ u.info21.lm_owf_password.length = 16;
+ u.info21.lm_owf_password.size = 16;
+ u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
+ u.info21.lm_password_set = true;
+ }
+
+ if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+ u.info21.nt_owf_password.length = 16;
+ u.info21.nt_owf_password.size = 16;
+ u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
+ u.info21.nt_password_set = true;
+ }
+
+ break;
+ case 23:
+ u.info23.info.fields_present = fields_present;
+ 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)) {
+ printf("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);
+ 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);
+ memcpy(u.info18.lm_pwd.hash, out.data, out.length);
+ }
+
+ break;
+ case 21:
+ if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ DATA_BLOB in,out;
+ 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);
+ u.info21.lm_owf_password.array = (uint16_t *)out.data;
+ }
+ if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
+ DATA_BLOB in,out;
+ 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);
+ u.info21.nt_owf_password.array = (uint16_t *)out.data;
+ }
+ break;
+ case 23:
+ arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
+ break;
+ case 24:
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+ break;
+ case 25:
+ arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
+ memcpy(&u.info25.password.data[516], confounder, 16);
+ break;
+ case 26:
+ arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
+ memcpy(&u.info26.password.data[516], confounder, 16);
+ break;
+ }
+
+ if (use_setinfo2) {
+ status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
+ } else {
+ status = dcerpc_samr_SetUserInfo(p, tctx, &s);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ if (fields_present == 0) {
+ expected_error = NT_STATUS_INVALID_PARAMETER;
+ }
+ if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
+ expected_error = NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(expected_error)) {
+ if (use_setinfo2) {
+ torture_assert_ntstatus_equal(tctx,
+ s2.out.result,
+ expected_error, "SetUserInfo2 failed");
+ } else {
+ torture_assert_ntstatus_equal(tctx,
+ s.out.result,
+ expected_error, "SetUserInfo failed");
+ }
+ *matched_expected_error = true;
+ return true;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo%s level %u failed - %s\n",
+ use_setinfo2 ? "2":"", level, nt_errstr(status));
+ ret = false;
+ } else {
+ *password = newpass;
+ }
+
+ return ret;
+}
+
static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle)
{
n.in.num_names = 2;
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
- printf("LookupNames[2] failed - %s\n", nt_errstr(status));
+ printf("LookupNames[2] failed - %s\n", nt_errstr(status));
if (NT_STATUS_IS_OK(status)) {
return NT_STATUS_UNSUCCESSFUL;
}
n.in.num_names = 0;
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_IS_OK(status)) {
- printf("LookupNames[0] failed - %s\n", nt_errstr(status));
+ printf("LookupNames[0] failed - %s\n", nt_errstr(status));
return status;
}
n.in.num_names = 1;
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
- printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
+ printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
if (NT_STATUS_IS_OK(status)) {
return NT_STATUS_UNSUCCESSFUL;
}
n.in.num_names = 2;
status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
- printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
+ printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
if (NT_STATUS_IS_OK(status)) {
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_OK;
}
-static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *domain_handle,
const char *name, struct policy_handle *user_handle)
{
struct samr_OpenUser r;
uint32_t rid;
- status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
+ status = test_LookupName(p, tctx, domain_handle, name, &rid);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
r.in.rid = rid;
r.out.user_handle = user_handle;
- status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenUser(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
}
}
#if 0
-static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
uint8_t old_nt_hash[16], new_nt_hash[16];
uint8_t old_lm_hash[16], new_lm_hash[16];
- status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
+ status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
if (!NT_STATUS_IS_OK(status)) {
return false;
}
r.in.cross2_present = 1;
r.in.lm_cross = &hash6;
- status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
+ status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
ret = false;
}
- if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+ if (!test_samr_handle_Close(p, tctx, &user_handle)) {
ret = false;
}
#endif
static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
- const char *acct_name,
+ const char *acct_name,
struct policy_handle *handle, char **password)
{
NTSTATUS status;
torture_comment(tctx, "Testing ChangePasswordUser\n");
- torture_assert(tctx, *password != NULL,
+ torture_assert(tctx, *password != NULL,
"Failing ChangePasswordUser as old password was NULL. Previous test failed?");
oldpass = *password;
r.in.lm_cross = &hash6;
status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
- torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
"expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
/* Unbreak the NT hash */
}
}
-
+
if (!test_samr_handle_Close(p, tctx, &user_handle)) {
ret = false;
}
torture_comment(tctx, "Testing OemChangePasswordUser2\n");
- torture_assert(tctx, *password != NULL,
+ torture_assert(tctx, *password != NULL,
"Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
oldpass = *password;
torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
- torture_assert(tctx, *password != NULL,
+ torture_assert(tctx, *password != NULL,
"Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
oldpass = *password;
}
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);
}
-bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
+bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
const char *account_string,
int policy_min_pw_len,
char **password,
torture_comment(tctx, "Using password '%s'\n", newpass);
}
- torture_assert(tctx, *password != NULL,
+ torture_assert(tctx, *password != NULL,
"Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
oldpass = *password;
encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
arcfour_crypt(nt_pass.data, old_nt_hash, 516);
E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
-
+
/* Break the verification */
nt_verifier.hash[0]++;
nt_errstr(status));
ret = false;
}
-
+
encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
arcfour_crypt(lm_pass.data, old_nt_hash, 516);
E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
/* Unbreak it again */
old_nt_hash[0]--;
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;
nt_errstr(status));
ret = false;
}
-
+
/* This shouldn't be a valid name */
init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
- printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
+ printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
SAMR_REJECT_OTHER, reject->reason);
return false;
}
}
/* We tested the order of precendence which is as follows:
-
- * pwd min_age
+
+ * pwd min_age
* pwd length
* pwd complexity
* pwd history
(last_password_change + dominfo->min_password_age > t)) {
if (reject->reason != SAMR_REJECT_OTHER) {
- printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
+ printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
SAMR_REJECT_OTHER, reject->reason);
return false;
}
(strlen(newpass) < dominfo->min_password_length)) {
if (reject->reason != SAMR_REJECT_TOO_SHORT) {
- printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
+ printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
SAMR_REJECT_TOO_SHORT, reject->reason);
return false;
}
strequal(oldpass, newpass)) {
if (reject->reason != SAMR_REJECT_IN_HISTORY) {
- printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
+ printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
SAMR_REJECT_IN_HISTORY, reject->reason);
return false;
}
} else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
if (reject->reason != SAMR_REJECT_COMPLEXITY) {
- printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
+ printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
SAMR_REJECT_COMPLEXITY, reject->reason);
return false;
}
if (reject->reason == SAMR_REJECT_TOO_SHORT) {
/* retry with adjusted size */
- return test_ChangePasswordUser3(p, tctx, account_string,
+ return test_ChangePasswordUser3(p, tctx, account_string,
dominfo->min_password_length,
- password, NULL, 0, false);
+ password, NULL, 0, false);
}
} else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
if (reject && reject->reason != SAMR_REJECT_OTHER) {
- printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
+ printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
SAMR_REJECT_OTHER, reject->reason);
return false;
}
/* Perhaps the server has a 'min password age' set? */
- } else {
+ } else {
torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
*password = talloc_strdup(tctx, newpass);
}
bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
const char *account_string,
- struct policy_handle *handle,
+ struct policy_handle *handle,
char **password)
{
NTSTATUS status;
new_random_pass = samr_very_rand_pass(tctx, 128);
- torture_assert(tctx, *password != NULL,
+ torture_assert(tctx, *password != NULL,
"Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
oldpass = *password;
ZERO_STRUCT(u);
- u.info25.info.fields_present = SAMR_FIELD_PASSWORD;
+ u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
set_pw_in_buffer(u.info25.password.data, &new_random_pass);
if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
if (reject && reject->reason != SAMR_REJECT_OTHER) {
- printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
+ printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
SAMR_REJECT_OTHER, reject->reason);
return false;
}
printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
ret = false;
}
-
+
newpass = samr_rand_pass(tctx, 128);
mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
if (reject && reject->reason != SAMR_REJECT_OTHER) {
- printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
+ printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
SAMR_REJECT_OTHER, reject->reason);
return false;
}
r.in.alias_handle = alias_handle;
r.in.sid = sid;
- status = dcerpc_samr_AddAliasMember(p, tctx, &r);
- torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
+ status = dcerpc_samr_AddAliasMember(p, tctx, &r);
+ torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
+
+ d.in.alias_handle = alias_handle;
+ d.in.sid = sid;
+
+ status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
+ torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
+
+ return true;
+}
+
+static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
+ struct policy_handle *alias_handle)
+{
+ struct samr_AddMultipleMembersToAlias a;
+ struct samr_RemoveMultipleMembersFromAlias r;
+ NTSTATUS status;
+ struct lsa_SidArray sids;
+
+ torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
+ a.in.alias_handle = alias_handle;
+ a.in.sids = &sids;
+
+ sids.num_sids = 3;
+ sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
+
+ sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
+ sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
+ sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
+
+ status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
+ torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
+
+
+ torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
+ r.in.alias_handle = alias_handle;
+ r.in.sids = &sids;
+
+ status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
+ torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+
+ /* strange! removing twice doesn't give any error */
+ status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
+ torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+
+ /* but removing an alias that isn't there does */
+ sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
+
+ status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
+
+ return true;
+}
+
+static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
+ struct policy_handle *user_handle)
+{
+ struct samr_TestPrivateFunctionsUser r;
+ NTSTATUS status;
+
+ torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
+
+ r.in.user_handle = user_handle;
+
+ status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
+
+ return true;
+}
+
+static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ bool use_info2,
+ NTTIME *pwdlastset)
+{
+ NTSTATUS status;
+ uint16_t levels[] = { /* 3, */ 5, 21 };
+ int i;
+ NTTIME pwdlastset3 = 0;
+ NTTIME pwdlastset5 = 0;
+ NTTIME pwdlastset21 = 0;
+
+ torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
+ use_info2 ? "2":"");
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+ struct samr_QueryUserInfo r;
+ struct samr_QueryUserInfo2 r2;
+ union samr_UserInfo *info;
+
+ if (use_info2) {
+ r2.in.user_handle = handle;
+ r2.in.level = levels[i];
+ r2.out.info = &info;
+ status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
+
+ } else {
+ r.in.user_handle = handle;
+ r.in.level = levels[i];
+ r.out.info = &info;
+ status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
+ }
+
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
+ printf("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;
+ break;
+ case 5:
+ pwdlastset5 = info->info5.last_password_change;
+ break;
+ case 21:
+ pwdlastset21 = info->info21.last_password_change;
+ break;
+ default:
+ return false;
+ }
+ }
+ /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
+ "pwdlastset mixup"); */
+ torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
+ "pwdlastset mixup");
+
+ *pwdlastset = pwdlastset21;
+
+ torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
+
+ return true;
+}
+
+static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
+ struct cli_credentials *machine_credentials,
+ struct cli_credentials *test_credentials,
+ struct netlogon_creds_CredentialState *creds,
+ NTSTATUS expected_result)
+{
+ NTSTATUS status;
+ struct netr_LogonSamLogon r;
+ struct netr_Authenticator auth, auth2;
+ union netr_LogonLevel logon;
+ union netr_Validation validation;
+ uint8_t authoritative;
+ struct netr_NetworkInfo ninfo;
+ DATA_BLOB names_blob, chal, lm_resp, nt_resp;
+ int flags = CLI_CRED_NTLM_AUTH;
+
+ if (lp_client_lanman_auth(tctx->lp_ctx)) {
+ flags |= CLI_CRED_LANMAN_AUTH;
+ }
+
+ if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
+ flags |= CLI_CRED_NTLMv2_AUTH;
+ }
+
+ cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
+ &ninfo.identity_info.account_name.string,
+ &ninfo.identity_info.domain_name.string);
+
+ generate_random_buffer(ninfo.challenge,
+ sizeof(ninfo.challenge));
+ chal = data_blob_const(ninfo.challenge,
+ sizeof(ninfo.challenge));
+
+ names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
+ cli_credentials_get_domain(machine_credentials));
+
+ status = cli_credentials_get_ntlm_response(test_credentials, tctx,
+ &flags,
+ chal,
+ names_blob,
+ &lm_resp, &nt_resp,
+ NULL, NULL);
+ torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
+
+ ninfo.lm.data = lm_resp.data;
+ ninfo.lm.length = lm_resp.length;
+
+ ninfo.nt.data = nt_resp.data;
+ ninfo.nt.length = nt_resp.length;
+
+ ninfo.identity_info.parameter_control =
+ MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
+ MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
+ ninfo.identity_info.logon_id_low = 0;
+ ninfo.identity_info.logon_id_high = 0;
+ ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
+
+ logon.network = &ninfo;
+
+ r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+ r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
+ r.in.credential = &auth;
+ r.in.return_authenticator = &auth2;
+ r.in.logon_level = 2;
+ r.in.logon = &logon;
+ r.out.validation = &validation;
+ r.out.authoritative = &authoritative;
+
+ d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
+
+ ZERO_STRUCT(auth2);
+ netlogon_creds_client_authenticator(creds, &auth);
+
+ r.in.validation_level = 2;
+
+ status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
+ return true;
+ } else {
+ torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
+ }
+
+ torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
+ "Credential chaining failed");
+
+ return true;
+}
+
+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)
+{
+ struct netlogon_creds_CredentialState *creds;
+
+ if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
+ return false;
+ }
+
+ return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
+ creds, expected_result);
+}
+
+static bool test_SamLogon_with_creds(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *machine_creds,
+ const char *acct_name,
+ char *password,
+ NTSTATUS expected_samlogon_result)
+{
+ bool ret = true;
+ struct cli_credentials *test_credentials;
+
+ test_credentials = cli_credentials_init(tctx);
+
+ cli_credentials_set_workstation(test_credentials,
+ TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
+ cli_credentials_set_domain(test_credentials,
+ lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
+ cli_credentials_set_username(test_credentials,
+ acct_name, CRED_SPECIFIED);
+ cli_credentials_set_password(test_credentials,
+ password, CRED_SPECIFIED);
+ cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
+
+ printf("testing samlogon as %s@%s password: %s\n",
+ acct_name, TEST_ACCOUNT_NAME_PWD, password);
+
+ if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
+ expected_samlogon_result)) {
+ torture_warning(tctx, "new password did not work\n");
+ ret = false;
+ }
+
+ return ret;
+}
+
+static bool test_SetPassword_level(struct dcerpc_pipe *p,
+ struct dcerpc_pipe *np,
+ struct torture_context *tctx,
+ struct policy_handle *handle,
+ uint16_t level,
+ uint32_t fields_present,
+ uint8_t password_expired,
+ bool *matched_expected_error,
+ bool use_setinfo2,
+ const char *acct_name,
+ char **password,
+ struct cli_credentials *machine_creds,
+ bool use_queryinfo2,
+ NTTIME *pwdlastset,
+ NTSTATUS expected_samlogon_result)
+{
+ const char *fields = NULL;
+ bool ret = true;
+
+ switch (level) {
+ case 21:
+ case 23:
+ case 25:
+ fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
+ fields_present);
+ break;
+ default:
+ break;
+ }
+
+ torture_comment(tctx, "Testing SetUserInfo%s level %d call "
+ "(password_expired: %d) %s\n",
+ use_setinfo2 ? "2":"", level, password_expired,
+ fields ? fields : "");
+
+ if (!test_SetUserPass_level_ex(p, tctx, handle, level,
+ fields_present,
+ password,
+ password_expired,
+ use_setinfo2,
+ matched_expected_error)) {
+ ret = false;
+ }
+
+ if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
+ use_queryinfo2,
+ pwdlastset)) {
+ ret = false;
+ }
+
+ if (*matched_expected_error == true) {
+ return ret;
+ }
+
+ if (!test_SamLogon_with_creds(tctx, np,
+ machine_creds,
+ acct_name,
+ *password,
+ expected_samlogon_result)) {
+ ret = false;
+ }
+
+ return ret;
+}
+
+static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ uint32_t acct_flags,
+ const char *acct_name,
+ struct policy_handle *handle,
+ char **password,
+ struct cli_credentials *machine_credentials)
+{
+ int s = 0, q = 0, f = 0, l = 0, z = 0;
+ bool ret = true;
+ int delay = 500000;
+ bool set_levels[] = { false, true };
+ bool query_levels[] = { false, true };
+ uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
+ uint32_t nonzeros[] = { 1, 24 };
+ uint32_t fields_present[] = {
+ 0,
+ SAMR_FIELD_EXPIRED_FLAG,
+ SAMR_FIELD_LAST_PWD_CHANGE,
+ SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
+ SAMR_FIELD_COMMENT,
+ SAMR_FIELD_NT_PASSWORD_PRESENT,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
+ };
+ NTSTATUS status;
+ struct dcerpc_pipe *np = NULL;
+
+ if (torture_setting_bool(tctx, "samba3", false)) {
+ delay = 1000000;
+ printf("Samba3 has second granularity, setting delay to: %d\n",
+ delay);
+ }
+
+ status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ /* set to 1 to enable testing for all possible opcode
+ (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
+ combinations */
+#if 0
+#define TEST_SET_LEVELS 1
+#define TEST_QUERY_LEVELS 1
+#endif
+ for (l=0; l<ARRAY_SIZE(levels); l++) {
+ for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
+ for (f=0; f<ARRAY_SIZE(fields_present); f++) {
+#ifdef TEST_SET_LEVELS
+ for (s=0; s<ARRAY_SIZE(set_levels); s++) {
+#endif
+#ifdef TEST_QUERY_LEVELS
+ for (q=0; q<ARRAY_SIZE(query_levels); q++) {
+#endif
+ NTTIME pwdlastset_old = 0;
+ NTTIME pwdlastset_new = 0;
+ bool matched_expected_error = false;
+ NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
+
+ torture_comment(tctx, "------------------------------\n"
+ "Testing pwdLastSet attribute for flags: 0x%08x "
+ "(s: %d (l: %d), q: %d)\n",
+ acct_flags, s, levels[l], q);
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
+ expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
+ }
+ break;
+ }
+
+
+ /* set #1 */
+
+ /* set a password and force password change (pwdlastset 0) by
+ * setting the password expired flag to a non-0 value */
+
+ if (!test_SetPassword_level(p, np, tctx, handle,
+ levels[l],
+ fields_present[f],
+ nonzeros[z],
+ &matched_expected_error,
+ set_levels[s],
+ acct_name,
+ password,
+ machine_credentials,
+ query_levels[q],
+ &pwdlastset_old,
+ expected_samlogon_result)) {
+ ret = false;
+ }
+
+ if (matched_expected_error == true) {
+ /* skipping on expected failure */
+ continue;
+ }
+
+ /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
+ * set without the SAMR_FIELD_EXPIRED_FLAG */
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if ((pwdlastset_new != 0) &&
+ !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
+ torture_comment(tctx, "not considering a non-0 "
+ "pwdLastSet as a an error as the "
+ "SAMR_FIELD_EXPIRED_FLAG has not "
+ "been set\n");
+ break;
+ }
+ default:
+ if (pwdlastset_new != 0) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected pwdLastSet 0 but got %lld\n",
+ pwdlastset_old);
+ ret = false;
+ }
+ break;
+ }
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (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");
+ ret = false;
+ }
+ break;
+ default:
+ if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
+ (pwdlastset_old >= pwdlastset_new)) {
+ torture_warning(tctx, "pwdlastset not increasing\n");
+ ret = false;
+ }
+ break;
+ }
+
+ usleep(delay);
+
+ /* set #2 */
+
+ /* set a password, pwdlastset needs to get updated (increased
+ * value), password_expired value used here is 0 */
+
+ if (!test_SetPassword_level(p, np, tctx, handle,
+ levels[l],
+ fields_present[f],
+ 0,
+ &matched_expected_error,
+ set_levels[s],
+ acct_name,
+ password,
+ machine_credentials,
+ query_levels[q],
+ &pwdlastset_new,
+ expected_samlogon_result)) {
+ ret = false;
+ }
+
+ /* when a password has been changed, pwdlastset must not be 0 afterwards
+ * and must be larger then the old value */
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+
+ /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
+ * password has been changed, old and new pwdlastset
+ * need to be the same value */
+
+ if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
+ !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
+ {
+ torture_assert_int_equal(tctx, pwdlastset_old,
+ pwdlastset_new, "pwdlastset must be equal");
+ break;
+ }
+ default:
+ if (pwdlastset_old >= pwdlastset_new) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
+ pwdlastset_old, pwdlastset_new);
+ ret = false;
+ }
+ if (pwdlastset_new == 0) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected non-0 pwdlastset, got: %lld\n",
+ pwdlastset_new);
+ ret = false;
+ }
+ }
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (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");
+ ret = false;
+ }
+ break;
+ default:
+ if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
+ (pwdlastset_old >= pwdlastset_new)) {
+ torture_warning(tctx, "pwdlastset not increasing\n");
+ ret = false;
+ }
+ break;
+ }
- d.in.alias_handle = alias_handle;
- d.in.sid = sid;
+ pwdlastset_old = pwdlastset_new;
- status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
- torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
+ usleep(delay);
- return true;
-}
+ /* set #2b */
-static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *alias_handle)
-{
- struct samr_AddMultipleMembersToAlias a;
- struct samr_RemoveMultipleMembersFromAlias r;
- NTSTATUS status;
- struct lsa_SidArray sids;
+ /* set a password, pwdlastset needs to get updated (increased
+ * value), password_expired value used here is 0 */
- torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
- a.in.alias_handle = alias_handle;
- a.in.sids = &sids;
+ if (!test_SetPassword_level(p, np, tctx, handle,
+ levels[l],
+ fields_present[f],
+ 0,
+ &matched_expected_error,
+ set_levels[s],
+ acct_name,
+ password,
+ machine_credentials,
+ query_levels[q],
+ &pwdlastset_new,
+ expected_samlogon_result)) {
+ ret = false;
+ }
- sids.num_sids = 3;
- sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
+ /* when a password has been changed, pwdlastset must not be 0 afterwards
+ * and must be larger then the old value */
- sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
- sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
- sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
- status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
- torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
+ /* if no password has been changed, old and new pwdlastset
+ * need to be the same value */
+ if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
+ {
+ torture_assert_int_equal(tctx, pwdlastset_old,
+ pwdlastset_new, "pwdlastset must be equal");
+ break;
+ }
+ default:
+ if (pwdlastset_old >= pwdlastset_new) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
+ pwdlastset_old, pwdlastset_new);
+ ret = false;
+ }
+ if (pwdlastset_new == 0) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected non-0 pwdlastset, got: %lld\n",
+ pwdlastset_new);
+ ret = false;
+ }
+ }
- torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
- r.in.alias_handle = alias_handle;
- r.in.sids = &sids;
+ /* set #3 */
+
+ /* set a password and force password change (pwdlastset 0) by
+ * setting the password expired flag to a non-0 value */
+
+ if (!test_SetPassword_level(p, np, tctx, handle,
+ levels[l],
+ fields_present[f],
+ nonzeros[z],
+ &matched_expected_error,
+ set_levels[s],
+ acct_name,
+ password,
+ machine_credentials,
+ query_levels[q],
+ &pwdlastset_new,
+ expected_samlogon_result)) {
+ ret = false;
+ }
- status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
- torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+ /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
+ * set without the SAMR_FIELD_EXPIRED_FLAG */
+
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if ((pwdlastset_new != 0) &&
+ !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
+ torture_comment(tctx, "not considering a non-0 "
+ "pwdLastSet as a an error as the "
+ "SAMR_FIELD_EXPIRED_FLAG has not "
+ "been set\n");
+ break;
+ }
- /* strange! removing twice doesn't give any error */
- status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
- torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
+ /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
+ * password has been changed, old and new pwdlastset
+ * need to be the same value */
- /* but removing an alias that isn't there does */
- sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
+ if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
+ !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
+ {
+ torture_assert_int_equal(tctx, pwdlastset_old,
+ pwdlastset_new, "pwdlastset must be equal");
+ break;
+ }
+ default:
- status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
- torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
+ if (pwdlastset_old == pwdlastset_new) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
+ pwdlastset_old, pwdlastset_new);
+ ret = false;
+ }
- return true;
-}
+ if (pwdlastset_new != 0) {
+ torture_warning(tctx, "pwdLastSet test failed: "
+ "expected pwdLastSet 0, got %lld\n",
+ pwdlastset_old);
+ ret = false;
+ }
+ break;
+ }
-static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *user_handle)
-{
- struct samr_TestPrivateFunctionsUser r;
- NTSTATUS status;
+ switch (levels[l]) {
+ case 21:
+ case 23:
+ case 25:
+ if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
+ (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");
+ ret = false;
+ }
+ break;
+ default:
+ if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
+ (pwdlastset_old >= pwdlastset_new)) {
+ torture_warning(tctx, "pwdlastset not increasing\n");
+ ret = false;
+ }
+ break;
+ }
- torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
+ /* if the level we are testing does not have a fields_present
+ * field, skip all fields present tests by setting f to to
+ * arraysize */
+ switch (levels[l]) {
+ case 18:
+ case 24:
+ case 26:
+ f = ARRAY_SIZE(fields_present);
+ break;
+ }
- r.in.user_handle = user_handle;
+#ifdef TEST_QUERY_LEVELS
+ }
+#endif
+#ifdef TEST_SET_LEVELS
+ }
+#endif
+ } /* fields present */
+ } /* nonzeros */
+ } /* levels */
- status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
- torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
+#undef TEST_SET_LEVELS
+#undef TEST_QUERY_LEVELS
- return true;
+ return ret;
}
-
-static bool test_user_ops(struct dcerpc_pipe *p,
+static bool test_user_ops(struct dcerpc_pipe *p,
struct torture_context *tctx,
- struct policy_handle *user_handle,
- struct policy_handle *domain_handle,
- uint32_t base_acct_flags,
- const char *base_acct_name, enum torture_samr_choice which_ops)
+ struct policy_handle *user_handle,
+ struct policy_handle *domain_handle,
+ uint32_t base_acct_flags,
+ const char *base_acct_name, enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
char *password = NULL;
struct samr_QueryUserInfo q;
int i;
uint32_t rid;
const uint32_t password_fields[] = {
- SAMR_FIELD_PASSWORD,
- SAMR_FIELD_PASSWORD2,
- SAMR_FIELD_PASSWORD | SAMR_FIELD_PASSWORD2,
+ SAMR_FIELD_NT_PASSWORD_PRESENT,
+ SAMR_FIELD_LM_PASSWORD_PRESENT,
+ SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
0
};
-
+
status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
if (!NT_STATUS_IS_OK(status)) {
ret = false;
if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
base_acct_name)) {
ret = false;
- }
+ }
if (!test_GetUserPwInfo(p, tctx, user_handle)) {
ret = false;
if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
char simple_pass[9];
char *v = generate_random_str(tctx, 1);
-
+
ZERO_STRUCT(simple_pass);
memset(simple_pass, *v, sizeof(simple_pass) - 1);
ret = false;
}
}
-
+
for (i = 0; password_fields[i]; i++) {
if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
ret = false;
- }
-
+ }
+
/* check it was set right */
if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
ret = false;
}
- }
+ }
for (i = 0; password_fields[i]; i++) {
if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
ret = false;
- }
-
+ }
+
/* check it was set right */
if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
ret = false;
}
- }
+ }
if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
ret = false;
- }
+ }
if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
ret = false;
- }
+ }
+
+ if (torture_setting_bool(tctx, "samba4", false)) {
+ printf("skipping Set Password level 18 and 21 against Samba4\n");
+ } else {
+
+ if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
+ ret = false;
+ }
+
+ if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
+ ret = false;
+ }
+
+ for (i = 0; password_fields[i]; i++) {
+
+ if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
+ /* we need to skip as that would break
+ * the ChangePasswordUser3 verify */
+ continue;
+ }
+
+ if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
+ ret = false;
+ }
+
+ /* check it was set right */
+ if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
+ ret = false;
+ }
+ }
+ }
q.in.user_handle = user_handle;
q.in.level = 5;
q.out.info = &info;
-
+
status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo level %u failed - %s\n",
+ printf("QueryUserInfo level %u failed - %s\n",
q.in.level, nt_errstr(status));
ret = false;
} else {
printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
info->info5.acct_flags,
expected_flags);
- ret = false;
+ /* FIXME: GD */
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ ret = false;
+ }
}
if (info->info5.rid != rid) {
printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
}
break;
+
+ 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");
+ }
+
+ break;
+
case TORTURE_SAMR_OTHER:
/* We just need the account to exist */
break;
{
bool ret = true;
- if (!test_QuerySecurity(p, tctx, alias_handle)) {
- ret = false;
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ if (!test_QuerySecurity(p, tctx, alias_handle)) {
+ ret = false;
+ }
}
if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
return true;
}
-bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+bool test_DeleteUser_byname(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle, const char *name)
{
NTSTATUS status;
struct policy_handle user_handle;
uint32_t rid;
- status = test_LookupName(p, mem_ctx, handle, name, &rid);
+ status = test_LookupName(p, tctx, handle, name, &rid);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
- status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
+ status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
d.in.user_handle = &user_handle;
d.out.user_handle = &user_handle;
- status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+ status = dcerpc_samr_DeleteUser(p, tctx, &d);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
}
-static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle, const char *name)
{
NTSTATUS status;
struct policy_handle group_handle;
uint32_t rid;
- status = test_LookupName(p, mem_ctx, handle, name, &rid);
+ status = test_LookupName(p, tctx, handle, name, &rid);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
r.in.rid = rid;
r.out.group_handle = &group_handle;
- status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenGroup(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
d.in.group_handle = &group_handle;
d.out.group_handle = &group_handle;
- status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
+ status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
}
-static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *domain_handle, const char *name)
+static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *domain_handle,
+ const char *name)
{
NTSTATUS status;
struct samr_OpenAlias r;
printf("testing DeleteAlias_byname\n");
- status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
+ status = test_LookupName(p, tctx, domain_handle, name, &rid);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
r.in.rid = rid;
r.out.alias_handle = &alias_handle;
- status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenAlias(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
d.in.alias_handle = &alias_handle;
d.out.alias_handle = &alias_handle;
- status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
+ status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
return false;
}
-static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *alias_handle)
+static bool test_DeleteAlias(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *alias_handle)
{
struct samr_DeleteDomAlias d;
NTSTATUS status;
d.in.alias_handle = alias_handle;
d.out.alias_handle = alias_handle;
- status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
+ status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
if (!NT_STATUS_IS_OK(status)) {
printf("DeleteAlias failed - %s\n", nt_errstr(status));
ret = false;
}
static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *domain_handle,
- struct policy_handle *alias_handle,
+ struct policy_handle *domain_handle,
+ struct policy_handle *alias_handle,
const struct dom_sid *domain_sid)
{
NTSTATUS status;
printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
return true;
} else {
- printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
+ printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
nt_errstr(status));
return false;
}
return ret;
}
-static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_ChangePassword(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
const char *acct_name,
struct policy_handle *domain_handle, char **password)
{
return false;
}
- if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
+ if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
ret = false;
}
- if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
+ if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
ret = false;
}
- if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
+ if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
ret = false;
}
/* test what happens when setting the old password again */
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
ret = false;
}
{
char simple_pass[9];
- char *v = generate_random_str(mem_ctx, 1);
+ char *v = generate_random_str(tctx, 1);
ZERO_STRUCT(simple_pass);
memset(simple_pass, *v, sizeof(simple_pass) - 1);
/* test what happens when picking a simple password */
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
ret = false;
}
}
r.out.info = &info;
printf("testing samr_QueryDomainInfo level 1\n");
- status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
return false;
}
s.in.info->info1.min_password_age = 0;
printf("testing samr_SetDomainInfo level 1\n");
- status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
+ status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
if (!NT_STATUS_IS_OK(status)) {
return false;
}
printf("calling test_ChangePasswordUser3 with too short password\n");
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
ret = false;
}
s.in.info->info1.min_password_length = len_old;
s.in.info->info1.password_properties = pwd_prop_old;
s.in.info->info1.min_password_age = min_pwd_age_old;
-
+
printf("testing samr_SetDomainInfo level 1\n");
- status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
+ status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
if (!NT_STATUS_IS_OK(status)) {
return false;
}
n.in.domain_handle = domain_handle;
n.in.num_names = 1;
- n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
- n.in.names[0].string = acct_name;
+ n.in.names = talloc_array(tctx, struct lsa_String, 1);
+ n.in.names[0].string = acct_name;
n.out.rids = &rids;
n.out.types = &types;
- status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+ status = dcerpc_samr_LookupNames(p, tctx, &n);
if (!NT_STATUS_IS_OK(status)) {
printf("LookupNames failed - %s\n", nt_errstr(status));
return false;
r.in.rid = n.out.rids->ids[0];
r.out.user_handle = &user_handle;
- status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenUser(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
return false;
q.in.level = 5;
q.out.info = &info;
- status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+ status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
printf("QueryUserInfo failed - %s\n", nt_errstr(status));
return false;
printf("calling test_ChangePasswordUser3 with too early password change\n");
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
info->info5.last_password_change, true)) {
ret = false;
}
/* we change passwords twice - this has the effect of verifying
they were changed correctly for the final call */
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
ret = false;
}
- if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
+ if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
ret = false;
}
}
static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *domain_handle,
+ struct policy_handle *domain_handle,
struct policy_handle *user_handle_out,
- struct dom_sid *domain_sid,
- enum torture_samr_choice which_ops)
+ struct dom_sid *domain_sid,
+ enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
TALLOC_CTX *user_ctx;
printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
return true;
} else {
- printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+ printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
nt_errstr(status));
return false;
}
q.in.user_handle = &user_handle;
q.in.level = 16;
q.out.info = &info;
-
+
status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo level %u failed - %s\n",
+ printf("QueryUserInfo level %u failed - %s\n",
q.in.level, nt_errstr(status));
ret = false;
} else {
ret = false;
}
}
-
- if (!test_user_ops(p, tctx, &user_handle, domain_handle,
- acct_flags, name.string, which_ops)) {
+
+ if (!test_user_ops(p, tctx, &user_handle, domain_handle,
+ acct_flags, name.string, which_ops,
+ machine_credentials)) {
ret = false;
}
-
+
if (user_handle_out) {
*user_handle_out = user_handle;
} else {
printf("Testing DeleteUser (createuser test)\n");
-
+
d.in.user_handle = &user_handle;
d.out.user_handle = &user_handle;
-
+
status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
if (!NT_STATUS_IS_OK(status)) {
printf("DeleteUser failed - %s\n", nt_errstr(status));
ret = false;
}
}
-
+
}
talloc_free(user_ctx);
-
+
return ret;
}
static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *domain_handle,
struct dom_sid *domain_sid,
- enum torture_samr_choice which_ops)
+ enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
NTSTATUS status;
struct samr_CreateUser2 r;
r.out.user_handle = &user_handle;
r.out.access_granted = &access_granted;
r.out.rid = &rid;
-
+
printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
-
+
status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
-
+
if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
continue;
} else {
- printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
+ printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
nt_errstr(status));
ret = false;
continue;
}
if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
- printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
+ printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
nt_errstr(status), nt_errstr(account_types[i].nt_status));
ret = false;
}
-
+
if (NT_STATUS_IS_OK(status)) {
q.in.user_handle = &user_handle;
q.in.level = 5;
q.out.info = &info;
-
+
status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo level %u failed - %s\n",
+ printf("QueryUserInfo level %u failed - %s\n",
q.in.level, nt_errstr(status));
ret = false;
} else {
info->info5.acct_flags,
expected_flags);
ret = false;
- }
+ }
switch (acct_flags) {
case ACB_SVRTRUST:
if (info->info5.primary_gid != DOMAIN_RID_DCS) {
- printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
+ printf("QuerUserInfo 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) {
- printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
+ printf("QuerUserInfo 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) {
- printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
+ printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
DOMAIN_RID_USERS, info->info5.primary_gid);
ret = false;
}
break;
}
}
-
- if (!test_user_ops(p, tctx, &user_handle, domain_handle,
- acct_flags, name.string, which_ops)) {
+
+ if (!test_user_ops(p, tctx, &user_handle, domain_handle,
+ acct_flags, name.string, which_ops,
+ machine_credentials)) {
ret = false;
}
printf("Testing DeleteUser (createuser2 test)\n");
-
+
d.in.user_handle = &user_handle;
d.out.user_handle = &user_handle;
-
+
status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
if (!NT_STATUS_IS_OK(status)) {
printf("DeleteUser failed - %s\n", nt_errstr(status));
return ret;
}
-static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.level = levels[i];
r.out.info = &info;
- status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryAliasInfo level %u failed - %s\n",
+ printf("QueryAliasInfo level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
return ret;
}
-static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.level = levels[i];
r.out.info = &info;
- status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryGroupInfo level %u failed - %s\n",
+ printf("QueryGroupInfo level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
return ret;
}
-static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryGroupMember(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.group_handle = handle;
r.out.rids = &rids;
- status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
ret = false;
}
-static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_SetGroupInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.level = levels[i];
r.out.info = &info;
- status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryGroupInfo level %u failed - %s\n",
+ printf("QueryGroupInfo level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
s.in.info = *r.out.info;
#if 0
- /* disabled this, as it changes the name only from the point of view of samr,
+ /* disabled this, as it changes the name only from the point of view of samr,
but leaves the name from the point of view of w2k3 internals (and ldap). This means
the name is still reserved, so creating the old name fails, but deleting by the old name
also fails */
init_lsa_String(&s.in.info->description, "test description");
}
- status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
+ status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
if (set_ok[i]) {
if (!NT_STATUS_IS_OK(status)) {
- printf("SetGroupInfo level %u failed - %s\n",
+ printf("SetGroupInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
}
} else {
if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
- printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+ printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
return ret;
}
-static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryUserInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.level = levels[i];
r.out.info = &info;
- status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo level %u failed - %s\n",
+ printf("QueryUserInfo level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
return ret;
}
-static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.level = levels[i];
r.out.info = &info;
- status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo2 level %u failed - %s\n",
+ printf("QueryUserInfo2 level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
return ret;
}
-static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_OpenUser(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle, uint32_t rid)
{
NTSTATUS status;
r.in.rid = rid;
r.out.user_handle = &user_handle;
- status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenUser(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
return false;
}
- if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
+ if (!test_QuerySecurity(p, tctx, &user_handle)) {
ret = false;
}
- if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
+ if (!test_QueryUserInfo(p, tctx, &user_handle)) {
ret = false;
}
- if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
+ if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
ret = false;
}
- if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
+ if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
ret = false;
}
- if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
+ if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
ret = false;
}
- if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+ if (!test_samr_handle_Close(p, tctx, &user_handle)) {
ret = false;
}
return ret;
}
-static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_OpenGroup(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle, uint32_t rid)
{
NTSTATUS status;
r.in.rid = rid;
r.out.group_handle = &group_handle;
- status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenGroup(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
return false;
}
- if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
- ret = false;
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ if (!test_QuerySecurity(p, tctx, &group_handle)) {
+ ret = false;
+ }
}
- if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
+ if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
ret = false;
}
- if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
+ if (!test_QueryGroupMember(p, tctx, &group_handle)) {
ret = false;
}
- if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
+ if (!test_samr_handle_Close(p, tctx, &group_handle)) {
ret = false;
}
return false;
}
- if (!test_QuerySecurity(p, tctx, &alias_handle)) {
- ret = false;
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ if (!test_QuerySecurity(p, tctx, &alias_handle)) {
+ ret = false;
+ }
}
if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
}
static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *handle, uint32_t rid,
+ struct policy_handle *handle, uint32_t rid,
uint32_t acct_flag_mask)
{
NTSTATUS status;
q.in.user_handle = &user_handle;
q.in.level = 16;
q.out.info = &info;
-
+
status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryUserInfo level 16 failed - %s\n",
+ printf("QueryUserInfo level 16 failed - %s\n",
nt_errstr(status));
ret = false;
} else {
ret = false;
}
}
-
+
if (!test_samr_handle_Close(p, tctx, &user_handle)) {
ret = false;
}
struct samr_SamArray *sam = NULL;
uint32_t num_entries = 0;
- uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
- ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
- ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
+ uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
+ ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
+ ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
ACB_PWNOEXP, 0};
printf("Testing EnumDomainUsers\n");
r.out.sam = &sam;
status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
- if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
+ if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
!NT_STATUS_IS_OK(status)) {
printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
return false;
}
-
+
torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
if (sam->count == 0) {
status = dcerpc_samr_LookupRids(p, tctx, &lr);
torture_assert_ntstatus_ok(tctx, status, "LookupRids");
- return ret;
+ return ret;
}
/*
try blasting the server with a bunch of sync requests
*/
-static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
for (i=0;i<ASYNC_COUNT;i++) {
status = dcerpc_ndr_request_recv(req[i]);
if (!NT_STATUS_IS_OK(status)) {
- printf("EnumDomainUsers[%d] failed - %s\n",
+ printf("EnumDomainUsers[%d] failed - %s\n",
i, nt_errstr(status));
return false;
}
}
-
+
torture_comment(tctx, "%d async requests OK\n", i);
return true;
}
-static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.out.num_entries = &num_entries;
r.out.sam = &sam;
- status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
+ status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
return false;
}
-
+
if (!sam) {
return false;
}
for (i=0;i<sam->count;i++) {
- if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
+ if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
ret = false;
}
}
return ret;
}
-static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.out.num_entries = &num_entries;
r.out.resume_handle = &resume_handle;
- status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
+ status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
return false;
}
-
+
if (!sam) {
return false;
}
for (i=0;i<sam->count;i++) {
- if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
+ if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
ret = false;
}
}
- return ret;
+ return ret;
}
-static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.name = &name;
r.out.idx = &idx;
- status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
+ status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
- if (ok_lvl[i] &&
+ if (ok_lvl[i] &&
!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
- printf("GetDisplayEnumerationIndex level %u failed - %s\n",
+ printf("GetDisplayEnumerationIndex level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
init_lsa_String(&name, "zzzzzzzz");
- status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
-
+ status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
+
if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
- printf("GetDisplayEnumerationIndex level %u failed - %s\n",
+ printf("GetDisplayEnumerationIndex level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
}
-
- return ret;
+
+ return ret;
}
-static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.in.name = &name;
r.out.idx = &idx;
- status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
- if (ok_lvl[i] &&
- !NT_STATUS_IS_OK(status) &&
+ status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
+ if (ok_lvl[i] &&
+ !NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
- printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
+ printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
init_lsa_String(&name, "zzzzzzzz");
- status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
+ status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
- printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
+ printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
}
-
- return ret;
+
+ return ret;
}
#define STRING_EQUAL_QUERY(s1, s2, user) \
ret = false; \
}
-static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct samr_QueryDisplayInfo *querydisplayinfo,
- bool *seen_testuser)
+ bool *seen_testuser)
{
struct samr_OpenUser r;
struct samr_QueryUserInfo q;
/* Not interested in validating just the account name */
return true;
}
-
+
r.out.user_handle = &user_handle;
-
+
switch (querydisplayinfo->in.level) {
case 1:
case 2:
- status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ status = dcerpc_samr_OpenUser(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
return false;
}
}
-
+
q.in.user_handle = &user_handle;
q.in.level = 21;
q.out.info = &info;
- status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
+ status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
if (!NT_STATUS_IS_OK(status)) {
printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
return false;
}
-
+
switch (querydisplayinfo->in.level) {
case 1:
if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
info->info21.rid, info->info21.account_name);
INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
info->info21.acct_flags, info->info21.account_name);
-
+
break;
case 2:
STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
info->info21.rid, info->info21.account_name);
INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
info->info21.acct_flags, info->info21.account_name);
-
+
if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
- printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
+ printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
info->info21.account_name.string);
}
info->info21.acct_flags);
return false;
}
-
+
break;
}
-
- if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
+
+ if (!test_samr_handle_Close(p, tctx, &user_handle)) {
return false;
}
}
return ret;
}
-static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.out.total_size = &total_size;
r.out.returned_size = &returned_size;
r.out.info = &disp_info;
-
- status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
+
+ status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
- printf("QueryDisplayInfo level %u failed - %s\n",
+ printf("QueryDisplayInfo level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
switch (r.in.level) {
case 1:
- if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
+ if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
ret = false;
}
r.in.start_idx += r.out.info->info1.count;
break;
case 2:
- if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
+ if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
ret = false;
}
r.in.start_idx += r.out.info->info2.count;
dom_info.out.info = &info;
/* Check number of users returned is correct */
- status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
+ status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDomainInfo level %u failed - %s\n",
+ printf("QueryDomainInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
break;
}
if (!seen_testuser) {
struct policy_handle user_handle;
- if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
- printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
+ if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
+ printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
info->general.domain_name.string);
ret = false;
- test_samr_handle_Close(p, mem_ctx, &user_handle);
+ test_samr_handle_Close(p, tctx, &user_handle);
}
}
break;
info->general.domain_name.string);
ret = false;
}
-
+
break;
}
}
-
- return ret;
+
+ return ret;
}
-static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *handle)
+static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *handle)
{
NTSTATUS status;
struct samr_QueryDisplayInfo2 r;
r.out.returned_size = &returned_size;
r.out.info = &info;
- status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDisplayInfo2 level %u failed - %s\n",
+ printf("QueryDisplayInfo2 level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
}
-
- return ret;
+
+ return ret;
}
static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDisplayInfo3 level %u failed - %s\n",
+ printf("QueryDisplayInfo3 level %u failed - %s\n",
levels[i], nt_errstr(status));
ret = false;
}
}
-
- return ret;
+
+ return ret;
}
-static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
struct policy_handle *handle)
{
NTSTATUS status;
r.out.info = &info;
do {
- status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
+ status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
printf("expected idx %d but got %d\n",
}
if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
!NT_STATUS_IS_OK(status)) {
- printf("QueryDisplayInfo level %u failed - %s\n",
+ printf("QueryDisplayInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
break;
} while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
NT_STATUS_IS_OK(status)) &&
*r.out.returned_size != 0);
-
- return ret;
+
+ return ret;
}
static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
int i;
bool ret = true;
- const char *domain_comment = talloc_asprintf(tctx,
- "Tortured by Samba4 RPC-SAMR: %s",
+ const char *domain_comment = talloc_asprintf(tctx,
+ "Tortured by Samba4 RPC-SAMR: %s",
timestring(tctx, time(NULL)));
s.in.domain_handle = handle;
s.in.level = 4;
s.in.info = talloc(tctx, union samr_DomainInfo);
-
+
s.in.info->oem.oem_information.string = domain_comment;
status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
if (!NT_STATUS_IS_OK(status)) {
- printf("SetDomainInfo level %u (set comment) failed - %s\n",
- r.in.level, nt_errstr(status));
+ printf("SetDomainInfo level %u (set comment) failed - %s\n",
+ s.in.level, nt_errstr(status));
return false;
}
status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDomainInfo level %u failed - %s\n",
+ printf("QueryDomainInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
if (set_ok[i]) {
if (!NT_STATUS_IS_OK(status)) {
- printf("SetDomainInfo level %u failed - %s\n",
+ printf("SetDomainInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
}
} else {
if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
- printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
+ printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDomainInfo level %u failed - %s\n",
+ printf("QueryDomainInfo level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
}
}
- return ret;
+ return ret;
}
status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("QueryDomainInfo2 level %u failed - %s\n",
+ printf("QueryDomainInfo2 level %u failed - %s\n",
r.in.level, nt_errstr(status));
ret = false;
continue;
}
}
- return true;
+ return true;
}
/* Test whether querydispinfo level 5 and enumdomgroups return the same
}
torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
-
+
torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
q2.in.domain_handle = handle;
r.in.domain_handle = domain_handle;
status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
- torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
return ret;
}
for (i=0;i<ARRAY_SIZE(rids);i++) {
torture_comment(tctx, "Testing RidToSid\n");
-
+
calc_sid = dom_sid_dup(tctx, domain_sid);
r.in.domain_handle = domain_handle;
r.in.rid = rids[i];
r.out.sid = &out_sid;
-
+
status = dcerpc_samr_RidToSid(p, tctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
if (!dom_sid_equal(calc_sid, out_sid)) {
- printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
+ printf("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;
return ret;
}
-static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *domain_handle,
struct policy_handle *group_handle)
{
}
-static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
- struct torture_context *tctx,
- struct policy_handle *domain_handle,
+static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
+ struct torture_context *tctx,
+ struct policy_handle *domain_handle,
struct policy_handle *group_handle,
struct dom_sid *domain_sid)
{
torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
return true;
} else {
- printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
+ printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
nt_errstr(status));
return false;
}
if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
- printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
+ printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
nt_errstr(status));
return false;
}
}
if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
-
- printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
+
+ printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
nt_errstr(status));
return false;
}
/*
its not totally clear what this does. It seems to accept any sid you like.
*/
-static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
+static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
struct torture_context *tctx,
struct policy_handle *domain_handle)
{
static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle);
-static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
+static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle, struct dom_sid *sid,
- enum torture_samr_choice which_ops)
+ enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
NTSTATUS status;
struct samr_OpenDomain r;
switch (which_ops) {
case TORTURE_SAMR_USER_ATTRIBUTES:
case TORTURE_SAMR_PASSWORDS:
- ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops);
- ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops);
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
+ }
+ ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
/* This test needs 'complex' users to validate */
ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
if (!ret) {
printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
}
break;
+ case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
+ }
+ ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, machine_credentials);
+ if (!ret) {
+ printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
+ }
+ break;
case TORTURE_SAMR_OTHER:
- ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops);
+ ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
if (!ret) {
printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
}
- ret &= test_QuerySecurity(p, tctx, &domain_handle);
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ ret &= test_QuerySecurity(p, tctx, &domain_handle);
+ }
ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
-
+
if (torture_setting_bool(tctx, "samba4", false)) {
torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
} else {
static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
struct policy_handle *handle, const char *domain,
- enum torture_samr_choice which_ops)
+ enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
NTSTATUS status;
struct samr_LookupDomain r;
ret = false;
}
- if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops)) {
+ if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
+ machine_credentials)) {
ret = false;
}
static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
- struct policy_handle *handle, enum torture_samr_choice which_ops)
+ struct policy_handle *handle, enum torture_samr_choice which_ops,
+ struct cli_credentials *machine_credentials)
{
NTSTATUS status;
struct samr_EnumDomains r;
}
for (i=0;i<sam->count;i++) {
- if (!test_LookupDomain(p, tctx, handle,
- sam->entries[i].name.string, which_ops)) {
+ if (!test_LookupDomain(p, tctx, handle,
+ sam->entries[i].name.string, which_ops,
+ machine_credentials)) {
ret = false;
}
}
ret &= test_Connect(p, torture, &handle);
- ret &= test_QuerySecurity(p, torture, &handle);
+ if (!torture_setting_bool(torture, "samba3", false)) {
+ ret &= test_QuerySecurity(p, torture, &handle);
+ }
- ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER);
+ ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
ret &= test_SetDsrmPassword(p, torture, &handle);
ret &= test_Connect(p, torture, &handle);
- ret &= test_QuerySecurity(p, torture, &handle);
+ if (!torture_setting_bool(torture, "samba3", false)) {
+ ret &= test_QuerySecurity(p, torture, &handle);
+ }
- ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES);
+ ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
ret &= test_SetDsrmPassword(p, torture, &handle);
ret &= test_Connect(p, torture, &handle);
- ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS);
+ ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
+
+ ret &= test_samr_handle_Close(p, torture, &handle);
+
+ return ret;
+}
+
+static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
+ struct dcerpc_pipe *p2,
+ struct cli_credentials *machine_credentials)
+{
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+ bool ret = true;
+ struct policy_handle handle;
+
+ status = torture_rpc_connection(torture, &p, &ndr_table_samr);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ ret &= test_Connect(p, torture, &handle);
+
+ ret &= test_EnumDomains(p, torture, &handle,
+ TORTURE_SAMR_PASSWORDS_PWDLASTSET,
+ machine_credentials);
ret &= test_samr_handle_Close(p, torture, &handle);
return ret;
}
+struct torture_suite *torture_rpc_samr_passwords_pwdlastset(struct torture_context *tctx)
+{
+ struct torture_suite *suite = torture_suite_create(tctx, "SAMR-PASSWORDS-PWDLASTSET");
+ struct torture_rpc_tcase *tcase;
+
+ tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
+ &ndr_table_samr,
+ TEST_ACCOUNT_NAME_PWD);
+
+ torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
+ torture_rpc_samr_pwdlastset);
+
+ return suite;
+}