2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Guenther Deschner 2008,2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "torture/torture.h"
25 #include "system/time.h"
26 #include "librpc/gen_ndr/lsa.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "librpc/gen_ndr/ndr_netlogon_c.h"
29 #include "librpc/gen_ndr/ndr_samr_c.h"
30 #include "librpc/gen_ndr/ndr_lsa_c.h"
31 #include "../lib/crypto/crypto.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "libcli/security/security.h"
34 #include "torture/rpc/rpc.h"
35 #include "param/param.h"
39 #define TEST_ACCOUNT_NAME "samrtorturetest"
40 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
41 #define TEST_ALIASNAME "samrtorturetestalias"
42 #define TEST_GROUPNAME "samrtorturetestgroup"
43 #define TEST_MACHINENAME "samrtestmach$"
44 #define TEST_DOMAINNAME "samrtestdom$"
46 enum torture_samr_choice
{
47 TORTURE_SAMR_PASSWORDS
,
48 TORTURE_SAMR_PASSWORDS_PWDLASTSET
,
49 TORTURE_SAMR_USER_ATTRIBUTES
,
50 TORTURE_SAMR_USER_PRIVILEGES
,
52 TORTURE_SAMR_MANY_ACCOUNTS
,
53 TORTURE_SAMR_MANY_GROUPS
,
54 TORTURE_SAMR_MANY_ALIASES
57 struct torture_samr_context
{
58 struct policy_handle handle
;
59 struct cli_credentials
*machine_credentials
;
60 enum torture_samr_choice choice
;
61 uint32_t num_objects_large_dc
;
64 static bool test_QueryUserInfo(struct dcerpc_pipe
*p
,
65 struct torture_context
*tctx
,
66 struct policy_handle
*handle
);
68 static bool test_QueryUserInfo2(struct dcerpc_pipe
*p
,
69 struct torture_context
*tctx
,
70 struct policy_handle
*handle
);
72 static bool test_QueryAliasInfo(struct dcerpc_pipe
*p
,
73 struct torture_context
*tctx
,
74 struct policy_handle
*handle
);
76 static bool test_ChangePassword(struct dcerpc_pipe
*p
,
77 struct torture_context
*tctx
,
78 const char *acct_name
,
79 struct policy_handle
*domain_handle
, char **password
);
81 static void init_lsa_String(struct lsa_String
*string
, const char *s
)
86 static void init_lsa_StringLarge(struct lsa_StringLarge
*string
, const char *s
)
91 static void init_lsa_BinaryString(struct lsa_BinaryString
*string
, const char *s
, uint32_t length
)
93 string
->length
= length
;
94 string
->size
= length
;
95 string
->array
= (uint16_t *)discard_const(s
);
98 bool test_samr_handle_Close(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
99 struct policy_handle
*handle
)
104 r
.in
.handle
= handle
;
105 r
.out
.handle
= handle
;
107 status
= dcerpc_samr_Close(p
, tctx
, &r
);
108 torture_assert_ntstatus_ok(tctx
, status
, "Close");
113 static bool test_Shutdown(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
114 struct policy_handle
*handle
)
117 struct samr_Shutdown r
;
119 if (!torture_setting_bool(tctx
, "dangerous", false)) {
120 torture_skip(tctx
, "samr_Shutdown disabled - enable dangerous tests to use\n");
124 r
.in
.connect_handle
= handle
;
126 torture_comment(tctx
, "testing samr_Shutdown\n");
128 status
= dcerpc_samr_Shutdown(p
, tctx
, &r
);
129 torture_assert_ntstatus_ok(tctx
, status
, "samr_Shutdown");
134 static bool test_SetDsrmPassword(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
135 struct policy_handle
*handle
)
138 struct samr_SetDsrmPassword r
;
139 struct lsa_String string
;
140 struct samr_Password hash
;
142 if (!torture_setting_bool(tctx
, "dangerous", false)) {
143 torture_skip(tctx
, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
146 E_md4hash("TeSTDSRM123", hash
.hash
);
148 init_lsa_String(&string
, "Administrator");
154 torture_comment(tctx
, "testing samr_SetDsrmPassword\n");
156 status
= dcerpc_samr_SetDsrmPassword(p
, tctx
, &r
);
157 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NOT_SUPPORTED
, "samr_SetDsrmPassword");
163 static bool test_QuerySecurity(struct dcerpc_pipe
*p
,
164 struct torture_context
*tctx
,
165 struct policy_handle
*handle
)
168 struct samr_QuerySecurity r
;
169 struct samr_SetSecurity s
;
170 struct sec_desc_buf
*sdbuf
= NULL
;
172 r
.in
.handle
= handle
;
174 r
.out
.sdbuf
= &sdbuf
;
176 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &r
);
177 torture_assert_ntstatus_ok(tctx
, status
, "QuerySecurity");
179 torture_assert(tctx
, sdbuf
!= NULL
, "sdbuf is NULL");
181 s
.in
.handle
= handle
;
185 if (torture_setting_bool(tctx
, "samba4", false)) {
186 torture_skip(tctx
, "skipping SetSecurity test against Samba4\n");
189 status
= dcerpc_samr_SetSecurity(p
, tctx
, &s
);
190 torture_assert_ntstatus_ok(tctx
, status
, "SetSecurity");
192 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &r
);
193 torture_assert_ntstatus_ok(tctx
, status
, "QuerySecurity");
199 static bool test_SetUserInfo(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
200 struct policy_handle
*handle
, uint32_t base_acct_flags
,
201 const char *base_account_name
)
204 struct samr_SetUserInfo s
;
205 struct samr_SetUserInfo2 s2
;
206 struct samr_QueryUserInfo q
;
207 struct samr_QueryUserInfo q0
;
208 union samr_UserInfo u
;
209 union samr_UserInfo
*info
;
211 const char *test_account_name
;
213 uint32_t user_extra_flags
= 0;
215 if (!torture_setting_bool(tctx
, "samba3", false)) {
216 if (base_acct_flags
== ACB_NORMAL
) {
217 /* When created, accounts are expired by default */
218 user_extra_flags
= ACB_PW_EXPIRED
;
222 s
.in
.user_handle
= handle
;
225 s2
.in
.user_handle
= handle
;
228 q
.in
.user_handle
= handle
;
232 #define TESTCALL(call, r) \
233 status = dcerpc_samr_ ##call(p, tctx, &r); \
234 if (!NT_STATUS_IS_OK(status)) { \
235 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
236 r.in.level, nt_errstr(status), __location__); \
241 #define STRING_EQUAL(s1, s2, field) \
242 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
243 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
244 #field, s2, __location__); \
249 #define MEM_EQUAL(s1, s2, length, field) \
250 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
251 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
252 #field, (const char *)s2, __location__); \
257 #define INT_EQUAL(i1, i2, field) \
259 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
260 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
265 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
266 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
268 TESTCALL(QueryUserInfo, q) \
270 s2.in.level = lvl1; \
273 ZERO_STRUCT(u.info21); \
274 u.info21.fields_present = fpval; \
276 init_lsa_String(&u.info ## lvl1.field1, value); \
277 TESTCALL(SetUserInfo, s) \
278 TESTCALL(SetUserInfo2, s2) \
279 init_lsa_String(&u.info ## lvl1.field1, ""); \
280 TESTCALL(QueryUserInfo, q); \
282 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
284 TESTCALL(QueryUserInfo, q) \
286 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
289 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
290 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
292 TESTCALL(QueryUserInfo, q) \
294 s2.in.level = lvl1; \
297 ZERO_STRUCT(u.info21); \
298 u.info21.fields_present = fpval; \
300 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
301 TESTCALL(SetUserInfo, s) \
302 TESTCALL(SetUserInfo2, s2) \
303 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
304 TESTCALL(QueryUserInfo, q); \
306 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
308 TESTCALL(QueryUserInfo, q) \
310 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
313 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
314 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
316 TESTCALL(QueryUserInfo, q) \
318 s2.in.level = lvl1; \
321 uint8_t *bits = u.info21.logon_hours.bits; \
322 ZERO_STRUCT(u.info21); \
323 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
324 u.info21.logon_hours.units_per_week = 168; \
325 u.info21.logon_hours.bits = bits; \
327 u.info21.fields_present = fpval; \
329 u.info ## lvl1.field1 = value; \
330 TESTCALL(SetUserInfo, s) \
331 TESTCALL(SetUserInfo2, s2) \
332 u.info ## lvl1.field1 = 0; \
333 TESTCALL(QueryUserInfo, q); \
335 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
337 TESTCALL(QueryUserInfo, q) \
339 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
342 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
343 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
347 do { TESTCALL(QueryUserInfo
, q0
) } while (0);
349 TEST_USERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment", 0);
350 TEST_USERINFO_STRING(2, comment
, 21, comment
, "xx2-21 comment", 0);
351 TEST_USERINFO_STRING(21, comment
, 21, comment
, "xx21-21 comment",
354 test_account_name
= talloc_asprintf(tctx
, "%sxx7-1", base_account_name
);
355 TEST_USERINFO_STRING(7, account_name
, 1, account_name
, base_account_name
, 0);
356 test_account_name
= talloc_asprintf(tctx
, "%sxx7-3", base_account_name
);
357 TEST_USERINFO_STRING(7, account_name
, 3, account_name
, base_account_name
, 0);
358 test_account_name
= talloc_asprintf(tctx
, "%sxx7-5", base_account_name
);
359 TEST_USERINFO_STRING(7, account_name
, 5, account_name
, base_account_name
, 0);
360 test_account_name
= talloc_asprintf(tctx
, "%sxx7-6", base_account_name
);
361 TEST_USERINFO_STRING(7, account_name
, 6, account_name
, base_account_name
, 0);
362 test_account_name
= talloc_asprintf(tctx
, "%sxx7-7", base_account_name
);
363 TEST_USERINFO_STRING(7, account_name
, 7, account_name
, base_account_name
, 0);
364 test_account_name
= talloc_asprintf(tctx
, "%sxx7-21", base_account_name
);
365 TEST_USERINFO_STRING(7, account_name
, 21, account_name
, base_account_name
, 0);
366 test_account_name
= base_account_name
;
367 TEST_USERINFO_STRING(21, account_name
, 21, account_name
, base_account_name
,
368 SAMR_FIELD_ACCOUNT_NAME
);
370 TEST_USERINFO_STRING(6, full_name
, 1, full_name
, "xx6-1 full_name", 0);
371 TEST_USERINFO_STRING(6, full_name
, 3, full_name
, "xx6-3 full_name", 0);
372 TEST_USERINFO_STRING(6, full_name
, 5, full_name
, "xx6-5 full_name", 0);
373 TEST_USERINFO_STRING(6, full_name
, 6, full_name
, "xx6-6 full_name", 0);
374 TEST_USERINFO_STRING(6, full_name
, 8, full_name
, "xx6-8 full_name", 0);
375 TEST_USERINFO_STRING(6, full_name
, 21, full_name
, "xx6-21 full_name", 0);
376 TEST_USERINFO_STRING(8, full_name
, 21, full_name
, "xx8-21 full_name", 0);
377 TEST_USERINFO_STRING(21, full_name
, 21, full_name
, "xx21-21 full_name",
378 SAMR_FIELD_FULL_NAME
);
380 TEST_USERINFO_STRING(6, full_name
, 1, full_name
, "", 0);
381 TEST_USERINFO_STRING(6, full_name
, 3, full_name
, "", 0);
382 TEST_USERINFO_STRING(6, full_name
, 5, full_name
, "", 0);
383 TEST_USERINFO_STRING(6, full_name
, 6, full_name
, "", 0);
384 TEST_USERINFO_STRING(6, full_name
, 8, full_name
, "", 0);
385 TEST_USERINFO_STRING(6, full_name
, 21, full_name
, "", 0);
386 TEST_USERINFO_STRING(8, full_name
, 21, full_name
, "", 0);
387 TEST_USERINFO_STRING(21, full_name
, 21, full_name
, "",
388 SAMR_FIELD_FULL_NAME
);
390 TEST_USERINFO_STRING(11, logon_script
, 3, logon_script
, "xx11-3 logon_script", 0);
391 TEST_USERINFO_STRING(11, logon_script
, 5, logon_script
, "xx11-5 logon_script", 0);
392 TEST_USERINFO_STRING(11, logon_script
, 21, logon_script
, "xx11-21 logon_script", 0);
393 TEST_USERINFO_STRING(21, logon_script
, 21, logon_script
, "xx21-21 logon_script",
394 SAMR_FIELD_LOGON_SCRIPT
);
396 TEST_USERINFO_STRING(12, profile_path
, 3, profile_path
, "xx12-3 profile_path", 0);
397 TEST_USERINFO_STRING(12, profile_path
, 5, profile_path
, "xx12-5 profile_path", 0);
398 TEST_USERINFO_STRING(12, profile_path
, 21, profile_path
, "xx12-21 profile_path", 0);
399 TEST_USERINFO_STRING(21, profile_path
, 21, profile_path
, "xx21-21 profile_path",
400 SAMR_FIELD_PROFILE_PATH
);
402 TEST_USERINFO_STRING(10, home_directory
, 3, home_directory
, "xx10-3 home_directory", 0);
403 TEST_USERINFO_STRING(10, home_directory
, 5, home_directory
, "xx10-5 home_directory", 0);
404 TEST_USERINFO_STRING(10, home_directory
, 21, home_directory
, "xx10-21 home_directory", 0);
405 TEST_USERINFO_STRING(21, home_directory
, 21, home_directory
, "xx21-21 home_directory",
406 SAMR_FIELD_HOME_DIRECTORY
);
407 TEST_USERINFO_STRING(21, home_directory
, 10, home_directory
, "xx21-10 home_directory",
408 SAMR_FIELD_HOME_DIRECTORY
);
410 TEST_USERINFO_STRING(10, home_drive
, 3, home_drive
, "xx10-3 home_drive", 0);
411 TEST_USERINFO_STRING(10, home_drive
, 5, home_drive
, "xx10-5 home_drive", 0);
412 TEST_USERINFO_STRING(10, home_drive
, 21, home_drive
, "xx10-21 home_drive", 0);
413 TEST_USERINFO_STRING(21, home_drive
, 21, home_drive
, "xx21-21 home_drive",
414 SAMR_FIELD_HOME_DRIVE
);
415 TEST_USERINFO_STRING(21, home_drive
, 10, home_drive
, "xx21-10 home_drive",
416 SAMR_FIELD_HOME_DRIVE
);
418 TEST_USERINFO_STRING(13, description
, 1, description
, "xx13-1 description", 0);
419 TEST_USERINFO_STRING(13, description
, 5, description
, "xx13-5 description", 0);
420 TEST_USERINFO_STRING(13, description
, 21, description
, "xx13-21 description", 0);
421 TEST_USERINFO_STRING(21, description
, 21, description
, "xx21-21 description",
422 SAMR_FIELD_DESCRIPTION
);
424 TEST_USERINFO_STRING(14, workstations
, 3, workstations
, "14workstation3", 0);
425 TEST_USERINFO_STRING(14, workstations
, 5, workstations
, "14workstation4", 0);
426 TEST_USERINFO_STRING(14, workstations
, 21, workstations
, "14workstation21", 0);
427 TEST_USERINFO_STRING(21, workstations
, 21, workstations
, "21workstation21",
428 SAMR_FIELD_WORKSTATIONS
);
429 TEST_USERINFO_STRING(21, workstations
, 3, workstations
, "21workstation3",
430 SAMR_FIELD_WORKSTATIONS
);
431 TEST_USERINFO_STRING(21, workstations
, 5, workstations
, "21workstation5",
432 SAMR_FIELD_WORKSTATIONS
);
433 TEST_USERINFO_STRING(21, workstations
, 14, workstations
, "21workstation14",
434 SAMR_FIELD_WORKSTATIONS
);
436 TEST_USERINFO_BINARYSTRING(20, parameters
, 21, parameters
, "xx20-21 parameters", 0);
437 TEST_USERINFO_BINARYSTRING(21, parameters
, 21, parameters
, "xx21-21 parameters",
438 SAMR_FIELD_PARAMETERS
);
439 TEST_USERINFO_BINARYSTRING(21, parameters
, 20, parameters
, "xx21-20 parameters",
440 SAMR_FIELD_PARAMETERS
);
441 /* also empty user parameters are allowed */
442 TEST_USERINFO_BINARYSTRING(20, parameters
, 21, parameters
, "", 0);
443 TEST_USERINFO_BINARYSTRING(21, parameters
, 21, parameters
, "",
444 SAMR_FIELD_PARAMETERS
);
445 TEST_USERINFO_BINARYSTRING(21, parameters
, 20, parameters
, "",
446 SAMR_FIELD_PARAMETERS
);
448 /* Samba 3 cannot store country_code and copy_page atm. - gd */
449 if (!torture_setting_bool(tctx
, "samba3", false)) {
450 TEST_USERINFO_INT(2, country_code
, 2, country_code
, __LINE__
, 0);
451 TEST_USERINFO_INT(2, country_code
, 21, country_code
, __LINE__
, 0);
452 TEST_USERINFO_INT(21, country_code
, 21, country_code
, __LINE__
,
453 SAMR_FIELD_COUNTRY_CODE
);
454 TEST_USERINFO_INT(21, country_code
, 2, country_code
, __LINE__
,
455 SAMR_FIELD_COUNTRY_CODE
);
457 TEST_USERINFO_INT(2, code_page
, 21, code_page
, __LINE__
, 0);
458 TEST_USERINFO_INT(21, code_page
, 21, code_page
, __LINE__
,
459 SAMR_FIELD_CODE_PAGE
);
460 TEST_USERINFO_INT(21, code_page
, 2, code_page
, __LINE__
,
461 SAMR_FIELD_CODE_PAGE
);
464 if (!torture_setting_bool(tctx
, "samba3", false)) {
465 TEST_USERINFO_INT(17, acct_expiry
, 21, acct_expiry
, __LINE__
, 0);
466 TEST_USERINFO_INT(17, acct_expiry
, 5, acct_expiry
, __LINE__
, 0);
467 TEST_USERINFO_INT(21, acct_expiry
, 21, acct_expiry
, __LINE__
,
468 SAMR_FIELD_ACCT_EXPIRY
);
469 TEST_USERINFO_INT(21, acct_expiry
, 5, acct_expiry
, __LINE__
,
470 SAMR_FIELD_ACCT_EXPIRY
);
471 TEST_USERINFO_INT(21, acct_expiry
, 17, acct_expiry
, __LINE__
,
472 SAMR_FIELD_ACCT_EXPIRY
);
474 /* Samba 3 can only store seconds / time_t in passdb - gd */
476 unix_to_nt_time(&nt
, time(NULL
) + __LINE__
);
477 TEST_USERINFO_INT(17, acct_expiry
, 21, acct_expiry
, nt
, 0);
478 unix_to_nt_time(&nt
, time(NULL
) + __LINE__
);
479 TEST_USERINFO_INT(17, acct_expiry
, 5, acct_expiry
, nt
, 0);
480 unix_to_nt_time(&nt
, time(NULL
) + __LINE__
);
481 TEST_USERINFO_INT(21, acct_expiry
, 21, acct_expiry
, nt
, SAMR_FIELD_ACCT_EXPIRY
);
482 unix_to_nt_time(&nt
, time(NULL
) + __LINE__
);
483 TEST_USERINFO_INT(21, acct_expiry
, 5, acct_expiry
, nt
, SAMR_FIELD_ACCT_EXPIRY
);
484 unix_to_nt_time(&nt
, time(NULL
) + __LINE__
);
485 TEST_USERINFO_INT(21, acct_expiry
, 17, acct_expiry
, nt
, SAMR_FIELD_ACCT_EXPIRY
);
488 TEST_USERINFO_INT(4, logon_hours
.bits
[3], 3, logon_hours
.bits
[3], 1, 0);
489 TEST_USERINFO_INT(4, logon_hours
.bits
[3], 5, logon_hours
.bits
[3], 2, 0);
490 TEST_USERINFO_INT(4, logon_hours
.bits
[3], 21, logon_hours
.bits
[3], 3, 0);
491 TEST_USERINFO_INT(21, logon_hours
.bits
[3], 21, logon_hours
.bits
[3], 4,
492 SAMR_FIELD_LOGON_HOURS
);
494 TEST_USERINFO_INT_EXP(16, acct_flags
, 5, acct_flags
,
495 (base_acct_flags
| ACB_DISABLED
| ACB_HOMDIRREQ
),
496 (base_acct_flags
| ACB_DISABLED
| ACB_HOMDIRREQ
| user_extra_flags
),
498 TEST_USERINFO_INT_EXP(16, acct_flags
, 5, acct_flags
,
499 (base_acct_flags
| ACB_DISABLED
),
500 (base_acct_flags
| ACB_DISABLED
| user_extra_flags
),
503 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
504 TEST_USERINFO_INT_EXP(16, acct_flags
, 5, acct_flags
,
505 (base_acct_flags
| ACB_DISABLED
| ACB_PWNOEXP
),
506 (base_acct_flags
| ACB_DISABLED
| ACB_PWNOEXP
),
508 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
509 (base_acct_flags
| ACB_DISABLED
| ACB_HOMDIRREQ
),
510 (base_acct_flags
| ACB_DISABLED
| ACB_HOMDIRREQ
| user_extra_flags
),
514 /* The 'autolock' flag doesn't stick - check this */
515 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
516 (base_acct_flags
| ACB_DISABLED
| ACB_AUTOLOCK
),
517 (base_acct_flags
| ACB_DISABLED
| user_extra_flags
),
520 /* Removing the 'disabled' flag doesn't stick - check this */
521 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
523 (base_acct_flags
| ACB_DISABLED
| user_extra_flags
),
527 /* Samba3 cannot store these atm */
528 if (!torture_setting_bool(tctx
, "samba3", false)) {
529 /* The 'store plaintext' flag does stick */
530 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
531 (base_acct_flags
| ACB_DISABLED
| ACB_ENC_TXT_PWD_ALLOWED
),
532 (base_acct_flags
| ACB_DISABLED
| ACB_ENC_TXT_PWD_ALLOWED
| user_extra_flags
),
534 /* The 'use DES' flag does stick */
535 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
536 (base_acct_flags
| ACB_DISABLED
| ACB_USE_DES_KEY_ONLY
),
537 (base_acct_flags
| ACB_DISABLED
| ACB_USE_DES_KEY_ONLY
| user_extra_flags
),
539 /* The 'don't require kerberos pre-authentication flag does stick */
540 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
541 (base_acct_flags
| ACB_DISABLED
| ACB_DONT_REQUIRE_PREAUTH
),
542 (base_acct_flags
| ACB_DISABLED
| ACB_DONT_REQUIRE_PREAUTH
| user_extra_flags
),
544 /* The 'no kerberos PAC required' flag sticks */
545 TEST_USERINFO_INT_EXP(16, acct_flags
, 21, acct_flags
,
546 (base_acct_flags
| ACB_DISABLED
| ACB_NO_AUTH_DATA_REQD
),
547 (base_acct_flags
| ACB_DISABLED
| ACB_NO_AUTH_DATA_REQD
| user_extra_flags
),
550 TEST_USERINFO_INT_EXP(21, acct_flags
, 21, acct_flags
,
551 (base_acct_flags
| ACB_DISABLED
),
552 (base_acct_flags
| ACB_DISABLED
| user_extra_flags
),
553 SAMR_FIELD_ACCT_FLAGS
);
556 /* these fail with win2003 - it appears you can't set the primary gid?
557 the set succeeds, but the gid isn't changed. Very weird! */
558 TEST_USERINFO_INT(9, primary_gid
, 1, primary_gid
, 513);
559 TEST_USERINFO_INT(9, primary_gid
, 3, primary_gid
, 513);
560 TEST_USERINFO_INT(9, primary_gid
, 5, primary_gid
, 513);
561 TEST_USERINFO_INT(9, primary_gid
, 21, primary_gid
, 513);
568 generate a random password for password change tests
570 static char *samr_rand_pass_silent(TALLOC_CTX
*mem_ctx
, int min_len
)
572 size_t len
= MAX(8, min_len
) + (random() % 6);
573 char *s
= generate_random_str(mem_ctx
, len
);
577 static char *samr_rand_pass(TALLOC_CTX
*mem_ctx
, int min_len
)
579 char *s
= samr_rand_pass_silent(mem_ctx
, min_len
);
580 printf("Generated password '%s'\n", s
);
586 generate a random password for password change tests
588 static DATA_BLOB
samr_very_rand_pass(TALLOC_CTX
*mem_ctx
, int len
)
591 DATA_BLOB password
= data_blob_talloc(mem_ctx
, NULL
, len
* 2 /* number of unicode chars */);
592 generate_random_buffer(password
.data
, password
.length
);
594 for (i
=0; i
< len
; i
++) {
595 if (((uint16_t *)password
.data
)[i
] == 0) {
596 ((uint16_t *)password
.data
)[i
] = 1;
604 generate a random password for password change tests (fixed length)
606 static char *samr_rand_pass_fixed_len(TALLOC_CTX
*mem_ctx
, int len
)
608 char *s
= generate_random_str(mem_ctx
, len
);
609 printf("Generated password '%s'\n", s
);
613 static bool test_SetUserPass(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
614 struct policy_handle
*handle
, char **password
)
617 struct samr_SetUserInfo s
;
618 union samr_UserInfo u
;
620 DATA_BLOB session_key
;
622 struct samr_GetUserPwInfo pwp
;
623 struct samr_PwInfo info
;
624 int policy_min_pw_len
= 0;
625 pwp
.in
.user_handle
= handle
;
626 pwp
.out
.info
= &info
;
628 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
629 if (NT_STATUS_IS_OK(status
)) {
630 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
632 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
634 s
.in
.user_handle
= handle
;
638 encode_pw_buffer(u
.info24
.password
.data
, newpass
, STR_UNICODE
);
639 u
.info24
.password_expired
= 0;
641 status
= dcerpc_fetch_session_key(p
, &session_key
);
642 if (!NT_STATUS_IS_OK(status
)) {
643 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
644 s
.in
.level
, nt_errstr(status
));
648 arcfour_crypt_blob(u
.info24
.password
.data
, 516, &session_key
);
650 torture_comment(tctx
, "Testing SetUserInfo level 24 (set password)\n");
652 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
653 if (!NT_STATUS_IS_OK(status
)) {
654 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
655 s
.in
.level
, nt_errstr(status
));
665 static bool test_SetUserPass_23(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
666 struct policy_handle
*handle
, uint32_t fields_present
,
670 struct samr_SetUserInfo s
;
671 union samr_UserInfo u
;
673 DATA_BLOB session_key
;
675 struct samr_GetUserPwInfo pwp
;
676 struct samr_PwInfo info
;
677 int policy_min_pw_len
= 0;
678 pwp
.in
.user_handle
= handle
;
679 pwp
.out
.info
= &info
;
681 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
682 if (NT_STATUS_IS_OK(status
)) {
683 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
685 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
687 s
.in
.user_handle
= handle
;
693 u
.info23
.info
.fields_present
= fields_present
;
695 encode_pw_buffer(u
.info23
.password
.data
, newpass
, STR_UNICODE
);
697 status
= dcerpc_fetch_session_key(p
, &session_key
);
698 if (!NT_STATUS_IS_OK(status
)) {
699 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
700 s
.in
.level
, nt_errstr(status
));
704 arcfour_crypt_blob(u
.info23
.password
.data
, 516, &session_key
);
706 torture_comment(tctx
, "Testing SetUserInfo level 23 (set password)\n");
708 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
709 if (!NT_STATUS_IS_OK(status
)) {
710 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
711 s
.in
.level
, nt_errstr(status
));
717 encode_pw_buffer(u
.info23
.password
.data
, newpass
, STR_UNICODE
);
719 status
= dcerpc_fetch_session_key(p
, &session_key
);
720 if (!NT_STATUS_IS_OK(status
)) {
721 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
722 s
.in
.level
, nt_errstr(status
));
726 /* This should break the key nicely */
727 session_key
.length
--;
728 arcfour_crypt_blob(u
.info23
.password
.data
, 516, &session_key
);
730 torture_comment(tctx
, "Testing SetUserInfo level 23 (set password) with wrong password\n");
732 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
733 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
734 torture_warning(tctx
, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
735 s
.in
.level
, nt_errstr(status
));
743 static bool test_SetUserPassEx(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
744 struct policy_handle
*handle
, bool makeshort
,
748 struct samr_SetUserInfo s
;
749 union samr_UserInfo u
;
751 DATA_BLOB session_key
;
752 DATA_BLOB confounded_session_key
= data_blob_talloc(tctx
, NULL
, 16);
753 uint8_t confounder
[16];
755 struct MD5Context ctx
;
756 struct samr_GetUserPwInfo pwp
;
757 struct samr_PwInfo info
;
758 int policy_min_pw_len
= 0;
759 pwp
.in
.user_handle
= handle
;
760 pwp
.out
.info
= &info
;
762 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
763 if (NT_STATUS_IS_OK(status
)) {
764 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
766 if (makeshort
&& policy_min_pw_len
) {
767 newpass
= samr_rand_pass_fixed_len(tctx
, policy_min_pw_len
- 1);
769 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
772 s
.in
.user_handle
= handle
;
776 encode_pw_buffer(u
.info26
.password
.data
, newpass
, STR_UNICODE
);
777 u
.info26
.password_expired
= 0;
779 status
= dcerpc_fetch_session_key(p
, &session_key
);
780 if (!NT_STATUS_IS_OK(status
)) {
781 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
782 s
.in
.level
, nt_errstr(status
));
786 generate_random_buffer((uint8_t *)confounder
, 16);
789 MD5Update(&ctx
, confounder
, 16);
790 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
791 MD5Final(confounded_session_key
.data
, &ctx
);
793 arcfour_crypt_blob(u
.info26
.password
.data
, 516, &confounded_session_key
);
794 memcpy(&u
.info26
.password
.data
[516], confounder
, 16);
796 torture_comment(tctx
, "Testing SetUserInfo level 26 (set password ex)\n");
798 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
799 if (!NT_STATUS_IS_OK(status
)) {
800 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
801 s
.in
.level
, nt_errstr(status
));
807 /* This should break the key nicely */
808 confounded_session_key
.data
[0]++;
810 arcfour_crypt_blob(u
.info26
.password
.data
, 516, &confounded_session_key
);
811 memcpy(&u
.info26
.password
.data
[516], confounder
, 16);
813 torture_comment(tctx
, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
815 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
816 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
817 torture_warning(tctx
, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
818 s
.in
.level
, nt_errstr(status
));
827 static bool test_SetUserPass_25(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
828 struct policy_handle
*handle
, uint32_t fields_present
,
832 struct samr_SetUserInfo s
;
833 union samr_UserInfo u
;
835 DATA_BLOB session_key
;
836 DATA_BLOB confounded_session_key
= data_blob_talloc(tctx
, NULL
, 16);
837 struct MD5Context ctx
;
838 uint8_t confounder
[16];
840 struct samr_GetUserPwInfo pwp
;
841 struct samr_PwInfo info
;
842 int policy_min_pw_len
= 0;
843 pwp
.in
.user_handle
= handle
;
844 pwp
.out
.info
= &info
;
846 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
847 if (NT_STATUS_IS_OK(status
)) {
848 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
850 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
852 s
.in
.user_handle
= handle
;
858 u
.info25
.info
.fields_present
= fields_present
;
860 encode_pw_buffer(u
.info25
.password
.data
, newpass
, STR_UNICODE
);
862 status
= dcerpc_fetch_session_key(p
, &session_key
);
863 if (!NT_STATUS_IS_OK(status
)) {
864 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
865 s
.in
.level
, nt_errstr(status
));
869 generate_random_buffer((uint8_t *)confounder
, 16);
872 MD5Update(&ctx
, confounder
, 16);
873 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
874 MD5Final(confounded_session_key
.data
, &ctx
);
876 arcfour_crypt_blob(u
.info25
.password
.data
, 516, &confounded_session_key
);
877 memcpy(&u
.info25
.password
.data
[516], confounder
, 16);
879 torture_comment(tctx
, "Testing SetUserInfo level 25 (set password ex)\n");
881 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
882 if (!NT_STATUS_IS_OK(status
)) {
883 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
884 s
.in
.level
, nt_errstr(status
));
890 /* This should break the key nicely */
891 confounded_session_key
.data
[0]++;
893 arcfour_crypt_blob(u
.info25
.password
.data
, 516, &confounded_session_key
);
894 memcpy(&u
.info25
.password
.data
[516], confounder
, 16);
896 torture_comment(tctx
, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
898 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
899 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
900 torture_warning(tctx
, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
901 s
.in
.level
, nt_errstr(status
));
908 static bool test_SetUserPass_18(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
909 struct policy_handle
*handle
, char **password
)
912 struct samr_SetUserInfo s
;
913 union samr_UserInfo u
;
915 DATA_BLOB session_key
;
917 struct samr_GetUserPwInfo pwp
;
918 struct samr_PwInfo info
;
919 int policy_min_pw_len
= 0;
920 uint8_t lm_hash
[16], nt_hash
[16];
922 pwp
.in
.user_handle
= handle
;
923 pwp
.out
.info
= &info
;
925 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
926 if (NT_STATUS_IS_OK(status
)) {
927 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
929 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
931 s
.in
.user_handle
= handle
;
937 u
.info18
.nt_pwd_active
= true;
938 u
.info18
.lm_pwd_active
= true;
940 E_md4hash(newpass
, nt_hash
);
941 E_deshash(newpass
, lm_hash
);
943 status
= dcerpc_fetch_session_key(p
, &session_key
);
944 if (!NT_STATUS_IS_OK(status
)) {
945 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
946 s
.in
.level
, nt_errstr(status
));
952 in
= data_blob_const(nt_hash
, 16);
953 out
= data_blob_talloc_zero(tctx
, 16);
954 sess_crypt_blob(&out
, &in
, &session_key
, true);
955 memcpy(u
.info18
.nt_pwd
.hash
, out
.data
, out
.length
);
959 in
= data_blob_const(lm_hash
, 16);
960 out
= data_blob_talloc_zero(tctx
, 16);
961 sess_crypt_blob(&out
, &in
, &session_key
, true);
962 memcpy(u
.info18
.lm_pwd
.hash
, out
.data
, out
.length
);
965 torture_comment(tctx
, "Testing SetUserInfo level 18 (set password hash)\n");
967 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
968 if (!NT_STATUS_IS_OK(status
)) {
969 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
970 s
.in
.level
, nt_errstr(status
));
979 static bool test_SetUserPass_21(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
980 struct policy_handle
*handle
, uint32_t fields_present
,
984 struct samr_SetUserInfo s
;
985 union samr_UserInfo u
;
987 DATA_BLOB session_key
;
989 struct samr_GetUserPwInfo pwp
;
990 struct samr_PwInfo info
;
991 int policy_min_pw_len
= 0;
992 uint8_t lm_hash
[16], nt_hash
[16];
994 pwp
.in
.user_handle
= handle
;
995 pwp
.out
.info
= &info
;
997 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
998 if (NT_STATUS_IS_OK(status
)) {
999 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
1001 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
1003 s
.in
.user_handle
= handle
;
1007 E_md4hash(newpass
, nt_hash
);
1008 E_deshash(newpass
, lm_hash
);
1012 u
.info21
.fields_present
= fields_present
;
1014 if (fields_present
& SAMR_FIELD_LM_PASSWORD_PRESENT
) {
1015 u
.info21
.lm_owf_password
.length
= 16;
1016 u
.info21
.lm_owf_password
.size
= 16;
1017 u
.info21
.lm_owf_password
.array
= (uint16_t *)lm_hash
;
1018 u
.info21
.lm_password_set
= true;
1021 if (fields_present
& SAMR_FIELD_NT_PASSWORD_PRESENT
) {
1022 u
.info21
.nt_owf_password
.length
= 16;
1023 u
.info21
.nt_owf_password
.size
= 16;
1024 u
.info21
.nt_owf_password
.array
= (uint16_t *)nt_hash
;
1025 u
.info21
.nt_password_set
= true;
1028 status
= dcerpc_fetch_session_key(p
, &session_key
);
1029 if (!NT_STATUS_IS_OK(status
)) {
1030 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
1031 s
.in
.level
, nt_errstr(status
));
1035 if (fields_present
& SAMR_FIELD_LM_PASSWORD_PRESENT
) {
1037 in
= data_blob_const(u
.info21
.lm_owf_password
.array
,
1038 u
.info21
.lm_owf_password
.length
);
1039 out
= data_blob_talloc_zero(tctx
, 16);
1040 sess_crypt_blob(&out
, &in
, &session_key
, true);
1041 u
.info21
.lm_owf_password
.array
= (uint16_t *)out
.data
;
1044 if (fields_present
& SAMR_FIELD_NT_PASSWORD_PRESENT
) {
1046 in
= data_blob_const(u
.info21
.nt_owf_password
.array
,
1047 u
.info21
.nt_owf_password
.length
);
1048 out
= data_blob_talloc_zero(tctx
, 16);
1049 sess_crypt_blob(&out
, &in
, &session_key
, true);
1050 u
.info21
.nt_owf_password
.array
= (uint16_t *)out
.data
;
1053 torture_comment(tctx
, "Testing SetUserInfo level 21 (set password hash)\n");
1055 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
1056 if (!NT_STATUS_IS_OK(status
)) {
1057 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
1058 s
.in
.level
, nt_errstr(status
));
1061 *password
= newpass
;
1064 /* try invalid length */
1065 if (fields_present
& SAMR_FIELD_NT_PASSWORD_PRESENT
) {
1067 u
.info21
.nt_owf_password
.length
++;
1069 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
1071 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
1072 torture_warning(tctx
, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1073 s
.in
.level
, nt_errstr(status
));
1078 if (fields_present
& SAMR_FIELD_LM_PASSWORD_PRESENT
) {
1080 u
.info21
.lm_owf_password
.length
++;
1082 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
1084 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
1085 torture_warning(tctx
, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1086 s
.in
.level
, nt_errstr(status
));
1094 static bool test_SetUserPass_level_ex(struct dcerpc_pipe
*p
,
1095 struct torture_context
*tctx
,
1096 struct policy_handle
*handle
,
1098 uint32_t fields_present
,
1099 char **password
, uint8_t password_expired
,
1101 bool *matched_expected_error
)
1104 NTSTATUS expected_error
= NT_STATUS_OK
;
1105 struct samr_SetUserInfo s
;
1106 struct samr_SetUserInfo2 s2
;
1107 union samr_UserInfo u
;
1109 DATA_BLOB session_key
;
1110 DATA_BLOB confounded_session_key
= data_blob_talloc(tctx
, NULL
, 16);
1111 struct MD5Context ctx
;
1112 uint8_t confounder
[16];
1114 struct samr_GetUserPwInfo pwp
;
1115 struct samr_PwInfo info
;
1116 int policy_min_pw_len
= 0;
1117 const char *comment
= NULL
;
1118 uint8_t lm_hash
[16], nt_hash
[16];
1120 pwp
.in
.user_handle
= handle
;
1121 pwp
.out
.info
= &info
;
1123 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
1124 if (NT_STATUS_IS_OK(status
)) {
1125 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
1127 newpass
= samr_rand_pass_silent(tctx
, policy_min_pw_len
);
1130 s2
.in
.user_handle
= handle
;
1132 s2
.in
.level
= level
;
1134 s
.in
.user_handle
= handle
;
1139 if (fields_present
& SAMR_FIELD_COMMENT
) {
1140 comment
= talloc_asprintf(tctx
, "comment: %ld\n", time(NULL
));
1147 E_md4hash(newpass
, nt_hash
);
1148 E_deshash(newpass
, lm_hash
);
1150 u
.info18
.nt_pwd_active
= true;
1151 u
.info18
.lm_pwd_active
= true;
1152 u
.info18
.password_expired
= password_expired
;
1154 memcpy(u
.info18
.lm_pwd
.hash
, lm_hash
, 16);
1155 memcpy(u
.info18
.nt_pwd
.hash
, nt_hash
, 16);
1159 E_md4hash(newpass
, nt_hash
);
1160 E_deshash(newpass
, lm_hash
);
1162 u
.info21
.fields_present
= fields_present
;
1163 u
.info21
.password_expired
= password_expired
;
1164 u
.info21
.comment
.string
= comment
;
1166 if (fields_present
& SAMR_FIELD_LM_PASSWORD_PRESENT
) {
1167 u
.info21
.lm_owf_password
.length
= 16;
1168 u
.info21
.lm_owf_password
.size
= 16;
1169 u
.info21
.lm_owf_password
.array
= (uint16_t *)lm_hash
;
1170 u
.info21
.lm_password_set
= true;
1173 if (fields_present
& SAMR_FIELD_NT_PASSWORD_PRESENT
) {
1174 u
.info21
.nt_owf_password
.length
= 16;
1175 u
.info21
.nt_owf_password
.size
= 16;
1176 u
.info21
.nt_owf_password
.array
= (uint16_t *)nt_hash
;
1177 u
.info21
.nt_password_set
= true;
1182 u
.info23
.info
.fields_present
= fields_present
;
1183 u
.info23
.info
.password_expired
= password_expired
;
1184 u
.info23
.info
.comment
.string
= comment
;
1186 encode_pw_buffer(u
.info23
.password
.data
, newpass
, STR_UNICODE
);
1190 u
.info24
.password_expired
= password_expired
;
1192 encode_pw_buffer(u
.info24
.password
.data
, newpass
, STR_UNICODE
);
1196 u
.info25
.info
.fields_present
= fields_present
;
1197 u
.info25
.info
.password_expired
= password_expired
;
1198 u
.info25
.info
.comment
.string
= comment
;
1200 encode_pw_buffer(u
.info25
.password
.data
, newpass
, STR_UNICODE
);
1204 u
.info26
.password_expired
= password_expired
;
1206 encode_pw_buffer(u
.info26
.password
.data
, newpass
, STR_UNICODE
);
1211 status
= dcerpc_fetch_session_key(p
, &session_key
);
1212 if (!NT_STATUS_IS_OK(status
)) {
1213 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
1214 s
.in
.level
, nt_errstr(status
));
1218 generate_random_buffer((uint8_t *)confounder
, 16);
1221 MD5Update(&ctx
, confounder
, 16);
1222 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
1223 MD5Final(confounded_session_key
.data
, &ctx
);
1229 in
= data_blob_const(u
.info18
.nt_pwd
.hash
, 16);
1230 out
= data_blob_talloc_zero(tctx
, 16);
1231 sess_crypt_blob(&out
, &in
, &session_key
, true);
1232 memcpy(u
.info18
.nt_pwd
.hash
, out
.data
, out
.length
);
1236 in
= data_blob_const(u
.info18
.lm_pwd
.hash
, 16);
1237 out
= data_blob_talloc_zero(tctx
, 16);
1238 sess_crypt_blob(&out
, &in
, &session_key
, true);
1239 memcpy(u
.info18
.lm_pwd
.hash
, out
.data
, out
.length
);
1244 if (fields_present
& SAMR_FIELD_LM_PASSWORD_PRESENT
) {
1246 in
= data_blob_const(u
.info21
.lm_owf_password
.array
,
1247 u
.info21
.lm_owf_password
.length
);
1248 out
= data_blob_talloc_zero(tctx
, 16);
1249 sess_crypt_blob(&out
, &in
, &session_key
, true);
1250 u
.info21
.lm_owf_password
.array
= (uint16_t *)out
.data
;
1252 if (fields_present
& SAMR_FIELD_NT_PASSWORD_PRESENT
) {
1254 in
= data_blob_const(u
.info21
.nt_owf_password
.array
,
1255 u
.info21
.nt_owf_password
.length
);
1256 out
= data_blob_talloc_zero(tctx
, 16);
1257 sess_crypt_blob(&out
, &in
, &session_key
, true);
1258 u
.info21
.nt_owf_password
.array
= (uint16_t *)out
.data
;
1262 arcfour_crypt_blob(u
.info23
.password
.data
, 516, &session_key
);
1265 arcfour_crypt_blob(u
.info24
.password
.data
, 516, &session_key
);
1268 arcfour_crypt_blob(u
.info25
.password
.data
, 516, &confounded_session_key
);
1269 memcpy(&u
.info25
.password
.data
[516], confounder
, 16);
1272 arcfour_crypt_blob(u
.info26
.password
.data
, 516, &confounded_session_key
);
1273 memcpy(&u
.info26
.password
.data
[516], confounder
, 16);
1278 status
= dcerpc_samr_SetUserInfo2(p
, tctx
, &s2
);
1280 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
1283 if (!NT_STATUS_IS_OK(status
)) {
1284 if (fields_present
== 0) {
1285 expected_error
= NT_STATUS_INVALID_PARAMETER
;
1287 if (fields_present
& SAMR_FIELD_LAST_PWD_CHANGE
) {
1288 expected_error
= NT_STATUS_ACCESS_DENIED
;
1292 if (!NT_STATUS_IS_OK(expected_error
)) {
1294 torture_assert_ntstatus_equal(tctx
,
1296 expected_error
, "SetUserInfo2 failed");
1298 torture_assert_ntstatus_equal(tctx
,
1300 expected_error
, "SetUserInfo failed");
1302 *matched_expected_error
= true;
1306 if (!NT_STATUS_IS_OK(status
)) {
1307 torture_warning(tctx
, "SetUserInfo%s level %u failed - %s\n",
1308 use_setinfo2
? "2":"", level
, nt_errstr(status
));
1311 *password
= newpass
;
1317 static bool test_SetAliasInfo(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1318 struct policy_handle
*handle
)
1321 struct samr_SetAliasInfo r
;
1322 struct samr_QueryAliasInfo q
;
1323 union samr_AliasInfo
*info
;
1324 uint16_t levels
[] = {2, 3};
1328 /* Ignoring switch level 1, as that includes the number of members for the alias
1329 * and setting this to a wrong value might have negative consequences
1332 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1333 torture_comment(tctx
, "Testing SetAliasInfo level %u\n", levels
[i
]);
1335 r
.in
.alias_handle
= handle
;
1336 r
.in
.level
= levels
[i
];
1337 r
.in
.info
= talloc(tctx
, union samr_AliasInfo
);
1338 switch (r
.in
.level
) {
1339 case ALIASINFONAME
: init_lsa_String(&r
.in
.info
->name
,TEST_ALIASNAME
); break;
1340 case ALIASINFODESCRIPTION
: init_lsa_String(&r
.in
.info
->description
,
1341 "Test Description, should test I18N as well"); break;
1342 case ALIASINFOALL
: torture_comment(tctx
, "ALIASINFOALL ignored\n"); break;
1345 status
= dcerpc_samr_SetAliasInfo(p
, tctx
, &r
);
1346 if (!NT_STATUS_IS_OK(status
)) {
1347 torture_warning(tctx
, "SetAliasInfo level %u failed - %s\n",
1348 levels
[i
], nt_errstr(status
));
1352 q
.in
.alias_handle
= handle
;
1353 q
.in
.level
= levels
[i
];
1356 status
= dcerpc_samr_QueryAliasInfo(p
, tctx
, &q
);
1357 if (!NT_STATUS_IS_OK(status
)) {
1358 torture_warning(tctx
, "QueryAliasInfo level %u failed - %s\n",
1359 levels
[i
], nt_errstr(status
));
1367 static bool test_GetGroupsForUser(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1368 struct policy_handle
*user_handle
)
1370 struct samr_GetGroupsForUser r
;
1371 struct samr_RidWithAttributeArray
*rids
= NULL
;
1374 torture_comment(tctx
, "testing GetGroupsForUser\n");
1376 r
.in
.user_handle
= user_handle
;
1379 status
= dcerpc_samr_GetGroupsForUser(p
, tctx
, &r
);
1380 torture_assert_ntstatus_ok(tctx
, status
, "GetGroupsForUser");
1386 static bool test_GetDomPwInfo(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1387 struct lsa_String
*domain_name
)
1390 struct samr_GetDomPwInfo r
;
1391 struct samr_PwInfo info
;
1393 r
.in
.domain_name
= domain_name
;
1396 torture_comment(tctx
, "Testing GetDomPwInfo with name %s\n", r
.in
.domain_name
->string
);
1398 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &r
);
1399 torture_assert_ntstatus_ok(tctx
, status
, "GetDomPwInfo");
1401 r
.in
.domain_name
->string
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
1402 torture_comment(tctx
, "Testing GetDomPwInfo with name %s\n", r
.in
.domain_name
->string
);
1404 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &r
);
1405 torture_assert_ntstatus_ok(tctx
, status
, "GetDomPwInfo");
1407 r
.in
.domain_name
->string
= "\\\\__NONAME__";
1408 torture_comment(tctx
, "Testing GetDomPwInfo with name %s\n", r
.in
.domain_name
->string
);
1410 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &r
);
1411 torture_assert_ntstatus_ok(tctx
, status
, "GetDomPwInfo");
1413 r
.in
.domain_name
->string
= "\\\\Builtin";
1414 torture_comment(tctx
, "Testing GetDomPwInfo with name %s\n", r
.in
.domain_name
->string
);
1416 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &r
);
1417 torture_assert_ntstatus_ok(tctx
, status
, "GetDomPwInfo");
1422 static bool test_GetUserPwInfo(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1423 struct policy_handle
*handle
)
1426 struct samr_GetUserPwInfo r
;
1427 struct samr_PwInfo info
;
1429 torture_comment(tctx
, "Testing GetUserPwInfo\n");
1431 r
.in
.user_handle
= handle
;
1434 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &r
);
1435 torture_assert_ntstatus_ok(tctx
, status
, "GetUserPwInfo");
1440 static NTSTATUS
test_LookupName(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1441 struct policy_handle
*domain_handle
, const char *name
,
1445 struct samr_LookupNames n
;
1446 struct lsa_String sname
[2];
1447 struct samr_Ids rids
, types
;
1449 init_lsa_String(&sname
[0], name
);
1451 n
.in
.domain_handle
= domain_handle
;
1455 n
.out
.types
= &types
;
1456 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
1457 if (NT_STATUS_IS_OK(status
)) {
1458 *rid
= n
.out
.rids
->ids
[0];
1463 init_lsa_String(&sname
[1], "xxNONAMExx");
1465 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
1466 if (!NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
1467 torture_warning(tctx
, "LookupNames[2] failed - %s\n", nt_errstr(status
));
1468 if (NT_STATUS_IS_OK(status
)) {
1469 return NT_STATUS_UNSUCCESSFUL
;
1475 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
1476 if (!NT_STATUS_IS_OK(status
)) {
1477 torture_warning(tctx
, "LookupNames[0] failed - %s\n", nt_errstr(status
));
1481 init_lsa_String(&sname
[0], "xxNONAMExx");
1483 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
1484 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NONE_MAPPED
)) {
1485 torture_warning(tctx
, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status
));
1486 if (NT_STATUS_IS_OK(status
)) {
1487 return NT_STATUS_UNSUCCESSFUL
;
1492 init_lsa_String(&sname
[0], "xxNONAMExx");
1493 init_lsa_String(&sname
[1], "xxNONAME2xx");
1495 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
1496 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NONE_MAPPED
)) {
1497 torture_warning(tctx
, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status
));
1498 if (NT_STATUS_IS_OK(status
)) {
1499 return NT_STATUS_UNSUCCESSFUL
;
1504 return NT_STATUS_OK
;
1507 static NTSTATUS
test_OpenUser_byname(struct dcerpc_pipe
*p
,
1508 struct torture_context
*tctx
,
1509 struct policy_handle
*domain_handle
,
1510 const char *name
, struct policy_handle
*user_handle
)
1513 struct samr_OpenUser r
;
1516 status
= test_LookupName(p
, tctx
, domain_handle
, name
, &rid
);
1517 if (!NT_STATUS_IS_OK(status
)) {
1521 r
.in
.domain_handle
= domain_handle
;
1522 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1524 r
.out
.user_handle
= user_handle
;
1525 status
= dcerpc_samr_OpenUser(p
, tctx
, &r
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1527 torture_warning(tctx
, "OpenUser_byname(%s -> %d) failed - %s\n", name
, rid
, nt_errstr(status
));
1534 static bool test_ChangePasswordNT3(struct dcerpc_pipe
*p
,
1535 struct torture_context
*tctx
,
1536 struct policy_handle
*handle
)
1539 struct samr_ChangePasswordUser r
;
1541 struct samr_Password hash1
, hash2
, hash3
, hash4
, hash5
, hash6
;
1542 struct policy_handle user_handle
;
1543 char *oldpass
= "test";
1544 char *newpass
= "test2";
1545 uint8_t old_nt_hash
[16], new_nt_hash
[16];
1546 uint8_t old_lm_hash
[16], new_lm_hash
[16];
1548 status
= test_OpenUser_byname(p
, tctx
, handle
, "testuser", &user_handle
);
1549 if (!NT_STATUS_IS_OK(status
)) {
1553 torture_comment(tctx
, "Testing ChangePasswordUser for user 'testuser'\n");
1555 torture_comment(tctx
, "old password: %s\n", oldpass
);
1556 torture_comment(tctx
, "new password: %s\n", newpass
);
1558 E_md4hash(oldpass
, old_nt_hash
);
1559 E_md4hash(newpass
, new_nt_hash
);
1560 E_deshash(oldpass
, old_lm_hash
);
1561 E_deshash(newpass
, new_lm_hash
);
1563 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
1564 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
1565 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
1566 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
1567 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
1568 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
1570 r
.in
.handle
= &user_handle
;
1571 r
.in
.lm_present
= 1;
1572 r
.in
.old_lm_crypted
= &hash1
;
1573 r
.in
.new_lm_crypted
= &hash2
;
1574 r
.in
.nt_present
= 1;
1575 r
.in
.old_nt_crypted
= &hash3
;
1576 r
.in
.new_nt_crypted
= &hash4
;
1577 r
.in
.cross1_present
= 1;
1578 r
.in
.nt_cross
= &hash5
;
1579 r
.in
.cross2_present
= 1;
1580 r
.in
.lm_cross
= &hash6
;
1582 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1583 if (!NT_STATUS_IS_OK(status
)) {
1584 torture_warning(tctx
, "ChangePasswordUser failed - %s\n", nt_errstr(status
));
1588 if (!test_samr_handle_Close(p
, tctx
, &user_handle
)) {
1596 static bool test_ChangePasswordUser(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1597 const char *acct_name
,
1598 struct policy_handle
*handle
, char **password
)
1601 struct samr_ChangePasswordUser r
;
1603 struct samr_Password hash1
, hash2
, hash3
, hash4
, hash5
, hash6
;
1604 struct policy_handle user_handle
;
1606 uint8_t old_nt_hash
[16], new_nt_hash
[16];
1607 uint8_t old_lm_hash
[16], new_lm_hash
[16];
1608 bool changed
= true;
1611 struct samr_GetUserPwInfo pwp
;
1612 struct samr_PwInfo info
;
1613 int policy_min_pw_len
= 0;
1615 status
= test_OpenUser_byname(p
, tctx
, handle
, acct_name
, &user_handle
);
1616 if (!NT_STATUS_IS_OK(status
)) {
1619 pwp
.in
.user_handle
= &user_handle
;
1620 pwp
.out
.info
= &info
;
1622 status
= dcerpc_samr_GetUserPwInfo(p
, tctx
, &pwp
);
1623 if (NT_STATUS_IS_OK(status
)) {
1624 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
1626 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
1628 torture_comment(tctx
, "Testing ChangePasswordUser\n");
1630 torture_assert(tctx
, *password
!= NULL
,
1631 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1633 oldpass
= *password
;
1635 E_md4hash(oldpass
, old_nt_hash
);
1636 E_md4hash(newpass
, new_nt_hash
);
1637 E_deshash(oldpass
, old_lm_hash
);
1638 E_deshash(newpass
, new_lm_hash
);
1640 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
1641 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
1642 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
1643 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
1644 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
1645 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
1647 r
.in
.user_handle
= &user_handle
;
1648 r
.in
.lm_present
= 1;
1649 /* Break the LM hash */
1651 r
.in
.old_lm_crypted
= &hash1
;
1652 r
.in
.new_lm_crypted
= &hash2
;
1653 r
.in
.nt_present
= 1;
1654 r
.in
.old_nt_crypted
= &hash3
;
1655 r
.in
.new_nt_crypted
= &hash4
;
1656 r
.in
.cross1_present
= 1;
1657 r
.in
.nt_cross
= &hash5
;
1658 r
.in
.cross2_present
= 1;
1659 r
.in
.lm_cross
= &hash6
;
1661 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1662 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_WRONG_PASSWORD
,
1663 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1665 /* Unbreak the LM hash */
1668 r
.in
.user_handle
= &user_handle
;
1669 r
.in
.lm_present
= 1;
1670 r
.in
.old_lm_crypted
= &hash1
;
1671 r
.in
.new_lm_crypted
= &hash2
;
1672 /* Break the NT hash */
1674 r
.in
.nt_present
= 1;
1675 r
.in
.old_nt_crypted
= &hash3
;
1676 r
.in
.new_nt_crypted
= &hash4
;
1677 r
.in
.cross1_present
= 1;
1678 r
.in
.nt_cross
= &hash5
;
1679 r
.in
.cross2_present
= 1;
1680 r
.in
.lm_cross
= &hash6
;
1682 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1683 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_WRONG_PASSWORD
,
1684 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1686 /* Unbreak the NT hash */
1689 r
.in
.user_handle
= &user_handle
;
1690 r
.in
.lm_present
= 1;
1691 r
.in
.old_lm_crypted
= &hash1
;
1692 r
.in
.new_lm_crypted
= &hash2
;
1693 r
.in
.nt_present
= 1;
1694 r
.in
.old_nt_crypted
= &hash3
;
1695 r
.in
.new_nt_crypted
= &hash4
;
1696 r
.in
.cross1_present
= 1;
1697 r
.in
.nt_cross
= &hash5
;
1698 r
.in
.cross2_present
= 1;
1699 /* Break the LM cross */
1701 r
.in
.lm_cross
= &hash6
;
1703 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1704 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1705 torture_warning(tctx
, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status
));
1709 /* Unbreak the LM cross */
1712 r
.in
.user_handle
= &user_handle
;
1713 r
.in
.lm_present
= 1;
1714 r
.in
.old_lm_crypted
= &hash1
;
1715 r
.in
.new_lm_crypted
= &hash2
;
1716 r
.in
.nt_present
= 1;
1717 r
.in
.old_nt_crypted
= &hash3
;
1718 r
.in
.new_nt_crypted
= &hash4
;
1719 r
.in
.cross1_present
= 1;
1720 /* Break the NT cross */
1722 r
.in
.nt_cross
= &hash5
;
1723 r
.in
.cross2_present
= 1;
1724 r
.in
.lm_cross
= &hash6
;
1726 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1727 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1728 torture_warning(tctx
, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status
));
1732 /* Unbreak the NT cross */
1736 /* Reset the hashes to not broken values */
1737 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
1738 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
1739 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
1740 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
1741 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
1742 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
1744 r
.in
.user_handle
= &user_handle
;
1745 r
.in
.lm_present
= 1;
1746 r
.in
.old_lm_crypted
= &hash1
;
1747 r
.in
.new_lm_crypted
= &hash2
;
1748 r
.in
.nt_present
= 1;
1749 r
.in
.old_nt_crypted
= &hash3
;
1750 r
.in
.new_nt_crypted
= &hash4
;
1751 r
.in
.cross1_present
= 1;
1752 r
.in
.nt_cross
= &hash5
;
1753 r
.in
.cross2_present
= 0;
1754 r
.in
.lm_cross
= NULL
;
1756 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1757 if (NT_STATUS_IS_OK(status
)) {
1759 *password
= newpass
;
1760 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION
, status
)) {
1761 torture_warning(tctx
, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status
));
1766 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
1768 E_md4hash(oldpass
, old_nt_hash
);
1769 E_md4hash(newpass
, new_nt_hash
);
1770 E_deshash(oldpass
, old_lm_hash
);
1771 E_deshash(newpass
, new_lm_hash
);
1774 /* Reset the hashes to not broken values */
1775 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
1776 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
1777 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
1778 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
1779 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
1780 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
1782 r
.in
.user_handle
= &user_handle
;
1783 r
.in
.lm_present
= 1;
1784 r
.in
.old_lm_crypted
= &hash1
;
1785 r
.in
.new_lm_crypted
= &hash2
;
1786 r
.in
.nt_present
= 1;
1787 r
.in
.old_nt_crypted
= &hash3
;
1788 r
.in
.new_nt_crypted
= &hash4
;
1789 r
.in
.cross1_present
= 0;
1790 r
.in
.nt_cross
= NULL
;
1791 r
.in
.cross2_present
= 1;
1792 r
.in
.lm_cross
= &hash6
;
1794 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1795 if (NT_STATUS_IS_OK(status
)) {
1797 *password
= newpass
;
1798 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION
, status
)) {
1799 torture_warning(tctx
, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status
));
1804 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
1806 E_md4hash(oldpass
, old_nt_hash
);
1807 E_md4hash(newpass
, new_nt_hash
);
1808 E_deshash(oldpass
, old_lm_hash
);
1809 E_deshash(newpass
, new_lm_hash
);
1812 /* Reset the hashes to not broken values */
1813 E_old_pw_hash(new_lm_hash
, old_lm_hash
, hash1
.hash
);
1814 E_old_pw_hash(old_lm_hash
, new_lm_hash
, hash2
.hash
);
1815 E_old_pw_hash(new_nt_hash
, old_nt_hash
, hash3
.hash
);
1816 E_old_pw_hash(old_nt_hash
, new_nt_hash
, hash4
.hash
);
1817 E_old_pw_hash(old_lm_hash
, new_nt_hash
, hash5
.hash
);
1818 E_old_pw_hash(old_nt_hash
, new_lm_hash
, hash6
.hash
);
1820 r
.in
.user_handle
= &user_handle
;
1821 r
.in
.lm_present
= 1;
1822 r
.in
.old_lm_crypted
= &hash1
;
1823 r
.in
.new_lm_crypted
= &hash2
;
1824 r
.in
.nt_present
= 1;
1825 r
.in
.old_nt_crypted
= &hash3
;
1826 r
.in
.new_nt_crypted
= &hash4
;
1827 r
.in
.cross1_present
= 1;
1828 r
.in
.nt_cross
= &hash5
;
1829 r
.in
.cross2_present
= 1;
1830 r
.in
.lm_cross
= &hash6
;
1832 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1833 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
1834 torture_comment(tctx
, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status
));
1835 } else if (!NT_STATUS_IS_OK(status
)) {
1836 torture_warning(tctx
, "ChangePasswordUser failed - %s\n", nt_errstr(status
));
1840 *password
= newpass
;
1843 r
.in
.user_handle
= &user_handle
;
1844 r
.in
.lm_present
= 1;
1845 r
.in
.old_lm_crypted
= &hash1
;
1846 r
.in
.new_lm_crypted
= &hash2
;
1847 r
.in
.nt_present
= 1;
1848 r
.in
.old_nt_crypted
= &hash3
;
1849 r
.in
.new_nt_crypted
= &hash4
;
1850 r
.in
.cross1_present
= 1;
1851 r
.in
.nt_cross
= &hash5
;
1852 r
.in
.cross2_present
= 1;
1853 r
.in
.lm_cross
= &hash6
;
1856 status
= dcerpc_samr_ChangePasswordUser(p
, tctx
, &r
);
1857 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
1858 torture_comment(tctx
, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status
));
1859 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1860 torture_warning(tctx
, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status
));
1866 if (!test_samr_handle_Close(p
, tctx
, &user_handle
)) {
1874 static bool test_OemChangePasswordUser2(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
1875 const char *acct_name
,
1876 struct policy_handle
*handle
, char **password
)
1879 struct samr_OemChangePasswordUser2 r
;
1881 struct samr_Password lm_verifier
;
1882 struct samr_CryptPassword lm_pass
;
1883 struct lsa_AsciiString server
, account
, account_bad
;
1886 uint8_t old_lm_hash
[16], new_lm_hash
[16];
1888 struct samr_GetDomPwInfo dom_pw_info
;
1889 struct samr_PwInfo info
;
1890 int policy_min_pw_len
= 0;
1892 struct lsa_String domain_name
;
1894 domain_name
.string
= "";
1895 dom_pw_info
.in
.domain_name
= &domain_name
;
1896 dom_pw_info
.out
.info
= &info
;
1898 torture_comment(tctx
, "Testing OemChangePasswordUser2\n");
1900 torture_assert(tctx
, *password
!= NULL
,
1901 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1903 oldpass
= *password
;
1905 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &dom_pw_info
);
1906 if (NT_STATUS_IS_OK(status
)) {
1907 policy_min_pw_len
= dom_pw_info
.out
.info
->min_password_length
;
1910 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
1912 server
.string
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
1913 account
.string
= acct_name
;
1915 E_deshash(oldpass
, old_lm_hash
);
1916 E_deshash(newpass
, new_lm_hash
);
1918 encode_pw_buffer(lm_pass
.data
, newpass
, STR_ASCII
);
1919 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
1920 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
1922 r
.in
.server
= &server
;
1923 r
.in
.account
= &account
;
1924 r
.in
.password
= &lm_pass
;
1925 r
.in
.hash
= &lm_verifier
;
1927 /* Break the verification */
1928 lm_verifier
.hash
[0]++;
1930 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
1932 if (!NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)
1933 && !NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1934 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1939 encode_pw_buffer(lm_pass
.data
, newpass
, STR_ASCII
);
1940 /* Break the old password */
1942 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
1943 /* unbreak it for the next operation */
1945 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
1947 r
.in
.server
= &server
;
1948 r
.in
.account
= &account
;
1949 r
.in
.password
= &lm_pass
;
1950 r
.in
.hash
= &lm_verifier
;
1952 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
1954 if (!NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)
1955 && !NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1956 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1961 encode_pw_buffer(lm_pass
.data
, newpass
, STR_ASCII
);
1962 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
1964 r
.in
.server
= &server
;
1965 r
.in
.account
= &account
;
1966 r
.in
.password
= &lm_pass
;
1969 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
1971 if (!NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)
1972 && !NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
1973 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1978 /* This shouldn't be a valid name */
1979 account_bad
.string
= TEST_ACCOUNT_NAME
"XX";
1980 r
.in
.account
= &account_bad
;
1982 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
1984 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
1985 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1990 /* This shouldn't be a valid name */
1991 account_bad
.string
= TEST_ACCOUNT_NAME
"XX";
1992 r
.in
.account
= &account_bad
;
1993 r
.in
.password
= &lm_pass
;
1994 r
.in
.hash
= &lm_verifier
;
1996 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
1998 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
1999 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2004 /* This shouldn't be a valid name */
2005 account_bad
.string
= TEST_ACCOUNT_NAME
"XX";
2006 r
.in
.account
= &account_bad
;
2007 r
.in
.password
= NULL
;
2008 r
.in
.hash
= &lm_verifier
;
2010 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
2012 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
2013 torture_warning(tctx
, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2018 E_deshash(oldpass
, old_lm_hash
);
2019 E_deshash(newpass
, new_lm_hash
);
2021 encode_pw_buffer(lm_pass
.data
, newpass
, STR_ASCII
);
2022 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
2023 E_old_pw_hash(new_lm_hash
, old_lm_hash
, lm_verifier
.hash
);
2025 r
.in
.server
= &server
;
2026 r
.in
.account
= &account
;
2027 r
.in
.password
= &lm_pass
;
2028 r
.in
.hash
= &lm_verifier
;
2030 status
= dcerpc_samr_OemChangePasswordUser2(p
, tctx
, &r
);
2031 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
2032 torture_comment(tctx
, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status
));
2033 } else if (!NT_STATUS_IS_OK(status
)) {
2034 torture_warning(tctx
, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status
));
2037 *password
= newpass
;
2044 static bool test_ChangePasswordUser2(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2045 const char *acct_name
,
2047 char *newpass
, bool allow_password_restriction
)
2050 struct samr_ChangePasswordUser2 r
;
2052 struct lsa_String server
, account
;
2053 struct samr_CryptPassword nt_pass
, lm_pass
;
2054 struct samr_Password nt_verifier
, lm_verifier
;
2056 uint8_t old_nt_hash
[16], new_nt_hash
[16];
2057 uint8_t old_lm_hash
[16], new_lm_hash
[16];
2059 struct samr_GetDomPwInfo dom_pw_info
;
2060 struct samr_PwInfo info
;
2062 struct lsa_String domain_name
;
2064 domain_name
.string
= "";
2065 dom_pw_info
.in
.domain_name
= &domain_name
;
2066 dom_pw_info
.out
.info
= &info
;
2068 torture_comment(tctx
, "Testing ChangePasswordUser2 on %s\n", acct_name
);
2070 torture_assert(tctx
, *password
!= NULL
,
2071 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2072 oldpass
= *password
;
2075 int policy_min_pw_len
= 0;
2076 status
= dcerpc_samr_GetDomPwInfo(p
, tctx
, &dom_pw_info
);
2077 if (NT_STATUS_IS_OK(status
)) {
2078 policy_min_pw_len
= dom_pw_info
.out
.info
->min_password_length
;
2081 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
2084 server
.string
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2085 init_lsa_String(&account
, acct_name
);
2087 E_md4hash(oldpass
, old_nt_hash
);
2088 E_md4hash(newpass
, new_nt_hash
);
2090 E_deshash(oldpass
, old_lm_hash
);
2091 E_deshash(newpass
, new_lm_hash
);
2093 encode_pw_buffer(lm_pass
.data
, newpass
, STR_ASCII
|STR_TERMINATE
);
2094 arcfour_crypt(lm_pass
.data
, old_lm_hash
, 516);
2095 E_old_pw_hash(new_nt_hash
, old_lm_hash
, lm_verifier
.hash
);
2097 encode_pw_buffer(nt_pass
.data
, newpass
, STR_UNICODE
);
2098 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2099 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2101 r
.in
.server
= &server
;
2102 r
.in
.account
= &account
;
2103 r
.in
.nt_password
= &nt_pass
;
2104 r
.in
.nt_verifier
= &nt_verifier
;
2106 r
.in
.lm_password
= &lm_pass
;
2107 r
.in
.lm_verifier
= &lm_verifier
;
2109 status
= dcerpc_samr_ChangePasswordUser2(p
, tctx
, &r
);
2110 if (allow_password_restriction
&& NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
2111 torture_comment(tctx
, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status
));
2112 } else if (!NT_STATUS_IS_OK(status
)) {
2113 torture_warning(tctx
, "ChangePasswordUser2 failed - %s\n", nt_errstr(status
));
2116 *password
= newpass
;
2123 bool test_ChangePasswordUser3(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2124 const char *account_string
,
2125 int policy_min_pw_len
,
2127 const char *newpass
,
2128 NTTIME last_password_change
,
2129 bool handle_reject_reason
)
2132 struct samr_ChangePasswordUser3 r
;
2134 struct lsa_String server
, account
, account_bad
;
2135 struct samr_CryptPassword nt_pass
, lm_pass
;
2136 struct samr_Password nt_verifier
, lm_verifier
;
2138 uint8_t old_nt_hash
[16], new_nt_hash
[16];
2139 uint8_t old_lm_hash
[16], new_lm_hash
[16];
2141 struct samr_DomInfo1
*dominfo
= NULL
;
2142 struct samr_ChangeReject
*reject
= NULL
;
2144 torture_comment(tctx
, "Testing ChangePasswordUser3\n");
2146 if (newpass
== NULL
) {
2148 if (policy_min_pw_len
== 0) {
2149 newpass
= samr_rand_pass(tctx
, policy_min_pw_len
);
2151 newpass
= samr_rand_pass_fixed_len(tctx
, policy_min_pw_len
);
2153 } while (check_password_quality(newpass
) == false);
2155 torture_comment(tctx
, "Using password '%s'\n", newpass
);
2158 torture_assert(tctx
, *password
!= NULL
,
2159 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2161 oldpass
= *password
;
2162 server
.string
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2163 init_lsa_String(&account
, account_string
);
2165 E_md4hash(oldpass
, old_nt_hash
);
2166 E_md4hash(newpass
, new_nt_hash
);
2168 E_deshash(oldpass
, old_lm_hash
);
2169 E_deshash(newpass
, new_lm_hash
);
2171 encode_pw_buffer(lm_pass
.data
, newpass
, STR_UNICODE
);
2172 arcfour_crypt(lm_pass
.data
, old_nt_hash
, 516);
2173 E_old_pw_hash(new_nt_hash
, old_lm_hash
, lm_verifier
.hash
);
2175 encode_pw_buffer(nt_pass
.data
, newpass
, STR_UNICODE
);
2176 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2177 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2179 /* Break the verification */
2180 nt_verifier
.hash
[0]++;
2182 r
.in
.server
= &server
;
2183 r
.in
.account
= &account
;
2184 r
.in
.nt_password
= &nt_pass
;
2185 r
.in
.nt_verifier
= &nt_verifier
;
2187 r
.in
.lm_password
= &lm_pass
;
2188 r
.in
.lm_verifier
= &lm_verifier
;
2189 r
.in
.password3
= NULL
;
2190 r
.out
.dominfo
= &dominfo
;
2191 r
.out
.reject
= &reject
;
2193 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2194 if (!NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
) &&
2195 (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
))) {
2196 torture_warning(tctx
, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2201 encode_pw_buffer(lm_pass
.data
, newpass
, STR_UNICODE
);
2202 arcfour_crypt(lm_pass
.data
, old_nt_hash
, 516);
2203 E_old_pw_hash(new_nt_hash
, old_lm_hash
, lm_verifier
.hash
);
2205 encode_pw_buffer(nt_pass
.data
, newpass
, STR_UNICODE
);
2206 /* Break the NT hash */
2208 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2209 /* Unbreak it again */
2211 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2213 r
.in
.server
= &server
;
2214 r
.in
.account
= &account
;
2215 r
.in
.nt_password
= &nt_pass
;
2216 r
.in
.nt_verifier
= &nt_verifier
;
2218 r
.in
.lm_password
= &lm_pass
;
2219 r
.in
.lm_verifier
= &lm_verifier
;
2220 r
.in
.password3
= NULL
;
2221 r
.out
.dominfo
= &dominfo
;
2222 r
.out
.reject
= &reject
;
2224 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2225 if (!NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
) &&
2226 (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
))) {
2227 torture_warning(tctx
, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2232 /* This shouldn't be a valid name */
2233 init_lsa_String(&account_bad
, talloc_asprintf(tctx
, "%sXX", account_string
));
2235 r
.in
.account
= &account_bad
;
2236 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2237 if (!NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
2238 torture_warning(tctx
, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2243 E_md4hash(oldpass
, old_nt_hash
);
2244 E_md4hash(newpass
, new_nt_hash
);
2246 E_deshash(oldpass
, old_lm_hash
);
2247 E_deshash(newpass
, new_lm_hash
);
2249 encode_pw_buffer(lm_pass
.data
, newpass
, STR_UNICODE
);
2250 arcfour_crypt(lm_pass
.data
, old_nt_hash
, 516);
2251 E_old_pw_hash(new_nt_hash
, old_lm_hash
, lm_verifier
.hash
);
2253 encode_pw_buffer(nt_pass
.data
, newpass
, STR_UNICODE
);
2254 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2255 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2257 r
.in
.server
= &server
;
2258 r
.in
.account
= &account
;
2259 r
.in
.nt_password
= &nt_pass
;
2260 r
.in
.nt_verifier
= &nt_verifier
;
2262 r
.in
.lm_password
= &lm_pass
;
2263 r
.in
.lm_verifier
= &lm_verifier
;
2264 r
.in
.password3
= NULL
;
2265 r
.out
.dominfo
= &dominfo
;
2266 r
.out
.reject
= &reject
;
2268 unix_to_nt_time(&t
, time(NULL
));
2270 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2272 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)
2275 && handle_reject_reason
2276 && (!null_nttime(last_password_change
) || !dominfo
->min_password_age
)) {
2277 if (dominfo
->password_properties
& DOMAIN_REFUSE_PASSWORD_CHANGE
) {
2279 if (reject
&& (reject
->reason
!= SAMR_REJECT_OTHER
)) {
2280 torture_warning(tctx
, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2281 SAMR_REJECT_OTHER
, reject
->reason
);
2286 /* We tested the order of precendence which is as follows:
2295 if ((dominfo
->min_password_age
> 0) && !null_nttime(last_password_change
) &&
2296 (last_password_change
+ dominfo
->min_password_age
> t
)) {
2298 if (reject
->reason
!= SAMR_REJECT_OTHER
) {
2299 torture_warning(tctx
, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2300 SAMR_REJECT_OTHER
, reject
->reason
);
2304 } else if ((dominfo
->min_password_length
> 0) &&
2305 (strlen(newpass
) < dominfo
->min_password_length
)) {
2307 if (reject
->reason
!= SAMR_REJECT_TOO_SHORT
) {
2308 torture_warning(tctx
, "expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2309 SAMR_REJECT_TOO_SHORT
, reject
->reason
);
2313 } else if ((dominfo
->password_history_length
> 0) &&
2314 strequal(oldpass
, newpass
)) {
2316 if (reject
->reason
!= SAMR_REJECT_IN_HISTORY
) {
2317 torture_warning(tctx
, "expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2318 SAMR_REJECT_IN_HISTORY
, reject
->reason
);
2321 } else if (dominfo
->password_properties
& DOMAIN_PASSWORD_COMPLEX
) {
2323 if (reject
->reason
!= SAMR_REJECT_COMPLEXITY
) {
2324 torture_warning(tctx
, "expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2325 SAMR_REJECT_COMPLEXITY
, reject
->reason
);
2331 if (reject
->reason
== SAMR_REJECT_TOO_SHORT
) {
2332 /* retry with adjusted size */
2333 return test_ChangePasswordUser3(p
, tctx
, account_string
,
2334 dominfo
->min_password_length
,
2335 password
, NULL
, 0, false);
2339 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
2340 if (reject
&& reject
->reason
!= SAMR_REJECT_OTHER
) {
2341 torture_warning(tctx
, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2342 SAMR_REJECT_OTHER
, reject
->reason
);
2345 /* Perhaps the server has a 'min password age' set? */
2348 torture_assert_ntstatus_ok(tctx
, status
, "ChangePasswordUser3");
2349 *password
= talloc_strdup(tctx
, newpass
);
2355 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2356 const char *account_string
,
2357 struct policy_handle
*handle
,
2361 struct samr_ChangePasswordUser3 r
;
2362 struct samr_SetUserInfo s
;
2363 union samr_UserInfo u
;
2364 DATA_BLOB session_key
;
2365 DATA_BLOB confounded_session_key
= data_blob_talloc(tctx
, NULL
, 16);
2366 uint8_t confounder
[16];
2367 struct MD5Context ctx
;
2370 struct lsa_String server
, account
;
2371 struct samr_CryptPassword nt_pass
;
2372 struct samr_Password nt_verifier
;
2373 DATA_BLOB new_random_pass
;
2376 uint8_t old_nt_hash
[16], new_nt_hash
[16];
2378 struct samr_DomInfo1
*dominfo
= NULL
;
2379 struct samr_ChangeReject
*reject
= NULL
;
2381 new_random_pass
= samr_very_rand_pass(tctx
, 128);
2383 torture_assert(tctx
, *password
!= NULL
,
2384 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2386 oldpass
= *password
;
2387 server
.string
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2388 init_lsa_String(&account
, account_string
);
2390 s
.in
.user_handle
= handle
;
2396 u
.info25
.info
.fields_present
= SAMR_FIELD_NT_PASSWORD_PRESENT
;
2398 set_pw_in_buffer(u
.info25
.password
.data
, &new_random_pass
);
2400 status
= dcerpc_fetch_session_key(p
, &session_key
);
2401 if (!NT_STATUS_IS_OK(status
)) {
2402 torture_warning(tctx
, "SetUserInfo level %u - no session key - %s\n",
2403 s
.in
.level
, nt_errstr(status
));
2407 generate_random_buffer((uint8_t *)confounder
, 16);
2410 MD5Update(&ctx
, confounder
, 16);
2411 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
2412 MD5Final(confounded_session_key
.data
, &ctx
);
2414 arcfour_crypt_blob(u
.info25
.password
.data
, 516, &confounded_session_key
);
2415 memcpy(&u
.info25
.password
.data
[516], confounder
, 16);
2417 torture_comment(tctx
, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2419 status
= dcerpc_samr_SetUserInfo(p
, tctx
, &s
);
2420 if (!NT_STATUS_IS_OK(status
)) {
2421 torture_warning(tctx
, "SetUserInfo level %u failed - %s\n",
2422 s
.in
.level
, nt_errstr(status
));
2426 torture_comment(tctx
, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2428 mdfour(old_nt_hash
, new_random_pass
.data
, new_random_pass
.length
);
2430 new_random_pass
= samr_very_rand_pass(tctx
, 128);
2432 mdfour(new_nt_hash
, new_random_pass
.data
, new_random_pass
.length
);
2434 set_pw_in_buffer(nt_pass
.data
, &new_random_pass
);
2435 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2436 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2438 r
.in
.server
= &server
;
2439 r
.in
.account
= &account
;
2440 r
.in
.nt_password
= &nt_pass
;
2441 r
.in
.nt_verifier
= &nt_verifier
;
2443 r
.in
.lm_password
= NULL
;
2444 r
.in
.lm_verifier
= NULL
;
2445 r
.in
.password3
= NULL
;
2446 r
.out
.dominfo
= &dominfo
;
2447 r
.out
.reject
= &reject
;
2449 unix_to_nt_time(&t
, time(NULL
));
2451 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2453 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
2454 if (reject
&& reject
->reason
!= SAMR_REJECT_OTHER
) {
2455 torture_warning(tctx
, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2456 SAMR_REJECT_OTHER
, reject
->reason
);
2459 /* Perhaps the server has a 'min password age' set? */
2461 } else if (!NT_STATUS_IS_OK(status
)) {
2462 torture_warning(tctx
, "ChangePasswordUser3 failed - %s\n", nt_errstr(status
));
2466 newpass
= samr_rand_pass(tctx
, 128);
2468 mdfour(old_nt_hash
, new_random_pass
.data
, new_random_pass
.length
);
2470 E_md4hash(newpass
, new_nt_hash
);
2472 encode_pw_buffer(nt_pass
.data
, newpass
, STR_UNICODE
);
2473 arcfour_crypt(nt_pass
.data
, old_nt_hash
, 516);
2474 E_old_pw_hash(new_nt_hash
, old_nt_hash
, nt_verifier
.hash
);
2476 r
.in
.server
= &server
;
2477 r
.in
.account
= &account
;
2478 r
.in
.nt_password
= &nt_pass
;
2479 r
.in
.nt_verifier
= &nt_verifier
;
2481 r
.in
.lm_password
= NULL
;
2482 r
.in
.lm_verifier
= NULL
;
2483 r
.in
.password3
= NULL
;
2484 r
.out
.dominfo
= &dominfo
;
2485 r
.out
.reject
= &reject
;
2487 unix_to_nt_time(&t
, time(NULL
));
2489 status
= dcerpc_samr_ChangePasswordUser3(p
, tctx
, &r
);
2491 if (NT_STATUS_EQUAL(status
, NT_STATUS_PASSWORD_RESTRICTION
)) {
2492 if (reject
&& reject
->reason
!= SAMR_REJECT_OTHER
) {
2493 torture_warning(tctx
, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2494 SAMR_REJECT_OTHER
, reject
->reason
);
2497 /* Perhaps the server has a 'min password age' set? */
2500 torture_assert_ntstatus_ok(tctx
, status
, "ChangePasswordUser3 (on second random password)");
2501 *password
= talloc_strdup(tctx
, newpass
);
2508 static bool test_GetMembersInAlias(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2509 struct policy_handle
*alias_handle
)
2511 struct samr_GetMembersInAlias r
;
2512 struct lsa_SidArray sids
;
2515 torture_comment(tctx
, "Testing GetMembersInAlias\n");
2517 r
.in
.alias_handle
= alias_handle
;
2520 status
= dcerpc_samr_GetMembersInAlias(p
, tctx
, &r
);
2521 torture_assert_ntstatus_ok(tctx
, status
, "GetMembersInAlias");
2526 static bool test_AddMemberToAlias(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2527 struct policy_handle
*alias_handle
,
2528 const struct dom_sid
*domain_sid
)
2530 struct samr_AddAliasMember r
;
2531 struct samr_DeleteAliasMember d
;
2533 struct dom_sid
*sid
;
2535 sid
= dom_sid_add_rid(tctx
, domain_sid
, 512);
2537 torture_comment(tctx
, "testing AddAliasMember\n");
2538 r
.in
.alias_handle
= alias_handle
;
2541 status
= dcerpc_samr_AddAliasMember(p
, tctx
, &r
);
2542 torture_assert_ntstatus_ok(tctx
, status
, "AddAliasMember");
2544 d
.in
.alias_handle
= alias_handle
;
2547 status
= dcerpc_samr_DeleteAliasMember(p
, tctx
, &d
);
2548 torture_assert_ntstatus_ok(tctx
, status
, "DelAliasMember");
2553 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2554 struct policy_handle
*alias_handle
)
2556 struct samr_AddMultipleMembersToAlias a
;
2557 struct samr_RemoveMultipleMembersFromAlias r
;
2559 struct lsa_SidArray sids
;
2561 torture_comment(tctx
, "testing AddMultipleMembersToAlias\n");
2562 a
.in
.alias_handle
= alias_handle
;
2566 sids
.sids
= talloc_array(tctx
, struct lsa_SidPtr
, 3);
2568 sids
.sids
[0].sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-1-2-3-1");
2569 sids
.sids
[1].sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-1-2-3-2");
2570 sids
.sids
[2].sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-1-2-3-3");
2572 status
= dcerpc_samr_AddMultipleMembersToAlias(p
, tctx
, &a
);
2573 torture_assert_ntstatus_ok(tctx
, status
, "AddMultipleMembersToAlias");
2576 torture_comment(tctx
, "testing RemoveMultipleMembersFromAlias\n");
2577 r
.in
.alias_handle
= alias_handle
;
2580 status
= dcerpc_samr_RemoveMultipleMembersFromAlias(p
, tctx
, &r
);
2581 torture_assert_ntstatus_ok(tctx
, status
, "RemoveMultipleMembersFromAlias");
2583 /* strange! removing twice doesn't give any error */
2584 status
= dcerpc_samr_RemoveMultipleMembersFromAlias(p
, tctx
, &r
);
2585 torture_assert_ntstatus_ok(tctx
, status
, "RemoveMultipleMembersFromAlias");
2587 /* but removing an alias that isn't there does */
2588 sids
.sids
[2].sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-1-2-3-4");
2590 status
= dcerpc_samr_RemoveMultipleMembersFromAlias(p
, tctx
, &r
);
2591 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
, "RemoveMultipleMembersFromAlias");
2596 static bool test_GetAliasMembership(struct dcerpc_pipe
*p
,
2597 struct torture_context
*tctx
,
2598 struct policy_handle
*domain_handle
)
2600 struct samr_GetAliasMembership r
;
2601 struct lsa_SidArray sids
;
2602 struct samr_Ids rids
;
2605 torture_comment(tctx
, "Testing GetAliasMembership\n");
2607 r
.in
.domain_handle
= domain_handle
;
2612 sids
.sids
= talloc_zero_array(tctx
, struct lsa_SidPtr
, sids
.num_sids
);
2614 status
= dcerpc_samr_GetAliasMembership(p
, tctx
, &r
);
2615 torture_assert_ntstatus_ok(tctx
, status
,
2616 "samr_GetAliasMembership failed");
2618 torture_assert_int_equal(tctx
, sids
.num_sids
, rids
.count
,
2619 "protocol misbehaviour");
2622 sids
.sids
= talloc_zero_array(tctx
, struct lsa_SidPtr
, sids
.num_sids
);
2623 sids
.sids
[0].sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-1-2-3-1");
2625 status
= dcerpc_samr_GetAliasMembership(p
, tctx
, &r
);
2626 torture_assert_ntstatus_ok(tctx
, status
,
2627 "samr_GetAliasMembership failed");
2630 /* only true for w2k8 it seems
2631 * win7, xp, w2k3 will return a 0 length array pointer */
2633 torture_assert(tctx
, (rids
.ids
&& !rids
.count
),
2634 "samr_GetAliasMembership protocol misbehaviour");
2636 torture_assert(tctx
, (!rids
.ids
&& rids
.count
),
2637 "samr_GetAliasMembership protocol misbehaviour");
2642 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
2643 struct policy_handle
*user_handle
)
2645 struct samr_TestPrivateFunctionsUser r
;
2648 torture_comment(tctx
, "Testing TestPrivateFunctionsUser\n");
2650 r
.in
.user_handle
= user_handle
;
2652 status
= dcerpc_samr_TestPrivateFunctionsUser(p
, tctx
, &r
);
2653 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NOT_IMPLEMENTED
, "TestPrivateFunctionsUser");
2658 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe
*p
,
2659 struct torture_context
*tctx
,
2660 struct policy_handle
*handle
,
2665 uint16_t levels
[] = { /* 3, */ 5, 21 };
2667 NTTIME pwdlastset3
= 0;
2668 NTTIME pwdlastset5
= 0;
2669 NTTIME pwdlastset21
= 0;
2671 torture_comment(tctx
, "Testing QueryUserInfo%s level 5 and 21 call ",
2672 use_info2
? "2":"");
2674 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2676 struct samr_QueryUserInfo r
;
2677 struct samr_QueryUserInfo2 r2
;
2678 union samr_UserInfo
*info
;
2681 r2
.in
.user_handle
= handle
;
2682 r2
.in
.level
= levels
[i
];
2683 r2
.out
.info
= &info
;
2684 status
= dcerpc_samr_QueryUserInfo2(p
, tctx
, &r2
);
2687 r
.in
.user_handle
= handle
;
2688 r
.in
.level
= levels
[i
];
2690 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &r
);
2693 if (!NT_STATUS_IS_OK(status
) &&
2694 !NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)) {
2695 torture_warning(tctx
, "QueryUserInfo%s level %u failed - %s\n",
2696 use_info2
? "2":"", levels
[i
], nt_errstr(status
));
2700 switch (levels
[i
]) {
2702 pwdlastset3
= info
->info3
.last_password_change
;
2705 pwdlastset5
= info
->info5
.last_password_change
;
2708 pwdlastset21
= info
->info21
.last_password_change
;
2714 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2715 "pwdlastset mixup"); */
2716 torture_assert_int_equal(tctx
, pwdlastset5
, pwdlastset21
,
2717 "pwdlastset mixup");
2719 *pwdlastset
= pwdlastset21
;
2721 torture_comment(tctx
, "(pwdlastset: %lld)\n", *pwdlastset
);
2726 static bool test_SamLogon(struct torture_context
*tctx
,
2727 struct dcerpc_pipe
*p
,
2728 struct cli_credentials
*test_credentials
,
2729 NTSTATUS expected_result
)
2732 struct netr_LogonSamLogonEx r
;
2733 union netr_LogonLevel logon
;
2734 union netr_Validation validation
;
2735 uint8_t authoritative
;
2736 struct netr_NetworkInfo ninfo
;
2737 DATA_BLOB names_blob
, chal
, lm_resp
, nt_resp
;
2738 int flags
= CLI_CRED_NTLM_AUTH
;
2739 uint32_t samlogon_flags
= 0;
2741 if (lp_client_lanman_auth(tctx
->lp_ctx
)) {
2742 flags
|= CLI_CRED_LANMAN_AUTH
;
2745 if (lp_client_ntlmv2_auth(tctx
->lp_ctx
)) {
2746 flags
|= CLI_CRED_NTLMv2_AUTH
;
2749 cli_credentials_get_ntlm_username_domain(test_credentials
, tctx
,
2750 &ninfo
.identity_info
.account_name
.string
,
2751 &ninfo
.identity_info
.domain_name
.string
);
2753 generate_random_buffer(ninfo
.challenge
,
2754 sizeof(ninfo
.challenge
));
2755 chal
= data_blob_const(ninfo
.challenge
,
2756 sizeof(ninfo
.challenge
));
2758 names_blob
= NTLMv2_generate_names_blob(tctx
, cli_credentials_get_workstation(test_credentials
),
2759 cli_credentials_get_domain(test_credentials
));
2761 status
= cli_credentials_get_ntlm_response(test_credentials
, tctx
,
2767 torture_assert_ntstatus_ok(tctx
, status
, "cli_credentials_get_ntlm_response failed");
2769 ninfo
.lm
.data
= lm_resp
.data
;
2770 ninfo
.lm
.length
= lm_resp
.length
;
2772 ninfo
.nt
.data
= nt_resp
.data
;
2773 ninfo
.nt
.length
= nt_resp
.length
;
2775 ninfo
.identity_info
.parameter_control
=
2776 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT
|
2777 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
;
2778 ninfo
.identity_info
.logon_id_low
= 0;
2779 ninfo
.identity_info
.logon_id_high
= 0;
2780 ninfo
.identity_info
.workstation
.string
= cli_credentials_get_workstation(test_credentials
);
2782 logon
.network
= &ninfo
;
2784 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2785 r
.in
.computer_name
= cli_credentials_get_workstation(test_credentials
);
2786 r
.in
.logon_level
= NetlogonNetworkInformation
;
2787 r
.in
.logon
= &logon
;
2788 r
.in
.flags
= &samlogon_flags
;
2789 r
.out
.flags
= &samlogon_flags
;
2790 r
.out
.validation
= &validation
;
2791 r
.out
.authoritative
= &authoritative
;
2793 torture_comment(tctx
, "Testing LogonSamLogon with name %s\n", ninfo
.identity_info
.account_name
.string
);
2795 r
.in
.validation_level
= 6;
2797 status
= dcerpc_netr_LogonSamLogonEx(p
, tctx
, &r
);
2798 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)) {
2799 r
.in
.validation_level
= 3;
2800 status
= dcerpc_netr_LogonSamLogonEx(p
, tctx
, &r
);
2802 if (!NT_STATUS_IS_OK(status
)) {
2803 torture_assert_ntstatus_equal(tctx
, status
, expected_result
, "LogonSamLogonEx failed");
2806 torture_assert_ntstatus_ok(tctx
, status
, "LogonSamLogonEx failed");
2812 static bool test_SamLogon_with_creds(struct torture_context
*tctx
,
2813 struct dcerpc_pipe
*p
,
2814 struct cli_credentials
*machine_creds
,
2815 const char *acct_name
,
2817 NTSTATUS expected_samlogon_result
)
2820 struct cli_credentials
*test_credentials
;
2822 test_credentials
= cli_credentials_init(tctx
);
2824 cli_credentials_set_workstation(test_credentials
,
2825 cli_credentials_get_workstation(machine_creds
), CRED_SPECIFIED
);
2826 cli_credentials_set_domain(test_credentials
,
2827 cli_credentials_get_domain(machine_creds
), CRED_SPECIFIED
);
2828 cli_credentials_set_username(test_credentials
,
2829 acct_name
, CRED_SPECIFIED
);
2830 cli_credentials_set_password(test_credentials
,
2831 password
, CRED_SPECIFIED
);
2833 torture_comment(tctx
, "testing samlogon as %s password: %s\n",
2834 acct_name
, password
);
2836 if (!test_SamLogon(tctx
, p
, test_credentials
,
2837 expected_samlogon_result
)) {
2838 torture_warning(tctx
, "new password did not work\n");
2845 static bool test_SetPassword_level(struct dcerpc_pipe
*p
,
2846 struct dcerpc_pipe
*np
,
2847 struct torture_context
*tctx
,
2848 struct policy_handle
*handle
,
2850 uint32_t fields_present
,
2851 uint8_t password_expired
,
2852 bool *matched_expected_error
,
2854 const char *acct_name
,
2856 struct cli_credentials
*machine_creds
,
2857 bool use_queryinfo2
,
2859 NTSTATUS expected_samlogon_result
)
2861 const char *fields
= NULL
;
2868 fields
= talloc_asprintf(tctx
, "(fields_present: 0x%08x)",
2875 torture_comment(tctx
, "Testing SetUserInfo%s level %d call "
2876 "(password_expired: %d) %s\n",
2877 use_setinfo2
? "2":"", level
, password_expired
,
2878 fields
? fields
: "");
2880 if (!test_SetUserPass_level_ex(p
, tctx
, handle
, level
,
2885 matched_expected_error
)) {
2889 if (!test_QueryUserInfo_pwdlastset(p
, tctx
, handle
,
2895 if (*matched_expected_error
== true) {
2899 if (!test_SamLogon_with_creds(tctx
, np
,
2903 expected_samlogon_result
)) {
2910 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe
*p
,
2911 struct torture_context
*tctx
,
2912 uint32_t acct_flags
,
2913 const char *acct_name
,
2914 struct policy_handle
*handle
,
2916 struct cli_credentials
*machine_credentials
)
2918 int s
= 0, q
= 0, f
= 0, l
= 0, z
= 0;
2919 struct dcerpc_binding
*b
;
2922 bool set_levels
[] = { false, true };
2923 bool query_levels
[] = { false, true };
2924 uint32_t levels
[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2925 uint32_t nonzeros
[] = { 1, 24 };
2926 uint32_t fields_present
[] = {
2928 SAMR_FIELD_EXPIRED_FLAG
,
2929 SAMR_FIELD_LAST_PWD_CHANGE
,
2930 SAMR_FIELD_EXPIRED_FLAG
| SAMR_FIELD_LAST_PWD_CHANGE
,
2932 SAMR_FIELD_NT_PASSWORD_PRESENT
,
2933 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LAST_PWD_CHANGE
,
2934 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LM_PASSWORD_PRESENT
,
2935 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LM_PASSWORD_PRESENT
| SAMR_FIELD_LAST_PWD_CHANGE
,
2936 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_EXPIRED_FLAG
,
2937 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LM_PASSWORD_PRESENT
| SAMR_FIELD_EXPIRED_FLAG
,
2938 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LM_PASSWORD_PRESENT
| SAMR_FIELD_LAST_PWD_CHANGE
| SAMR_FIELD_EXPIRED_FLAG
2941 struct dcerpc_pipe
*np
= NULL
;
2943 if (torture_setting_bool(tctx
, "samba3", false)) {
2945 torture_comment(tctx
, "Samba3 has second granularity, setting delay to: %d\n",
2949 status
= torture_rpc_binding(tctx
, &b
);
2950 if (!NT_STATUS_IS_OK(status
)) {
2955 /* We have to use schannel, otherwise the SamLogonEx fails
2956 * with INTERNAL_ERROR */
2958 b
->flags
&= ~DCERPC_AUTH_OPTIONS
;
2959 b
->flags
|= DCERPC_SCHANNEL
| DCERPC_SIGN
| DCERPC_SCHANNEL_128
;
2961 status
= dcerpc_pipe_connect_b(tctx
, &np
, b
,
2962 &ndr_table_netlogon
,
2963 machine_credentials
, tctx
->ev
, tctx
->lp_ctx
);
2965 if (!NT_STATUS_IS_OK(status
)) {
2966 torture_warning(tctx
, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status
));
2971 /* set to 1 to enable testing for all possible opcode
2972 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2975 #define TEST_ALL_LEVELS 1
2976 #define TEST_SET_LEVELS 1
2977 #define TEST_QUERY_LEVELS 1
2979 #ifdef TEST_ALL_LEVELS
2980 for (l
=0; l
<ARRAY_SIZE(levels
); l
++) {
2982 for (l
=0; l
<(ARRAY_SIZE(levels
))/2; l
++) {
2984 for (z
=0; z
<ARRAY_SIZE(nonzeros
); z
++) {
2985 for (f
=0; f
<ARRAY_SIZE(fields_present
); f
++) {
2986 #ifdef TEST_SET_LEVELS
2987 for (s
=0; s
<ARRAY_SIZE(set_levels
); s
++) {
2989 #ifdef TEST_QUERY_LEVELS
2990 for (q
=0; q
<ARRAY_SIZE(query_levels
); q
++) {
2992 NTTIME pwdlastset_old
= 0;
2993 NTTIME pwdlastset_new
= 0;
2994 bool matched_expected_error
= false;
2995 NTSTATUS expected_samlogon_result
= NT_STATUS_ACCOUNT_DISABLED
;
2997 torture_comment(tctx
, "------------------------------\n"
2998 "Testing pwdLastSet attribute for flags: 0x%08x "
2999 "(s: %d (l: %d), q: %d)\n",
3000 acct_flags
, s
, levels
[l
], q
);
3002 switch (levels
[l
]) {
3006 if (!((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3007 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
))) {
3008 expected_samlogon_result
= NT_STATUS_WRONG_PASSWORD
;
3016 /* set a password and force password change (pwdlastset 0) by
3017 * setting the password expired flag to a non-0 value */
3019 if (!test_SetPassword_level(p
, np
, tctx
, handle
,
3023 &matched_expected_error
,
3027 machine_credentials
,
3030 expected_samlogon_result
)) {
3034 if (matched_expected_error
== true) {
3035 /* skipping on expected failure */
3039 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3040 * set without the SAMR_FIELD_EXPIRED_FLAG */
3042 switch (levels
[l
]) {
3046 if ((pwdlastset_new
!= 0) &&
3047 !(fields_present
[f
] & SAMR_FIELD_EXPIRED_FLAG
)) {
3048 torture_comment(tctx
, "not considering a non-0 "
3049 "pwdLastSet as a an error as the "
3050 "SAMR_FIELD_EXPIRED_FLAG has not "
3055 if (pwdlastset_new
!= 0) {
3056 torture_warning(tctx
, "pwdLastSet test failed: "
3057 "expected pwdLastSet 0 but got %lld\n",
3064 switch (levels
[l
]) {
3068 if (((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3069 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)) &&
3070 (pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3071 (pwdlastset_old
>= pwdlastset_new
)) {
3072 torture_warning(tctx
, "pwdlastset not increasing\n");
3077 if ((pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3078 (pwdlastset_old
>= pwdlastset_new
)) {
3079 torture_warning(tctx
, "pwdlastset not increasing\n");
3089 /* set a password, pwdlastset needs to get updated (increased
3090 * value), password_expired value used here is 0 */
3092 if (!test_SetPassword_level(p
, np
, tctx
, handle
,
3096 &matched_expected_error
,
3100 machine_credentials
,
3103 expected_samlogon_result
)) {
3107 /* when a password has been changed, pwdlastset must not be 0 afterwards
3108 * and must be larger then the old value */
3110 switch (levels
[l
]) {
3115 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3116 * password has been changed, old and new pwdlastset
3117 * need to be the same value */
3119 if (!(fields_present
[f
] & SAMR_FIELD_EXPIRED_FLAG
) &&
3120 !((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3121 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)))
3123 torture_assert_int_equal(tctx
, pwdlastset_old
,
3124 pwdlastset_new
, "pwdlastset must be equal");
3128 if (pwdlastset_old
>= pwdlastset_new
) {
3129 torture_warning(tctx
, "pwdLastSet test failed: "
3130 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3131 pwdlastset_old
, pwdlastset_new
);
3134 if (pwdlastset_new
== 0) {
3135 torture_warning(tctx
, "pwdLastSet test failed: "
3136 "expected non-0 pwdlastset, got: %lld\n",
3142 switch (levels
[l
]) {
3146 if (((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3147 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)) &&
3148 (pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3149 (pwdlastset_old
>= pwdlastset_new
)) {
3150 torture_warning(tctx
, "pwdlastset not increasing\n");
3155 if ((pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3156 (pwdlastset_old
>= pwdlastset_new
)) {
3157 torture_warning(tctx
, "pwdlastset not increasing\n");
3163 pwdlastset_old
= pwdlastset_new
;
3169 /* set a password, pwdlastset needs to get updated (increased
3170 * value), password_expired value used here is 0 */
3172 if (!test_SetPassword_level(p
, np
, tctx
, handle
,
3176 &matched_expected_error
,
3180 machine_credentials
,
3183 expected_samlogon_result
)) {
3187 /* when a password has been changed, pwdlastset must not be 0 afterwards
3188 * and must be larger then the old value */
3190 switch (levels
[l
]) {
3195 /* if no password has been changed, old and new pwdlastset
3196 * need to be the same value */
3198 if (!((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3199 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)))
3201 torture_assert_int_equal(tctx
, pwdlastset_old
,
3202 pwdlastset_new
, "pwdlastset must be equal");
3206 if (pwdlastset_old
>= pwdlastset_new
) {
3207 torture_warning(tctx
, "pwdLastSet test failed: "
3208 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3209 pwdlastset_old
, pwdlastset_new
);
3212 if (pwdlastset_new
== 0) {
3213 torture_warning(tctx
, "pwdLastSet test failed: "
3214 "expected non-0 pwdlastset, got: %lld\n",
3222 /* set a password and force password change (pwdlastset 0) by
3223 * setting the password expired flag to a non-0 value */
3225 if (!test_SetPassword_level(p
, np
, tctx
, handle
,
3229 &matched_expected_error
,
3233 machine_credentials
,
3236 expected_samlogon_result
)) {
3240 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3241 * set without the SAMR_FIELD_EXPIRED_FLAG */
3243 switch (levels
[l
]) {
3247 if ((pwdlastset_new
!= 0) &&
3248 !(fields_present
[f
] & SAMR_FIELD_EXPIRED_FLAG
)) {
3249 torture_comment(tctx
, "not considering a non-0 "
3250 "pwdLastSet as a an error as the "
3251 "SAMR_FIELD_EXPIRED_FLAG has not "
3256 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3257 * password has been changed, old and new pwdlastset
3258 * need to be the same value */
3260 if (!(fields_present
[f
] & SAMR_FIELD_EXPIRED_FLAG
) &&
3261 !((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3262 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)))
3264 torture_assert_int_equal(tctx
, pwdlastset_old
,
3265 pwdlastset_new
, "pwdlastset must be equal");
3270 if (pwdlastset_old
== pwdlastset_new
) {
3271 torture_warning(tctx
, "pwdLastSet test failed: "
3272 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3273 pwdlastset_old
, pwdlastset_new
);
3277 if (pwdlastset_new
!= 0) {
3278 torture_warning(tctx
, "pwdLastSet test failed: "
3279 "expected pwdLastSet 0, got %lld\n",
3286 switch (levels
[l
]) {
3290 if (((fields_present
[f
] & SAMR_FIELD_NT_PASSWORD_PRESENT
) ||
3291 (fields_present
[f
] & SAMR_FIELD_LM_PASSWORD_PRESENT
)) &&
3292 (pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3293 (pwdlastset_old
>= pwdlastset_new
)) {
3294 torture_warning(tctx
, "pwdlastset not increasing\n");
3299 if ((pwdlastset_old
> 0) && (pwdlastset_new
> 0) &&
3300 (pwdlastset_old
>= pwdlastset_new
)) {
3301 torture_warning(tctx
, "pwdlastset not increasing\n");
3307 /* if the level we are testing does not have a fields_present
3308 * field, skip all fields present tests by setting f to to
3310 switch (levels
[l
]) {
3314 f
= ARRAY_SIZE(fields_present
);
3318 #ifdef TEST_QUERY_LEVELS
3321 #ifdef TEST_SET_LEVELS
3324 } /* fields present */
3328 #undef TEST_SET_LEVELS
3329 #undef TEST_QUERY_LEVELS
3336 static bool test_DeleteUser_with_privs(struct dcerpc_pipe
*p
,
3337 struct dcerpc_pipe
*lp
,
3338 struct torture_context
*tctx
,
3339 struct policy_handle
*domain_handle
,
3340 struct policy_handle
*lsa_handle
,
3341 struct policy_handle
*user_handle
,
3342 const struct dom_sid
*domain_sid
,
3344 struct cli_credentials
*machine_credentials
)
3349 struct policy_handle lsa_acct_handle
;
3350 struct dom_sid
*user_sid
;
3352 user_sid
= dom_sid_add_rid(tctx
, domain_sid
, rid
);
3355 struct lsa_EnumAccountRights r
;
3356 struct lsa_RightSet rights
;
3358 torture_comment(tctx
, "Testing LSA EnumAccountRights\n");
3360 r
.in
.handle
= lsa_handle
;
3361 r
.in
.sid
= user_sid
;
3362 r
.out
.rights
= &rights
;
3364 status
= dcerpc_lsa_EnumAccountRights(lp
, tctx
, &r
);
3365 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
3366 "Expected enum rights for account to fail");
3370 struct lsa_RightSet rights
;
3371 struct lsa_StringLarge names
[2];
3372 struct lsa_AddAccountRights r
;
3374 torture_comment(tctx
, "Testing LSA AddAccountRights\n");
3376 init_lsa_StringLarge(&names
[0], "SeMachineAccountPrivilege");
3377 init_lsa_StringLarge(&names
[1], NULL
);
3380 rights
.names
= names
;
3382 r
.in
.handle
= lsa_handle
;
3383 r
.in
.sid
= user_sid
;
3384 r
.in
.rights
= &rights
;
3386 status
= dcerpc_lsa_AddAccountRights(lp
, tctx
, &r
);
3387 torture_assert_ntstatus_ok(tctx
, status
,
3388 "Failed to add privileges");
3392 struct lsa_EnumAccounts r
;
3393 uint32_t resume_handle
= 0;
3394 struct lsa_SidArray lsa_sid_array
;
3396 bool found_sid
= false;
3398 torture_comment(tctx
, "Testing LSA EnumAccounts\n");
3400 r
.in
.handle
= lsa_handle
;
3401 r
.in
.num_entries
= 0x1000;
3402 r
.in
.resume_handle
= &resume_handle
;
3403 r
.out
.sids
= &lsa_sid_array
;
3404 r
.out
.resume_handle
= &resume_handle
;
3406 status
= dcerpc_lsa_EnumAccounts(lp
, tctx
, &r
);
3407 torture_assert_ntstatus_ok(tctx
, status
,
3408 "Failed to enum accounts");
3410 for (i
=0; i
< lsa_sid_array
.num_sids
; i
++) {
3411 if (dom_sid_equal(user_sid
, lsa_sid_array
.sids
[i
].sid
)) {
3416 torture_assert(tctx
, found_sid
,
3417 "failed to list privileged account");
3421 struct lsa_EnumAccountRights r
;
3422 struct lsa_RightSet user_rights
;
3424 torture_comment(tctx
, "Testing LSA EnumAccountRights\n");
3426 r
.in
.handle
= lsa_handle
;
3427 r
.in
.sid
= user_sid
;
3428 r
.out
.rights
= &user_rights
;
3430 status
= dcerpc_lsa_EnumAccountRights(lp
, tctx
, &r
);
3431 torture_assert_ntstatus_ok(tctx
, status
,
3432 "Failed to enum rights for account");
3434 if (user_rights
.count
< 1) {
3435 torture_warning(tctx
, "failed to find newly added rights");
3441 struct lsa_OpenAccount r
;
3443 torture_comment(tctx
, "Testing LSA OpenAccount\n");
3445 r
.in
.handle
= lsa_handle
;
3446 r
.in
.sid
= user_sid
;
3447 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3448 r
.out
.acct_handle
= &lsa_acct_handle
;
3450 status
= dcerpc_lsa_OpenAccount(lp
, tctx
, &r
);
3451 torture_assert_ntstatus_ok(tctx
, status
,
3452 "Failed to open lsa account");
3456 struct lsa_GetSystemAccessAccount r
;
3457 uint32_t access_mask
;
3459 torture_comment(tctx
, "Testing LSA GetSystemAccessAccount\n");
3461 r
.in
.handle
= &lsa_acct_handle
;
3462 r
.out
.access_mask
= &access_mask
;
3464 status
= dcerpc_lsa_GetSystemAccessAccount(lp
, tctx
, &r
);
3465 torture_assert_ntstatus_ok(tctx
, status
,
3466 "Failed to get lsa system access account");
3472 torture_comment(tctx
, "Testing LSA Close\n");
3474 r
.in
.handle
= &lsa_acct_handle
;
3475 r
.out
.handle
= &lsa_acct_handle
;
3477 status
= dcerpc_lsa_Close(lp
, tctx
, &r
);
3478 torture_assert_ntstatus_ok(tctx
, status
,
3479 "Failed to close lsa");
3483 struct samr_DeleteUser r
;
3485 torture_comment(tctx
, "Testing SAMR DeleteUser\n");
3487 r
.in
.user_handle
= user_handle
;
3488 r
.out
.user_handle
= user_handle
;
3490 status
= dcerpc_samr_DeleteUser(p
, tctx
, &r
);
3491 torture_assert_ntstatus_ok(tctx
, status
, "Delete User failed");
3495 struct lsa_EnumAccounts r
;
3496 uint32_t resume_handle
= 0;
3497 struct lsa_SidArray lsa_sid_array
;
3499 bool found_sid
= false;
3501 torture_comment(tctx
, "Testing LSA EnumAccounts\n");
3503 r
.in
.handle
= lsa_handle
;
3504 r
.in
.num_entries
= 0x1000;
3505 r
.in
.resume_handle
= &resume_handle
;
3506 r
.out
.sids
= &lsa_sid_array
;
3507 r
.out
.resume_handle
= &resume_handle
;
3509 status
= dcerpc_lsa_EnumAccounts(lp
, tctx
, &r
);
3510 torture_assert_ntstatus_ok(tctx
, status
,
3511 "Failed to enum accounts");
3513 for (i
=0; i
< lsa_sid_array
.num_sids
; i
++) {
3514 if (dom_sid_equal(user_sid
, lsa_sid_array
.sids
[i
].sid
)) {
3519 torture_assert(tctx
, found_sid
,
3520 "failed to list privileged account");
3524 struct lsa_EnumAccountRights r
;
3525 struct lsa_RightSet user_rights
;
3527 torture_comment(tctx
, "Testing LSA EnumAccountRights\n");
3529 r
.in
.handle
= lsa_handle
;
3530 r
.in
.sid
= user_sid
;
3531 r
.out
.rights
= &user_rights
;
3533 status
= dcerpc_lsa_EnumAccountRights(lp
, tctx
, &r
);
3534 torture_assert_ntstatus_ok(tctx
, status
,
3535 "Failed to enum rights for account");
3537 if (user_rights
.count
< 1) {
3538 torture_warning(tctx
, "failed to find newly added rights");
3544 struct lsa_OpenAccount r
;
3546 torture_comment(tctx
, "Testing LSA OpenAccount\n");
3548 r
.in
.handle
= lsa_handle
;
3549 r
.in
.sid
= user_sid
;
3550 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3551 r
.out
.acct_handle
= &lsa_acct_handle
;
3553 status
= dcerpc_lsa_OpenAccount(lp
, tctx
, &r
);
3554 torture_assert_ntstatus_ok(tctx
, status
,
3555 "Failed to open lsa account");
3559 struct lsa_GetSystemAccessAccount r
;
3560 uint32_t access_mask
;
3562 torture_comment(tctx
, "Testing LSA GetSystemAccessAccount\n");
3564 r
.in
.handle
= &lsa_acct_handle
;
3565 r
.out
.access_mask
= &access_mask
;
3567 status
= dcerpc_lsa_GetSystemAccessAccount(lp
, tctx
, &r
);
3568 torture_assert_ntstatus_ok(tctx
, status
,
3569 "Failed to get lsa system access account");
3573 struct lsa_DeleteObject r
;
3575 torture_comment(tctx
, "Testing LSA DeleteObject\n");
3577 r
.in
.handle
= &lsa_acct_handle
;
3578 r
.out
.handle
= &lsa_acct_handle
;
3580 status
= dcerpc_lsa_DeleteObject(lp
, tctx
, &r
);
3581 torture_assert_ntstatus_ok(tctx
, status
,
3582 "Failed to delete object");
3586 struct lsa_EnumAccounts r
;
3587 uint32_t resume_handle
= 0;
3588 struct lsa_SidArray lsa_sid_array
;
3590 bool found_sid
= false;
3592 torture_comment(tctx
, "Testing LSA EnumAccounts\n");
3594 r
.in
.handle
= lsa_handle
;
3595 r
.in
.num_entries
= 0x1000;
3596 r
.in
.resume_handle
= &resume_handle
;
3597 r
.out
.sids
= &lsa_sid_array
;
3598 r
.out
.resume_handle
= &resume_handle
;
3600 status
= dcerpc_lsa_EnumAccounts(lp
, tctx
, &r
);
3601 torture_assert_ntstatus_ok(tctx
, status
,
3602 "Failed to enum accounts");
3604 for (i
=0; i
< lsa_sid_array
.num_sids
; i
++) {
3605 if (dom_sid_equal(user_sid
, lsa_sid_array
.sids
[i
].sid
)) {
3610 torture_assert(tctx
, !found_sid
,
3611 "should not have listed privileged account");
3615 struct lsa_EnumAccountRights r
;
3616 struct lsa_RightSet user_rights
;
3618 torture_comment(tctx
, "Testing LSA EnumAccountRights\n");
3620 r
.in
.handle
= lsa_handle
;
3621 r
.in
.sid
= user_sid
;
3622 r
.out
.rights
= &user_rights
;
3624 status
= dcerpc_lsa_EnumAccountRights(lp
, tctx
, &r
);
3625 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
3626 "Failed to enum rights for account");
3632 static bool test_user_ops(struct dcerpc_pipe
*p
,
3633 struct torture_context
*tctx
,
3634 struct policy_handle
*user_handle
,
3635 struct policy_handle
*domain_handle
,
3636 const struct dom_sid
*domain_sid
,
3637 uint32_t base_acct_flags
,
3638 const char *base_acct_name
, enum torture_samr_choice which_ops
,
3639 struct cli_credentials
*machine_credentials
)
3641 char *password
= NULL
;
3642 struct samr_QueryUserInfo q
;
3643 union samr_UserInfo
*info
;
3649 const uint32_t password_fields
[] = {
3650 SAMR_FIELD_NT_PASSWORD_PRESENT
,
3651 SAMR_FIELD_LM_PASSWORD_PRESENT
,
3652 SAMR_FIELD_NT_PASSWORD_PRESENT
| SAMR_FIELD_LM_PASSWORD_PRESENT
,
3656 status
= test_LookupName(p
, tctx
, domain_handle
, base_acct_name
, &rid
);
3657 if (!NT_STATUS_IS_OK(status
)) {
3661 switch (which_ops
) {
3662 case TORTURE_SAMR_USER_ATTRIBUTES
:
3663 if (!test_QuerySecurity(p
, tctx
, user_handle
)) {
3667 if (!test_QueryUserInfo(p
, tctx
, user_handle
)) {
3671 if (!test_QueryUserInfo2(p
, tctx
, user_handle
)) {
3675 if (!test_SetUserInfo(p
, tctx
, user_handle
, base_acct_flags
,
3680 if (!test_GetUserPwInfo(p
, tctx
, user_handle
)) {
3684 if (!test_TestPrivateFunctionsUser(p
, tctx
, user_handle
)) {
3688 if (!test_SetUserPass(p
, tctx
, user_handle
, &password
)) {
3692 case TORTURE_SAMR_PASSWORDS
:
3693 if (base_acct_flags
& (ACB_WSTRUST
|ACB_DOMTRUST
|ACB_SVRTRUST
)) {
3694 char simple_pass
[9];
3695 char *v
= generate_random_str(tctx
, 1);
3697 ZERO_STRUCT(simple_pass
);
3698 memset(simple_pass
, *v
, sizeof(simple_pass
) - 1);
3700 torture_comment(tctx
, "Testing machine account password policy rules\n");
3702 /* Workstation trust accounts don't seem to need to honour password quality policy */
3703 if (!test_SetUserPassEx(p
, tctx
, user_handle
, true, &password
)) {
3707 if (!test_ChangePasswordUser2(p
, tctx
, base_acct_name
, &password
, simple_pass
, false)) {
3711 /* reset again, to allow another 'user' password change */
3712 if (!test_SetUserPassEx(p
, tctx
, user_handle
, true, &password
)) {
3716 /* Try a 'short' password */
3717 if (!test_ChangePasswordUser2(p
, tctx
, base_acct_name
, &password
, samr_rand_pass(tctx
, 4), false)) {
3721 /* Try a compleatly random password */
3722 if (!test_ChangePasswordRandomBytes(p
, tctx
, base_acct_name
, user_handle
, &password
)) {
3727 for (i
= 0; password_fields
[i
]; i
++) {
3728 if (!test_SetUserPass_23(p
, tctx
, user_handle
, password_fields
[i
], &password
)) {
3732 /* check it was set right */
3733 if (!test_ChangePasswordUser3(p
, tctx
, base_acct_name
, 0, &password
, NULL
, 0, false)) {
3738 for (i
= 0; password_fields
[i
]; i
++) {
3739 if (!test_SetUserPass_25(p
, tctx
, user_handle
, password_fields
[i
], &password
)) {
3743 /* check it was set right */
3744 if (!test_ChangePasswordUser3(p
, tctx
, base_acct_name
, 0, &password
, NULL
, 0, false)) {
3749 if (!test_SetUserPassEx(p
, tctx
, user_handle
, false, &password
)) {
3753 if (!test_ChangePassword(p
, tctx
, base_acct_name
, domain_handle
, &password
)) {
3757 if (torture_setting_bool(tctx
, "samba4", false)) {
3758 torture_comment(tctx
, "skipping Set Password level 18 and 21 against Samba4\n");
3761 if (!test_SetUserPass_18(p
, tctx
, user_handle
, &password
)) {
3765 if (!test_ChangePasswordUser3(p
, tctx
, base_acct_name
, 0, &password
, NULL
, 0, false)) {
3769 for (i
= 0; password_fields
[i
]; i
++) {
3771 if (password_fields
[i
] == SAMR_FIELD_LM_PASSWORD_PRESENT
) {
3772 /* we need to skip as that would break
3773 * the ChangePasswordUser3 verify */
3777 if (!test_SetUserPass_21(p
, tctx
, user_handle
, password_fields
[i
], &password
)) {
3781 /* check it was set right */
3782 if (!test_ChangePasswordUser3(p
, tctx
, base_acct_name
, 0, &password
, NULL
, 0, false)) {
3788 q
.in
.user_handle
= user_handle
;
3792 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &q
);
3793 if (!NT_STATUS_IS_OK(status
)) {
3794 torture_warning(tctx
, "QueryUserInfo level %u failed - %s\n",
3795 q
.in
.level
, nt_errstr(status
));
3798 uint32_t expected_flags
= (base_acct_flags
| ACB_PWNOTREQ
| ACB_DISABLED
);
3799 if ((info
->info5
.acct_flags
) != expected_flags
) {
3800 torture_warning(tctx
, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3801 info
->info5
.acct_flags
,
3804 if (!torture_setting_bool(tctx
, "samba3", false)) {
3808 if (info
->info5
.rid
!= rid
) {
3809 torture_warning(tctx
, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3810 info
->info5
.rid
, rid
);
3817 case TORTURE_SAMR_PASSWORDS_PWDLASTSET
:
3819 /* test last password change timestamp behaviour */
3820 if (!test_SetPassword_pwdlastset(p
, tctx
, base_acct_flags
,
3822 user_handle
, &password
,
3823 machine_credentials
)) {
3828 torture_comment(tctx
, "pwdLastSet test succeeded\n");
3830 torture_warning(tctx
, "pwdLastSet test failed\n");
3835 case TORTURE_SAMR_USER_PRIVILEGES
: {
3837 struct dcerpc_pipe
*lp
;
3838 struct policy_handle
*lsa_handle
;
3840 status
= torture_rpc_connection(tctx
, &lp
, &ndr_table_lsarpc
);
3841 torture_assert_ntstatus_ok(tctx
, status
, "Failed to open LSA pipe");
3843 if (!test_lsa_OpenPolicy2(lp
, tctx
, &lsa_handle
)) {
3847 if (!test_DeleteUser_with_privs(p
, lp
, tctx
,
3848 domain_handle
, lsa_handle
, user_handle
,
3850 machine_credentials
)) {
3854 if (!test_lsa_Close(lp
, tctx
, lsa_handle
)) {
3859 torture_warning(tctx
, "privileged user delete test failed\n");
3864 case TORTURE_SAMR_OTHER
:
3865 /* We just need the account to exist */
3871 static bool test_alias_ops(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
3872 struct policy_handle
*alias_handle
,
3873 const struct dom_sid
*domain_sid
)
3877 if (!torture_setting_bool(tctx
, "samba3", false)) {
3878 if (!test_QuerySecurity(p
, tctx
, alias_handle
)) {
3883 if (!test_QueryAliasInfo(p
, tctx
, alias_handle
)) {
3887 if (!test_SetAliasInfo(p
, tctx
, alias_handle
)) {
3891 if (!test_AddMemberToAlias(p
, tctx
, alias_handle
, domain_sid
)) {
3895 if (torture_setting_bool(tctx
, "samba3", false) ||
3896 torture_setting_bool(tctx
, "samba4", false)) {
3897 torture_comment(tctx
, "skipping MultipleMembers Alias tests against Samba\n");
3901 if (!test_AddMultipleMembersToAlias(p
, tctx
, alias_handle
)) {
3909 static bool test_DeleteUser(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
3910 struct policy_handle
*user_handle
)
3912 struct samr_DeleteUser d
;
3914 torture_comment(tctx
, "Testing DeleteUser\n");
3916 d
.in
.user_handle
= user_handle
;
3917 d
.out
.user_handle
= user_handle
;
3919 status
= dcerpc_samr_DeleteUser(p
, tctx
, &d
);
3920 torture_assert_ntstatus_ok(tctx
, status
, "DeleteUser");
3925 bool test_DeleteUser_byname(struct dcerpc_pipe
*p
,
3926 struct torture_context
*tctx
,
3927 struct policy_handle
*handle
, const char *name
)
3930 struct samr_DeleteUser d
;
3931 struct policy_handle user_handle
;
3934 status
= test_LookupName(p
, tctx
, handle
, name
, &rid
);
3935 if (!NT_STATUS_IS_OK(status
)) {
3939 status
= test_OpenUser_byname(p
, tctx
, handle
, name
, &user_handle
);
3940 if (!NT_STATUS_IS_OK(status
)) {
3944 d
.in
.user_handle
= &user_handle
;
3945 d
.out
.user_handle
= &user_handle
;
3946 status
= dcerpc_samr_DeleteUser(p
, tctx
, &d
);
3947 if (!NT_STATUS_IS_OK(status
)) {
3954 torture_warning(tctx
, "DeleteUser_byname(%s) failed - %s\n", name
, nt_errstr(status
));
3959 static bool test_DeleteGroup_byname(struct dcerpc_pipe
*p
,
3960 struct torture_context
*tctx
,
3961 struct policy_handle
*handle
, const char *name
)
3964 struct samr_OpenGroup r
;
3965 struct samr_DeleteDomainGroup d
;
3966 struct policy_handle group_handle
;
3969 status
= test_LookupName(p
, tctx
, handle
, name
, &rid
);
3970 if (!NT_STATUS_IS_OK(status
)) {
3974 r
.in
.domain_handle
= handle
;
3975 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3977 r
.out
.group_handle
= &group_handle
;
3978 status
= dcerpc_samr_OpenGroup(p
, tctx
, &r
);
3979 if (!NT_STATUS_IS_OK(status
)) {
3983 d
.in
.group_handle
= &group_handle
;
3984 d
.out
.group_handle
= &group_handle
;
3985 status
= dcerpc_samr_DeleteDomainGroup(p
, tctx
, &d
);
3986 if (!NT_STATUS_IS_OK(status
)) {
3993 torture_warning(tctx
, "DeleteGroup_byname(%s) failed - %s\n", name
, nt_errstr(status
));
3998 static bool test_DeleteAlias_byname(struct dcerpc_pipe
*p
,
3999 struct torture_context
*tctx
,
4000 struct policy_handle
*domain_handle
,
4004 struct samr_OpenAlias r
;
4005 struct samr_DeleteDomAlias d
;
4006 struct policy_handle alias_handle
;
4009 torture_comment(tctx
, "testing DeleteAlias_byname\n");
4011 status
= test_LookupName(p
, tctx
, domain_handle
, name
, &rid
);
4012 if (!NT_STATUS_IS_OK(status
)) {
4016 r
.in
.domain_handle
= domain_handle
;
4017 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4019 r
.out
.alias_handle
= &alias_handle
;
4020 status
= dcerpc_samr_OpenAlias(p
, tctx
, &r
);
4021 if (!NT_STATUS_IS_OK(status
)) {
4025 d
.in
.alias_handle
= &alias_handle
;
4026 d
.out
.alias_handle
= &alias_handle
;
4027 status
= dcerpc_samr_DeleteDomAlias(p
, tctx
, &d
);
4028 if (!NT_STATUS_IS_OK(status
)) {
4035 torture_warning(tctx
, "DeleteAlias_byname(%s) failed - %s\n", name
, nt_errstr(status
));
4039 static bool test_DeleteAlias(struct dcerpc_pipe
*p
,
4040 struct torture_context
*tctx
,
4041 struct policy_handle
*alias_handle
)
4043 struct samr_DeleteDomAlias d
;
4047 torture_comment(tctx
, "Testing DeleteAlias\n");
4049 d
.in
.alias_handle
= alias_handle
;
4050 d
.out
.alias_handle
= alias_handle
;
4052 status
= dcerpc_samr_DeleteDomAlias(p
, tctx
, &d
);
4053 if (!NT_STATUS_IS_OK(status
)) {
4054 torture_warning(tctx
, "DeleteAlias failed - %s\n", nt_errstr(status
));
4061 static bool test_CreateAlias(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
4062 struct policy_handle
*domain_handle
,
4063 const char *alias_name
,
4064 struct policy_handle
*alias_handle
,
4065 const struct dom_sid
*domain_sid
,
4069 struct samr_CreateDomAlias r
;
4070 struct lsa_String name
;
4074 init_lsa_String(&name
, alias_name
);
4075 r
.in
.domain_handle
= domain_handle
;
4076 r
.in
.alias_name
= &name
;
4077 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4078 r
.out
.alias_handle
= alias_handle
;
4081 torture_comment(tctx
, "Testing CreateAlias (%s)\n", r
.in
.alias_name
->string
);
4083 status
= dcerpc_samr_CreateDomAlias(p
, tctx
, &r
);
4085 if (dom_sid_equal(domain_sid
, dom_sid_parse_talloc(tctx
, SID_BUILTIN
))) {
4086 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
4087 torture_comment(tctx
, "Server correctly refused create of '%s'\n", r
.in
.alias_name
->string
);
4090 torture_warning(tctx
, "Server should have refused create of '%s', got %s instead\n", r
.in
.alias_name
->string
,
4096 if (NT_STATUS_EQUAL(status
, NT_STATUS_ALIAS_EXISTS
)) {
4097 if (!test_DeleteAlias_byname(p
, tctx
, domain_handle
, r
.in
.alias_name
->string
)) {
4100 status
= dcerpc_samr_CreateDomAlias(p
, tctx
, &r
);
4103 if (!NT_STATUS_IS_OK(status
)) {
4104 torture_warning(tctx
, "CreateAlias failed - %s\n", nt_errstr(status
));
4112 if (!test_alias_ops(p
, tctx
, alias_handle
, domain_sid
)) {
4119 static bool test_ChangePassword(struct dcerpc_pipe
*p
,
4120 struct torture_context
*tctx
,
4121 const char *acct_name
,
4122 struct policy_handle
*domain_handle
, char **password
)
4130 if (!test_ChangePasswordUser(p
, tctx
, acct_name
, domain_handle
, password
)) {
4134 if (!test_ChangePasswordUser2(p
, tctx
, acct_name
, password
, 0, true)) {
4138 if (!test_OemChangePasswordUser2(p
, tctx
, acct_name
, domain_handle
, password
)) {
4142 /* test what happens when setting the old password again */
4143 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, 0, password
, *password
, 0, true)) {
4148 char simple_pass
[9];
4149 char *v
= generate_random_str(tctx
, 1);
4151 ZERO_STRUCT(simple_pass
);
4152 memset(simple_pass
, *v
, sizeof(simple_pass
) - 1);
4154 /* test what happens when picking a simple password */
4155 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, 0, password
, simple_pass
, 0, true)) {
4160 /* set samr_SetDomainInfo level 1 with min_length 5 */
4162 struct samr_QueryDomainInfo r
;
4163 union samr_DomainInfo
*info
= NULL
;
4164 struct samr_SetDomainInfo s
;
4165 uint16_t len_old
, len
;
4166 uint32_t pwd_prop_old
;
4167 int64_t min_pwd_age_old
;
4172 r
.in
.domain_handle
= domain_handle
;
4176 torture_comment(tctx
, "testing samr_QueryDomainInfo level 1\n");
4177 status
= dcerpc_samr_QueryDomainInfo(p
, tctx
, &r
);
4178 if (!NT_STATUS_IS_OK(status
)) {
4182 s
.in
.domain_handle
= domain_handle
;
4186 /* remember the old min length, so we can reset it */
4187 len_old
= s
.in
.info
->info1
.min_password_length
;
4188 s
.in
.info
->info1
.min_password_length
= len
;
4189 pwd_prop_old
= s
.in
.info
->info1
.password_properties
;
4190 /* turn off password complexity checks for this test */
4191 s
.in
.info
->info1
.password_properties
&= ~DOMAIN_PASSWORD_COMPLEX
;
4193 min_pwd_age_old
= s
.in
.info
->info1
.min_password_age
;
4194 s
.in
.info
->info1
.min_password_age
= 0;
4196 torture_comment(tctx
, "testing samr_SetDomainInfo level 1\n");
4197 status
= dcerpc_samr_SetDomainInfo(p
, tctx
, &s
);
4198 if (!NT_STATUS_IS_OK(status
)) {
4202 torture_comment(tctx
, "calling test_ChangePasswordUser3 with too short password\n");
4204 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, len
- 1, password
, NULL
, 0, true)) {
4208 s
.in
.info
->info1
.min_password_length
= len_old
;
4209 s
.in
.info
->info1
.password_properties
= pwd_prop_old
;
4210 s
.in
.info
->info1
.min_password_age
= min_pwd_age_old
;
4212 torture_comment(tctx
, "testing samr_SetDomainInfo level 1\n");
4213 status
= dcerpc_samr_SetDomainInfo(p
, tctx
, &s
);
4214 if (!NT_STATUS_IS_OK(status
)) {
4222 struct samr_OpenUser r
;
4223 struct samr_QueryUserInfo q
;
4224 union samr_UserInfo
*info
;
4225 struct samr_LookupNames n
;
4226 struct policy_handle user_handle
;
4227 struct samr_Ids rids
, types
;
4229 n
.in
.domain_handle
= domain_handle
;
4231 n
.in
.names
= talloc_array(tctx
, struct lsa_String
, 1);
4232 n
.in
.names
[0].string
= acct_name
;
4234 n
.out
.types
= &types
;
4236 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
4237 if (!NT_STATUS_IS_OK(status
)) {
4238 torture_warning(tctx
, "LookupNames failed - %s\n", nt_errstr(status
));
4242 r
.in
.domain_handle
= domain_handle
;
4243 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4244 r
.in
.rid
= n
.out
.rids
->ids
[0];
4245 r
.out
.user_handle
= &user_handle
;
4247 status
= dcerpc_samr_OpenUser(p
, tctx
, &r
);
4248 if (!NT_STATUS_IS_OK(status
)) {
4249 torture_warning(tctx
, "OpenUser(%u) failed - %s\n", n
.out
.rids
->ids
[0], nt_errstr(status
));
4253 q
.in
.user_handle
= &user_handle
;
4257 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &q
);
4258 if (!NT_STATUS_IS_OK(status
)) {
4259 torture_warning(tctx
, "QueryUserInfo failed - %s\n", nt_errstr(status
));
4263 torture_comment(tctx
, "calling test_ChangePasswordUser3 with too early password change\n");
4265 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, 0, password
, NULL
,
4266 info
->info5
.last_password_change
, true)) {
4271 /* we change passwords twice - this has the effect of verifying
4272 they were changed correctly for the final call */
4273 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, 0, password
, NULL
, 0, true)) {
4277 if (!test_ChangePasswordUser3(p
, tctx
, acct_name
, 0, password
, NULL
, 0, true)) {
4284 static bool test_CreateUser(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
4285 struct policy_handle
*domain_handle
,
4286 const char *user_name
,
4287 struct policy_handle
*user_handle_out
,
4288 struct dom_sid
*domain_sid
,
4289 enum torture_samr_choice which_ops
,
4290 struct cli_credentials
*machine_credentials
,
4294 TALLOC_CTX
*user_ctx
;
4297 struct samr_CreateUser r
;
4298 struct samr_QueryUserInfo q
;
4299 union samr_UserInfo
*info
;
4300 struct samr_DeleteUser d
;
4303 /* This call creates a 'normal' account - check that it really does */
4304 const uint32_t acct_flags
= ACB_NORMAL
;
4305 struct lsa_String name
;
4308 struct policy_handle user_handle
;
4309 user_ctx
= talloc_named(tctx
, 0, "test_CreateUser2 per-user context");
4310 init_lsa_String(&name
, user_name
);
4312 r
.in
.domain_handle
= domain_handle
;
4313 r
.in
.account_name
= &name
;
4314 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4315 r
.out
.user_handle
= &user_handle
;
4318 torture_comment(tctx
, "Testing CreateUser(%s)\n", r
.in
.account_name
->string
);
4320 status
= dcerpc_samr_CreateUser(p
, user_ctx
, &r
);
4322 if (dom_sid_equal(domain_sid
, dom_sid_parse_talloc(tctx
, SID_BUILTIN
))) {
4323 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) || NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4324 torture_comment(tctx
, "Server correctly refused create of '%s'\n", r
.in
.account_name
->string
);
4327 torture_warning(tctx
, "Server should have refused create of '%s', got %s instead\n", r
.in
.account_name
->string
,
4333 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
4334 if (!test_DeleteUser_byname(p
, user_ctx
, domain_handle
, r
.in
.account_name
->string
)) {
4335 talloc_free(user_ctx
);
4338 status
= dcerpc_samr_CreateUser(p
, user_ctx
, &r
);
4341 if (!NT_STATUS_IS_OK(status
)) {
4342 talloc_free(user_ctx
);
4343 torture_warning(tctx
, "CreateUser failed - %s\n", nt_errstr(status
));
4348 if (user_handle_out
) {
4349 *user_handle_out
= user_handle
;
4355 q
.in
.user_handle
= &user_handle
;
4359 status
= dcerpc_samr_QueryUserInfo(p
, user_ctx
, &q
);
4360 if (!NT_STATUS_IS_OK(status
)) {
4361 torture_warning(tctx
, "QueryUserInfo level %u failed - %s\n",
4362 q
.in
.level
, nt_errstr(status
));
4365 if ((info
->info16
.acct_flags
& acct_flags
) != acct_flags
) {
4366 torture_warning(tctx
, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4367 info
->info16
.acct_flags
,
4373 if (!test_user_ops(p
, tctx
, &user_handle
, domain_handle
,
4374 domain_sid
, acct_flags
, name
.string
, which_ops
,
4375 machine_credentials
)) {
4379 if (user_handle_out
) {
4380 *user_handle_out
= user_handle
;
4382 torture_comment(tctx
, "Testing DeleteUser (createuser test)\n");
4384 d
.in
.user_handle
= &user_handle
;
4385 d
.out
.user_handle
= &user_handle
;
4387 status
= dcerpc_samr_DeleteUser(p
, user_ctx
, &d
);
4388 if (!NT_STATUS_IS_OK(status
)) {
4389 torture_warning(tctx
, "DeleteUser failed - %s\n", nt_errstr(status
));
4396 talloc_free(user_ctx
);
4402 static bool test_CreateUser2(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
4403 struct policy_handle
*domain_handle
,
4404 struct dom_sid
*domain_sid
,
4405 enum torture_samr_choice which_ops
,
4406 struct cli_credentials
*machine_credentials
)
4409 struct samr_CreateUser2 r
;
4410 struct samr_QueryUserInfo q
;
4411 union samr_UserInfo
*info
;
4412 struct samr_DeleteUser d
;
4413 struct policy_handle user_handle
;
4415 struct lsa_String name
;
4420 uint32_t acct_flags
;
4421 const char *account_name
;
4423 } account_types
[] = {
4424 { ACB_NORMAL
, TEST_ACCOUNT_NAME
, NT_STATUS_OK
},
4425 { ACB_NORMAL
| ACB_DISABLED
, TEST_ACCOUNT_NAME
, NT_STATUS_INVALID_PARAMETER
},
4426 { ACB_NORMAL
| ACB_PWNOEXP
, TEST_ACCOUNT_NAME
, NT_STATUS_INVALID_PARAMETER
},
4427 { ACB_WSTRUST
, TEST_MACHINENAME
, NT_STATUS_OK
},
4428 { ACB_WSTRUST
| ACB_DISABLED
, TEST_MACHINENAME
, NT_STATUS_INVALID_PARAMETER
},
4429 { ACB_WSTRUST
| ACB_PWNOEXP
, TEST_MACHINENAME
, NT_STATUS_INVALID_PARAMETER
},
4430 { ACB_SVRTRUST
, TEST_MACHINENAME
, NT_STATUS_OK
},
4431 { ACB_SVRTRUST
| ACB_DISABLED
, TEST_MACHINENAME
, NT_STATUS_INVALID_PARAMETER
},
4432 { ACB_SVRTRUST
| ACB_PWNOEXP
, TEST_MACHINENAME
, NT_STATUS_INVALID_PARAMETER
},
4433 { ACB_DOMTRUST
, TEST_DOMAINNAME
, NT_STATUS_ACCESS_DENIED
},
4434 { ACB_DOMTRUST
| ACB_DISABLED
, TEST_DOMAINNAME
, NT_STATUS_INVALID_PARAMETER
},
4435 { ACB_DOMTRUST
| ACB_PWNOEXP
, TEST_DOMAINNAME
, NT_STATUS_INVALID_PARAMETER
},
4436 { 0, TEST_ACCOUNT_NAME
, NT_STATUS_INVALID_PARAMETER
},
4437 { ACB_DISABLED
, TEST_ACCOUNT_NAME
, NT_STATUS_INVALID_PARAMETER
},
4438 { 0, NULL
, NT_STATUS_INVALID_PARAMETER
}
4441 for (i
= 0; account_types
[i
].account_name
; i
++) {
4442 TALLOC_CTX
*user_ctx
;
4443 uint32_t acct_flags
= account_types
[i
].acct_flags
;
4444 uint32_t access_granted
;
4445 user_ctx
= talloc_named(tctx
, 0, "test_CreateUser2 per-user context");
4446 init_lsa_String(&name
, account_types
[i
].account_name
);
4448 r
.in
.domain_handle
= domain_handle
;
4449 r
.in
.account_name
= &name
;
4450 r
.in
.acct_flags
= acct_flags
;
4451 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4452 r
.out
.user_handle
= &user_handle
;
4453 r
.out
.access_granted
= &access_granted
;
4456 torture_comment(tctx
, "Testing CreateUser2(%s, 0x%x)\n", r
.in
.account_name
->string
, acct_flags
);
4458 status
= dcerpc_samr_CreateUser2(p
, user_ctx
, &r
);
4460 if (dom_sid_equal(domain_sid
, dom_sid_parse_talloc(tctx
, SID_BUILTIN
))) {
4461 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) || NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4462 torture_comment(tctx
, "Server correctly refused create of '%s'\n", r
.in
.account_name
->string
);
4465 torture_warning(tctx
, "Server should have refused create of '%s', got %s instead\n", r
.in
.account_name
->string
,
4472 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
4473 if (!test_DeleteUser_byname(p
, user_ctx
, domain_handle
, r
.in
.account_name
->string
)) {
4474 talloc_free(user_ctx
);
4478 status
= dcerpc_samr_CreateUser2(p
, user_ctx
, &r
);
4481 if (!NT_STATUS_EQUAL(status
, account_types
[i
].nt_status
)) {
4482 torture_warning(tctx
, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4483 nt_errstr(status
), nt_errstr(account_types
[i
].nt_status
));
4487 if (NT_STATUS_IS_OK(status
)) {
4488 q
.in
.user_handle
= &user_handle
;
4492 status
= dcerpc_samr_QueryUserInfo(p
, user_ctx
, &q
);
4493 if (!NT_STATUS_IS_OK(status
)) {
4494 torture_warning(tctx
, "QueryUserInfo level %u failed - %s\n",
4495 q
.in
.level
, nt_errstr(status
));
4498 uint32_t expected_flags
= (acct_flags
| ACB_PWNOTREQ
| ACB_DISABLED
);
4499 if (acct_flags
== ACB_NORMAL
) {
4500 expected_flags
|= ACB_PW_EXPIRED
;
4502 if ((info
->info5
.acct_flags
) != expected_flags
) {
4503 torture_warning(tctx
, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4504 info
->info5
.acct_flags
,
4508 switch (acct_flags
) {
4510 if (info
->info5
.primary_gid
!= DOMAIN_RID_DCS
) {
4511 torture_warning(tctx
, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4512 DOMAIN_RID_DCS
, info
->info5
.primary_gid
);
4517 if (info
->info5
.primary_gid
!= DOMAIN_RID_DOMAIN_MEMBERS
) {
4518 torture_warning(tctx
, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4519 DOMAIN_RID_DOMAIN_MEMBERS
, info
->info5
.primary_gid
);
4524 if (info
->info5
.primary_gid
!= DOMAIN_RID_USERS
) {
4525 torture_warning(tctx
, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4526 DOMAIN_RID_USERS
, info
->info5
.primary_gid
);
4533 if (!test_user_ops(p
, tctx
, &user_handle
, domain_handle
,
4534 domain_sid
, acct_flags
, name
.string
, which_ops
,
4535 machine_credentials
)) {
4539 if (!policy_handle_empty(&user_handle
)) {
4540 torture_comment(tctx
, "Testing DeleteUser (createuser2 test)\n");
4542 d
.in
.user_handle
= &user_handle
;
4543 d
.out
.user_handle
= &user_handle
;
4545 status
= dcerpc_samr_DeleteUser(p
, user_ctx
, &d
);
4546 if (!NT_STATUS_IS_OK(status
)) {
4547 torture_warning(tctx
, "DeleteUser failed - %s\n", nt_errstr(status
));
4552 talloc_free(user_ctx
);
4558 static bool test_QueryAliasInfo(struct dcerpc_pipe
*p
,
4559 struct torture_context
*tctx
,
4560 struct policy_handle
*handle
)
4563 struct samr_QueryAliasInfo r
;
4564 union samr_AliasInfo
*info
;
4565 uint16_t levels
[] = {1, 2, 3};
4569 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4570 torture_comment(tctx
, "Testing QueryAliasInfo level %u\n", levels
[i
]);
4572 r
.in
.alias_handle
= handle
;
4573 r
.in
.level
= levels
[i
];
4576 status
= dcerpc_samr_QueryAliasInfo(p
, tctx
, &r
);
4577 if (!NT_STATUS_IS_OK(status
)) {
4578 torture_warning(tctx
, "QueryAliasInfo level %u failed - %s\n",
4579 levels
[i
], nt_errstr(status
));
4587 static bool test_QueryGroupInfo(struct dcerpc_pipe
*p
,
4588 struct torture_context
*tctx
,
4589 struct policy_handle
*handle
)
4592 struct samr_QueryGroupInfo r
;
4593 union samr_GroupInfo
*info
;
4594 uint16_t levels
[] = {1, 2, 3, 4, 5};
4598 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4599 torture_comment(tctx
, "Testing QueryGroupInfo level %u\n", levels
[i
]);
4601 r
.in
.group_handle
= handle
;
4602 r
.in
.level
= levels
[i
];
4605 status
= dcerpc_samr_QueryGroupInfo(p
, tctx
, &r
);
4606 if (!NT_STATUS_IS_OK(status
)) {
4607 torture_warning(tctx
, "QueryGroupInfo level %u failed - %s\n",
4608 levels
[i
], nt_errstr(status
));
4616 static bool test_QueryGroupMember(struct dcerpc_pipe
*p
,
4617 struct torture_context
*tctx
,
4618 struct policy_handle
*handle
)
4621 struct samr_QueryGroupMember r
;
4622 struct samr_RidTypeArray
*rids
= NULL
;
4625 torture_comment(tctx
, "Testing QueryGroupMember\n");
4627 r
.in
.group_handle
= handle
;
4630 status
= dcerpc_samr_QueryGroupMember(p
, tctx
, &r
);
4631 if (!NT_STATUS_IS_OK(status
)) {
4632 torture_warning(tctx
, "QueryGroupInfo failed - %s\n", nt_errstr(status
));
4640 static bool test_SetGroupInfo(struct dcerpc_pipe
*p
,
4641 struct torture_context
*tctx
,
4642 struct policy_handle
*handle
)
4645 struct samr_QueryGroupInfo r
;
4646 union samr_GroupInfo
*info
;
4647 struct samr_SetGroupInfo s
;
4648 uint16_t levels
[] = {1, 2, 3, 4};
4649 uint16_t set_ok
[] = {0, 1, 1, 1};
4653 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4654 torture_comment(tctx
, "Testing QueryGroupInfo level %u\n", levels
[i
]);
4656 r
.in
.group_handle
= handle
;
4657 r
.in
.level
= levels
[i
];
4660 status
= dcerpc_samr_QueryGroupInfo(p
, tctx
, &r
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4662 torture_warning(tctx
, "QueryGroupInfo level %u failed - %s\n",
4663 levels
[i
], nt_errstr(status
));
4667 torture_comment(tctx
, "Testing SetGroupInfo level %u\n", levels
[i
]);
4669 s
.in
.group_handle
= handle
;
4670 s
.in
.level
= levels
[i
];
4671 s
.in
.info
= *r
.out
.info
;
4674 /* disabled this, as it changes the name only from the point of view of samr,
4675 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4676 the name is still reserved, so creating the old name fails, but deleting by the old name
4678 if (s
.in
.level
== 2) {
4679 init_lsa_String(&s
.in
.info
->string
, "NewName");
4683 if (s
.in
.level
== 4) {
4684 init_lsa_String(&s
.in
.info
->description
, "test description");
4687 status
= dcerpc_samr_SetGroupInfo(p
, tctx
, &s
);
4689 if (!NT_STATUS_IS_OK(status
)) {
4690 torture_warning(tctx
, "SetGroupInfo level %u failed - %s\n",
4691 r
.in
.level
, nt_errstr(status
));
4696 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS
, status
)) {
4697 torture_warning(tctx
, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4698 r
.in
.level
, nt_errstr(status
));
4708 static bool test_QueryUserInfo(struct dcerpc_pipe
*p
,
4709 struct torture_context
*tctx
,
4710 struct policy_handle
*handle
)
4713 struct samr_QueryUserInfo r
;
4714 union samr_UserInfo
*info
;
4715 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4716 11, 12, 13, 14, 16, 17, 20, 21};
4720 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4721 torture_comment(tctx
, "Testing QueryUserInfo level %u\n", levels
[i
]);
4723 r
.in
.user_handle
= handle
;
4724 r
.in
.level
= levels
[i
];
4727 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &r
);
4728 if (!NT_STATUS_IS_OK(status
)) {
4729 torture_warning(tctx
, "QueryUserInfo level %u failed - %s\n",
4730 levels
[i
], nt_errstr(status
));
4738 static bool test_QueryUserInfo2(struct dcerpc_pipe
*p
,
4739 struct torture_context
*tctx
,
4740 struct policy_handle
*handle
)
4743 struct samr_QueryUserInfo2 r
;
4744 union samr_UserInfo
*info
;
4745 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4746 11, 12, 13, 14, 16, 17, 20, 21};
4750 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4751 torture_comment(tctx
, "Testing QueryUserInfo2 level %u\n", levels
[i
]);
4753 r
.in
.user_handle
= handle
;
4754 r
.in
.level
= levels
[i
];
4757 status
= dcerpc_samr_QueryUserInfo2(p
, tctx
, &r
);
4758 if (!NT_STATUS_IS_OK(status
)) {
4759 torture_warning(tctx
, "QueryUserInfo2 level %u failed - %s\n",
4760 levels
[i
], nt_errstr(status
));
4768 static bool test_OpenUser(struct dcerpc_pipe
*p
,
4769 struct torture_context
*tctx
,
4770 struct policy_handle
*handle
, uint32_t rid
)
4773 struct samr_OpenUser r
;
4774 struct policy_handle user_handle
;
4777 torture_comment(tctx
, "Testing OpenUser(%u)\n", rid
);
4779 r
.in
.domain_handle
= handle
;
4780 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4782 r
.out
.user_handle
= &user_handle
;
4784 status
= dcerpc_samr_OpenUser(p
, tctx
, &r
);
4785 if (!NT_STATUS_IS_OK(status
)) {
4786 torture_warning(tctx
, "OpenUser(%u) failed - %s\n", rid
, nt_errstr(status
));
4790 if (!test_QuerySecurity(p
, tctx
, &user_handle
)) {
4794 if (!test_QueryUserInfo(p
, tctx
, &user_handle
)) {
4798 if (!test_QueryUserInfo2(p
, tctx
, &user_handle
)) {
4802 if (!test_GetUserPwInfo(p
, tctx
, &user_handle
)) {
4806 if (!test_GetGroupsForUser(p
,tctx
, &user_handle
)) {
4810 if (!test_samr_handle_Close(p
, tctx
, &user_handle
)) {
4817 static bool test_OpenGroup(struct dcerpc_pipe
*p
,
4818 struct torture_context
*tctx
,
4819 struct policy_handle
*handle
, uint32_t rid
)
4822 struct samr_OpenGroup r
;
4823 struct policy_handle group_handle
;
4826 torture_comment(tctx
, "Testing OpenGroup(%u)\n", rid
);
4828 r
.in
.domain_handle
= handle
;
4829 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4831 r
.out
.group_handle
= &group_handle
;
4833 status
= dcerpc_samr_OpenGroup(p
, tctx
, &r
);
4834 if (!NT_STATUS_IS_OK(status
)) {
4835 torture_warning(tctx
, "OpenGroup(%u) failed - %s\n", rid
, nt_errstr(status
));
4839 if (!torture_setting_bool(tctx
, "samba3", false)) {
4840 if (!test_QuerySecurity(p
, tctx
, &group_handle
)) {
4845 if (!test_QueryGroupInfo(p
, tctx
, &group_handle
)) {
4849 if (!test_QueryGroupMember(p
, tctx
, &group_handle
)) {
4853 if (!test_samr_handle_Close(p
, tctx
, &group_handle
)) {
4860 static bool test_OpenAlias(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
4861 struct policy_handle
*handle
, uint32_t rid
)
4864 struct samr_OpenAlias r
;
4865 struct policy_handle alias_handle
;
4868 torture_comment(tctx
, "Testing OpenAlias(%u)\n", rid
);
4870 r
.in
.domain_handle
= handle
;
4871 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4873 r
.out
.alias_handle
= &alias_handle
;
4875 status
= dcerpc_samr_OpenAlias(p
, tctx
, &r
);
4876 if (!NT_STATUS_IS_OK(status
)) {
4877 torture_warning(tctx
, "OpenAlias(%u) failed - %s\n", rid
, nt_errstr(status
));
4881 if (!torture_setting_bool(tctx
, "samba3", false)) {
4882 if (!test_QuerySecurity(p
, tctx
, &alias_handle
)) {
4887 if (!test_QueryAliasInfo(p
, tctx
, &alias_handle
)) {
4891 if (!test_GetMembersInAlias(p
, tctx
, &alias_handle
)) {
4895 if (!test_samr_handle_Close(p
, tctx
, &alias_handle
)) {
4902 static bool check_mask(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
4903 struct policy_handle
*handle
, uint32_t rid
,
4904 uint32_t acct_flag_mask
)
4907 struct samr_OpenUser r
;
4908 struct samr_QueryUserInfo q
;
4909 union samr_UserInfo
*info
;
4910 struct policy_handle user_handle
;
4913 torture_comment(tctx
, "Testing OpenUser(%u)\n", rid
);
4915 r
.in
.domain_handle
= handle
;
4916 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4918 r
.out
.user_handle
= &user_handle
;
4920 status
= dcerpc_samr_OpenUser(p
, tctx
, &r
);
4921 if (!NT_STATUS_IS_OK(status
)) {
4922 torture_warning(tctx
, "OpenUser(%u) failed - %s\n", rid
, nt_errstr(status
));
4926 q
.in
.user_handle
= &user_handle
;
4930 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &q
);
4931 if (!NT_STATUS_IS_OK(status
)) {
4932 torture_warning(tctx
, "QueryUserInfo level 16 failed - %s\n",
4936 if ((acct_flag_mask
& info
->info16
.acct_flags
) == 0) {
4937 torture_warning(tctx
, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4938 acct_flag_mask
, info
->info16
.acct_flags
, rid
);
4943 if (!test_samr_handle_Close(p
, tctx
, &user_handle
)) {
4950 static bool test_EnumDomainUsers_all(struct dcerpc_pipe
*p
,
4951 struct torture_context
*tctx
,
4952 struct policy_handle
*handle
)
4954 NTSTATUS status
= STATUS_MORE_ENTRIES
;
4955 struct samr_EnumDomainUsers r
;
4956 uint32_t mask
, resume_handle
=0;
4959 struct samr_LookupNames n
;
4960 struct samr_LookupRids lr
;
4961 struct lsa_Strings names
;
4962 struct samr_Ids rids
, types
;
4963 struct samr_SamArray
*sam
= NULL
;
4964 uint32_t num_entries
= 0;
4966 uint32_t masks
[] = {ACB_NORMAL
, ACB_DOMTRUST
, ACB_WSTRUST
,
4967 ACB_DISABLED
, ACB_NORMAL
| ACB_DISABLED
,
4968 ACB_SVRTRUST
| ACB_DOMTRUST
| ACB_WSTRUST
,
4971 torture_comment(tctx
, "Testing EnumDomainUsers\n");
4973 for (mask_idx
=0;mask_idx
<ARRAY_SIZE(masks
);mask_idx
++) {
4974 r
.in
.domain_handle
= handle
;
4975 r
.in
.resume_handle
= &resume_handle
;
4976 r
.in
.acct_flags
= mask
= masks
[mask_idx
];
4977 r
.in
.max_size
= (uint32_t)-1;
4978 r
.out
.resume_handle
= &resume_handle
;
4979 r
.out
.num_entries
= &num_entries
;
4982 status
= dcerpc_samr_EnumDomainUsers(p
, tctx
, &r
);
4983 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
) &&
4984 !NT_STATUS_IS_OK(status
)) {
4985 torture_warning(tctx
, "EnumDomainUsers failed - %s\n", nt_errstr(status
));
4989 torture_assert(tctx
, sam
, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4991 if (sam
->count
== 0) {
4995 for (i
=0;i
<sam
->count
;i
++) {
4997 if (!check_mask(p
, tctx
, handle
, sam
->entries
[i
].idx
, mask
)) {
5000 } else if (!test_OpenUser(p
, tctx
, handle
, sam
->entries
[i
].idx
)) {
5006 torture_comment(tctx
, "Testing LookupNames\n");
5007 n
.in
.domain_handle
= handle
;
5008 n
.in
.num_names
= sam
->count
;
5009 n
.in
.names
= talloc_array(tctx
, struct lsa_String
, sam
->count
);
5011 n
.out
.types
= &types
;
5012 for (i
=0;i
<sam
->count
;i
++) {
5013 n
.in
.names
[i
].string
= sam
->entries
[i
].name
.string
;
5015 status
= dcerpc_samr_LookupNames(p
, tctx
, &n
);
5016 if (!NT_STATUS_IS_OK(status
)) {
5017 torture_warning(tctx
, "LookupNames failed - %s\n", nt_errstr(status
));
5022 torture_comment(tctx
, "Testing LookupRids\n");
5023 lr
.in
.domain_handle
= handle
;
5024 lr
.in
.num_rids
= sam
->count
;
5025 lr
.in
.rids
= talloc_array(tctx
, uint32_t, sam
->count
);
5026 lr
.out
.names
= &names
;
5027 lr
.out
.types
= &types
;
5028 for (i
=0;i
<sam
->count
;i
++) {
5029 lr
.in
.rids
[i
] = sam
->entries
[i
].idx
;
5031 status
= dcerpc_samr_LookupRids(p
, tctx
, &lr
);
5032 torture_assert_ntstatus_ok(tctx
, status
, "LookupRids");
5038 try blasting the server with a bunch of sync requests
5040 static bool test_EnumDomainUsers_async(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5041 struct policy_handle
*handle
)
5044 struct samr_EnumDomainUsers r
;
5045 uint32_t resume_handle
=0;
5047 #define ASYNC_COUNT 100
5048 struct rpc_request
*req
[ASYNC_COUNT
];
5050 if (!torture_setting_bool(tctx
, "dangerous", false)) {
5051 torture_skip(tctx
, "samr async test disabled - enable dangerous tests to use\n");
5054 torture_comment(tctx
, "Testing EnumDomainUsers_async\n");
5056 r
.in
.domain_handle
= handle
;
5057 r
.in
.resume_handle
= &resume_handle
;
5058 r
.in
.acct_flags
= 0;
5059 r
.in
.max_size
= (uint32_t)-1;
5060 r
.out
.resume_handle
= &resume_handle
;
5062 for (i
=0;i
<ASYNC_COUNT
;i
++) {
5063 req
[i
] = dcerpc_samr_EnumDomainUsers_send(p
, tctx
, &r
);
5066 for (i
=0;i
<ASYNC_COUNT
;i
++) {
5067 status
= dcerpc_ndr_request_recv(req
[i
]);
5068 if (!NT_STATUS_IS_OK(status
)) {
5069 torture_warning(tctx
, "EnumDomainUsers[%d] failed - %s\n",
5070 i
, nt_errstr(status
));
5075 torture_comment(tctx
, "%d async requests OK\n", i
);
5080 static bool test_EnumDomainGroups_all(struct dcerpc_pipe
*p
,
5081 struct torture_context
*tctx
,
5082 struct policy_handle
*handle
)
5085 struct samr_EnumDomainGroups r
;
5086 uint32_t resume_handle
=0;
5087 struct samr_SamArray
*sam
= NULL
;
5088 uint32_t num_entries
= 0;
5092 torture_comment(tctx
, "Testing EnumDomainGroups\n");
5094 r
.in
.domain_handle
= handle
;
5095 r
.in
.resume_handle
= &resume_handle
;
5096 r
.in
.max_size
= (uint32_t)-1;
5097 r
.out
.resume_handle
= &resume_handle
;
5098 r
.out
.num_entries
= &num_entries
;
5101 status
= dcerpc_samr_EnumDomainGroups(p
, tctx
, &r
);
5102 if (!NT_STATUS_IS_OK(status
)) {
5103 torture_warning(tctx
, "EnumDomainGroups failed - %s\n", nt_errstr(status
));
5111 for (i
=0;i
<sam
->count
;i
++) {
5112 if (!test_OpenGroup(p
, tctx
, handle
, sam
->entries
[i
].idx
)) {
5120 static bool test_EnumDomainAliases_all(struct dcerpc_pipe
*p
,
5121 struct torture_context
*tctx
,
5122 struct policy_handle
*handle
)
5125 struct samr_EnumDomainAliases r
;
5126 uint32_t resume_handle
=0;
5127 struct samr_SamArray
*sam
= NULL
;
5128 uint32_t num_entries
= 0;
5132 torture_comment(tctx
, "Testing EnumDomainAliases\n");
5134 r
.in
.domain_handle
= handle
;
5135 r
.in
.resume_handle
= &resume_handle
;
5136 r
.in
.max_size
= (uint32_t)-1;
5138 r
.out
.num_entries
= &num_entries
;
5139 r
.out
.resume_handle
= &resume_handle
;
5141 status
= dcerpc_samr_EnumDomainAliases(p
, tctx
, &r
);
5142 if (!NT_STATUS_IS_OK(status
)) {
5143 torture_warning(tctx
, "EnumDomainAliases failed - %s\n", nt_errstr(status
));
5151 for (i
=0;i
<sam
->count
;i
++) {
5152 if (!test_OpenAlias(p
, tctx
, handle
, sam
->entries
[i
].idx
)) {
5160 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe
*p
,
5161 struct torture_context
*tctx
,
5162 struct policy_handle
*handle
)
5165 struct samr_GetDisplayEnumerationIndex r
;
5167 uint16_t levels
[] = {1, 2, 3, 4, 5};
5168 uint16_t ok_lvl
[] = {1, 1, 1, 0, 0};
5169 struct lsa_String name
;
5173 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5174 torture_comment(tctx
, "Testing GetDisplayEnumerationIndex level %u\n", levels
[i
]);
5176 init_lsa_String(&name
, TEST_ACCOUNT_NAME
);
5178 r
.in
.domain_handle
= handle
;
5179 r
.in
.level
= levels
[i
];
5183 status
= dcerpc_samr_GetDisplayEnumerationIndex(p
, tctx
, &r
);
5186 !NT_STATUS_IS_OK(status
) &&
5187 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES
, status
)) {
5188 torture_warning(tctx
, "GetDisplayEnumerationIndex level %u failed - %s\n",
5189 levels
[i
], nt_errstr(status
));
5193 init_lsa_String(&name
, "zzzzzzzz");
5195 status
= dcerpc_samr_GetDisplayEnumerationIndex(p
, tctx
, &r
);
5197 if (ok_lvl
[i
] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES
, status
)) {
5198 torture_warning(tctx
, "GetDisplayEnumerationIndex level %u failed - %s\n",
5199 levels
[i
], nt_errstr(status
));
5207 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe
*p
,
5208 struct torture_context
*tctx
,
5209 struct policy_handle
*handle
)
5212 struct samr_GetDisplayEnumerationIndex2 r
;
5214 uint16_t levels
[] = {1, 2, 3, 4, 5};
5215 uint16_t ok_lvl
[] = {1, 1, 1, 0, 0};
5216 struct lsa_String name
;
5220 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5221 torture_comment(tctx
, "Testing GetDisplayEnumerationIndex2 level %u\n", levels
[i
]);
5223 init_lsa_String(&name
, TEST_ACCOUNT_NAME
);
5225 r
.in
.domain_handle
= handle
;
5226 r
.in
.level
= levels
[i
];
5230 status
= dcerpc_samr_GetDisplayEnumerationIndex2(p
, tctx
, &r
);
5232 !NT_STATUS_IS_OK(status
) &&
5233 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES
, status
)) {
5234 torture_warning(tctx
, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5235 levels
[i
], nt_errstr(status
));
5239 init_lsa_String(&name
, "zzzzzzzz");
5241 status
= dcerpc_samr_GetDisplayEnumerationIndex2(p
, tctx
, &r
);
5242 if (ok_lvl
[i
] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES
, status
)) {
5243 torture_warning(tctx
, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5244 levels
[i
], nt_errstr(status
));
5252 #define STRING_EQUAL_QUERY(s1, s2, user) \
5253 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
5254 /* odd, but valid */ \
5255 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
5256 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
5257 #s1, user.string, s1.string, s2.string, __location__); \
5260 #define INT_EQUAL_QUERY(s1, s2, user) \
5262 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
5263 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
5267 static bool test_each_DisplayInfo_user(struct dcerpc_pipe
*p
,
5268 struct torture_context
*tctx
,
5269 struct samr_QueryDisplayInfo
*querydisplayinfo
,
5270 bool *seen_testuser
)
5272 struct samr_OpenUser r
;
5273 struct samr_QueryUserInfo q
;
5274 union samr_UserInfo
*info
;
5275 struct policy_handle user_handle
;
5278 r
.in
.domain_handle
= querydisplayinfo
->in
.domain_handle
;
5279 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
5280 for (i
= 0; ; i
++) {
5281 switch (querydisplayinfo
->in
.level
) {
5283 if (i
>= querydisplayinfo
->out
.info
->info1
.count
) {
5286 r
.in
.rid
= querydisplayinfo
->out
.info
->info1
.entries
[i
].rid
;
5289 if (i
>= querydisplayinfo
->out
.info
->info2
.count
) {
5292 r
.in
.rid
= querydisplayinfo
->out
.info
->info2
.entries
[i
].rid
;
5298 /* Not interested in validating just the account name */
5302 r
.out
.user_handle
= &user_handle
;
5304 switch (querydisplayinfo
->in
.level
) {
5307 status
= dcerpc_samr_OpenUser(p
, tctx
, &r
);
5308 if (!NT_STATUS_IS_OK(status
)) {
5309 torture_warning(tctx
, "OpenUser(%u) failed - %s\n", r
.in
.rid
, nt_errstr(status
));
5314 q
.in
.user_handle
= &user_handle
;
5317 status
= dcerpc_samr_QueryUserInfo(p
, tctx
, &q
);
5318 if (!NT_STATUS_IS_OK(status
)) {
5319 torture_warning(tctx
, "QueryUserInfo(%u) failed - %s\n", r
.in
.rid
, nt_errstr(status
));
5323 switch (querydisplayinfo
->in
.level
) {
5325 if (seen_testuser
&& strcmp(info
->info21
.account_name
.string
, TEST_ACCOUNT_NAME
) == 0) {
5326 *seen_testuser
= true;
5328 STRING_EQUAL_QUERY(querydisplayinfo
->out
.info
->info1
.entries
[i
].full_name
,
5329 info
->info21
.full_name
, info
->info21
.account_name
);
5330 STRING_EQUAL_QUERY(querydisplayinfo
->out
.info
->info1
.entries
[i
].account_name
,
5331 info
->info21
.account_name
, info
->info21
.account_name
);
5332 STRING_EQUAL_QUERY(querydisplayinfo
->out
.info
->info1
.entries
[i
].description
,
5333 info
->info21
.description
, info
->info21
.account_name
);
5334 INT_EQUAL_QUERY(querydisplayinfo
->out
.info
->info1
.entries
[i
].rid
,
5335 info
->info21
.rid
, info
->info21
.account_name
);
5336 INT_EQUAL_QUERY(querydisplayinfo
->out
.info
->info1
.entries
[i
].acct_flags
,
5337 info
->info21
.acct_flags
, info
->info21
.account_name
);
5341 STRING_EQUAL_QUERY(querydisplayinfo
->out
.info
->info2
.entries
[i
].account_name
,
5342 info
->info21
.account_name
, info
->info21
.account_name
);
5343 STRING_EQUAL_QUERY(querydisplayinfo
->out
.info
->info2
.entries
[i
].description
,
5344 info
->info21
.description
, info
->info21
.account_name
);
5345 INT_EQUAL_QUERY(querydisplayinfo
->out
.info
->info2
.entries
[i
].rid
,
5346 info
->info21
.rid
, info
->info21
.account_name
);
5347 INT_EQUAL_QUERY((querydisplayinfo
->out
.info
->info2
.entries
[i
].acct_flags
& ~ACB_NORMAL
),
5348 info
->info21
.acct_flags
, info
->info21
.account_name
);
5350 if (!(querydisplayinfo
->out
.info
->info2
.entries
[i
].acct_flags
& ACB_NORMAL
)) {
5351 torture_warning(tctx
, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
5352 info
->info21
.account_name
.string
);
5355 if (!(info
->info21
.acct_flags
& (ACB_WSTRUST
| ACB_SVRTRUST
))) {
5356 torture_warning(tctx
, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
5357 info
->info21
.account_name
.string
,
5358 querydisplayinfo
->out
.info
->info2
.entries
[i
].acct_flags
,
5359 info
->info21
.acct_flags
);
5366 if (!test_samr_handle_Close(p
, tctx
, &user_handle
)) {
5373 static bool test_QueryDisplayInfo(struct dcerpc_pipe
*p
,
5374 struct torture_context
*tctx
,
5375 struct policy_handle
*handle
)
5378 struct samr_QueryDisplayInfo r
;
5379 struct samr_QueryDomainInfo dom_info
;
5380 union samr_DomainInfo
*info
= NULL
;
5382 uint16_t levels
[] = {1, 2, 3, 4, 5};
5384 bool seen_testuser
= false;
5385 uint32_t total_size
;
5386 uint32_t returned_size
;
5387 union samr_DispInfo disp_info
;
5390 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5391 torture_comment(tctx
, "Testing QueryDisplayInfo level %u\n", levels
[i
]);
5394 status
= STATUS_MORE_ENTRIES
;
5395 while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
5396 r
.in
.domain_handle
= handle
;
5397 r
.in
.level
= levels
[i
];
5398 r
.in
.max_entries
= 2;
5399 r
.in
.buf_size
= (uint32_t)-1;
5400 r
.out
.total_size
= &total_size
;
5401 r
.out
.returned_size
= &returned_size
;
5402 r
.out
.info
= &disp_info
;
5404 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &r
);
5405 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
) && !NT_STATUS_IS_OK(status
)) {
5406 torture_warning(tctx
, "QueryDisplayInfo level %u failed - %s\n",
5407 levels
[i
], nt_errstr(status
));
5410 switch (r
.in
.level
) {
5412 if (!test_each_DisplayInfo_user(p
, tctx
, &r
, &seen_testuser
)) {
5415 r
.in
.start_idx
+= r
.out
.info
->info1
.count
;
5418 if (!test_each_DisplayInfo_user(p
, tctx
, &r
, NULL
)) {
5421 r
.in
.start_idx
+= r
.out
.info
->info2
.count
;
5424 r
.in
.start_idx
+= r
.out
.info
->info3
.count
;
5427 r
.in
.start_idx
+= r
.out
.info
->info4
.count
;
5430 r
.in
.start_idx
+= r
.out
.info
->info5
.count
;
5434 dom_info
.in
.domain_handle
= handle
;
5435 dom_info
.in
.level
= 2;
5436 dom_info
.out
.info
= &info
;
5438 /* Check number of users returned is correct */
5439 status
= dcerpc_samr_QueryDomainInfo(p
, tctx
, &dom_info
);
5440 if (!NT_STATUS_IS_OK(status
)) {
5441 torture_warning(tctx
, "QueryDomainInfo level %u failed - %s\n",
5442 r
.in
.level
, nt_errstr(status
));
5446 switch (r
.in
.level
) {
5449 if (info
->general
.num_users
< r
.in
.start_idx
) {
5450 torture_warning(tctx
, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5451 r
.in
.start_idx
, info
->general
.num_groups
,
5452 info
->general
.domain_name
.string
);
5455 if (!seen_testuser
) {
5456 struct policy_handle user_handle
;
5457 if (NT_STATUS_IS_OK(test_OpenUser_byname(p
, tctx
, handle
, TEST_ACCOUNT_NAME
, &user_handle
))) {
5458 torture_warning(tctx
, "Didn't find test user " TEST_ACCOUNT_NAME
" in enumeration of %s\n",
5459 info
->general
.domain_name
.string
);
5461 test_samr_handle_Close(p
, tctx
, &user_handle
);
5467 if (info
->general
.num_groups
!= r
.in
.start_idx
) {
5468 torture_warning(tctx
, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5469 r
.in
.start_idx
, info
->general
.num_groups
,
5470 info
->general
.domain_name
.string
);
5482 static bool test_QueryDisplayInfo2(struct dcerpc_pipe
*p
,
5483 struct torture_context
*tctx
,
5484 struct policy_handle
*handle
)
5487 struct samr_QueryDisplayInfo2 r
;
5489 uint16_t levels
[] = {1, 2, 3, 4, 5};
5491 uint32_t total_size
;
5492 uint32_t returned_size
;
5493 union samr_DispInfo info
;
5495 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5496 torture_comment(tctx
, "Testing QueryDisplayInfo2 level %u\n", levels
[i
]);
5498 r
.in
.domain_handle
= handle
;
5499 r
.in
.level
= levels
[i
];
5501 r
.in
.max_entries
= 1000;
5502 r
.in
.buf_size
= (uint32_t)-1;
5503 r
.out
.total_size
= &total_size
;
5504 r
.out
.returned_size
= &returned_size
;
5507 status
= dcerpc_samr_QueryDisplayInfo2(p
, tctx
, &r
);
5508 if (!NT_STATUS_IS_OK(status
)) {
5509 torture_warning(tctx
, "QueryDisplayInfo2 level %u failed - %s\n",
5510 levels
[i
], nt_errstr(status
));
5518 static bool test_QueryDisplayInfo3(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5519 struct policy_handle
*handle
)
5522 struct samr_QueryDisplayInfo3 r
;
5524 uint16_t levels
[] = {1, 2, 3, 4, 5};
5526 uint32_t total_size
;
5527 uint32_t returned_size
;
5528 union samr_DispInfo info
;
5530 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5531 torture_comment(tctx
, "Testing QueryDisplayInfo3 level %u\n", levels
[i
]);
5533 r
.in
.domain_handle
= handle
;
5534 r
.in
.level
= levels
[i
];
5536 r
.in
.max_entries
= 1000;
5537 r
.in
.buf_size
= (uint32_t)-1;
5538 r
.out
.total_size
= &total_size
;
5539 r
.out
.returned_size
= &returned_size
;
5542 status
= dcerpc_samr_QueryDisplayInfo3(p
, tctx
, &r
);
5543 if (!NT_STATUS_IS_OK(status
)) {
5544 torture_warning(tctx
, "QueryDisplayInfo3 level %u failed - %s\n",
5545 levels
[i
], nt_errstr(status
));
5554 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe
*p
,
5555 struct torture_context
*tctx
,
5556 struct policy_handle
*handle
)
5559 struct samr_QueryDisplayInfo r
;
5561 uint32_t total_size
;
5562 uint32_t returned_size
;
5563 union samr_DispInfo info
;
5565 torture_comment(tctx
, "Testing QueryDisplayInfo continuation\n");
5567 r
.in
.domain_handle
= handle
;
5570 r
.in
.max_entries
= 1;
5571 r
.in
.buf_size
= (uint32_t)-1;
5572 r
.out
.total_size
= &total_size
;
5573 r
.out
.returned_size
= &returned_size
;
5577 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &r
);
5578 if (NT_STATUS_IS_OK(status
) && *r
.out
.returned_size
!= 0) {
5579 if (r
.out
.info
->info1
.entries
[0].idx
!= r
.in
.start_idx
+ 1) {
5580 torture_warning(tctx
, "expected idx %d but got %d\n",
5582 r
.out
.info
->info1
.entries
[0].idx
);
5586 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
) &&
5587 !NT_STATUS_IS_OK(status
)) {
5588 torture_warning(tctx
, "QueryDisplayInfo level %u failed - %s\n",
5589 r
.in
.level
, nt_errstr(status
));
5594 } while ((NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
) ||
5595 NT_STATUS_IS_OK(status
)) &&
5596 *r
.out
.returned_size
!= 0);
5601 static bool test_QueryDomainInfo(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5602 struct policy_handle
*handle
)
5605 struct samr_QueryDomainInfo r
;
5606 union samr_DomainInfo
*info
= NULL
;
5607 struct samr_SetDomainInfo s
;
5608 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5609 uint16_t set_ok
[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5612 const char *domain_comment
= talloc_asprintf(tctx
,
5613 "Tortured by Samba4 RPC-SAMR: %s",
5614 timestring(tctx
, time(NULL
)));
5616 s
.in
.domain_handle
= handle
;
5618 s
.in
.info
= talloc(tctx
, union samr_DomainInfo
);
5620 s
.in
.info
->oem
.oem_information
.string
= domain_comment
;
5621 status
= dcerpc_samr_SetDomainInfo(p
, tctx
, &s
);
5622 if (!NT_STATUS_IS_OK(status
)) {
5623 torture_warning(tctx
, "SetDomainInfo level %u (set comment) failed - %s\n",
5624 s
.in
.level
, nt_errstr(status
));
5628 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5629 torture_comment(tctx
, "Testing QueryDomainInfo level %u\n", levels
[i
]);
5631 r
.in
.domain_handle
= handle
;
5632 r
.in
.level
= levels
[i
];
5635 status
= dcerpc_samr_QueryDomainInfo(p
, tctx
, &r
);
5636 if (!NT_STATUS_IS_OK(status
)) {
5637 torture_warning(tctx
, "QueryDomainInfo level %u failed - %s\n",
5638 r
.in
.level
, nt_errstr(status
));
5643 switch (levels
[i
]) {
5645 if (strcmp(info
->general
.oem_information
.string
, domain_comment
) != 0) {
5646 torture_warning(tctx
, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5647 levels
[i
], info
->general
.oem_information
.string
, domain_comment
);
5648 if (!torture_setting_bool(tctx
, "samba3", false)) {
5652 if (!info
->general
.primary
.string
) {
5653 torture_warning(tctx
, "QueryDomainInfo level %u returned no PDC name\n",
5656 } else if (info
->general
.role
== SAMR_ROLE_DOMAIN_PDC
) {
5657 if (dcerpc_server_name(p
) && strcasecmp_m(dcerpc_server_name(p
), info
->general
.primary
.string
) != 0) {
5658 torture_warning(tctx
, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5659 levels
[i
], info
->general
.primary
.string
, dcerpc_server_name(p
));
5664 if (strcmp(info
->oem
.oem_information
.string
, domain_comment
) != 0) {
5665 torture_warning(tctx
, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5666 levels
[i
], info
->oem
.oem_information
.string
, domain_comment
);
5667 if (!torture_setting_bool(tctx
, "samba3", false)) {
5673 if (!info
->info6
.primary
.string
) {
5674 torture_warning(tctx
, "QueryDomainInfo level %u returned no PDC name\n",
5680 if (strcmp(info
->general2
.general
.oem_information
.string
, domain_comment
) != 0) {
5681 torture_warning(tctx
, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5682 levels
[i
], info
->general2
.general
.oem_information
.string
, domain_comment
);
5683 if (!torture_setting_bool(tctx
, "samba3", false)) {
5690 torture_comment(tctx
, "Testing SetDomainInfo level %u\n", levels
[i
]);
5692 s
.in
.domain_handle
= handle
;
5693 s
.in
.level
= levels
[i
];
5696 status
= dcerpc_samr_SetDomainInfo(p
, tctx
, &s
);
5698 if (!NT_STATUS_IS_OK(status
)) {
5699 torture_warning(tctx
, "SetDomainInfo level %u failed - %s\n",
5700 r
.in
.level
, nt_errstr(status
));
5705 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS
, status
)) {
5706 torture_warning(tctx
, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5707 r
.in
.level
, nt_errstr(status
));
5713 status
= dcerpc_samr_QueryDomainInfo(p
, tctx
, &r
);
5714 if (!NT_STATUS_IS_OK(status
)) {
5715 torture_warning(tctx
, "QueryDomainInfo level %u failed - %s\n",
5716 r
.in
.level
, nt_errstr(status
));
5726 static bool test_QueryDomainInfo2(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5727 struct policy_handle
*handle
)
5730 struct samr_QueryDomainInfo2 r
;
5731 union samr_DomainInfo
*info
= NULL
;
5732 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5736 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
5737 torture_comment(tctx
, "Testing QueryDomainInfo2 level %u\n", levels
[i
]);
5739 r
.in
.domain_handle
= handle
;
5740 r
.in
.level
= levels
[i
];
5743 status
= dcerpc_samr_QueryDomainInfo2(p
, tctx
, &r
);
5744 if (!NT_STATUS_IS_OK(status
)) {
5745 torture_warning(tctx
, "QueryDomainInfo2 level %u failed - %s\n",
5746 r
.in
.level
, nt_errstr(status
));
5755 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5756 set of group names. */
5757 static bool test_GroupList(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5758 struct policy_handle
*handle
)
5760 struct samr_EnumDomainGroups q1
;
5761 struct samr_QueryDisplayInfo q2
;
5763 uint32_t resume_handle
=0;
5764 struct samr_SamArray
*sam
= NULL
;
5765 uint32_t num_entries
= 0;
5768 uint32_t total_size
;
5769 uint32_t returned_size
;
5770 union samr_DispInfo info
;
5773 const char **names
= NULL
;
5775 torture_comment(tctx
, "Testing coherency of querydispinfo vs enumdomgroups\n");
5777 q1
.in
.domain_handle
= handle
;
5778 q1
.in
.resume_handle
= &resume_handle
;
5780 q1
.out
.resume_handle
= &resume_handle
;
5781 q1
.out
.num_entries
= &num_entries
;
5784 status
= STATUS_MORE_ENTRIES
;
5785 while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
5786 status
= dcerpc_samr_EnumDomainGroups(p
, tctx
, &q1
);
5788 if (!NT_STATUS_IS_OK(status
) &&
5789 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
5792 for (i
=0; i
<*q1
.out
.num_entries
; i
++) {
5793 add_string_to_array(tctx
,
5794 sam
->entries
[i
].name
.string
,
5795 &names
, &num_names
);
5799 torture_assert_ntstatus_ok(tctx
, status
, "EnumDomainGroups");
5801 torture_assert(tctx
, sam
, "EnumDomainGroups failed to return sam");
5803 q2
.in
.domain_handle
= handle
;
5805 q2
.in
.start_idx
= 0;
5806 q2
.in
.max_entries
= 5;
5807 q2
.in
.buf_size
= (uint32_t)-1;
5808 q2
.out
.total_size
= &total_size
;
5809 q2
.out
.returned_size
= &returned_size
;
5810 q2
.out
.info
= &info
;
5812 status
= STATUS_MORE_ENTRIES
;
5813 while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
5814 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &q2
);
5816 if (!NT_STATUS_IS_OK(status
) &&
5817 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
5820 for (i
=0; i
<q2
.out
.info
->info5
.count
; i
++) {
5822 const char *name
= q2
.out
.info
->info5
.entries
[i
].account_name
.string
;
5824 for (j
=0; j
<num_names
; j
++) {
5825 if (names
[j
] == NULL
)
5827 if (strequal(names
[j
], name
)) {
5835 torture_warning(tctx
, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5840 q2
.in
.start_idx
+= q2
.out
.info
->info5
.count
;
5843 if (!NT_STATUS_IS_OK(status
)) {
5844 torture_warning(tctx
, "QueryDisplayInfo level 5 failed - %s\n",
5849 for (i
=0; i
<num_names
; i
++) {
5850 if (names
[i
] != NULL
) {
5851 torture_warning(tctx
, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5860 static bool test_DeleteDomainGroup(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5861 struct policy_handle
*group_handle
)
5863 struct samr_DeleteDomainGroup d
;
5866 torture_comment(tctx
, "Testing DeleteDomainGroup\n");
5868 d
.in
.group_handle
= group_handle
;
5869 d
.out
.group_handle
= group_handle
;
5871 status
= dcerpc_samr_DeleteDomainGroup(p
, tctx
, &d
);
5872 torture_assert_ntstatus_ok(tctx
, status
, "DeleteDomainGroup");
5877 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5878 struct policy_handle
*domain_handle
)
5880 struct samr_TestPrivateFunctionsDomain r
;
5884 torture_comment(tctx
, "Testing TestPrivateFunctionsDomain\n");
5886 r
.in
.domain_handle
= domain_handle
;
5888 status
= dcerpc_samr_TestPrivateFunctionsDomain(p
, tctx
, &r
);
5889 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NOT_IMPLEMENTED
, "TestPrivateFunctionsDomain");
5894 static bool test_RidToSid(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5895 struct dom_sid
*domain_sid
,
5896 struct policy_handle
*domain_handle
)
5898 struct samr_RidToSid r
;
5901 struct dom_sid
*calc_sid
, *out_sid
;
5902 int rids
[] = { 0, 42, 512, 10200 };
5905 for (i
=0;i
<ARRAY_SIZE(rids
);i
++) {
5906 torture_comment(tctx
, "Testing RidToSid\n");
5908 calc_sid
= dom_sid_dup(tctx
, domain_sid
);
5909 r
.in
.domain_handle
= domain_handle
;
5911 r
.out
.sid
= &out_sid
;
5913 status
= dcerpc_samr_RidToSid(p
, tctx
, &r
);
5914 if (!NT_STATUS_IS_OK(status
)) {
5915 torture_warning(tctx
, "RidToSid for %d failed - %s\n", rids
[i
], nt_errstr(status
));
5918 calc_sid
= dom_sid_add_rid(calc_sid
, calc_sid
, rids
[i
]);
5920 if (!dom_sid_equal(calc_sid
, out_sid
)) {
5921 torture_warning(tctx
, "RidToSid for %d failed - got %s, expected %s\n", rids
[i
],
5922 dom_sid_string(tctx
, out_sid
),
5923 dom_sid_string(tctx
, calc_sid
));
5932 static bool test_GetBootKeyInformation(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5933 struct policy_handle
*domain_handle
)
5935 struct samr_GetBootKeyInformation r
;
5938 uint32_t unknown
= 0;
5940 torture_comment(tctx
, "Testing GetBootKeyInformation\n");
5942 r
.in
.domain_handle
= domain_handle
;
5943 r
.out
.unknown
= &unknown
;
5945 status
= dcerpc_samr_GetBootKeyInformation(p
, tctx
, &r
);
5946 if (!NT_STATUS_IS_OK(status
)) {
5947 /* w2k3 seems to fail this sometimes and pass it sometimes */
5948 torture_comment(tctx
, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status
));
5954 static bool test_AddGroupMember(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
5955 struct policy_handle
*domain_handle
,
5956 struct policy_handle
*group_handle
)
5959 struct samr_AddGroupMember r
;
5960 struct samr_DeleteGroupMember d
;
5961 struct samr_QueryGroupMember q
;
5962 struct samr_RidTypeArray
*rids
= NULL
;
5963 struct samr_SetMemberAttributesOfGroup s
;
5965 bool found_member
= false;
5968 status
= test_LookupName(p
, tctx
, domain_handle
, TEST_ACCOUNT_NAME
, &rid
);
5969 torture_assert_ntstatus_ok(tctx
, status
, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME
);
5971 r
.in
.group_handle
= group_handle
;
5973 r
.in
.flags
= 0; /* ??? */
5975 torture_comment(tctx
, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
5977 d
.in
.group_handle
= group_handle
;
5980 status
= dcerpc_samr_DeleteGroupMember(p
, tctx
, &d
);
5981 torture_assert_ntstatus_equal(tctx
, NT_STATUS_MEMBER_NOT_IN_GROUP
, status
, "DeleteGroupMember");
5983 status
= dcerpc_samr_AddGroupMember(p
, tctx
, &r
);
5984 torture_assert_ntstatus_ok(tctx
, status
, "AddGroupMember");
5986 status
= dcerpc_samr_AddGroupMember(p
, tctx
, &r
);
5987 torture_assert_ntstatus_equal(tctx
, NT_STATUS_MEMBER_IN_GROUP
, status
, "AddGroupMember");
5989 if (torture_setting_bool(tctx
, "samba4", false) ||
5990 torture_setting_bool(tctx
, "samba3", false)) {
5991 torture_comment(tctx
, "skipping SetMemberAttributesOfGroup test against Samba\n");
5993 /* this one is quite strange. I am using random inputs in the
5994 hope of triggering an error that might give us a clue */
5996 s
.in
.group_handle
= group_handle
;
5997 s
.in
.unknown1
= random();
5998 s
.in
.unknown2
= random();
6000 status
= dcerpc_samr_SetMemberAttributesOfGroup(p
, tctx
, &s
);
6001 torture_assert_ntstatus_ok(tctx
, status
, "SetMemberAttributesOfGroup");
6004 q
.in
.group_handle
= group_handle
;
6007 status
= dcerpc_samr_QueryGroupMember(p
, tctx
, &q
);
6008 torture_assert_ntstatus_ok(tctx
, status
, "QueryGroupMember");
6009 torture_assert(tctx
, rids
, "QueryGroupMember did not fill in rids structure");
6011 for (i
=0; i
< rids
->count
; i
++) {
6012 if (rids
->rids
[i
] == rid
) {
6013 found_member
= true;
6017 torture_assert(tctx
, found_member
, "QueryGroupMember did not list newly added member");
6019 status
= dcerpc_samr_DeleteGroupMember(p
, tctx
, &d
);
6020 torture_assert_ntstatus_ok(tctx
, status
, "DeleteGroupMember");
6023 found_member
= false;
6025 status
= dcerpc_samr_QueryGroupMember(p
, tctx
, &q
);
6026 torture_assert_ntstatus_ok(tctx
, status
, "QueryGroupMember");
6027 torture_assert(tctx
, rids
, "QueryGroupMember did not fill in rids structure");
6029 for (i
=0; i
< rids
->count
; i
++) {
6030 if (rids
->rids
[i
] == rid
) {
6031 found_member
= true;
6035 torture_assert(tctx
, !found_member
, "QueryGroupMember does still list removed member");
6037 status
= dcerpc_samr_AddGroupMember(p
, tctx
, &r
);
6038 torture_assert_ntstatus_ok(tctx
, status
, "AddGroupMember");
6044 static bool test_CreateDomainGroup(struct dcerpc_pipe
*p
,
6045 struct torture_context
*tctx
,
6046 struct policy_handle
*domain_handle
,
6047 const char *group_name
,
6048 struct policy_handle
*group_handle
,
6049 struct dom_sid
*domain_sid
,
6053 struct samr_CreateDomainGroup r
;
6055 struct lsa_String name
;
6058 init_lsa_String(&name
, group_name
);
6060 r
.in
.domain_handle
= domain_handle
;
6062 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6063 r
.out
.group_handle
= group_handle
;
6066 torture_comment(tctx
, "Testing CreateDomainGroup(%s)\n", r
.in
.name
->string
);
6068 status
= dcerpc_samr_CreateDomainGroup(p
, tctx
, &r
);
6070 if (dom_sid_equal(domain_sid
, dom_sid_parse_talloc(tctx
, SID_BUILTIN
))) {
6071 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6072 torture_comment(tctx
, "Server correctly refused create of '%s'\n", r
.in
.name
->string
);
6075 torture_warning(tctx
, "Server should have refused create of '%s', got %s instead\n", r
.in
.name
->string
,
6081 if (NT_STATUS_EQUAL(status
, NT_STATUS_GROUP_EXISTS
)) {
6082 if (!test_DeleteGroup_byname(p
, tctx
, domain_handle
, r
.in
.name
->string
)) {
6083 torture_warning(tctx
, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r
.in
.name
->string
,
6087 status
= dcerpc_samr_CreateDomainGroup(p
, tctx
, &r
);
6089 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
6090 if (!test_DeleteUser_byname(p
, tctx
, domain_handle
, r
.in
.name
->string
)) {
6092 torture_warning(tctx
, "CreateDomainGroup failed: Could not delete user %s - %s\n", r
.in
.name
->string
,
6096 status
= dcerpc_samr_CreateDomainGroup(p
, tctx
, &r
);
6098 torture_assert_ntstatus_ok(tctx
, status
, "CreateDomainGroup");
6104 if (!test_AddGroupMember(p
, tctx
, domain_handle
, group_handle
)) {
6105 torture_warning(tctx
, "CreateDomainGroup failed - %s\n", nt_errstr(status
));
6109 if (!test_SetGroupInfo(p
, tctx
, group_handle
)) {
6118 its not totally clear what this does. It seems to accept any sid you like.
6120 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe
*p
,
6121 struct torture_context
*tctx
,
6122 struct policy_handle
*domain_handle
)
6125 struct samr_RemoveMemberFromForeignDomain r
;
6127 r
.in
.domain_handle
= domain_handle
;
6128 r
.in
.sid
= dom_sid_parse_talloc(tctx
, "S-1-5-32-12-34-56-78");
6130 status
= dcerpc_samr_RemoveMemberFromForeignDomain(p
, tctx
, &r
);
6131 torture_assert_ntstatus_ok(tctx
, status
, "RemoveMemberFromForeignDomain");
6136 static bool test_EnumDomainUsers(struct dcerpc_pipe
*p
,
6137 struct torture_context
*tctx
,
6138 struct policy_handle
*domain_handle
,
6139 uint32_t *total_num_entries_p
)
6142 struct samr_EnumDomainUsers r
;
6143 uint32_t resume_handle
= 0;
6144 uint32_t num_entries
= 0;
6145 uint32_t total_num_entries
= 0;
6146 struct samr_SamArray
*sam
;
6148 r
.in
.domain_handle
= domain_handle
;
6149 r
.in
.acct_flags
= 0;
6150 r
.in
.max_size
= (uint32_t)-1;
6151 r
.in
.resume_handle
= &resume_handle
;
6154 r
.out
.num_entries
= &num_entries
;
6155 r
.out
.resume_handle
= &resume_handle
;
6157 torture_comment(tctx
, "Testing EnumDomainUsers\n");
6160 status
= dcerpc_samr_EnumDomainUsers(p
, tctx
, &r
);
6161 if (NT_STATUS_IS_ERR(status
)) {
6162 torture_assert_ntstatus_ok(tctx
, status
,
6163 "failed to enumerate users");
6166 total_num_entries
+= num_entries
;
6167 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
6169 if (total_num_entries_p
) {
6170 *total_num_entries_p
= total_num_entries
;
6176 static bool test_EnumDomainGroups(struct dcerpc_pipe
*p
,
6177 struct torture_context
*tctx
,
6178 struct policy_handle
*domain_handle
,
6179 uint32_t *total_num_entries_p
)
6182 struct samr_EnumDomainGroups r
;
6183 uint32_t resume_handle
= 0;
6184 uint32_t num_entries
= 0;
6185 uint32_t total_num_entries
= 0;
6186 struct samr_SamArray
*sam
;
6188 r
.in
.domain_handle
= domain_handle
;
6189 r
.in
.max_size
= (uint32_t)-1;
6190 r
.in
.resume_handle
= &resume_handle
;
6193 r
.out
.num_entries
= &num_entries
;
6194 r
.out
.resume_handle
= &resume_handle
;
6196 torture_comment(tctx
, "Testing EnumDomainGroups\n");
6199 status
= dcerpc_samr_EnumDomainGroups(p
, tctx
, &r
);
6200 if (NT_STATUS_IS_ERR(status
)) {
6201 torture_assert_ntstatus_ok(tctx
, status
,
6202 "failed to enumerate groups");
6205 total_num_entries
+= num_entries
;
6206 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
6208 if (total_num_entries_p
) {
6209 *total_num_entries_p
= total_num_entries
;
6215 static bool test_EnumDomainAliases(struct dcerpc_pipe
*p
,
6216 struct torture_context
*tctx
,
6217 struct policy_handle
*domain_handle
,
6218 uint32_t *total_num_entries_p
)
6221 struct samr_EnumDomainAliases r
;
6222 uint32_t resume_handle
= 0;
6223 uint32_t num_entries
= 0;
6224 uint32_t total_num_entries
= 0;
6225 struct samr_SamArray
*sam
;
6227 r
.in
.domain_handle
= domain_handle
;
6228 r
.in
.max_size
= (uint32_t)-1;
6229 r
.in
.resume_handle
= &resume_handle
;
6232 r
.out
.num_entries
= &num_entries
;
6233 r
.out
.resume_handle
= &resume_handle
;
6235 torture_comment(tctx
, "Testing EnumDomainAliases\n");
6238 status
= dcerpc_samr_EnumDomainAliases(p
, tctx
, &r
);
6239 if (NT_STATUS_IS_ERR(status
)) {
6240 torture_assert_ntstatus_ok(tctx
, status
,
6241 "failed to enumerate aliases");
6244 total_num_entries
+= num_entries
;
6245 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
6247 if (total_num_entries_p
) {
6248 *total_num_entries_p
= total_num_entries
;
6254 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe
*p
,
6255 struct torture_context
*tctx
,
6256 struct policy_handle
*handle
,
6258 uint32_t *total_num_entries_p
)
6261 struct samr_QueryDisplayInfo r
;
6262 uint32_t total_num_entries
= 0;
6264 r
.in
.domain_handle
= handle
;
6267 r
.in
.max_entries
= (uint32_t)-1;
6268 r
.in
.buf_size
= (uint32_t)-1;
6270 torture_comment(tctx
, "Testing QueryDisplayInfo\n");
6273 uint32_t total_size
;
6274 uint32_t returned_size
;
6275 union samr_DispInfo info
;
6277 r
.out
.total_size
= &total_size
;
6278 r
.out
.returned_size
= &returned_size
;
6281 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &r
);
6282 if (NT_STATUS_IS_ERR(status
)) {
6283 torture_assert_ntstatus_ok(tctx
, status
,
6284 "failed to query displayinfo");
6287 if (*r
.out
.returned_size
== 0) {
6291 switch (r
.in
.level
) {
6293 total_num_entries
+= info
.info1
.count
;
6294 r
.in
.start_idx
+= info
.info1
.entries
[info
.info1
.count
- 1].idx
+ 1;
6297 total_num_entries
+= info
.info2
.count
;
6298 r
.in
.start_idx
+= info
.info2
.entries
[info
.info2
.count
- 1].idx
+ 1;
6301 total_num_entries
+= info
.info3
.count
;
6302 r
.in
.start_idx
+= info
.info3
.entries
[info
.info3
.count
- 1].idx
+ 1;
6305 total_num_entries
+= info
.info4
.count
;
6306 r
.in
.start_idx
+= info
.info4
.entries
[info
.info4
.count
- 1].idx
+ 1;
6309 total_num_entries
+= info
.info5
.count
;
6310 r
.in
.start_idx
+= info
.info5
.entries
[info
.info5
.count
- 1].idx
+ 1;
6316 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
6318 if (total_num_entries_p
) {
6319 *total_num_entries_p
= total_num_entries
;
6325 static bool test_ManyObjects(struct dcerpc_pipe
*p
,
6326 struct torture_context
*tctx
,
6327 struct policy_handle
*domain_handle
,
6328 struct dom_sid
*domain_sid
,
6329 struct torture_samr_context
*ctx
)
6331 uint32_t num_total
= ctx
->num_objects_large_dc
;
6332 uint32_t num_enum
= 0;
6333 uint32_t num_disp
= 0;
6334 uint32_t num_created
= 0;
6335 uint32_t num_anounced
= 0;
6340 struct policy_handle
*handles
= talloc_zero_array(tctx
, struct policy_handle
, num_total
);
6345 struct samr_QueryDomainInfo2 r
;
6346 union samr_DomainInfo
*info
;
6347 r
.in
.domain_handle
= domain_handle
;
6351 status
= dcerpc_samr_QueryDomainInfo2(p
, tctx
, &r
);
6352 torture_assert_ntstatus_ok(tctx
, status
,
6353 "failed to query domain info");
6355 switch (ctx
->choice
) {
6356 case TORTURE_SAMR_MANY_ACCOUNTS
:
6357 num_anounced
= info
->general
.num_users
;
6359 case TORTURE_SAMR_MANY_GROUPS
:
6360 num_anounced
= info
->general
.num_groups
;
6362 case TORTURE_SAMR_MANY_ALIASES
:
6363 num_anounced
= info
->general
.num_aliases
;
6372 for (i
=0; i
< num_total
; i
++) {
6374 const char *name
= NULL
;
6376 switch (ctx
->choice
) {
6377 case TORTURE_SAMR_MANY_ACCOUNTS
:
6378 name
= talloc_asprintf(tctx
, "%s%04d", TEST_ACCOUNT_NAME
, i
);
6379 ret
&= test_CreateUser(p
, tctx
, domain_handle
, name
, &handles
[i
], domain_sid
, 0, NULL
, false);
6381 case TORTURE_SAMR_MANY_GROUPS
:
6382 name
= talloc_asprintf(tctx
, "%s%04d", TEST_GROUPNAME
, i
);
6383 ret
&= test_CreateDomainGroup(p
, tctx
, domain_handle
, name
, &handles
[i
], domain_sid
, false);
6385 case TORTURE_SAMR_MANY_ALIASES
:
6386 name
= talloc_asprintf(tctx
, "%s%04d", TEST_ALIASNAME
, i
);
6387 ret
&= test_CreateAlias(p
, tctx
, domain_handle
, name
, &handles
[i
], domain_sid
, false);
6392 if (!policy_handle_empty(&handles
[i
])) {
6399 switch (ctx
->choice
) {
6400 case TORTURE_SAMR_MANY_ACCOUNTS
:
6401 ret
&= test_EnumDomainUsers(p
, tctx
, domain_handle
, &num_enum
);
6403 case TORTURE_SAMR_MANY_GROUPS
:
6404 ret
&= test_EnumDomainGroups(p
, tctx
, domain_handle
, &num_enum
);
6406 case TORTURE_SAMR_MANY_ALIASES
:
6407 ret
&= test_EnumDomainAliases(p
, tctx
, domain_handle
, &num_enum
);
6415 switch (ctx
->choice
) {
6416 case TORTURE_SAMR_MANY_ACCOUNTS
:
6417 ret
&= test_QueryDisplayInfo_level(p
, tctx
, domain_handle
, 1, &num_disp
);
6419 case TORTURE_SAMR_MANY_GROUPS
:
6420 ret
&= test_QueryDisplayInfo_level(p
, tctx
, domain_handle
, 3, &num_disp
);
6422 case TORTURE_SAMR_MANY_ALIASES
:
6423 /* no aliases in dispinfo */
6429 /* close or delete */
6431 for (i
=0; i
< num_total
; i
++) {
6433 if (policy_handle_empty(&handles
[i
])) {
6437 if (torture_setting_bool(tctx
, "samba3", false)) {
6438 ret
&= test_samr_handle_Close(p
, tctx
, &handles
[i
]);
6440 switch (ctx
->choice
) {
6441 case TORTURE_SAMR_MANY_ACCOUNTS
:
6442 ret
&= test_DeleteUser(p
, tctx
, &handles
[i
]);
6444 case TORTURE_SAMR_MANY_GROUPS
:
6445 ret
&= test_DeleteDomainGroup(p
, tctx
, &handles
[i
]);
6447 case TORTURE_SAMR_MANY_ALIASES
:
6448 ret
&= test_DeleteAlias(p
, tctx
, &handles
[i
]);
6456 talloc_free(handles
);
6458 if (ctx
->choice
== TORTURE_SAMR_MANY_ACCOUNTS
&& num_enum
!= num_anounced
+ num_created
) {
6459 torture_comment(tctx
,
6460 "unexpected number of results (%u) returned in enum call, expected %u\n",
6461 num_enum
, num_anounced
+ num_created
);
6463 torture_comment(tctx
,
6464 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
6465 num_disp
, num_anounced
+ num_created
);
6470 static bool test_Connect(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
6471 struct policy_handle
*handle
);
6473 static bool test_OpenDomain(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
6474 struct torture_samr_context
*ctx
, struct dom_sid
*sid
)
6477 struct samr_OpenDomain r
;
6478 struct policy_handle domain_handle
;
6479 struct policy_handle alias_handle
;
6480 struct policy_handle user_handle
;
6481 struct policy_handle group_handle
;
6484 ZERO_STRUCT(alias_handle
);
6485 ZERO_STRUCT(user_handle
);
6486 ZERO_STRUCT(group_handle
);
6487 ZERO_STRUCT(domain_handle
);
6489 torture_comment(tctx
, "Testing OpenDomain of %s\n", dom_sid_string(tctx
, sid
));
6491 r
.in
.connect_handle
= &ctx
->handle
;
6492 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6494 r
.out
.domain_handle
= &domain_handle
;
6496 status
= dcerpc_samr_OpenDomain(p
, tctx
, &r
);
6497 torture_assert_ntstatus_ok(tctx
, status
, "OpenDomain");
6499 /* run the domain tests with the main handle closed - this tests
6500 the servers reference counting */
6501 torture_assert(tctx
, test_samr_handle_Close(p
, tctx
, &ctx
->handle
), "Failed to close SAMR handle");
6503 switch (ctx
->choice
) {
6504 case TORTURE_SAMR_PASSWORDS
:
6505 case TORTURE_SAMR_USER_PRIVILEGES
:
6506 if (!torture_setting_bool(tctx
, "samba3", false)) {
6507 ret
&= test_CreateUser2(p
, tctx
, &domain_handle
, sid
, ctx
->choice
, NULL
);
6509 ret
&= test_CreateUser(p
, tctx
, &domain_handle
, TEST_ACCOUNT_NAME
, &user_handle
, sid
, ctx
->choice
, NULL
, true);
6511 torture_warning(tctx
, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx
, sid
));
6514 case TORTURE_SAMR_USER_ATTRIBUTES
:
6515 if (!torture_setting_bool(tctx
, "samba3", false)) {
6516 ret
&= test_CreateUser2(p
, tctx
, &domain_handle
, sid
, ctx
->choice
, NULL
);
6518 ret
&= test_CreateUser(p
, tctx
, &domain_handle
, TEST_ACCOUNT_NAME
, &user_handle
, sid
, ctx
->choice
, NULL
, true);
6519 /* This test needs 'complex' users to validate */
6520 ret
&= test_QueryDisplayInfo(p
, tctx
, &domain_handle
);
6522 torture_warning(tctx
, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx
, sid
));
6525 case TORTURE_SAMR_PASSWORDS_PWDLASTSET
:
6526 if (!torture_setting_bool(tctx
, "samba3", false)) {
6527 ret
&= test_CreateUser2(p
, tctx
, &domain_handle
, sid
, ctx
->choice
, ctx
->machine_credentials
);
6529 ret
&= test_CreateUser(p
, tctx
, &domain_handle
, TEST_ACCOUNT_NAME
, &user_handle
, sid
, ctx
->choice
, ctx
->machine_credentials
, true);
6531 torture_warning(tctx
, "Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx
, sid
));
6534 case TORTURE_SAMR_MANY_ACCOUNTS
:
6535 case TORTURE_SAMR_MANY_GROUPS
:
6536 case TORTURE_SAMR_MANY_ALIASES
:
6537 ret
&= test_ManyObjects(p
, tctx
, &domain_handle
, sid
, ctx
);
6539 torture_warning(tctx
, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx
, sid
));
6542 case TORTURE_SAMR_OTHER
:
6543 ret
&= test_CreateUser(p
, tctx
, &domain_handle
, TEST_ACCOUNT_NAME
, &user_handle
, sid
, ctx
->choice
, NULL
, true);
6545 torture_warning(tctx
, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx
, sid
));
6547 if (!torture_setting_bool(tctx
, "samba3", false)) {
6548 ret
&= test_QuerySecurity(p
, tctx
, &domain_handle
);
6550 ret
&= test_RemoveMemberFromForeignDomain(p
, tctx
, &domain_handle
);
6551 ret
&= test_CreateAlias(p
, tctx
, &domain_handle
, TEST_ALIASNAME
, &alias_handle
, sid
, true);
6552 ret
&= test_CreateDomainGroup(p
, tctx
, &domain_handle
, TEST_GROUPNAME
, &group_handle
, sid
, true);
6553 ret
&= test_GetAliasMembership(p
, tctx
, &domain_handle
);
6554 ret
&= test_QueryDomainInfo(p
, tctx
, &domain_handle
);
6555 ret
&= test_QueryDomainInfo2(p
, tctx
, &domain_handle
);
6556 ret
&= test_EnumDomainUsers_all(p
, tctx
, &domain_handle
);
6557 ret
&= test_EnumDomainUsers_async(p
, tctx
, &domain_handle
);
6558 ret
&= test_EnumDomainGroups_all(p
, tctx
, &domain_handle
);
6559 ret
&= test_EnumDomainAliases_all(p
, tctx
, &domain_handle
);
6560 ret
&= test_QueryDisplayInfo2(p
, tctx
, &domain_handle
);
6561 ret
&= test_QueryDisplayInfo3(p
, tctx
, &domain_handle
);
6562 ret
&= test_QueryDisplayInfo_continue(p
, tctx
, &domain_handle
);
6564 if (torture_setting_bool(tctx
, "samba4", false)) {
6565 torture_comment(tctx
, "skipping GetDisplayEnumerationIndex test against Samba4\n");
6567 ret
&= test_GetDisplayEnumerationIndex(p
, tctx
, &domain_handle
);
6568 ret
&= test_GetDisplayEnumerationIndex2(p
, tctx
, &domain_handle
);
6570 ret
&= test_GroupList(p
, tctx
, &domain_handle
);
6571 ret
&= test_TestPrivateFunctionsDomain(p
, tctx
, &domain_handle
);
6572 ret
&= test_RidToSid(p
, tctx
, sid
, &domain_handle
);
6573 ret
&= test_GetBootKeyInformation(p
, tctx
, &domain_handle
);
6575 torture_comment(tctx
, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx
, sid
));
6580 if (!policy_handle_empty(&user_handle
) &&
6581 !test_DeleteUser(p
, tctx
, &user_handle
)) {
6585 if (!policy_handle_empty(&alias_handle
) &&
6586 !test_DeleteAlias(p
, tctx
, &alias_handle
)) {
6590 if (!policy_handle_empty(&group_handle
) &&
6591 !test_DeleteDomainGroup(p
, tctx
, &group_handle
)) {
6595 torture_assert(tctx
, test_samr_handle_Close(p
, tctx
, &domain_handle
), "Failed to close SAMR domain handle");
6597 torture_assert(tctx
, test_Connect(p
, tctx
, &ctx
->handle
), "Faile to re-connect SAMR handle");
6598 /* reconnect the main handle */
6601 torture_warning(tctx
, "Testing domain %s failed!\n", dom_sid_string(tctx
, sid
));
6607 static bool test_LookupDomain(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
6608 struct torture_samr_context
*ctx
, const char *domain
)
6611 struct samr_LookupDomain r
;
6612 struct dom_sid2
*sid
= NULL
;
6613 struct lsa_String n1
;
6614 struct lsa_String n2
;
6617 torture_comment(tctx
, "Testing LookupDomain(%s)\n", domain
);
6619 /* check for correct error codes */
6620 r
.in
.connect_handle
= &ctx
->handle
;
6621 r
.in
.domain_name
= &n2
;
6625 status
= dcerpc_samr_LookupDomain(p
, tctx
, &r
);
6626 torture_assert_ntstatus_equal(tctx
, NT_STATUS_INVALID_PARAMETER
, status
, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
6628 init_lsa_String(&n2
, "xxNODOMAINxx");
6630 status
= dcerpc_samr_LookupDomain(p
, tctx
, &r
);
6631 torture_assert_ntstatus_equal(tctx
, NT_STATUS_NO_SUCH_DOMAIN
, status
, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
6633 r
.in
.connect_handle
= &ctx
->handle
;
6635 init_lsa_String(&n1
, domain
);
6636 r
.in
.domain_name
= &n1
;
6638 status
= dcerpc_samr_LookupDomain(p
, tctx
, &r
);
6639 torture_assert_ntstatus_ok(tctx
, status
, "LookupDomain");
6641 if (!test_GetDomPwInfo(p
, tctx
, &n1
)) {
6645 if (!test_OpenDomain(p
, tctx
, ctx
, *r
.out
.sid
)) {
6653 static bool test_EnumDomains(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
6654 struct torture_samr_context
*ctx
)
6657 struct samr_EnumDomains r
;
6658 uint32_t resume_handle
= 0;
6659 uint32_t num_entries
= 0;
6660 struct samr_SamArray
*sam
= NULL
;
6664 r
.in
.connect_handle
= &ctx
->handle
;
6665 r
.in
.resume_handle
= &resume_handle
;
6666 r
.in
.buf_size
= (uint32_t)-1;
6667 r
.out
.resume_handle
= &resume_handle
;
6668 r
.out
.num_entries
= &num_entries
;
6671 status
= dcerpc_samr_EnumDomains(p
, tctx
, &r
);
6672 torture_assert_ntstatus_ok(tctx
, status
, "EnumDomains");
6678 for (i
=0;i
<sam
->count
;i
++) {
6679 if (!test_LookupDomain(p
, tctx
, ctx
,
6680 sam
->entries
[i
].name
.string
)) {
6685 status
= dcerpc_samr_EnumDomains(p
, tctx
, &r
);
6686 torture_assert_ntstatus_ok(tctx
, status
, "EnumDomains");
6692 static bool test_Connect(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
6693 struct policy_handle
*handle
)
6696 struct samr_Connect r
;
6697 struct samr_Connect2 r2
;
6698 struct samr_Connect3 r3
;
6699 struct samr_Connect4 r4
;
6700 struct samr_Connect5 r5
;
6701 union samr_ConnectInfo info
;
6702 struct policy_handle h
;
6703 uint32_t level_out
= 0;
6704 bool ret
= true, got_handle
= false;
6706 torture_comment(tctx
, "testing samr_Connect\n");
6708 r
.in
.system_name
= 0;
6709 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6710 r
.out
.connect_handle
= &h
;
6712 status
= dcerpc_samr_Connect(p
, tctx
, &r
);
6713 if (!NT_STATUS_IS_OK(status
)) {
6714 torture_comment(tctx
, "Connect failed - %s\n", nt_errstr(status
));
6721 torture_comment(tctx
, "testing samr_Connect2\n");
6723 r2
.in
.system_name
= NULL
;
6724 r2
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6725 r2
.out
.connect_handle
= &h
;
6727 status
= dcerpc_samr_Connect2(p
, tctx
, &r2
);
6728 if (!NT_STATUS_IS_OK(status
)) {
6729 torture_comment(tctx
, "Connect2 failed - %s\n", nt_errstr(status
));
6733 test_samr_handle_Close(p
, tctx
, handle
);
6739 torture_comment(tctx
, "testing samr_Connect3\n");
6741 r3
.in
.system_name
= NULL
;
6743 r3
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6744 r3
.out
.connect_handle
= &h
;
6746 status
= dcerpc_samr_Connect3(p
, tctx
, &r3
);
6747 if (!NT_STATUS_IS_OK(status
)) {
6748 torture_warning(tctx
, "Connect3 failed - %s\n", nt_errstr(status
));
6752 test_samr_handle_Close(p
, tctx
, handle
);
6758 torture_comment(tctx
, "testing samr_Connect4\n");
6760 r4
.in
.system_name
= "";
6761 r4
.in
.client_version
= 0;
6762 r4
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6763 r4
.out
.connect_handle
= &h
;
6765 status
= dcerpc_samr_Connect4(p
, tctx
, &r4
);
6766 if (!NT_STATUS_IS_OK(status
)) {
6767 torture_warning(tctx
, "Connect4 failed - %s\n", nt_errstr(status
));
6771 test_samr_handle_Close(p
, tctx
, handle
);
6777 torture_comment(tctx
, "testing samr_Connect5\n");
6779 info
.info1
.client_version
= 0;
6780 info
.info1
.unknown2
= 0;
6782 r5
.in
.system_name
= "";
6783 r5
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6785 r5
.out
.level_out
= &level_out
;
6786 r5
.in
.info_in
= &info
;
6787 r5
.out
.info_out
= &info
;
6788 r5
.out
.connect_handle
= &h
;
6790 status
= dcerpc_samr_Connect5(p
, tctx
, &r5
);
6791 if (!NT_STATUS_IS_OK(status
)) {
6792 torture_warning(tctx
, "Connect5 failed - %s\n", nt_errstr(status
));
6796 test_samr_handle_Close(p
, tctx
, handle
);
6806 bool torture_rpc_samr(struct torture_context
*torture
)
6809 struct dcerpc_pipe
*p
;
6811 struct torture_samr_context
*ctx
;
6813 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6814 if (!NT_STATUS_IS_OK(status
)) {
6818 ctx
= talloc_zero(torture
, struct torture_samr_context
);
6820 ctx
->choice
= TORTURE_SAMR_OTHER
;
6822 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
6824 if (!torture_setting_bool(torture
, "samba3", false)) {
6825 ret
&= test_QuerySecurity(p
, torture
, &ctx
->handle
);
6828 ret
&= test_EnumDomains(p
, torture
, ctx
);
6830 ret
&= test_SetDsrmPassword(p
, torture
, &ctx
->handle
);
6832 ret
&= test_Shutdown(p
, torture
, &ctx
->handle
);
6834 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
6840 bool torture_rpc_samr_users(struct torture_context
*torture
)
6843 struct dcerpc_pipe
*p
;
6845 struct torture_samr_context
*ctx
;
6847 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6848 if (!NT_STATUS_IS_OK(status
)) {
6852 ctx
= talloc_zero(torture
, struct torture_samr_context
);
6854 ctx
->choice
= TORTURE_SAMR_USER_ATTRIBUTES
;
6856 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
6858 if (!torture_setting_bool(torture
, "samba3", false)) {
6859 ret
&= test_QuerySecurity(p
, torture
, &ctx
->handle
);
6862 ret
&= test_EnumDomains(p
, torture
, ctx
);
6864 ret
&= test_SetDsrmPassword(p
, torture
, &ctx
->handle
);
6866 ret
&= test_Shutdown(p
, torture
, &ctx
->handle
);
6868 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
6874 bool torture_rpc_samr_passwords(struct torture_context
*torture
)
6877 struct dcerpc_pipe
*p
;
6879 struct torture_samr_context
*ctx
;
6881 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6882 if (!NT_STATUS_IS_OK(status
)) {
6886 ctx
= talloc_zero(torture
, struct torture_samr_context
);
6888 ctx
->choice
= TORTURE_SAMR_PASSWORDS
;
6890 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
6892 ret
&= test_EnumDomains(p
, torture
, ctx
);
6894 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
6899 static bool torture_rpc_samr_pwdlastset(struct torture_context
*torture
,
6900 struct dcerpc_pipe
*p2
,
6901 struct cli_credentials
*machine_credentials
)
6904 struct dcerpc_pipe
*p
;
6906 struct torture_samr_context
*ctx
;
6908 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6909 if (!NT_STATUS_IS_OK(status
)) {
6913 ctx
= talloc_zero(torture
, struct torture_samr_context
);
6915 ctx
->choice
= TORTURE_SAMR_PASSWORDS_PWDLASTSET
;
6916 ctx
->machine_credentials
= machine_credentials
;
6918 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
6920 ret
&= test_EnumDomains(p
, torture
, ctx
);
6922 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
6927 struct torture_suite
*torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX
*mem_ctx
)
6929 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-PASSWORDS-PWDLASTSET");
6930 struct torture_rpc_tcase
*tcase
;
6932 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "samr",
6934 TEST_ACCOUNT_NAME_PWD
);
6936 torture_rpc_tcase_add_test_creds(tcase
, "pwdLastSet",
6937 torture_rpc_samr_pwdlastset
);
6942 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context
*torture
,
6943 struct dcerpc_pipe
*p2
,
6944 struct cli_credentials
*machine_credentials
)
6947 struct dcerpc_pipe
*p
;
6949 struct torture_samr_context
*ctx
;
6951 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6952 if (!NT_STATUS_IS_OK(status
)) {
6956 ctx
= talloc_zero(torture
, struct torture_samr_context
);
6958 ctx
->choice
= TORTURE_SAMR_USER_PRIVILEGES
;
6959 ctx
->machine_credentials
= machine_credentials
;
6961 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
6963 ret
&= test_EnumDomains(p
, torture
, ctx
);
6965 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
6970 struct torture_suite
*torture_rpc_samr_user_privileges(TALLOC_CTX
*mem_ctx
)
6972 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-USERS-PRIVILEGES");
6973 struct torture_rpc_tcase
*tcase
;
6975 tcase
= torture_suite_add_machine_bdc_rpc_iface_tcase(suite
, "samr",
6977 TEST_ACCOUNT_NAME_PWD
);
6979 torture_rpc_tcase_add_test_creds(tcase
, "delete_privileged_user",
6980 torture_rpc_samr_users_privileges_delete_user
);
6985 static bool torture_rpc_samr_many_accounts(struct torture_context
*torture
,
6986 struct dcerpc_pipe
*p2
,
6990 struct dcerpc_pipe
*p
;
6992 struct torture_samr_context
*ctx
=
6993 talloc_get_type_abort(data
, struct torture_samr_context
);
6995 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
6996 if (!NT_STATUS_IS_OK(status
)) {
7000 ctx
->choice
= TORTURE_SAMR_MANY_ACCOUNTS
;
7001 ctx
->num_objects_large_dc
= torture_setting_int(torture
, "large_dc",
7002 ctx
->num_objects_large_dc
);
7004 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
7006 ret
&= test_EnumDomains(p
, torture
, ctx
);
7008 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
7013 static bool torture_rpc_samr_many_groups(struct torture_context
*torture
,
7014 struct dcerpc_pipe
*p2
,
7018 struct dcerpc_pipe
*p
;
7020 struct torture_samr_context
*ctx
=
7021 talloc_get_type_abort(data
, struct torture_samr_context
);
7023 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
7024 if (!NT_STATUS_IS_OK(status
)) {
7028 ctx
->choice
= TORTURE_SAMR_MANY_GROUPS
;
7029 ctx
->num_objects_large_dc
= torture_setting_int(torture
, "large_dc",
7030 ctx
->num_objects_large_dc
);
7032 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
7034 ret
&= test_EnumDomains(p
, torture
, ctx
);
7036 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
7041 static bool torture_rpc_samr_many_aliases(struct torture_context
*torture
,
7042 struct dcerpc_pipe
*p2
,
7046 struct dcerpc_pipe
*p
;
7048 struct torture_samr_context
*ctx
=
7049 talloc_get_type_abort(data
, struct torture_samr_context
);
7051 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
7052 if (!NT_STATUS_IS_OK(status
)) {
7056 ctx
->choice
= TORTURE_SAMR_MANY_ALIASES
;
7057 ctx
->num_objects_large_dc
= torture_setting_int(torture
, "large_dc",
7058 ctx
->num_objects_large_dc
);
7060 ret
&= test_Connect(p
, torture
, &ctx
->handle
);
7062 ret
&= test_EnumDomains(p
, torture
, ctx
);
7064 ret
&= test_samr_handle_Close(p
, torture
, &ctx
->handle
);
7069 struct torture_suite
*torture_rpc_samr_large_dc(TALLOC_CTX
*mem_ctx
)
7071 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-LARGE-DC");
7072 struct torture_rpc_tcase
*tcase
;
7073 struct torture_samr_context
*ctx
;
7075 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "samr", &ndr_table_samr
);
7077 ctx
= talloc_zero(suite
, struct torture_samr_context
);
7078 ctx
->num_objects_large_dc
= 150;
7080 torture_rpc_tcase_add_test_ex(tcase
, "many_aliases",
7081 torture_rpc_samr_many_aliases
, ctx
);
7082 torture_rpc_tcase_add_test_ex(tcase
, "many_groups",
7083 torture_rpc_samr_many_groups
, ctx
);
7084 torture_rpc_tcase_add_test_ex(tcase
, "many_accounts",
7085 torture_rpc_samr_many_accounts
, ctx
);