s4-smbtorture: add torture_samr_context to carry some RPC-SAMR-X specifics.
[Samba.git] / source4 / torture / rpc / samr.c
blob177e41ff3dbd05a93fd61e5e5014a7791cf77c35
1 /*
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/>.
23 #include "includes.h"
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"
37 #include <unistd.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,
51 TORTURE_SAMR_OTHER,
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)
83 string->string = s;
86 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
88 string->string = 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)
101 NTSTATUS status;
102 struct samr_Close r;
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");
110 return true;
113 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
114 struct policy_handle *handle)
116 NTSTATUS status;
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");
121 return true;
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");
131 return true;
134 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
135 struct policy_handle *handle)
137 NTSTATUS status;
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");
150 r.in.name = &string;
151 r.in.unknown = 0;
152 r.in.hash = &hash;
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");
159 return true;
163 static bool test_QuerySecurity(struct dcerpc_pipe *p,
164 struct torture_context *tctx,
165 struct policy_handle *handle)
167 NTSTATUS status;
168 struct samr_QuerySecurity r;
169 struct samr_SetSecurity s;
170 struct sec_desc_buf *sdbuf = NULL;
172 r.in.handle = handle;
173 r.in.sec_info = 7;
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;
182 s.in.sec_info = 7;
183 s.in.sdbuf = sdbuf;
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");
195 return true;
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)
203 NTSTATUS status;
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;
210 bool ret = true;
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;
223 s.in.info = &u;
225 s2.in.user_handle = handle;
226 s2.in.info = &u;
228 q.in.user_handle = handle;
229 q.out.info = &info;
230 q0 = q;
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__); \
237 ret = false; \
238 break; \
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__); \
245 ret = false; \
246 break; \
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__); \
253 ret = false; \
254 break; \
257 #define INT_EQUAL(i1, i2, field) \
258 if (i1 != i2) { \
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__); \
261 ret = false; \
262 break; \
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); \
267 q.in.level = lvl1; \
268 TESTCALL(QueryUserInfo, q) \
269 s.in.level = lvl1; \
270 s2.in.level = lvl1; \
271 u = *info; \
272 if (lvl1 == 21) { \
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); \
281 u = *info; \
282 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
283 q.in.level = lvl2; \
284 TESTCALL(QueryUserInfo, q) \
285 u = *info; \
286 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
287 } while (0)
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); \
291 q.in.level = lvl1; \
292 TESTCALL(QueryUserInfo, q) \
293 s.in.level = lvl1; \
294 s2.in.level = lvl1; \
295 u = *info; \
296 if (lvl1 == 21) { \
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); \
305 u = *info; \
306 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
307 q.in.level = lvl2; \
308 TESTCALL(QueryUserInfo, q) \
309 u = *info; \
310 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
311 } while (0)
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); \
315 q.in.level = lvl1; \
316 TESTCALL(QueryUserInfo, q) \
317 s.in.level = lvl1; \
318 s2.in.level = lvl1; \
319 u = *info; \
320 if (lvl1 == 21) { \
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); \
334 u = *info; \
335 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
336 q.in.level = lvl2; \
337 TESTCALL(QueryUserInfo, q) \
338 u = *info; \
339 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
340 } while (0)
342 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
343 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
344 } while (0)
346 q0.in.level = 12;
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",
352 SAMR_FIELD_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);
473 } else {
474 /* Samba 3 can only store seconds / time_t in passdb - gd */
475 NTTIME nt;
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),
519 #if 0
520 /* Removing the 'disabled' flag doesn't stick - check this */
521 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
522 (base_acct_flags),
523 (base_acct_flags | ACB_DISABLED | user_extra_flags),
525 #endif
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);
555 #if 0
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);
562 #endif
564 return ret;
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);
574 return s;
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);
581 return s;
586 generate a random password for password change tests
588 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
590 int i;
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;
600 return password;
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);
610 return s;
613 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
614 struct policy_handle *handle, char **password)
616 NTSTATUS status;
617 struct samr_SetUserInfo s;
618 union samr_UserInfo u;
619 bool ret = true;
620 DATA_BLOB session_key;
621 char *newpass;
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;
635 s.in.info = &u;
636 s.in.level = 24;
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));
645 return false;
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));
656 ret = false;
657 } else {
658 *password = newpass;
661 return ret;
665 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
666 struct policy_handle *handle, uint32_t fields_present,
667 char **password)
669 NTSTATUS status;
670 struct samr_SetUserInfo s;
671 union samr_UserInfo u;
672 bool ret = true;
673 DATA_BLOB session_key;
674 char *newpass;
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;
688 s.in.info = &u;
689 s.in.level = 23;
691 ZERO_STRUCT(u);
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));
701 return false;
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));
712 ret = false;
713 } else {
714 *password = newpass;
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));
723 return false;
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));
736 ret = false;
739 return ret;
743 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
744 struct policy_handle *handle, bool makeshort,
745 char **password)
747 NTSTATUS status;
748 struct samr_SetUserInfo s;
749 union samr_UserInfo u;
750 bool ret = true;
751 DATA_BLOB session_key;
752 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
753 uint8_t confounder[16];
754 char *newpass;
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);
768 } else {
769 newpass = samr_rand_pass(tctx, policy_min_pw_len);
772 s.in.user_handle = handle;
773 s.in.info = &u;
774 s.in.level = 26;
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));
783 return false;
786 generate_random_buffer((uint8_t *)confounder, 16);
788 MD5Init(&ctx);
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));
802 ret = false;
803 } else {
804 *password = newpass;
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));
819 ret = false;
820 } else {
821 *password = newpass;
824 return ret;
827 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
828 struct policy_handle *handle, uint32_t fields_present,
829 char **password)
831 NTSTATUS status;
832 struct samr_SetUserInfo s;
833 union samr_UserInfo u;
834 bool ret = true;
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];
839 char *newpass;
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;
853 s.in.info = &u;
854 s.in.level = 25;
856 ZERO_STRUCT(u);
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));
866 return false;
869 generate_random_buffer((uint8_t *)confounder, 16);
871 MD5Init(&ctx);
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));
885 ret = false;
886 } else {
887 *password = newpass;
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));
902 ret = false;
905 return ret;
908 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
909 struct policy_handle *handle, char **password)
911 NTSTATUS status;
912 struct samr_SetUserInfo s;
913 union samr_UserInfo u;
914 bool ret = true;
915 DATA_BLOB session_key;
916 char *newpass;
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;
932 s.in.info = &u;
933 s.in.level = 18;
935 ZERO_STRUCT(u);
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));
947 return false;
951 DATA_BLOB in,out;
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);
958 DATA_BLOB in,out;
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));
971 ret = false;
972 } else {
973 *password = newpass;
976 return ret;
979 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
980 struct policy_handle *handle, uint32_t fields_present,
981 char **password)
983 NTSTATUS status;
984 struct samr_SetUserInfo s;
985 union samr_UserInfo u;
986 bool ret = true;
987 DATA_BLOB session_key;
988 char *newpass;
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;
1004 s.in.info = &u;
1005 s.in.level = 21;
1007 E_md4hash(newpass, nt_hash);
1008 E_deshash(newpass, lm_hash);
1010 ZERO_STRUCT(u);
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));
1032 return false;
1035 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1036 DATA_BLOB in,out;
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) {
1045 DATA_BLOB in,out;
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));
1059 ret = false;
1060 } else {
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));
1074 ret = false;
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));
1087 ret = false;
1091 return ret;
1094 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1095 struct torture_context *tctx,
1096 struct policy_handle *handle,
1097 uint16_t level,
1098 uint32_t fields_present,
1099 char **password, uint8_t password_expired,
1100 bool use_setinfo2,
1101 bool *matched_expected_error)
1103 NTSTATUS status;
1104 NTSTATUS expected_error = NT_STATUS_OK;
1105 struct samr_SetUserInfo s;
1106 struct samr_SetUserInfo2 s2;
1107 union samr_UserInfo u;
1108 bool ret = true;
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];
1113 char *newpass;
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);
1129 if (use_setinfo2) {
1130 s2.in.user_handle = handle;
1131 s2.in.info = &u;
1132 s2.in.level = level;
1133 } else {
1134 s.in.user_handle = handle;
1135 s.in.info = &u;
1136 s.in.level = level;
1139 if (fields_present & SAMR_FIELD_COMMENT) {
1140 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1143 ZERO_STRUCT(u);
1145 switch (level) {
1146 case 18:
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);
1157 break;
1158 case 21:
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;
1180 break;
1181 case 23:
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);
1188 break;
1189 case 24:
1190 u.info24.password_expired = password_expired;
1192 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1194 break;
1195 case 25:
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);
1202 break;
1203 case 26:
1204 u.info26.password_expired = password_expired;
1206 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1208 break;
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));
1215 return false;
1218 generate_random_buffer((uint8_t *)confounder, 16);
1220 MD5Init(&ctx);
1221 MD5Update(&ctx, confounder, 16);
1222 MD5Update(&ctx, session_key.data, session_key.length);
1223 MD5Final(confounded_session_key.data, &ctx);
1225 switch (level) {
1226 case 18:
1228 DATA_BLOB in,out;
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);
1235 DATA_BLOB in,out;
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);
1242 break;
1243 case 21:
1244 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1245 DATA_BLOB in,out;
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) {
1253 DATA_BLOB in,out;
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;
1260 break;
1261 case 23:
1262 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1263 break;
1264 case 24:
1265 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1266 break;
1267 case 25:
1268 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1269 memcpy(&u.info25.password.data[516], confounder, 16);
1270 break;
1271 case 26:
1272 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1273 memcpy(&u.info26.password.data[516], confounder, 16);
1274 break;
1277 if (use_setinfo2) {
1278 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1279 } else {
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)) {
1293 if (use_setinfo2) {
1294 torture_assert_ntstatus_equal(tctx,
1295 s2.out.result,
1296 expected_error, "SetUserInfo2 failed");
1297 } else {
1298 torture_assert_ntstatus_equal(tctx,
1299 s.out.result,
1300 expected_error, "SetUserInfo failed");
1302 *matched_expected_error = true;
1303 return 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));
1309 ret = false;
1310 } else {
1311 *password = newpass;
1314 return ret;
1317 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1318 struct policy_handle *handle)
1320 NTSTATUS status;
1321 struct samr_SetAliasInfo r;
1322 struct samr_QueryAliasInfo q;
1323 union samr_AliasInfo *info;
1324 uint16_t levels[] = {2, 3};
1325 int i;
1326 bool ret = true;
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));
1349 ret = false;
1352 q.in.alias_handle = handle;
1353 q.in.level = levels[i];
1354 q.out.info = &info;
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));
1360 ret = false;
1364 return ret;
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;
1372 NTSTATUS status;
1374 torture_comment(tctx, "testing GetGroupsForUser\n");
1376 r.in.user_handle = user_handle;
1377 r.out.rids = &rids;
1379 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1380 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1382 return true;
1386 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1387 struct lsa_String *domain_name)
1389 NTSTATUS status;
1390 struct samr_GetDomPwInfo r;
1391 struct samr_PwInfo info;
1393 r.in.domain_name = domain_name;
1394 r.out.info = &info;
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");
1419 return true;
1422 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1423 struct policy_handle *handle)
1425 NTSTATUS status;
1426 struct samr_GetUserPwInfo r;
1427 struct samr_PwInfo info;
1429 torture_comment(tctx, "Testing GetUserPwInfo\n");
1431 r.in.user_handle = handle;
1432 r.out.info = &info;
1434 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1435 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1437 return true;
1440 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1441 struct policy_handle *domain_handle, const char *name,
1442 uint32_t *rid)
1444 NTSTATUS status;
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;
1452 n.in.num_names = 1;
1453 n.in.names = sname;
1454 n.out.rids = &rids;
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];
1459 } else {
1460 return status;
1463 init_lsa_String(&sname[1], "xxNONAMExx");
1464 n.in.num_names = 2;
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;
1471 return status;
1474 n.in.num_names = 0;
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));
1478 return status;
1481 init_lsa_String(&sname[0], "xxNONAMExx");
1482 n.in.num_names = 1;
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;
1489 return status;
1492 init_lsa_String(&sname[0], "xxNONAMExx");
1493 init_lsa_String(&sname[1], "xxNONAME2xx");
1494 n.in.num_names = 2;
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;
1501 return status;
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)
1512 NTSTATUS status;
1513 struct samr_OpenUser r;
1514 uint32_t rid;
1516 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 return status;
1521 r.in.domain_handle = domain_handle;
1522 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1523 r.in.rid = rid;
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));
1530 return status;
1533 #if 0
1534 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1535 struct torture_context *tctx,
1536 struct policy_handle *handle)
1538 NTSTATUS status;
1539 struct samr_ChangePasswordUser r;
1540 bool ret = true;
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)) {
1550 return false;
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));
1585 ret = false;
1588 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1589 ret = false;
1592 return ret;
1594 #endif
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)
1600 NTSTATUS status;
1601 struct samr_ChangePasswordUser r;
1602 bool ret = true;
1603 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1604 struct policy_handle user_handle;
1605 char *oldpass;
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;
1610 char *newpass;
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)) {
1617 return false;
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 */
1650 hash1.hash[0]++;
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 */
1666 hash1.hash[0]--;
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 */
1673 hash3.hash[0]--;
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 */
1687 hash3.hash[0]--;
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 */
1700 hash6.hash[0]++;
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));
1706 ret = false;
1709 /* Unbreak the LM cross */
1710 hash6.hash[0]--;
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 */
1721 hash5.hash[0]++;
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));
1729 ret = false;
1732 /* Unbreak the NT cross */
1733 hash5.hash[0]--;
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)) {
1758 changed = true;
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));
1762 ret = false;
1765 oldpass = newpass;
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)) {
1796 changed = true;
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));
1800 ret = false;
1803 oldpass = newpass;
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));
1837 ret = false;
1838 } else {
1839 changed = true;
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;
1855 if (changed) {
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));
1861 ret = false;
1866 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1867 ret = false;
1870 return ret;
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)
1878 NTSTATUS status;
1879 struct samr_OemChangePasswordUser2 r;
1880 bool ret = true;
1881 struct samr_Password lm_verifier;
1882 struct samr_CryptPassword lm_pass;
1883 struct lsa_AsciiString server, account, account_bad;
1884 char *oldpass;
1885 char *newpass;
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",
1935 nt_errstr(status));
1936 ret = false;
1939 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1940 /* Break the old password */
1941 old_lm_hash[0]++;
1942 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1943 /* unbreak it for the next operation */
1944 old_lm_hash[0]--;
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",
1957 nt_errstr(status));
1958 ret = false;
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;
1967 r.in.hash = NULL;
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",
1974 nt_errstr(status));
1975 ret = false;
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",
1986 nt_errstr(status));
1987 ret = false;
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",
2000 nt_errstr(status));
2001 ret = false;
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",
2014 nt_errstr(status));
2015 ret = false;
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));
2035 ret = false;
2036 } else {
2037 *password = newpass;
2040 return ret;
2044 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2045 const char *acct_name,
2046 char **password,
2047 char *newpass, bool allow_password_restriction)
2049 NTSTATUS status;
2050 struct samr_ChangePasswordUser2 r;
2051 bool ret = true;
2052 struct lsa_String server, account;
2053 struct samr_CryptPassword nt_pass, lm_pass;
2054 struct samr_Password nt_verifier, lm_verifier;
2055 char *oldpass;
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;
2074 if (!newpass) {
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;
2105 r.in.lm_change = 1;
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));
2114 ret = false;
2115 } else {
2116 *password = newpass;
2119 return ret;
2123 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2124 const char *account_string,
2125 int policy_min_pw_len,
2126 char **password,
2127 const char *newpass,
2128 NTTIME last_password_change,
2129 bool handle_reject_reason)
2131 NTSTATUS status;
2132 struct samr_ChangePasswordUser3 r;
2133 bool ret = true;
2134 struct lsa_String server, account, account_bad;
2135 struct samr_CryptPassword nt_pass, lm_pass;
2136 struct samr_Password nt_verifier, lm_verifier;
2137 char *oldpass;
2138 uint8_t old_nt_hash[16], new_nt_hash[16];
2139 uint8_t old_lm_hash[16], new_lm_hash[16];
2140 NTTIME t;
2141 struct samr_DomInfo1 *dominfo = NULL;
2142 struct userPwdChangeFailureInformation *reject = NULL;
2144 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2146 if (newpass == NULL) {
2147 do {
2148 if (policy_min_pw_len == 0) {
2149 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2150 } else {
2151 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2153 } while (check_password_quality(newpass) == false);
2154 } else {
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;
2186 r.in.lm_change = 1;
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",
2197 nt_errstr(status));
2198 ret = false;
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 */
2207 old_nt_hash[0]++;
2208 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2209 /* Unbreak it again */
2210 old_nt_hash[0]--;
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;
2217 r.in.lm_change = 1;
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",
2228 nt_errstr(status));
2229 ret = false;
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",
2239 nt_errstr(status));
2240 ret = false;
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;
2261 r.in.lm_change = 1;
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)
2273 && dominfo
2274 && reject
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->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2280 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2281 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2282 return false;
2286 /* We tested the order of precendence which is as follows:
2288 * pwd min_age
2289 * pwd length
2290 * pwd complexity
2291 * pwd history
2293 Guenther */
2295 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2296 (last_password_change + dominfo->min_password_age > t)) {
2298 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2299 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2300 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2301 return false;
2304 } else if ((dominfo->min_password_length > 0) &&
2305 (strlen(newpass) < dominfo->min_password_length)) {
2307 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2308 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2309 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2310 return false;
2313 } else if ((dominfo->password_history_length > 0) &&
2314 strequal(oldpass, newpass)) {
2316 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2317 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2318 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2319 return false;
2321 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2323 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2324 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2325 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2326 return false;
2331 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_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->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2341 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2342 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2343 return false;
2345 /* Perhaps the server has a 'min password age' set? */
2347 } else {
2348 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2349 *password = talloc_strdup(tctx, newpass);
2352 return ret;
2355 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2356 const char *account_string,
2357 struct policy_handle *handle,
2358 char **password)
2360 NTSTATUS status;
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;
2369 bool ret = true;
2370 struct lsa_String server, account;
2371 struct samr_CryptPassword nt_pass;
2372 struct samr_Password nt_verifier;
2373 DATA_BLOB new_random_pass;
2374 char *newpass;
2375 char *oldpass;
2376 uint8_t old_nt_hash[16], new_nt_hash[16];
2377 NTTIME t;
2378 struct samr_DomInfo1 *dominfo = NULL;
2379 struct userPwdChangeFailureInformation *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;
2391 s.in.info = &u;
2392 s.in.level = 25;
2394 ZERO_STRUCT(u);
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));
2404 return false;
2407 generate_random_buffer((uint8_t *)confounder, 16);
2409 MD5Init(&ctx);
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));
2423 ret = false;
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;
2442 r.in.lm_change = 0;
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->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2455 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2456 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2457 return false;
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));
2463 ret = false;
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;
2480 r.in.lm_change = 0;
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->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2493 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2494 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2495 return false;
2497 /* Perhaps the server has a 'min password age' set? */
2499 } else {
2500 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2501 *password = talloc_strdup(tctx, newpass);
2504 return ret;
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;
2513 NTSTATUS status;
2515 torture_comment(tctx, "Testing GetMembersInAlias\n");
2517 r.in.alias_handle = alias_handle;
2518 r.out.sids = &sids;
2520 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2521 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2523 return true;
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;
2532 NTSTATUS status;
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;
2539 r.in.sid = sid;
2541 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2542 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2544 d.in.alias_handle = alias_handle;
2545 d.in.sid = sid;
2547 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2548 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2550 return true;
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;
2558 NTSTATUS status;
2559 struct lsa_SidArray sids;
2561 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2562 a.in.alias_handle = alias_handle;
2563 a.in.sids = &sids;
2565 sids.num_sids = 3;
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;
2578 r.in.sids = &sids;
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");
2593 return true;
2596 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2597 struct policy_handle *user_handle)
2599 struct samr_TestPrivateFunctionsUser r;
2600 NTSTATUS status;
2602 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2604 r.in.user_handle = user_handle;
2606 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2607 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2609 return true;
2612 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2613 struct torture_context *tctx,
2614 struct policy_handle *handle,
2615 bool use_info2,
2616 NTTIME *pwdlastset)
2618 NTSTATUS status;
2619 uint16_t levels[] = { /* 3, */ 5, 21 };
2620 int i;
2621 NTTIME pwdlastset3 = 0;
2622 NTTIME pwdlastset5 = 0;
2623 NTTIME pwdlastset21 = 0;
2625 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2626 use_info2 ? "2":"");
2628 for (i=0; i<ARRAY_SIZE(levels); i++) {
2630 struct samr_QueryUserInfo r;
2631 struct samr_QueryUserInfo2 r2;
2632 union samr_UserInfo *info;
2634 if (use_info2) {
2635 r2.in.user_handle = handle;
2636 r2.in.level = levels[i];
2637 r2.out.info = &info;
2638 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2640 } else {
2641 r.in.user_handle = handle;
2642 r.in.level = levels[i];
2643 r.out.info = &info;
2644 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2647 if (!NT_STATUS_IS_OK(status) &&
2648 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2649 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2650 use_info2 ? "2":"", levels[i], nt_errstr(status));
2651 return false;
2654 switch (levels[i]) {
2655 case 3:
2656 pwdlastset3 = info->info3.last_password_change;
2657 break;
2658 case 5:
2659 pwdlastset5 = info->info5.last_password_change;
2660 break;
2661 case 21:
2662 pwdlastset21 = info->info21.last_password_change;
2663 break;
2664 default:
2665 return false;
2668 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2669 "pwdlastset mixup"); */
2670 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2671 "pwdlastset mixup");
2673 *pwdlastset = pwdlastset21;
2675 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2677 return true;
2680 static bool test_SamLogon(struct torture_context *tctx,
2681 struct dcerpc_pipe *p,
2682 struct cli_credentials *test_credentials,
2683 NTSTATUS expected_result)
2685 NTSTATUS status;
2686 struct netr_LogonSamLogonEx r;
2687 union netr_LogonLevel logon;
2688 union netr_Validation validation;
2689 uint8_t authoritative;
2690 struct netr_NetworkInfo ninfo;
2691 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2692 int flags = CLI_CRED_NTLM_AUTH;
2693 uint32_t samlogon_flags = 0;
2695 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2696 flags |= CLI_CRED_LANMAN_AUTH;
2699 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2700 flags |= CLI_CRED_NTLMv2_AUTH;
2703 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2704 &ninfo.identity_info.account_name.string,
2705 &ninfo.identity_info.domain_name.string);
2707 generate_random_buffer(ninfo.challenge,
2708 sizeof(ninfo.challenge));
2709 chal = data_blob_const(ninfo.challenge,
2710 sizeof(ninfo.challenge));
2712 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2713 cli_credentials_get_domain(test_credentials));
2715 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2716 &flags,
2717 chal,
2718 names_blob,
2719 &lm_resp, &nt_resp,
2720 NULL, NULL);
2721 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2723 ninfo.lm.data = lm_resp.data;
2724 ninfo.lm.length = lm_resp.length;
2726 ninfo.nt.data = nt_resp.data;
2727 ninfo.nt.length = nt_resp.length;
2729 ninfo.identity_info.parameter_control =
2730 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2731 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2732 ninfo.identity_info.logon_id_low = 0;
2733 ninfo.identity_info.logon_id_high = 0;
2734 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(test_credentials);
2736 logon.network = &ninfo;
2738 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2739 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2740 r.in.logon_level = NetlogonNetworkInformation;
2741 r.in.logon = &logon;
2742 r.in.flags = &samlogon_flags;
2743 r.out.flags = &samlogon_flags;
2744 r.out.validation = &validation;
2745 r.out.authoritative = &authoritative;
2747 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2749 r.in.validation_level = 6;
2751 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2752 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2753 r.in.validation_level = 3;
2754 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2758 return true;
2759 } else {
2760 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2763 return true;
2766 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2767 struct dcerpc_pipe *p,
2768 struct cli_credentials *machine_creds,
2769 const char *acct_name,
2770 char *password,
2771 NTSTATUS expected_samlogon_result)
2773 bool ret = true;
2774 struct cli_credentials *test_credentials;
2776 test_credentials = cli_credentials_init(tctx);
2778 cli_credentials_set_workstation(test_credentials,
2779 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2780 cli_credentials_set_domain(test_credentials,
2781 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2782 cli_credentials_set_username(test_credentials,
2783 acct_name, CRED_SPECIFIED);
2784 cli_credentials_set_password(test_credentials,
2785 password, CRED_SPECIFIED);
2787 torture_comment(tctx, "testing samlogon as %s password: %s\n",
2788 acct_name, password);
2790 if (!test_SamLogon(tctx, p, test_credentials,
2791 expected_samlogon_result)) {
2792 torture_warning(tctx, "new password did not work\n");
2793 ret = false;
2796 return ret;
2799 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2800 struct dcerpc_pipe *np,
2801 struct torture_context *tctx,
2802 struct policy_handle *handle,
2803 uint16_t level,
2804 uint32_t fields_present,
2805 uint8_t password_expired,
2806 bool *matched_expected_error,
2807 bool use_setinfo2,
2808 const char *acct_name,
2809 char **password,
2810 struct cli_credentials *machine_creds,
2811 bool use_queryinfo2,
2812 NTTIME *pwdlastset,
2813 NTSTATUS expected_samlogon_result)
2815 const char *fields = NULL;
2816 bool ret = true;
2818 switch (level) {
2819 case 21:
2820 case 23:
2821 case 25:
2822 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2823 fields_present);
2824 break;
2825 default:
2826 break;
2829 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2830 "(password_expired: %d) %s\n",
2831 use_setinfo2 ? "2":"", level, password_expired,
2832 fields ? fields : "");
2834 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2835 fields_present,
2836 password,
2837 password_expired,
2838 use_setinfo2,
2839 matched_expected_error)) {
2840 ret = false;
2843 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2844 use_queryinfo2,
2845 pwdlastset)) {
2846 ret = false;
2849 if (*matched_expected_error == true) {
2850 return ret;
2853 if (!test_SamLogon_with_creds(tctx, np,
2854 machine_creds,
2855 acct_name,
2856 *password,
2857 expected_samlogon_result)) {
2858 ret = false;
2861 return ret;
2864 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2865 struct torture_context *tctx,
2866 uint32_t acct_flags,
2867 const char *acct_name,
2868 struct policy_handle *handle,
2869 char **password,
2870 struct cli_credentials *machine_credentials)
2872 int s = 0, q = 0, f = 0, l = 0, z = 0;
2873 struct dcerpc_binding *b;
2874 bool ret = true;
2875 int delay = 50000;
2876 bool set_levels[] = { false, true };
2877 bool query_levels[] = { false, true };
2878 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2879 uint32_t nonzeros[] = { 1, 24 };
2880 uint32_t fields_present[] = {
2882 SAMR_FIELD_EXPIRED_FLAG,
2883 SAMR_FIELD_LAST_PWD_CHANGE,
2884 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2885 SAMR_FIELD_COMMENT,
2886 SAMR_FIELD_NT_PASSWORD_PRESENT,
2887 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2888 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2889 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2890 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2891 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2892 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2894 NTSTATUS status;
2895 struct dcerpc_pipe *np = NULL;
2897 if (torture_setting_bool(tctx, "samba3", false)) {
2898 delay = 999999;
2899 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
2900 delay);
2903 status = torture_rpc_binding(tctx, &b);
2904 if (!NT_STATUS_IS_OK(status)) {
2905 ret = false;
2906 return ret;
2909 /* We have to use schannel, otherwise the SamLogonEx fails
2910 * with INTERNAL_ERROR */
2912 b->flags &= ~DCERPC_AUTH_OPTIONS;
2913 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2915 status = dcerpc_pipe_connect_b(tctx, &np, b,
2916 &ndr_table_netlogon,
2917 machine_credentials, tctx->ev, tctx->lp_ctx);
2919 if (!NT_STATUS_IS_OK(status)) {
2920 torture_warning(tctx, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
2921 ret = false;
2922 return ret;
2925 /* set to 1 to enable testing for all possible opcode
2926 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2927 combinations */
2928 #if 0
2929 #define TEST_ALL_LEVELS 1
2930 #define TEST_SET_LEVELS 1
2931 #define TEST_QUERY_LEVELS 1
2932 #endif
2933 #ifdef TEST_ALL_LEVELS
2934 for (l=0; l<ARRAY_SIZE(levels); l++) {
2935 #else
2936 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
2937 #endif
2938 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2939 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2940 #ifdef TEST_SET_LEVELS
2941 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2942 #endif
2943 #ifdef TEST_QUERY_LEVELS
2944 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2945 #endif
2946 NTTIME pwdlastset_old = 0;
2947 NTTIME pwdlastset_new = 0;
2948 bool matched_expected_error = false;
2949 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2951 torture_comment(tctx, "------------------------------\n"
2952 "Testing pwdLastSet attribute for flags: 0x%08x "
2953 "(s: %d (l: %d), q: %d)\n",
2954 acct_flags, s, levels[l], q);
2956 switch (levels[l]) {
2957 case 21:
2958 case 23:
2959 case 25:
2960 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2961 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2962 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2964 break;
2968 /* set #1 */
2970 /* set a password and force password change (pwdlastset 0) by
2971 * setting the password expired flag to a non-0 value */
2973 if (!test_SetPassword_level(p, np, tctx, handle,
2974 levels[l],
2975 fields_present[f],
2976 nonzeros[z],
2977 &matched_expected_error,
2978 set_levels[s],
2979 acct_name,
2980 password,
2981 machine_credentials,
2982 query_levels[q],
2983 &pwdlastset_old,
2984 expected_samlogon_result)) {
2985 ret = false;
2988 if (matched_expected_error == true) {
2989 /* skipping on expected failure */
2990 continue;
2993 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2994 * set without the SAMR_FIELD_EXPIRED_FLAG */
2996 switch (levels[l]) {
2997 case 21:
2998 case 23:
2999 case 25:
3000 if ((pwdlastset_new != 0) &&
3001 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3002 torture_comment(tctx, "not considering a non-0 "
3003 "pwdLastSet as a an error as the "
3004 "SAMR_FIELD_EXPIRED_FLAG has not "
3005 "been set\n");
3006 break;
3008 default:
3009 if (pwdlastset_new != 0) {
3010 torture_warning(tctx, "pwdLastSet test failed: "
3011 "expected pwdLastSet 0 but got %lld\n",
3012 pwdlastset_old);
3013 ret = false;
3015 break;
3018 switch (levels[l]) {
3019 case 21:
3020 case 23:
3021 case 25:
3022 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3023 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3024 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3025 (pwdlastset_old >= pwdlastset_new)) {
3026 torture_warning(tctx, "pwdlastset not increasing\n");
3027 ret = false;
3029 break;
3030 default:
3031 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3032 (pwdlastset_old >= pwdlastset_new)) {
3033 torture_warning(tctx, "pwdlastset not increasing\n");
3034 ret = false;
3036 break;
3039 usleep(delay);
3041 /* set #2 */
3043 /* set a password, pwdlastset needs to get updated (increased
3044 * value), password_expired value used here is 0 */
3046 if (!test_SetPassword_level(p, np, tctx, handle,
3047 levels[l],
3048 fields_present[f],
3050 &matched_expected_error,
3051 set_levels[s],
3052 acct_name,
3053 password,
3054 machine_credentials,
3055 query_levels[q],
3056 &pwdlastset_new,
3057 expected_samlogon_result)) {
3058 ret = false;
3061 /* when a password has been changed, pwdlastset must not be 0 afterwards
3062 * and must be larger then the old value */
3064 switch (levels[l]) {
3065 case 21:
3066 case 23:
3067 case 25:
3069 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3070 * password has been changed, old and new pwdlastset
3071 * need to be the same value */
3073 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3074 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3075 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3077 torture_assert_int_equal(tctx, pwdlastset_old,
3078 pwdlastset_new, "pwdlastset must be equal");
3079 break;
3081 default:
3082 if (pwdlastset_old >= pwdlastset_new) {
3083 torture_warning(tctx, "pwdLastSet test failed: "
3084 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3085 pwdlastset_old, pwdlastset_new);
3086 ret = false;
3088 if (pwdlastset_new == 0) {
3089 torture_warning(tctx, "pwdLastSet test failed: "
3090 "expected non-0 pwdlastset, got: %lld\n",
3091 pwdlastset_new);
3092 ret = false;
3096 switch (levels[l]) {
3097 case 21:
3098 case 23:
3099 case 25:
3100 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3101 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3102 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3103 (pwdlastset_old >= pwdlastset_new)) {
3104 torture_warning(tctx, "pwdlastset not increasing\n");
3105 ret = false;
3107 break;
3108 default:
3109 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3110 (pwdlastset_old >= pwdlastset_new)) {
3111 torture_warning(tctx, "pwdlastset not increasing\n");
3112 ret = false;
3114 break;
3117 pwdlastset_old = pwdlastset_new;
3119 usleep(delay);
3121 /* set #2b */
3123 /* set a password, pwdlastset needs to get updated (increased
3124 * value), password_expired value used here is 0 */
3126 if (!test_SetPassword_level(p, np, tctx, handle,
3127 levels[l],
3128 fields_present[f],
3130 &matched_expected_error,
3131 set_levels[s],
3132 acct_name,
3133 password,
3134 machine_credentials,
3135 query_levels[q],
3136 &pwdlastset_new,
3137 expected_samlogon_result)) {
3138 ret = false;
3141 /* when a password has been changed, pwdlastset must not be 0 afterwards
3142 * and must be larger then the old value */
3144 switch (levels[l]) {
3145 case 21:
3146 case 23:
3147 case 25:
3149 /* if no password has been changed, old and new pwdlastset
3150 * need to be the same value */
3152 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3153 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3155 torture_assert_int_equal(tctx, pwdlastset_old,
3156 pwdlastset_new, "pwdlastset must be equal");
3157 break;
3159 default:
3160 if (pwdlastset_old >= pwdlastset_new) {
3161 torture_warning(tctx, "pwdLastSet test failed: "
3162 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3163 pwdlastset_old, pwdlastset_new);
3164 ret = false;
3166 if (pwdlastset_new == 0) {
3167 torture_warning(tctx, "pwdLastSet test failed: "
3168 "expected non-0 pwdlastset, got: %lld\n",
3169 pwdlastset_new);
3170 ret = false;
3174 /* set #3 */
3176 /* set a password and force password change (pwdlastset 0) by
3177 * setting the password expired flag to a non-0 value */
3179 if (!test_SetPassword_level(p, np, tctx, handle,
3180 levels[l],
3181 fields_present[f],
3182 nonzeros[z],
3183 &matched_expected_error,
3184 set_levels[s],
3185 acct_name,
3186 password,
3187 machine_credentials,
3188 query_levels[q],
3189 &pwdlastset_new,
3190 expected_samlogon_result)) {
3191 ret = false;
3194 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3195 * set without the SAMR_FIELD_EXPIRED_FLAG */
3197 switch (levels[l]) {
3198 case 21:
3199 case 23:
3200 case 25:
3201 if ((pwdlastset_new != 0) &&
3202 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3203 torture_comment(tctx, "not considering a non-0 "
3204 "pwdLastSet as a an error as the "
3205 "SAMR_FIELD_EXPIRED_FLAG has not "
3206 "been set\n");
3207 break;
3210 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3211 * password has been changed, old and new pwdlastset
3212 * need to be the same value */
3214 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3215 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3216 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3218 torture_assert_int_equal(tctx, pwdlastset_old,
3219 pwdlastset_new, "pwdlastset must be equal");
3220 break;
3222 default:
3224 if (pwdlastset_old == pwdlastset_new) {
3225 torture_warning(tctx, "pwdLastSet test failed: "
3226 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3227 pwdlastset_old, pwdlastset_new);
3228 ret = false;
3231 if (pwdlastset_new != 0) {
3232 torture_warning(tctx, "pwdLastSet test failed: "
3233 "expected pwdLastSet 0, got %lld\n",
3234 pwdlastset_old);
3235 ret = false;
3237 break;
3240 switch (levels[l]) {
3241 case 21:
3242 case 23:
3243 case 25:
3244 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3245 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3246 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3247 (pwdlastset_old >= pwdlastset_new)) {
3248 torture_warning(tctx, "pwdlastset not increasing\n");
3249 ret = false;
3251 break;
3252 default:
3253 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3254 (pwdlastset_old >= pwdlastset_new)) {
3255 torture_warning(tctx, "pwdlastset not increasing\n");
3256 ret = false;
3258 break;
3261 /* if the level we are testing does not have a fields_present
3262 * field, skip all fields present tests by setting f to to
3263 * arraysize */
3264 switch (levels[l]) {
3265 case 18:
3266 case 24:
3267 case 26:
3268 f = ARRAY_SIZE(fields_present);
3269 break;
3272 #ifdef TEST_QUERY_LEVELS
3274 #endif
3275 #ifdef TEST_SET_LEVELS
3277 #endif
3278 } /* fields present */
3279 } /* nonzeros */
3280 } /* levels */
3282 #undef TEST_SET_LEVELS
3283 #undef TEST_QUERY_LEVELS
3285 talloc_free(np);
3287 return ret;
3290 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
3291 struct dcerpc_pipe *lp,
3292 struct torture_context *tctx,
3293 struct policy_handle *domain_handle,
3294 struct policy_handle *lsa_handle,
3295 struct policy_handle *user_handle,
3296 const struct dom_sid *domain_sid,
3297 uint32_t rid,
3298 struct cli_credentials *machine_credentials)
3300 NTSTATUS status;
3301 bool ret = true;
3303 struct policy_handle lsa_acct_handle;
3304 struct dom_sid *user_sid;
3306 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
3309 struct lsa_EnumAccountRights r;
3310 struct lsa_RightSet rights;
3312 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3314 r.in.handle = lsa_handle;
3315 r.in.sid = user_sid;
3316 r.out.rights = &rights;
3318 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3319 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3320 "Expected enum rights for account to fail");
3324 struct lsa_RightSet rights;
3325 struct lsa_StringLarge names[2];
3326 struct lsa_AddAccountRights r;
3328 torture_comment(tctx, "Testing LSA AddAccountRights\n");
3330 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
3331 init_lsa_StringLarge(&names[1], NULL);
3333 rights.count = 1;
3334 rights.names = names;
3336 r.in.handle = lsa_handle;
3337 r.in.sid = user_sid;
3338 r.in.rights = &rights;
3340 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
3341 torture_assert_ntstatus_ok(tctx, status,
3342 "Failed to add privileges");
3346 struct lsa_EnumAccounts r;
3347 uint32_t resume_handle = 0;
3348 struct lsa_SidArray lsa_sid_array;
3349 int i;
3350 bool found_sid = false;
3352 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3354 r.in.handle = lsa_handle;
3355 r.in.num_entries = 0x1000;
3356 r.in.resume_handle = &resume_handle;
3357 r.out.sids = &lsa_sid_array;
3358 r.out.resume_handle = &resume_handle;
3360 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3361 torture_assert_ntstatus_ok(tctx, status,
3362 "Failed to enum accounts");
3364 for (i=0; i < lsa_sid_array.num_sids; i++) {
3365 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3366 found_sid = true;
3370 torture_assert(tctx, found_sid,
3371 "failed to list privileged account");
3375 struct lsa_EnumAccountRights r;
3376 struct lsa_RightSet user_rights;
3378 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3380 r.in.handle = lsa_handle;
3381 r.in.sid = user_sid;
3382 r.out.rights = &user_rights;
3384 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3385 torture_assert_ntstatus_ok(tctx, status,
3386 "Failed to enum rights for account");
3388 if (user_rights.count < 1) {
3389 torture_warning(tctx, "failed to find newly added rights");
3390 return false;
3395 struct lsa_OpenAccount r;
3397 torture_comment(tctx, "Testing LSA OpenAccount\n");
3399 r.in.handle = lsa_handle;
3400 r.in.sid = user_sid;
3401 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3402 r.out.acct_handle = &lsa_acct_handle;
3404 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3405 torture_assert_ntstatus_ok(tctx, status,
3406 "Failed to open lsa account");
3410 struct lsa_GetSystemAccessAccount r;
3411 uint32_t access_mask;
3413 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3415 r.in.handle = &lsa_acct_handle;
3416 r.out.access_mask = &access_mask;
3418 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3419 torture_assert_ntstatus_ok(tctx, status,
3420 "Failed to get lsa system access account");
3424 struct lsa_Close r;
3426 torture_comment(tctx, "Testing LSA Close\n");
3428 r.in.handle = &lsa_acct_handle;
3429 r.out.handle = &lsa_acct_handle;
3431 status = dcerpc_lsa_Close(lp, tctx, &r);
3432 torture_assert_ntstatus_ok(tctx, status,
3433 "Failed to close lsa");
3437 struct samr_DeleteUser r;
3439 torture_comment(tctx, "Testing SAMR DeleteUser\n");
3441 r.in.user_handle = user_handle;
3442 r.out.user_handle = user_handle;
3444 status = dcerpc_samr_DeleteUser(p, tctx, &r);
3445 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
3449 struct lsa_EnumAccounts r;
3450 uint32_t resume_handle = 0;
3451 struct lsa_SidArray lsa_sid_array;
3452 int i;
3453 bool found_sid = false;
3455 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3457 r.in.handle = lsa_handle;
3458 r.in.num_entries = 0x1000;
3459 r.in.resume_handle = &resume_handle;
3460 r.out.sids = &lsa_sid_array;
3461 r.out.resume_handle = &resume_handle;
3463 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3464 torture_assert_ntstatus_ok(tctx, status,
3465 "Failed to enum accounts");
3467 for (i=0; i < lsa_sid_array.num_sids; i++) {
3468 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3469 found_sid = true;
3473 torture_assert(tctx, found_sid,
3474 "failed to list privileged account");
3478 struct lsa_EnumAccountRights r;
3479 struct lsa_RightSet user_rights;
3481 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3483 r.in.handle = lsa_handle;
3484 r.in.sid = user_sid;
3485 r.out.rights = &user_rights;
3487 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3488 torture_assert_ntstatus_ok(tctx, status,
3489 "Failed to enum rights for account");
3491 if (user_rights.count < 1) {
3492 torture_warning(tctx, "failed to find newly added rights");
3493 return false;
3498 struct lsa_OpenAccount r;
3500 torture_comment(tctx, "Testing LSA OpenAccount\n");
3502 r.in.handle = lsa_handle;
3503 r.in.sid = user_sid;
3504 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3505 r.out.acct_handle = &lsa_acct_handle;
3507 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3508 torture_assert_ntstatus_ok(tctx, status,
3509 "Failed to open lsa account");
3513 struct lsa_GetSystemAccessAccount r;
3514 uint32_t access_mask;
3516 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3518 r.in.handle = &lsa_acct_handle;
3519 r.out.access_mask = &access_mask;
3521 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3522 torture_assert_ntstatus_ok(tctx, status,
3523 "Failed to get lsa system access account");
3527 struct lsa_DeleteObject r;
3529 torture_comment(tctx, "Testing LSA DeleteObject\n");
3531 r.in.handle = &lsa_acct_handle;
3532 r.out.handle = &lsa_acct_handle;
3534 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
3535 torture_assert_ntstatus_ok(tctx, status,
3536 "Failed to delete object");
3540 struct lsa_EnumAccounts r;
3541 uint32_t resume_handle = 0;
3542 struct lsa_SidArray lsa_sid_array;
3543 int i;
3544 bool found_sid = false;
3546 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3548 r.in.handle = lsa_handle;
3549 r.in.num_entries = 0x1000;
3550 r.in.resume_handle = &resume_handle;
3551 r.out.sids = &lsa_sid_array;
3552 r.out.resume_handle = &resume_handle;
3554 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3555 torture_assert_ntstatus_ok(tctx, status,
3556 "Failed to enum accounts");
3558 for (i=0; i < lsa_sid_array.num_sids; i++) {
3559 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3560 found_sid = true;
3564 torture_assert(tctx, !found_sid,
3565 "should not have listed privileged account");
3569 struct lsa_EnumAccountRights r;
3570 struct lsa_RightSet user_rights;
3572 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3574 r.in.handle = lsa_handle;
3575 r.in.sid = user_sid;
3576 r.out.rights = &user_rights;
3578 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3579 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3580 "Failed to enum rights for account");
3583 return ret;
3586 static bool test_user_ops(struct dcerpc_pipe *p,
3587 struct torture_context *tctx,
3588 struct policy_handle *user_handle,
3589 struct policy_handle *domain_handle,
3590 const struct dom_sid *domain_sid,
3591 uint32_t base_acct_flags,
3592 const char *base_acct_name, enum torture_samr_choice which_ops,
3593 struct cli_credentials *machine_credentials)
3595 char *password = NULL;
3596 struct samr_QueryUserInfo q;
3597 union samr_UserInfo *info;
3598 NTSTATUS status;
3600 bool ret = true;
3601 int i;
3602 uint32_t rid;
3603 const uint32_t password_fields[] = {
3604 SAMR_FIELD_NT_PASSWORD_PRESENT,
3605 SAMR_FIELD_LM_PASSWORD_PRESENT,
3606 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3610 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 ret = false;
3615 switch (which_ops) {
3616 case TORTURE_SAMR_USER_ATTRIBUTES:
3617 if (!test_QuerySecurity(p, tctx, user_handle)) {
3618 ret = false;
3621 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3622 ret = false;
3625 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3626 ret = false;
3629 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3630 base_acct_name)) {
3631 ret = false;
3634 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3635 ret = false;
3638 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3639 ret = false;
3642 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3643 ret = false;
3645 break;
3646 case TORTURE_SAMR_PASSWORDS:
3647 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3648 char simple_pass[9];
3649 char *v = generate_random_str(tctx, 1);
3651 ZERO_STRUCT(simple_pass);
3652 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3654 torture_comment(tctx, "Testing machine account password policy rules\n");
3656 /* Workstation trust accounts don't seem to need to honour password quality policy */
3657 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3658 ret = false;
3661 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3662 ret = false;
3665 /* reset again, to allow another 'user' password change */
3666 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3667 ret = false;
3670 /* Try a 'short' password */
3671 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3672 ret = false;
3675 /* Try a compleatly random password */
3676 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3677 ret = false;
3681 for (i = 0; password_fields[i]; i++) {
3682 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3683 ret = false;
3686 /* check it was set right */
3687 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3688 ret = false;
3692 for (i = 0; password_fields[i]; i++) {
3693 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3694 ret = false;
3697 /* check it was set right */
3698 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3699 ret = false;
3703 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3704 ret = false;
3707 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3708 ret = false;
3711 if (torture_setting_bool(tctx, "samba4", false)) {
3712 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
3713 } else {
3715 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3716 ret = false;
3719 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3720 ret = false;
3723 for (i = 0; password_fields[i]; i++) {
3725 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3726 /* we need to skip as that would break
3727 * the ChangePasswordUser3 verify */
3728 continue;
3731 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3732 ret = false;
3735 /* check it was set right */
3736 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3737 ret = false;
3742 q.in.user_handle = user_handle;
3743 q.in.level = 5;
3744 q.out.info = &info;
3746 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
3749 q.in.level, nt_errstr(status));
3750 ret = false;
3751 } else {
3752 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3753 if ((info->info5.acct_flags) != expected_flags) {
3754 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3755 info->info5.acct_flags,
3756 expected_flags);
3757 /* FIXME: GD */
3758 if (!torture_setting_bool(tctx, "samba3", false)) {
3759 ret = false;
3762 if (info->info5.rid != rid) {
3763 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3764 info->info5.rid, rid);
3769 break;
3771 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3773 /* test last password change timestamp behaviour */
3774 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3775 base_acct_name,
3776 user_handle, &password,
3777 machine_credentials)) {
3778 ret = false;
3781 if (ret == true) {
3782 torture_comment(tctx, "pwdLastSet test succeeded\n");
3783 } else {
3784 torture_warning(tctx, "pwdLastSet test failed\n");
3787 break;
3789 case TORTURE_SAMR_USER_PRIVILEGES: {
3791 struct dcerpc_pipe *lp;
3792 struct policy_handle *lsa_handle;
3794 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
3795 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
3797 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
3798 ret = false;
3801 if (!test_DeleteUser_with_privs(p, lp, tctx,
3802 domain_handle, lsa_handle, user_handle,
3803 domain_sid, rid,
3804 machine_credentials)) {
3805 ret = false;
3808 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
3809 ret = false;
3812 if (!ret) {
3813 torture_warning(tctx, "privileged user delete test failed\n");
3816 break;
3818 case TORTURE_SAMR_OTHER:
3819 /* We just need the account to exist */
3820 break;
3822 return ret;
3825 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3826 struct policy_handle *alias_handle,
3827 const struct dom_sid *domain_sid)
3829 bool ret = true;
3831 if (!torture_setting_bool(tctx, "samba3", false)) {
3832 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3833 ret = false;
3837 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3838 ret = false;
3841 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3842 ret = false;
3845 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3846 ret = false;
3849 if (torture_setting_bool(tctx, "samba3", false) ||
3850 torture_setting_bool(tctx, "samba4", false)) {
3851 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
3852 return ret;
3855 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3856 ret = false;
3859 return ret;
3863 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3864 struct policy_handle *user_handle)
3866 struct samr_DeleteUser d;
3867 NTSTATUS status;
3868 torture_comment(tctx, "Testing DeleteUser\n");
3870 d.in.user_handle = user_handle;
3871 d.out.user_handle = user_handle;
3873 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3874 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3876 return true;
3879 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
3880 struct torture_context *tctx,
3881 struct policy_handle *handle, const char *name)
3883 NTSTATUS status;
3884 struct samr_DeleteUser d;
3885 struct policy_handle user_handle;
3886 uint32_t rid;
3888 status = test_LookupName(p, tctx, handle, name, &rid);
3889 if (!NT_STATUS_IS_OK(status)) {
3890 goto failed;
3893 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 goto failed;
3898 d.in.user_handle = &user_handle;
3899 d.out.user_handle = &user_handle;
3900 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 goto failed;
3905 return true;
3907 failed:
3908 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3909 return false;
3913 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
3914 struct torture_context *tctx,
3915 struct policy_handle *handle, const char *name)
3917 NTSTATUS status;
3918 struct samr_OpenGroup r;
3919 struct samr_DeleteDomainGroup d;
3920 struct policy_handle group_handle;
3921 uint32_t rid;
3923 status = test_LookupName(p, tctx, handle, name, &rid);
3924 if (!NT_STATUS_IS_OK(status)) {
3925 goto failed;
3928 r.in.domain_handle = handle;
3929 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3930 r.in.rid = rid;
3931 r.out.group_handle = &group_handle;
3932 status = dcerpc_samr_OpenGroup(p, tctx, &r);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 goto failed;
3937 d.in.group_handle = &group_handle;
3938 d.out.group_handle = &group_handle;
3939 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
3940 if (!NT_STATUS_IS_OK(status)) {
3941 goto failed;
3944 return true;
3946 failed:
3947 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3948 return false;
3952 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
3953 struct torture_context *tctx,
3954 struct policy_handle *domain_handle,
3955 const char *name)
3957 NTSTATUS status;
3958 struct samr_OpenAlias r;
3959 struct samr_DeleteDomAlias d;
3960 struct policy_handle alias_handle;
3961 uint32_t rid;
3963 torture_comment(tctx, "testing DeleteAlias_byname\n");
3965 status = test_LookupName(p, tctx, domain_handle, name, &rid);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 goto failed;
3970 r.in.domain_handle = domain_handle;
3971 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3972 r.in.rid = rid;
3973 r.out.alias_handle = &alias_handle;
3974 status = dcerpc_samr_OpenAlias(p, tctx, &r);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 goto failed;
3979 d.in.alias_handle = &alias_handle;
3980 d.out.alias_handle = &alias_handle;
3981 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3982 if (!NT_STATUS_IS_OK(status)) {
3983 goto failed;
3986 return true;
3988 failed:
3989 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3990 return false;
3993 static bool test_DeleteAlias(struct dcerpc_pipe *p,
3994 struct torture_context *tctx,
3995 struct policy_handle *alias_handle)
3997 struct samr_DeleteDomAlias d;
3998 NTSTATUS status;
3999 bool ret = true;
4001 torture_comment(tctx, "Testing DeleteAlias\n");
4003 d.in.alias_handle = alias_handle;
4004 d.out.alias_handle = alias_handle;
4006 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4009 ret = false;
4012 return ret;
4015 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4016 struct policy_handle *domain_handle,
4017 const char *alias_name,
4018 struct policy_handle *alias_handle,
4019 const struct dom_sid *domain_sid,
4020 bool test_alias)
4022 NTSTATUS status;
4023 struct samr_CreateDomAlias r;
4024 struct lsa_String name;
4025 uint32_t rid;
4026 bool ret = true;
4028 init_lsa_String(&name, alias_name);
4029 r.in.domain_handle = domain_handle;
4030 r.in.alias_name = &name;
4031 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4032 r.out.alias_handle = alias_handle;
4033 r.out.rid = &rid;
4035 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4037 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4039 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4040 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4041 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4042 return true;
4043 } else {
4044 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4045 nt_errstr(status));
4046 return false;
4050 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4051 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4052 return false;
4054 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4059 return false;
4062 if (!test_alias) {
4063 return ret;
4066 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4067 ret = false;
4070 return ret;
4073 static bool test_ChangePassword(struct dcerpc_pipe *p,
4074 struct torture_context *tctx,
4075 const char *acct_name,
4076 struct policy_handle *domain_handle, char **password)
4078 bool ret = true;
4080 if (!*password) {
4081 return false;
4084 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4085 ret = false;
4088 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4089 ret = false;
4092 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4093 ret = false;
4096 /* test what happens when setting the old password again */
4097 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4098 ret = false;
4102 char simple_pass[9];
4103 char *v = generate_random_str(tctx, 1);
4105 ZERO_STRUCT(simple_pass);
4106 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4108 /* test what happens when picking a simple password */
4109 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4110 ret = false;
4114 /* set samr_SetDomainInfo level 1 with min_length 5 */
4116 struct samr_QueryDomainInfo r;
4117 union samr_DomainInfo *info = NULL;
4118 struct samr_SetDomainInfo s;
4119 uint16_t len_old, len;
4120 uint32_t pwd_prop_old;
4121 int64_t min_pwd_age_old;
4122 NTSTATUS status;
4124 len = 5;
4126 r.in.domain_handle = domain_handle;
4127 r.in.level = 1;
4128 r.out.info = &info;
4130 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
4131 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
4132 if (!NT_STATUS_IS_OK(status)) {
4133 return false;
4136 s.in.domain_handle = domain_handle;
4137 s.in.level = 1;
4138 s.in.info = info;
4140 /* remember the old min length, so we can reset it */
4141 len_old = s.in.info->info1.min_password_length;
4142 s.in.info->info1.min_password_length = len;
4143 pwd_prop_old = s.in.info->info1.password_properties;
4144 /* turn off password complexity checks for this test */
4145 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
4147 min_pwd_age_old = s.in.info->info1.min_password_age;
4148 s.in.info->info1.min_password_age = 0;
4150 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4151 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 return false;
4156 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
4158 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
4159 ret = false;
4162 s.in.info->info1.min_password_length = len_old;
4163 s.in.info->info1.password_properties = pwd_prop_old;
4164 s.in.info->info1.min_password_age = min_pwd_age_old;
4166 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4167 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4168 if (!NT_STATUS_IS_OK(status)) {
4169 return false;
4175 NTSTATUS status;
4176 struct samr_OpenUser r;
4177 struct samr_QueryUserInfo q;
4178 union samr_UserInfo *info;
4179 struct samr_LookupNames n;
4180 struct policy_handle user_handle;
4181 struct samr_Ids rids, types;
4183 n.in.domain_handle = domain_handle;
4184 n.in.num_names = 1;
4185 n.in.names = talloc_array(tctx, struct lsa_String, 1);
4186 n.in.names[0].string = acct_name;
4187 n.out.rids = &rids;
4188 n.out.types = &types;
4190 status = dcerpc_samr_LookupNames(p, tctx, &n);
4191 if (!NT_STATUS_IS_OK(status)) {
4192 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
4193 return false;
4196 r.in.domain_handle = domain_handle;
4197 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4198 r.in.rid = n.out.rids->ids[0];
4199 r.out.user_handle = &user_handle;
4201 status = dcerpc_samr_OpenUser(p, tctx, &r);
4202 if (!NT_STATUS_IS_OK(status)) {
4203 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
4204 return false;
4207 q.in.user_handle = &user_handle;
4208 q.in.level = 5;
4209 q.out.info = &info;
4211 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
4214 return false;
4217 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
4219 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
4220 info->info5.last_password_change, true)) {
4221 ret = false;
4225 /* we change passwords twice - this has the effect of verifying
4226 they were changed correctly for the final call */
4227 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4228 ret = false;
4231 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4232 ret = false;
4235 return ret;
4238 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4239 struct policy_handle *domain_handle,
4240 const char *user_name,
4241 struct policy_handle *user_handle_out,
4242 struct dom_sid *domain_sid,
4243 enum torture_samr_choice which_ops,
4244 struct cli_credentials *machine_credentials,
4245 bool test_user)
4248 TALLOC_CTX *user_ctx;
4250 NTSTATUS status;
4251 struct samr_CreateUser r;
4252 struct samr_QueryUserInfo q;
4253 union samr_UserInfo *info;
4254 struct samr_DeleteUser d;
4255 uint32_t rid;
4257 /* This call creates a 'normal' account - check that it really does */
4258 const uint32_t acct_flags = ACB_NORMAL;
4259 struct lsa_String name;
4260 bool ret = true;
4262 struct policy_handle user_handle;
4263 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4264 init_lsa_String(&name, user_name);
4266 r.in.domain_handle = domain_handle;
4267 r.in.account_name = &name;
4268 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4269 r.out.user_handle = &user_handle;
4270 r.out.rid = &rid;
4272 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
4274 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4276 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4277 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4278 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4279 return true;
4280 } else {
4281 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4282 nt_errstr(status));
4283 return false;
4287 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4288 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4289 talloc_free(user_ctx);
4290 return false;
4292 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4295 if (!NT_STATUS_IS_OK(status)) {
4296 talloc_free(user_ctx);
4297 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
4298 return false;
4301 if (!test_user) {
4302 if (user_handle_out) {
4303 *user_handle_out = user_handle;
4305 return ret;
4309 q.in.user_handle = &user_handle;
4310 q.in.level = 16;
4311 q.out.info = &info;
4313 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4314 if (!NT_STATUS_IS_OK(status)) {
4315 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4316 q.in.level, nt_errstr(status));
4317 ret = false;
4318 } else {
4319 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
4320 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4321 info->info16.acct_flags,
4322 acct_flags);
4323 ret = false;
4327 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4328 domain_sid, acct_flags, name.string, which_ops,
4329 machine_credentials)) {
4330 ret = false;
4333 if (user_handle_out) {
4334 *user_handle_out = user_handle;
4335 } else {
4336 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
4338 d.in.user_handle = &user_handle;
4339 d.out.user_handle = &user_handle;
4341 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4344 ret = false;
4350 talloc_free(user_ctx);
4352 return ret;
4356 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
4357 struct policy_handle *domain_handle,
4358 struct dom_sid *domain_sid,
4359 enum torture_samr_choice which_ops,
4360 struct cli_credentials *machine_credentials)
4362 NTSTATUS status;
4363 struct samr_CreateUser2 r;
4364 struct samr_QueryUserInfo q;
4365 union samr_UserInfo *info;
4366 struct samr_DeleteUser d;
4367 struct policy_handle user_handle;
4368 uint32_t rid;
4369 struct lsa_String name;
4370 bool ret = true;
4371 int i;
4373 struct {
4374 uint32_t acct_flags;
4375 const char *account_name;
4376 NTSTATUS nt_status;
4377 } account_types[] = {
4378 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
4379 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4380 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4381 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4382 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4383 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4384 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4385 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4386 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4387 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
4388 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4389 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4390 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4391 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4392 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4395 for (i = 0; account_types[i].account_name; i++) {
4396 TALLOC_CTX *user_ctx;
4397 uint32_t acct_flags = account_types[i].acct_flags;
4398 uint32_t access_granted;
4399 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4400 init_lsa_String(&name, account_types[i].account_name);
4402 r.in.domain_handle = domain_handle;
4403 r.in.account_name = &name;
4404 r.in.acct_flags = acct_flags;
4405 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4406 r.out.user_handle = &user_handle;
4407 r.out.access_granted = &access_granted;
4408 r.out.rid = &rid;
4410 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4412 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4414 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4415 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4416 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4417 continue;
4418 } else {
4419 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4420 nt_errstr(status));
4421 ret = false;
4422 continue;
4426 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4427 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4428 talloc_free(user_ctx);
4429 ret = false;
4430 continue;
4432 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4435 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4436 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4437 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4438 ret = false;
4441 if (NT_STATUS_IS_OK(status)) {
4442 q.in.user_handle = &user_handle;
4443 q.in.level = 5;
4444 q.out.info = &info;
4446 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4449 q.in.level, nt_errstr(status));
4450 ret = false;
4451 } else {
4452 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4453 if (acct_flags == ACB_NORMAL) {
4454 expected_flags |= ACB_PW_EXPIRED;
4456 if ((info->info5.acct_flags) != expected_flags) {
4457 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4458 info->info5.acct_flags,
4459 expected_flags);
4460 ret = false;
4462 switch (acct_flags) {
4463 case ACB_SVRTRUST:
4464 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4465 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4466 DOMAIN_RID_DCS, info->info5.primary_gid);
4467 ret = false;
4469 break;
4470 case ACB_WSTRUST:
4471 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4472 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4473 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4474 ret = false;
4476 break;
4477 case ACB_NORMAL:
4478 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4479 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4480 DOMAIN_RID_USERS, info->info5.primary_gid);
4481 ret = false;
4483 break;
4487 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4488 domain_sid, acct_flags, name.string, which_ops,
4489 machine_credentials)) {
4490 ret = false;
4493 if (!policy_handle_empty(&user_handle)) {
4494 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
4496 d.in.user_handle = &user_handle;
4497 d.out.user_handle = &user_handle;
4499 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4500 if (!NT_STATUS_IS_OK(status)) {
4501 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4502 ret = false;
4506 talloc_free(user_ctx);
4509 return ret;
4512 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
4513 struct torture_context *tctx,
4514 struct policy_handle *handle)
4516 NTSTATUS status;
4517 struct samr_QueryAliasInfo r;
4518 union samr_AliasInfo *info;
4519 uint16_t levels[] = {1, 2, 3};
4520 int i;
4521 bool ret = true;
4523 for (i=0;i<ARRAY_SIZE(levels);i++) {
4524 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
4526 r.in.alias_handle = handle;
4527 r.in.level = levels[i];
4528 r.out.info = &info;
4530 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
4533 levels[i], nt_errstr(status));
4534 ret = false;
4538 return ret;
4541 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
4542 struct torture_context *tctx,
4543 struct policy_handle *handle)
4545 NTSTATUS status;
4546 struct samr_QueryGroupInfo r;
4547 union samr_GroupInfo *info;
4548 uint16_t levels[] = {1, 2, 3, 4, 5};
4549 int i;
4550 bool ret = true;
4552 for (i=0;i<ARRAY_SIZE(levels);i++) {
4553 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4555 r.in.group_handle = handle;
4556 r.in.level = levels[i];
4557 r.out.info = &info;
4559 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4562 levels[i], nt_errstr(status));
4563 ret = false;
4567 return ret;
4570 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
4571 struct torture_context *tctx,
4572 struct policy_handle *handle)
4574 NTSTATUS status;
4575 struct samr_QueryGroupMember r;
4576 struct samr_RidTypeArray *rids = NULL;
4577 bool ret = true;
4579 torture_comment(tctx, "Testing QueryGroupMember\n");
4581 r.in.group_handle = handle;
4582 r.out.rids = &rids;
4584 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
4585 if (!NT_STATUS_IS_OK(status)) {
4586 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
4587 ret = false;
4590 return ret;
4594 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
4595 struct torture_context *tctx,
4596 struct policy_handle *handle)
4598 NTSTATUS status;
4599 struct samr_QueryGroupInfo r;
4600 union samr_GroupInfo *info;
4601 struct samr_SetGroupInfo s;
4602 uint16_t levels[] = {1, 2, 3, 4};
4603 uint16_t set_ok[] = {0, 1, 1, 1};
4604 int i;
4605 bool ret = true;
4607 for (i=0;i<ARRAY_SIZE(levels);i++) {
4608 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4610 r.in.group_handle = handle;
4611 r.in.level = levels[i];
4612 r.out.info = &info;
4614 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4617 levels[i], nt_errstr(status));
4618 ret = false;
4621 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
4623 s.in.group_handle = handle;
4624 s.in.level = levels[i];
4625 s.in.info = *r.out.info;
4627 #if 0
4628 /* disabled this, as it changes the name only from the point of view of samr,
4629 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4630 the name is still reserved, so creating the old name fails, but deleting by the old name
4631 also fails */
4632 if (s.in.level == 2) {
4633 init_lsa_String(&s.in.info->string, "NewName");
4635 #endif
4637 if (s.in.level == 4) {
4638 init_lsa_String(&s.in.info->description, "test description");
4641 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
4642 if (set_ok[i]) {
4643 if (!NT_STATUS_IS_OK(status)) {
4644 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
4645 r.in.level, nt_errstr(status));
4646 ret = false;
4647 continue;
4649 } else {
4650 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4651 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4652 r.in.level, nt_errstr(status));
4653 ret = false;
4654 continue;
4659 return ret;
4662 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
4663 struct torture_context *tctx,
4664 struct policy_handle *handle)
4666 NTSTATUS status;
4667 struct samr_QueryUserInfo r;
4668 union samr_UserInfo *info;
4669 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4670 11, 12, 13, 14, 16, 17, 20, 21};
4671 int i;
4672 bool ret = true;
4674 for (i=0;i<ARRAY_SIZE(levels);i++) {
4675 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
4677 r.in.user_handle = handle;
4678 r.in.level = levels[i];
4679 r.out.info = &info;
4681 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
4682 if (!NT_STATUS_IS_OK(status)) {
4683 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4684 levels[i], nt_errstr(status));
4685 ret = false;
4689 return ret;
4692 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
4693 struct torture_context *tctx,
4694 struct policy_handle *handle)
4696 NTSTATUS status;
4697 struct samr_QueryUserInfo2 r;
4698 union samr_UserInfo *info;
4699 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4700 11, 12, 13, 14, 16, 17, 20, 21};
4701 int i;
4702 bool ret = true;
4704 for (i=0;i<ARRAY_SIZE(levels);i++) {
4705 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
4707 r.in.user_handle = handle;
4708 r.in.level = levels[i];
4709 r.out.info = &info;
4711 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
4712 if (!NT_STATUS_IS_OK(status)) {
4713 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
4714 levels[i], nt_errstr(status));
4715 ret = false;
4719 return ret;
4722 static bool test_OpenUser(struct dcerpc_pipe *p,
4723 struct torture_context *tctx,
4724 struct policy_handle *handle, uint32_t rid)
4726 NTSTATUS status;
4727 struct samr_OpenUser r;
4728 struct policy_handle user_handle;
4729 bool ret = true;
4731 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4733 r.in.domain_handle = handle;
4734 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4735 r.in.rid = rid;
4736 r.out.user_handle = &user_handle;
4738 status = dcerpc_samr_OpenUser(p, tctx, &r);
4739 if (!NT_STATUS_IS_OK(status)) {
4740 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4741 return false;
4744 if (!test_QuerySecurity(p, tctx, &user_handle)) {
4745 ret = false;
4748 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
4749 ret = false;
4752 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
4753 ret = false;
4756 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
4757 ret = false;
4760 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
4761 ret = false;
4764 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4765 ret = false;
4768 return ret;
4771 static bool test_OpenGroup(struct dcerpc_pipe *p,
4772 struct torture_context *tctx,
4773 struct policy_handle *handle, uint32_t rid)
4775 NTSTATUS status;
4776 struct samr_OpenGroup r;
4777 struct policy_handle group_handle;
4778 bool ret = true;
4780 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
4782 r.in.domain_handle = handle;
4783 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4784 r.in.rid = rid;
4785 r.out.group_handle = &group_handle;
4787 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4788 if (!NT_STATUS_IS_OK(status)) {
4789 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4790 return false;
4793 if (!torture_setting_bool(tctx, "samba3", false)) {
4794 if (!test_QuerySecurity(p, tctx, &group_handle)) {
4795 ret = false;
4799 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
4800 ret = false;
4803 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
4804 ret = false;
4807 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
4808 ret = false;
4811 return ret;
4814 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4815 struct policy_handle *handle, uint32_t rid)
4817 NTSTATUS status;
4818 struct samr_OpenAlias r;
4819 struct policy_handle alias_handle;
4820 bool ret = true;
4822 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4824 r.in.domain_handle = handle;
4825 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4826 r.in.rid = rid;
4827 r.out.alias_handle = &alias_handle;
4829 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4832 return false;
4835 if (!torture_setting_bool(tctx, "samba3", false)) {
4836 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4837 ret = false;
4841 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4842 ret = false;
4845 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4846 ret = false;
4849 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4850 ret = false;
4853 return ret;
4856 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4857 struct policy_handle *handle, uint32_t rid,
4858 uint32_t acct_flag_mask)
4860 NTSTATUS status;
4861 struct samr_OpenUser r;
4862 struct samr_QueryUserInfo q;
4863 union samr_UserInfo *info;
4864 struct policy_handle user_handle;
4865 bool ret = true;
4867 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4869 r.in.domain_handle = handle;
4870 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4871 r.in.rid = rid;
4872 r.out.user_handle = &user_handle;
4874 status = dcerpc_samr_OpenUser(p, tctx, &r);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4877 return false;
4880 q.in.user_handle = &user_handle;
4881 q.in.level = 16;
4882 q.out.info = &info;
4884 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4885 if (!NT_STATUS_IS_OK(status)) {
4886 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
4887 nt_errstr(status));
4888 ret = false;
4889 } else {
4890 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4891 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4892 acct_flag_mask, info->info16.acct_flags, rid);
4893 ret = false;
4897 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4898 ret = false;
4901 return ret;
4904 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
4905 struct torture_context *tctx,
4906 struct policy_handle *handle)
4908 NTSTATUS status = STATUS_MORE_ENTRIES;
4909 struct samr_EnumDomainUsers r;
4910 uint32_t mask, resume_handle=0;
4911 int i, mask_idx;
4912 bool ret = true;
4913 struct samr_LookupNames n;
4914 struct samr_LookupRids lr ;
4915 struct lsa_Strings names;
4916 struct samr_Ids rids, types;
4917 struct samr_SamArray *sam = NULL;
4918 uint32_t num_entries = 0;
4920 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4921 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4922 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4923 ACB_PWNOEXP, 0};
4925 torture_comment(tctx, "Testing EnumDomainUsers\n");
4927 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4928 r.in.domain_handle = handle;
4929 r.in.resume_handle = &resume_handle;
4930 r.in.acct_flags = mask = masks[mask_idx];
4931 r.in.max_size = (uint32_t)-1;
4932 r.out.resume_handle = &resume_handle;
4933 r.out.num_entries = &num_entries;
4934 r.out.sam = &sam;
4936 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4937 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4938 !NT_STATUS_IS_OK(status)) {
4939 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
4940 return false;
4943 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4945 if (sam->count == 0) {
4946 continue;
4949 for (i=0;i<sam->count;i++) {
4950 if (mask) {
4951 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4952 ret = false;
4954 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4955 ret = false;
4960 torture_comment(tctx, "Testing LookupNames\n");
4961 n.in.domain_handle = handle;
4962 n.in.num_names = sam->count;
4963 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4964 n.out.rids = &rids;
4965 n.out.types = &types;
4966 for (i=0;i<sam->count;i++) {
4967 n.in.names[i].string = sam->entries[i].name.string;
4969 status = dcerpc_samr_LookupNames(p, tctx, &n);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
4972 ret = false;
4976 torture_comment(tctx, "Testing LookupRids\n");
4977 lr.in.domain_handle = handle;
4978 lr.in.num_rids = sam->count;
4979 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4980 lr.out.names = &names;
4981 lr.out.types = &types;
4982 for (i=0;i<sam->count;i++) {
4983 lr.in.rids[i] = sam->entries[i].idx;
4985 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4986 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4988 return ret;
4992 try blasting the server with a bunch of sync requests
4994 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4995 struct policy_handle *handle)
4997 NTSTATUS status;
4998 struct samr_EnumDomainUsers r;
4999 uint32_t resume_handle=0;
5000 int i;
5001 #define ASYNC_COUNT 100
5002 struct rpc_request *req[ASYNC_COUNT];
5004 if (!torture_setting_bool(tctx, "dangerous", false)) {
5005 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5008 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5010 r.in.domain_handle = handle;
5011 r.in.resume_handle = &resume_handle;
5012 r.in.acct_flags = 0;
5013 r.in.max_size = (uint32_t)-1;
5014 r.out.resume_handle = &resume_handle;
5016 for (i=0;i<ASYNC_COUNT;i++) {
5017 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5020 for (i=0;i<ASYNC_COUNT;i++) {
5021 status = dcerpc_ndr_request_recv(req[i]);
5022 if (!NT_STATUS_IS_OK(status)) {
5023 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5024 i, nt_errstr(status));
5025 return false;
5029 torture_comment(tctx, "%d async requests OK\n", i);
5031 return true;
5034 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5035 struct torture_context *tctx,
5036 struct policy_handle *handle)
5038 NTSTATUS status;
5039 struct samr_EnumDomainGroups r;
5040 uint32_t resume_handle=0;
5041 struct samr_SamArray *sam = NULL;
5042 uint32_t num_entries = 0;
5043 int i;
5044 bool ret = true;
5046 torture_comment(tctx, "Testing EnumDomainGroups\n");
5048 r.in.domain_handle = handle;
5049 r.in.resume_handle = &resume_handle;
5050 r.in.max_size = (uint32_t)-1;
5051 r.out.resume_handle = &resume_handle;
5052 r.out.num_entries = &num_entries;
5053 r.out.sam = &sam;
5055 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5056 if (!NT_STATUS_IS_OK(status)) {
5057 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5058 return false;
5061 if (!sam) {
5062 return false;
5065 for (i=0;i<sam->count;i++) {
5066 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5067 ret = false;
5071 return ret;
5074 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5075 struct torture_context *tctx,
5076 struct policy_handle *handle)
5078 NTSTATUS status;
5079 struct samr_EnumDomainAliases r;
5080 uint32_t resume_handle=0;
5081 struct samr_SamArray *sam = NULL;
5082 uint32_t num_entries = 0;
5083 int i;
5084 bool ret = true;
5086 torture_comment(tctx, "Testing EnumDomainAliases\n");
5088 r.in.domain_handle = handle;
5089 r.in.resume_handle = &resume_handle;
5090 r.in.max_size = (uint32_t)-1;
5091 r.out.sam = &sam;
5092 r.out.num_entries = &num_entries;
5093 r.out.resume_handle = &resume_handle;
5095 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5096 if (!NT_STATUS_IS_OK(status)) {
5097 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5098 return false;
5101 if (!sam) {
5102 return false;
5105 for (i=0;i<sam->count;i++) {
5106 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5107 ret = false;
5111 return ret;
5114 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5115 struct torture_context *tctx,
5116 struct policy_handle *handle)
5118 NTSTATUS status;
5119 struct samr_GetDisplayEnumerationIndex r;
5120 bool ret = true;
5121 uint16_t levels[] = {1, 2, 3, 4, 5};
5122 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5123 struct lsa_String name;
5124 uint32_t idx = 0;
5125 int i;
5127 for (i=0;i<ARRAY_SIZE(levels);i++) {
5128 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
5130 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5132 r.in.domain_handle = handle;
5133 r.in.level = levels[i];
5134 r.in.name = &name;
5135 r.out.idx = &idx;
5137 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5139 if (ok_lvl[i] &&
5140 !NT_STATUS_IS_OK(status) &&
5141 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5142 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
5143 levels[i], nt_errstr(status));
5144 ret = false;
5147 init_lsa_String(&name, "zzzzzzzz");
5149 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5151 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5152 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
5153 levels[i], nt_errstr(status));
5154 ret = false;
5158 return ret;
5161 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
5162 struct torture_context *tctx,
5163 struct policy_handle *handle)
5165 NTSTATUS status;
5166 struct samr_GetDisplayEnumerationIndex2 r;
5167 bool ret = true;
5168 uint16_t levels[] = {1, 2, 3, 4, 5};
5169 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5170 struct lsa_String name;
5171 uint32_t idx = 0;
5172 int i;
5174 for (i=0;i<ARRAY_SIZE(levels);i++) {
5175 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
5177 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5179 r.in.domain_handle = handle;
5180 r.in.level = levels[i];
5181 r.in.name = &name;
5182 r.out.idx = &idx;
5184 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5185 if (ok_lvl[i] &&
5186 !NT_STATUS_IS_OK(status) &&
5187 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5188 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5189 levels[i], nt_errstr(status));
5190 ret = false;
5193 init_lsa_String(&name, "zzzzzzzz");
5195 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5196 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5197 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5198 levels[i], nt_errstr(status));
5199 ret = false;
5203 return ret;
5206 #define STRING_EQUAL_QUERY(s1, s2, user) \
5207 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
5208 /* odd, but valid */ \
5209 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
5210 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
5211 #s1, user.string, s1.string, s2.string, __location__); \
5212 ret = false; \
5214 #define INT_EQUAL_QUERY(s1, s2, user) \
5215 if (s1 != s2) { \
5216 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
5217 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
5218 ret = false; \
5221 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
5222 struct torture_context *tctx,
5223 struct samr_QueryDisplayInfo *querydisplayinfo,
5224 bool *seen_testuser)
5226 struct samr_OpenUser r;
5227 struct samr_QueryUserInfo q;
5228 union samr_UserInfo *info;
5229 struct policy_handle user_handle;
5230 int i, ret = true;
5231 NTSTATUS status;
5232 r.in.domain_handle = querydisplayinfo->in.domain_handle;
5233 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5234 for (i = 0; ; i++) {
5235 switch (querydisplayinfo->in.level) {
5236 case 1:
5237 if (i >= querydisplayinfo->out.info->info1.count) {
5238 return ret;
5240 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
5241 break;
5242 case 2:
5243 if (i >= querydisplayinfo->out.info->info2.count) {
5244 return ret;
5246 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
5247 break;
5248 case 3:
5249 /* Groups */
5250 case 4:
5251 case 5:
5252 /* Not interested in validating just the account name */
5253 return true;
5256 r.out.user_handle = &user_handle;
5258 switch (querydisplayinfo->in.level) {
5259 case 1:
5260 case 2:
5261 status = dcerpc_samr_OpenUser(p, tctx, &r);
5262 if (!NT_STATUS_IS_OK(status)) {
5263 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5264 return false;
5268 q.in.user_handle = &user_handle;
5269 q.in.level = 21;
5270 q.out.info = &info;
5271 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5272 if (!NT_STATUS_IS_OK(status)) {
5273 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5274 return false;
5277 switch (querydisplayinfo->in.level) {
5278 case 1:
5279 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
5280 *seen_testuser = true;
5282 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
5283 info->info21.full_name, info->info21.account_name);
5284 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
5285 info->info21.account_name, info->info21.account_name);
5286 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
5287 info->info21.description, info->info21.account_name);
5288 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
5289 info->info21.rid, info->info21.account_name);
5290 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
5291 info->info21.acct_flags, info->info21.account_name);
5293 break;
5294 case 2:
5295 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
5296 info->info21.account_name, info->info21.account_name);
5297 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
5298 info->info21.description, info->info21.account_name);
5299 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
5300 info->info21.rid, info->info21.account_name);
5301 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
5302 info->info21.acct_flags, info->info21.account_name);
5304 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
5305 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
5306 info->info21.account_name.string);
5309 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
5310 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
5311 info->info21.account_name.string,
5312 querydisplayinfo->out.info->info2.entries[i].acct_flags,
5313 info->info21.acct_flags);
5314 return false;
5317 break;
5320 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5321 return false;
5324 return ret;
5327 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
5328 struct torture_context *tctx,
5329 struct policy_handle *handle)
5331 NTSTATUS status;
5332 struct samr_QueryDisplayInfo r;
5333 struct samr_QueryDomainInfo dom_info;
5334 union samr_DomainInfo *info = NULL;
5335 bool ret = true;
5336 uint16_t levels[] = {1, 2, 3, 4, 5};
5337 int i;
5338 bool seen_testuser = false;
5339 uint32_t total_size;
5340 uint32_t returned_size;
5341 union samr_DispInfo disp_info;
5344 for (i=0;i<ARRAY_SIZE(levels);i++) {
5345 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
5347 r.in.start_idx = 0;
5348 status = STATUS_MORE_ENTRIES;
5349 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5350 r.in.domain_handle = handle;
5351 r.in.level = levels[i];
5352 r.in.max_entries = 2;
5353 r.in.buf_size = (uint32_t)-1;
5354 r.out.total_size = &total_size;
5355 r.out.returned_size = &returned_size;
5356 r.out.info = &disp_info;
5358 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5359 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
5360 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5361 levels[i], nt_errstr(status));
5362 ret = false;
5364 switch (r.in.level) {
5365 case 1:
5366 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
5367 ret = false;
5369 r.in.start_idx += r.out.info->info1.count;
5370 break;
5371 case 2:
5372 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
5373 ret = false;
5375 r.in.start_idx += r.out.info->info2.count;
5376 break;
5377 case 3:
5378 r.in.start_idx += r.out.info->info3.count;
5379 break;
5380 case 4:
5381 r.in.start_idx += r.out.info->info4.count;
5382 break;
5383 case 5:
5384 r.in.start_idx += r.out.info->info5.count;
5385 break;
5388 dom_info.in.domain_handle = handle;
5389 dom_info.in.level = 2;
5390 dom_info.out.info = &info;
5392 /* Check number of users returned is correct */
5393 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5396 r.in.level, nt_errstr(status));
5397 ret = false;
5398 break;
5400 switch (r.in.level) {
5401 case 1:
5402 case 4:
5403 if (info->general.num_users < r.in.start_idx) {
5404 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5405 r.in.start_idx, info->general.num_groups,
5406 info->general.domain_name.string);
5407 ret = false;
5409 if (!seen_testuser) {
5410 struct policy_handle user_handle;
5411 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5412 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5413 info->general.domain_name.string);
5414 ret = false;
5415 test_samr_handle_Close(p, tctx, &user_handle);
5418 break;
5419 case 3:
5420 case 5:
5421 if (info->general.num_groups != r.in.start_idx) {
5422 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5423 r.in.start_idx, info->general.num_groups,
5424 info->general.domain_name.string);
5425 ret = false;
5428 break;
5433 return ret;
5436 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
5437 struct torture_context *tctx,
5438 struct policy_handle *handle)
5440 NTSTATUS status;
5441 struct samr_QueryDisplayInfo2 r;
5442 bool ret = true;
5443 uint16_t levels[] = {1, 2, 3, 4, 5};
5444 int i;
5445 uint32_t total_size;
5446 uint32_t returned_size;
5447 union samr_DispInfo info;
5449 for (i=0;i<ARRAY_SIZE(levels);i++) {
5450 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
5452 r.in.domain_handle = handle;
5453 r.in.level = levels[i];
5454 r.in.start_idx = 0;
5455 r.in.max_entries = 1000;
5456 r.in.buf_size = (uint32_t)-1;
5457 r.out.total_size = &total_size;
5458 r.out.returned_size = &returned_size;
5459 r.out.info = &info;
5461 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
5464 levels[i], nt_errstr(status));
5465 ret = false;
5469 return ret;
5472 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5473 struct policy_handle *handle)
5475 NTSTATUS status;
5476 struct samr_QueryDisplayInfo3 r;
5477 bool ret = true;
5478 uint16_t levels[] = {1, 2, 3, 4, 5};
5479 int i;
5480 uint32_t total_size;
5481 uint32_t returned_size;
5482 union samr_DispInfo info;
5484 for (i=0;i<ARRAY_SIZE(levels);i++) {
5485 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5487 r.in.domain_handle = handle;
5488 r.in.level = levels[i];
5489 r.in.start_idx = 0;
5490 r.in.max_entries = 1000;
5491 r.in.buf_size = (uint32_t)-1;
5492 r.out.total_size = &total_size;
5493 r.out.returned_size = &returned_size;
5494 r.out.info = &info;
5496 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5497 if (!NT_STATUS_IS_OK(status)) {
5498 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
5499 levels[i], nt_errstr(status));
5500 ret = false;
5504 return ret;
5508 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
5509 struct torture_context *tctx,
5510 struct policy_handle *handle)
5512 NTSTATUS status;
5513 struct samr_QueryDisplayInfo r;
5514 bool ret = true;
5515 uint32_t total_size;
5516 uint32_t returned_size;
5517 union samr_DispInfo info;
5519 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
5521 r.in.domain_handle = handle;
5522 r.in.level = 1;
5523 r.in.start_idx = 0;
5524 r.in.max_entries = 1;
5525 r.in.buf_size = (uint32_t)-1;
5526 r.out.total_size = &total_size;
5527 r.out.returned_size = &returned_size;
5528 r.out.info = &info;
5530 do {
5531 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5532 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5533 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5534 torture_warning(tctx, "expected idx %d but got %d\n",
5535 r.in.start_idx + 1,
5536 r.out.info->info1.entries[0].idx);
5537 break;
5540 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5541 !NT_STATUS_IS_OK(status)) {
5542 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5543 r.in.level, nt_errstr(status));
5544 ret = false;
5545 break;
5547 r.in.start_idx++;
5548 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5549 NT_STATUS_IS_OK(status)) &&
5550 *r.out.returned_size != 0);
5552 return ret;
5555 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5556 struct policy_handle *handle)
5558 NTSTATUS status;
5559 struct samr_QueryDomainInfo r;
5560 union samr_DomainInfo *info = NULL;
5561 struct samr_SetDomainInfo s;
5562 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5563 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5564 int i;
5565 bool ret = true;
5566 const char *domain_comment = talloc_asprintf(tctx,
5567 "Tortured by Samba4 RPC-SAMR: %s",
5568 timestring(tctx, time(NULL)));
5570 s.in.domain_handle = handle;
5571 s.in.level = 4;
5572 s.in.info = talloc(tctx, union samr_DomainInfo);
5574 s.in.info->oem.oem_information.string = domain_comment;
5575 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5576 if (!NT_STATUS_IS_OK(status)) {
5577 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
5578 s.in.level, nt_errstr(status));
5579 return false;
5582 for (i=0;i<ARRAY_SIZE(levels);i++) {
5583 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5585 r.in.domain_handle = handle;
5586 r.in.level = levels[i];
5587 r.out.info = &info;
5589 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5590 if (!NT_STATUS_IS_OK(status)) {
5591 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5592 r.in.level, nt_errstr(status));
5593 ret = false;
5594 continue;
5597 switch (levels[i]) {
5598 case 2:
5599 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5600 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5601 levels[i], info->general.oem_information.string, domain_comment);
5602 if (!torture_setting_bool(tctx, "samba3", false)) {
5603 ret = false;
5606 if (!info->general.primary.string) {
5607 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5608 levels[i]);
5609 ret = false;
5610 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5611 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5612 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5613 levels[i], info->general.primary.string, dcerpc_server_name(p));
5616 break;
5617 case 4:
5618 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5619 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5620 levels[i], info->oem.oem_information.string, domain_comment);
5621 if (!torture_setting_bool(tctx, "samba3", false)) {
5622 ret = false;
5625 break;
5626 case 6:
5627 if (!info->info6.primary.string) {
5628 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5629 levels[i]);
5630 ret = false;
5632 break;
5633 case 11:
5634 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5635 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5636 levels[i], info->general2.general.oem_information.string, domain_comment);
5637 if (!torture_setting_bool(tctx, "samba3", false)) {
5638 ret = false;
5641 break;
5644 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5646 s.in.domain_handle = handle;
5647 s.in.level = levels[i];
5648 s.in.info = info;
5650 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5651 if (set_ok[i]) {
5652 if (!NT_STATUS_IS_OK(status)) {
5653 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
5654 r.in.level, nt_errstr(status));
5655 ret = false;
5656 continue;
5658 } else {
5659 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5660 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5661 r.in.level, nt_errstr(status));
5662 ret = false;
5663 continue;
5667 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5670 r.in.level, nt_errstr(status));
5671 ret = false;
5672 continue;
5676 return ret;
5680 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5681 struct policy_handle *handle)
5683 NTSTATUS status;
5684 struct samr_QueryDomainInfo2 r;
5685 union samr_DomainInfo *info = NULL;
5686 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5687 int i;
5688 bool ret = true;
5690 for (i=0;i<ARRAY_SIZE(levels);i++) {
5691 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
5693 r.in.domain_handle = handle;
5694 r.in.level = levels[i];
5695 r.out.info = &info;
5697 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
5700 r.in.level, nt_errstr(status));
5701 ret = false;
5702 continue;
5706 return true;
5709 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5710 set of group names. */
5711 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5712 struct policy_handle *handle)
5714 struct samr_EnumDomainGroups q1;
5715 struct samr_QueryDisplayInfo q2;
5716 NTSTATUS status;
5717 uint32_t resume_handle=0;
5718 struct samr_SamArray *sam = NULL;
5719 uint32_t num_entries = 0;
5720 int i;
5721 bool ret = true;
5722 uint32_t total_size;
5723 uint32_t returned_size;
5724 union samr_DispInfo info;
5726 int num_names = 0;
5727 const char **names = NULL;
5729 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5731 q1.in.domain_handle = handle;
5732 q1.in.resume_handle = &resume_handle;
5733 q1.in.max_size = 5;
5734 q1.out.resume_handle = &resume_handle;
5735 q1.out.num_entries = &num_entries;
5736 q1.out.sam = &sam;
5738 status = STATUS_MORE_ENTRIES;
5739 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5740 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5742 if (!NT_STATUS_IS_OK(status) &&
5743 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5744 break;
5746 for (i=0; i<*q1.out.num_entries; i++) {
5747 add_string_to_array(tctx,
5748 sam->entries[i].name.string,
5749 &names, &num_names);
5753 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5755 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5757 q2.in.domain_handle = handle;
5758 q2.in.level = 5;
5759 q2.in.start_idx = 0;
5760 q2.in.max_entries = 5;
5761 q2.in.buf_size = (uint32_t)-1;
5762 q2.out.total_size = &total_size;
5763 q2.out.returned_size = &returned_size;
5764 q2.out.info = &info;
5766 status = STATUS_MORE_ENTRIES;
5767 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5768 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5770 if (!NT_STATUS_IS_OK(status) &&
5771 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5772 break;
5774 for (i=0; i<q2.out.info->info5.count; i++) {
5775 int j;
5776 const char *name = q2.out.info->info5.entries[i].account_name.string;
5777 bool found = false;
5778 for (j=0; j<num_names; j++) {
5779 if (names[j] == NULL)
5780 continue;
5781 if (strequal(names[j], name)) {
5782 names[j] = NULL;
5783 found = true;
5784 break;
5788 if (!found) {
5789 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5790 name);
5791 ret = false;
5794 q2.in.start_idx += q2.out.info->info5.count;
5797 if (!NT_STATUS_IS_OK(status)) {
5798 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
5799 nt_errstr(status));
5800 ret = false;
5803 for (i=0; i<num_names; i++) {
5804 if (names[i] != NULL) {
5805 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5806 names[i]);
5807 ret = false;
5811 return ret;
5814 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5815 struct policy_handle *group_handle)
5817 struct samr_DeleteDomainGroup d;
5818 NTSTATUS status;
5820 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5822 d.in.group_handle = group_handle;
5823 d.out.group_handle = group_handle;
5825 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5826 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5828 return true;
5831 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5832 struct policy_handle *domain_handle)
5834 struct samr_TestPrivateFunctionsDomain r;
5835 NTSTATUS status;
5836 bool ret = true;
5838 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5840 r.in.domain_handle = domain_handle;
5842 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5843 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
5845 return ret;
5848 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5849 struct dom_sid *domain_sid,
5850 struct policy_handle *domain_handle)
5852 struct samr_RidToSid r;
5853 NTSTATUS status;
5854 bool ret = true;
5855 struct dom_sid *calc_sid, *out_sid;
5856 int rids[] = { 0, 42, 512, 10200 };
5857 int i;
5859 for (i=0;i<ARRAY_SIZE(rids);i++) {
5860 torture_comment(tctx, "Testing RidToSid\n");
5862 calc_sid = dom_sid_dup(tctx, domain_sid);
5863 r.in.domain_handle = domain_handle;
5864 r.in.rid = rids[i];
5865 r.out.sid = &out_sid;
5867 status = dcerpc_samr_RidToSid(p, tctx, &r);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5870 ret = false;
5871 } else {
5872 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5874 if (!dom_sid_equal(calc_sid, out_sid)) {
5875 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
5876 dom_sid_string(tctx, out_sid),
5877 dom_sid_string(tctx, calc_sid));
5878 ret = false;
5883 return ret;
5886 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5887 struct policy_handle *domain_handle)
5889 struct samr_GetBootKeyInformation r;
5890 NTSTATUS status;
5891 bool ret = true;
5892 uint32_t unknown = 0;
5894 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5896 r.in.domain_handle = domain_handle;
5897 r.out.unknown = &unknown;
5899 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5900 if (!NT_STATUS_IS_OK(status)) {
5901 /* w2k3 seems to fail this sometimes and pass it sometimes */
5902 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5905 return ret;
5908 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5909 struct policy_handle *domain_handle,
5910 struct policy_handle *group_handle)
5912 NTSTATUS status;
5913 struct samr_AddGroupMember r;
5914 struct samr_DeleteGroupMember d;
5915 struct samr_QueryGroupMember q;
5916 struct samr_RidTypeArray *rids = NULL;
5917 struct samr_SetMemberAttributesOfGroup s;
5918 uint32_t rid;
5919 bool found_member = false;
5920 int i;
5922 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5923 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5925 r.in.group_handle = group_handle;
5926 r.in.rid = rid;
5927 r.in.flags = 0; /* ??? */
5929 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
5931 d.in.group_handle = group_handle;
5932 d.in.rid = rid;
5934 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5935 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5937 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5938 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5940 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5941 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5943 if (torture_setting_bool(tctx, "samba4", false) ||
5944 torture_setting_bool(tctx, "samba3", false)) {
5945 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
5946 } else {
5947 /* this one is quite strange. I am using random inputs in the
5948 hope of triggering an error that might give us a clue */
5950 s.in.group_handle = group_handle;
5951 s.in.unknown1 = random();
5952 s.in.unknown2 = random();
5954 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5955 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5958 q.in.group_handle = group_handle;
5959 q.out.rids = &rids;
5961 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5962 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5963 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
5965 for (i=0; i < rids->count; i++) {
5966 if (rids->rids[i] == rid) {
5967 found_member = true;
5971 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
5973 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5974 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5976 rids = NULL;
5977 found_member = false;
5979 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5980 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5981 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
5983 for (i=0; i < rids->count; i++) {
5984 if (rids->rids[i] == rid) {
5985 found_member = true;
5989 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
5991 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5992 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5994 return true;
5998 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5999 struct torture_context *tctx,
6000 struct policy_handle *domain_handle,
6001 const char *group_name,
6002 struct policy_handle *group_handle,
6003 struct dom_sid *domain_sid,
6004 bool test_group)
6006 NTSTATUS status;
6007 struct samr_CreateDomainGroup r;
6008 uint32_t rid;
6009 struct lsa_String name;
6010 bool ret = true;
6012 init_lsa_String(&name, group_name);
6014 r.in.domain_handle = domain_handle;
6015 r.in.name = &name;
6016 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6017 r.out.group_handle = group_handle;
6018 r.out.rid = &rid;
6020 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6022 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6024 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6025 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6026 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6027 return true;
6028 } else {
6029 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6030 nt_errstr(status));
6031 return false;
6035 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6036 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6037 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6038 nt_errstr(status));
6039 return false;
6041 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6043 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6044 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6046 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6047 nt_errstr(status));
6048 return false;
6050 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6052 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6054 if (!test_group) {
6055 return ret;
6058 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6059 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6060 ret = false;
6063 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6064 ret = false;
6067 return ret;
6072 its not totally clear what this does. It seems to accept any sid you like.
6074 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6075 struct torture_context *tctx,
6076 struct policy_handle *domain_handle)
6078 NTSTATUS status;
6079 struct samr_RemoveMemberFromForeignDomain r;
6081 r.in.domain_handle = domain_handle;
6082 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6084 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6085 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6087 return true;
6090 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6091 struct torture_context *tctx,
6092 struct policy_handle *domain_handle,
6093 uint32_t *total_num_entries_p)
6095 NTSTATUS status;
6096 struct samr_EnumDomainUsers r;
6097 uint32_t resume_handle = 0;
6098 uint32_t num_entries = 0;
6099 uint32_t total_num_entries = 0;
6100 struct samr_SamArray *sam;
6102 r.in.domain_handle = domain_handle;
6103 r.in.acct_flags = 0;
6104 r.in.max_size = (uint32_t)-1;
6105 r.in.resume_handle = &resume_handle;
6107 r.out.sam = &sam;
6108 r.out.num_entries = &num_entries;
6109 r.out.resume_handle = &resume_handle;
6111 torture_comment(tctx, "Testing EnumDomainUsers\n");
6113 do {
6114 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6115 if (NT_STATUS_IS_ERR(status)) {
6116 torture_assert_ntstatus_ok(tctx, status,
6117 "failed to enumerate users");
6120 total_num_entries += num_entries;
6121 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6123 if (total_num_entries_p) {
6124 *total_num_entries_p = total_num_entries;
6127 return true;
6130 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
6131 struct torture_context *tctx,
6132 struct policy_handle *domain_handle,
6133 uint32_t *total_num_entries_p)
6135 NTSTATUS status;
6136 struct samr_EnumDomainGroups r;
6137 uint32_t resume_handle = 0;
6138 uint32_t num_entries = 0;
6139 uint32_t total_num_entries = 0;
6140 struct samr_SamArray *sam;
6142 r.in.domain_handle = domain_handle;
6143 r.in.max_size = (uint32_t)-1;
6144 r.in.resume_handle = &resume_handle;
6146 r.out.sam = &sam;
6147 r.out.num_entries = &num_entries;
6148 r.out.resume_handle = &resume_handle;
6150 torture_comment(tctx, "Testing EnumDomainGroups\n");
6152 do {
6153 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
6154 if (NT_STATUS_IS_ERR(status)) {
6155 torture_assert_ntstatus_ok(tctx, status,
6156 "failed to enumerate groups");
6159 total_num_entries += num_entries;
6160 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6162 if (total_num_entries_p) {
6163 *total_num_entries_p = total_num_entries;
6166 return true;
6169 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
6170 struct torture_context *tctx,
6171 struct policy_handle *domain_handle,
6172 uint32_t *total_num_entries_p)
6174 NTSTATUS status;
6175 struct samr_EnumDomainAliases r;
6176 uint32_t resume_handle = 0;
6177 uint32_t num_entries = 0;
6178 uint32_t total_num_entries = 0;
6179 struct samr_SamArray *sam;
6181 r.in.domain_handle = domain_handle;
6182 r.in.max_size = (uint32_t)-1;
6183 r.in.resume_handle = &resume_handle;
6185 r.out.sam = &sam;
6186 r.out.num_entries = &num_entries;
6187 r.out.resume_handle = &resume_handle;
6189 torture_comment(tctx, "Testing EnumDomainAliases\n");
6191 do {
6192 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
6193 if (NT_STATUS_IS_ERR(status)) {
6194 torture_assert_ntstatus_ok(tctx, status,
6195 "failed to enumerate aliases");
6198 total_num_entries += num_entries;
6199 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6201 if (total_num_entries_p) {
6202 *total_num_entries_p = total_num_entries;
6205 return true;
6208 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
6209 struct torture_context *tctx,
6210 struct policy_handle *handle,
6211 uint16_t level,
6212 uint32_t *total_num_entries_p)
6214 NTSTATUS status;
6215 struct samr_QueryDisplayInfo r;
6216 uint32_t total_num_entries = 0;
6218 r.in.domain_handle = handle;
6219 r.in.level = level;
6220 r.in.start_idx = 0;
6221 r.in.max_entries = (uint32_t)-1;
6222 r.in.buf_size = (uint32_t)-1;
6224 torture_comment(tctx, "Testing QueryDisplayInfo\n");
6226 do {
6227 uint32_t total_size;
6228 uint32_t returned_size;
6229 union samr_DispInfo info;
6231 r.out.total_size = &total_size;
6232 r.out.returned_size = &returned_size;
6233 r.out.info = &info;
6235 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6236 if (NT_STATUS_IS_ERR(status)) {
6237 torture_assert_ntstatus_ok(tctx, status,
6238 "failed to query displayinfo");
6241 if (*r.out.returned_size == 0) {
6242 break;
6245 switch (r.in.level) {
6246 case 1:
6247 total_num_entries += info.info1.count;
6248 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
6249 break;
6250 case 2:
6251 total_num_entries += info.info2.count;
6252 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
6253 break;
6254 case 3:
6255 total_num_entries += info.info3.count;
6256 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
6257 break;
6258 case 4:
6259 total_num_entries += info.info4.count;
6260 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
6261 break;
6262 case 5:
6263 total_num_entries += info.info5.count;
6264 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
6265 break;
6266 default:
6267 return false;
6270 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6272 if (total_num_entries_p) {
6273 *total_num_entries_p = total_num_entries;
6276 return true;
6279 static bool test_ManyObjects(struct dcerpc_pipe *p,
6280 struct torture_context *tctx,
6281 struct policy_handle *domain_handle,
6282 struct dom_sid *domain_sid,
6283 struct torture_samr_context *ctx)
6285 uint32_t num_total = ctx->num_objects_large_dc;
6286 uint32_t num_enum = 0;
6287 uint32_t num_disp = 0;
6288 uint32_t num_created = 0;
6289 uint32_t num_anounced = 0;
6290 bool ret = true;
6291 NTSTATUS status;
6292 uint32_t i;
6294 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
6296 /* query */
6299 struct samr_QueryDomainInfo2 r;
6300 union samr_DomainInfo *info;
6301 r.in.domain_handle = domain_handle;
6302 r.in.level = 2;
6303 r.out.info = &info;
6305 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6306 torture_assert_ntstatus_ok(tctx, status,
6307 "failed to query domain info");
6309 switch (ctx->choice) {
6310 case TORTURE_SAMR_MANY_ACCOUNTS:
6311 num_anounced = info->general.num_users;
6312 break;
6313 case TORTURE_SAMR_MANY_GROUPS:
6314 num_anounced = info->general.num_groups;
6315 break;
6316 case TORTURE_SAMR_MANY_ALIASES:
6317 num_anounced = info->general.num_aliases;
6318 break;
6319 default:
6320 return false;
6324 /* create */
6326 for (i=0; i < num_total; i++) {
6328 const char *name = NULL;
6330 switch (ctx->choice) {
6331 case TORTURE_SAMR_MANY_ACCOUNTS:
6332 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
6333 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
6334 break;
6335 case TORTURE_SAMR_MANY_GROUPS:
6336 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
6337 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6338 break;
6339 case TORTURE_SAMR_MANY_ALIASES:
6340 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
6341 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6342 break;
6343 default:
6344 return false;
6346 if (!policy_handle_empty(&handles[i])) {
6347 num_created++;
6351 /* enum */
6353 switch (ctx->choice) {
6354 case TORTURE_SAMR_MANY_ACCOUNTS:
6355 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
6356 break;
6357 case TORTURE_SAMR_MANY_GROUPS:
6358 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
6359 break;
6360 case TORTURE_SAMR_MANY_ALIASES:
6361 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
6362 break;
6363 default:
6364 return false;
6367 /* dispinfo */
6369 switch (ctx->choice) {
6370 case TORTURE_SAMR_MANY_ACCOUNTS:
6371 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
6372 break;
6373 case TORTURE_SAMR_MANY_GROUPS:
6374 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
6375 break;
6376 case TORTURE_SAMR_MANY_ALIASES:
6377 /* no aliases in dispinfo */
6378 break;
6379 default:
6380 return false;
6383 /* close or delete */
6385 for (i=0; i < num_total; i++) {
6387 if (policy_handle_empty(&handles[i])) {
6388 continue;
6391 if (torture_setting_bool(tctx, "samba3", false)) {
6392 ret &= test_samr_handle_Close(p, tctx, &handles[i]);
6393 } else {
6394 switch (ctx->choice) {
6395 case TORTURE_SAMR_MANY_ACCOUNTS:
6396 ret &= test_DeleteUser(p, tctx, &handles[i]);
6397 break;
6398 case TORTURE_SAMR_MANY_GROUPS:
6399 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
6400 break;
6401 case TORTURE_SAMR_MANY_ALIASES:
6402 ret &= test_DeleteAlias(p, tctx, &handles[i]);
6403 break;
6404 default:
6405 return false;
6410 talloc_free(handles);
6412 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
6413 torture_comment(tctx,
6414 "unexpected number of results (%u) returned in enum call, expected %u\n",
6415 num_enum, num_anounced + num_created);
6417 torture_comment(tctx,
6418 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
6419 num_disp, num_anounced + num_created);
6421 return ret;
6424 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6425 struct policy_handle *handle);
6427 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6428 struct torture_samr_context *ctx, struct dom_sid *sid)
6430 NTSTATUS status;
6431 struct samr_OpenDomain r;
6432 struct policy_handle domain_handle;
6433 struct policy_handle alias_handle;
6434 struct policy_handle user_handle;
6435 struct policy_handle group_handle;
6436 bool ret = true;
6438 ZERO_STRUCT(alias_handle);
6439 ZERO_STRUCT(user_handle);
6440 ZERO_STRUCT(group_handle);
6441 ZERO_STRUCT(domain_handle);
6443 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
6445 r.in.connect_handle = &ctx->handle;
6446 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6447 r.in.sid = sid;
6448 r.out.domain_handle = &domain_handle;
6450 status = dcerpc_samr_OpenDomain(p, tctx, &r);
6451 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
6453 /* run the domain tests with the main handle closed - this tests
6454 the servers reference counting */
6455 torture_assert(tctx, test_samr_handle_Close(p, tctx, &ctx->handle), "Failed to close SAMR handle");
6457 switch (ctx->choice) {
6458 case TORTURE_SAMR_PASSWORDS:
6459 case TORTURE_SAMR_USER_PRIVILEGES:
6460 if (!torture_setting_bool(tctx, "samba3", false)) {
6461 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
6463 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6464 if (!ret) {
6465 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
6467 break;
6468 case TORTURE_SAMR_USER_ATTRIBUTES:
6469 if (!torture_setting_bool(tctx, "samba3", false)) {
6470 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
6472 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6473 /* This test needs 'complex' users to validate */
6474 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
6475 if (!ret) {
6476 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
6478 break;
6479 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
6480 if (!torture_setting_bool(tctx, "samba3", false)) {
6481 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
6483 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
6484 if (!ret) {
6485 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
6487 break;
6488 case TORTURE_SAMR_MANY_ACCOUNTS:
6489 case TORTURE_SAMR_MANY_GROUPS:
6490 case TORTURE_SAMR_MANY_ALIASES:
6491 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
6492 if (!ret) {
6493 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
6495 break;
6496 case TORTURE_SAMR_OTHER:
6497 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6498 if (!ret) {
6499 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
6501 if (!torture_setting_bool(tctx, "samba3", false)) {
6502 ret &= test_QuerySecurity(p, tctx, &domain_handle);
6504 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
6505 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
6506 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
6507 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
6508 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
6509 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
6510 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
6511 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
6512 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
6513 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
6514 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
6515 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
6517 if (torture_setting_bool(tctx, "samba4", false)) {
6518 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
6519 } else {
6520 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
6521 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
6523 ret &= test_GroupList(p, tctx, &domain_handle);
6524 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
6525 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
6526 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
6527 if (!ret) {
6528 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
6530 break;
6533 if (!policy_handle_empty(&user_handle) &&
6534 !test_DeleteUser(p, tctx, &user_handle)) {
6535 ret = false;
6538 if (!policy_handle_empty(&alias_handle) &&
6539 !test_DeleteAlias(p, tctx, &alias_handle)) {
6540 ret = false;
6543 if (!policy_handle_empty(&group_handle) &&
6544 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
6545 ret = false;
6548 torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
6550 torture_assert(tctx, test_Connect(p, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
6551 /* reconnect the main handle */
6553 if (!ret) {
6554 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
6557 return ret;
6560 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6561 struct torture_samr_context *ctx, const char *domain)
6563 NTSTATUS status;
6564 struct samr_LookupDomain r;
6565 struct dom_sid2 *sid = NULL;
6566 struct lsa_String n1;
6567 struct lsa_String n2;
6568 bool ret = true;
6570 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
6572 /* check for correct error codes */
6573 r.in.connect_handle = &ctx->handle;
6574 r.in.domain_name = &n2;
6575 r.out.sid = &sid;
6576 n2.string = NULL;
6578 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6579 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
6581 init_lsa_String(&n2, "xxNODOMAINxx");
6583 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6584 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
6586 r.in.connect_handle = &ctx->handle;
6588 init_lsa_String(&n1, domain);
6589 r.in.domain_name = &n1;
6591 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6592 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
6594 if (!test_GetDomPwInfo(p, tctx, &n1)) {
6595 ret = false;
6598 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
6599 ret = false;
6602 return ret;
6606 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
6607 struct torture_samr_context *ctx)
6609 NTSTATUS status;
6610 struct samr_EnumDomains r;
6611 uint32_t resume_handle = 0;
6612 uint32_t num_entries = 0;
6613 struct samr_SamArray *sam = NULL;
6614 int i;
6615 bool ret = true;
6617 r.in.connect_handle = &ctx->handle;
6618 r.in.resume_handle = &resume_handle;
6619 r.in.buf_size = (uint32_t)-1;
6620 r.out.resume_handle = &resume_handle;
6621 r.out.num_entries = &num_entries;
6622 r.out.sam = &sam;
6624 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6625 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6627 if (!*r.out.sam) {
6628 return false;
6631 for (i=0;i<sam->count;i++) {
6632 if (!test_LookupDomain(p, tctx, ctx,
6633 sam->entries[i].name.string)) {
6634 ret = false;
6638 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6639 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6641 return ret;
6645 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6646 struct policy_handle *handle)
6648 NTSTATUS status;
6649 struct samr_Connect r;
6650 struct samr_Connect2 r2;
6651 struct samr_Connect3 r3;
6652 struct samr_Connect4 r4;
6653 struct samr_Connect5 r5;
6654 union samr_ConnectInfo info;
6655 struct policy_handle h;
6656 uint32_t level_out = 0;
6657 bool ret = true, got_handle = false;
6659 torture_comment(tctx, "testing samr_Connect\n");
6661 r.in.system_name = 0;
6662 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6663 r.out.connect_handle = &h;
6665 status = dcerpc_samr_Connect(p, tctx, &r);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
6668 ret = false;
6669 } else {
6670 got_handle = true;
6671 *handle = h;
6674 torture_comment(tctx, "testing samr_Connect2\n");
6676 r2.in.system_name = NULL;
6677 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6678 r2.out.connect_handle = &h;
6680 status = dcerpc_samr_Connect2(p, tctx, &r2);
6681 if (!NT_STATUS_IS_OK(status)) {
6682 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
6683 ret = false;
6684 } else {
6685 if (got_handle) {
6686 test_samr_handle_Close(p, tctx, handle);
6688 got_handle = true;
6689 *handle = h;
6692 torture_comment(tctx, "testing samr_Connect3\n");
6694 r3.in.system_name = NULL;
6695 r3.in.unknown = 0;
6696 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6697 r3.out.connect_handle = &h;
6699 status = dcerpc_samr_Connect3(p, tctx, &r3);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
6702 ret = false;
6703 } else {
6704 if (got_handle) {
6705 test_samr_handle_Close(p, tctx, handle);
6707 got_handle = true;
6708 *handle = h;
6711 torture_comment(tctx, "testing samr_Connect4\n");
6713 r4.in.system_name = "";
6714 r4.in.client_version = 0;
6715 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6716 r4.out.connect_handle = &h;
6718 status = dcerpc_samr_Connect4(p, tctx, &r4);
6719 if (!NT_STATUS_IS_OK(status)) {
6720 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
6721 ret = false;
6722 } else {
6723 if (got_handle) {
6724 test_samr_handle_Close(p, tctx, handle);
6726 got_handle = true;
6727 *handle = h;
6730 torture_comment(tctx, "testing samr_Connect5\n");
6732 info.info1.client_version = 0;
6733 info.info1.unknown2 = 0;
6735 r5.in.system_name = "";
6736 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6737 r5.in.level_in = 1;
6738 r5.out.level_out = &level_out;
6739 r5.in.info_in = &info;
6740 r5.out.info_out = &info;
6741 r5.out.connect_handle = &h;
6743 status = dcerpc_samr_Connect5(p, tctx, &r5);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
6746 ret = false;
6747 } else {
6748 if (got_handle) {
6749 test_samr_handle_Close(p, tctx, handle);
6751 got_handle = true;
6752 *handle = h;
6755 return ret;
6759 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_context *tctx)
6761 struct samr_ValidatePassword r;
6762 union samr_ValidatePasswordReq req;
6763 union samr_ValidatePasswordRep *repp = NULL;
6764 NTSTATUS status;
6765 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
6766 int i;
6768 torture_comment(tctx, "testing samr_ValidatePassword\n");
6770 ZERO_STRUCT(r);
6771 r.in.level = NetValidatePasswordReset;
6772 r.in.req = &req;
6773 r.out.rep = &repp;
6775 ZERO_STRUCT(req);
6776 req.req3.account.string = "non-existant-account-aklsdji";
6778 for (i=0; passwords[i]; i++) {
6779 req.req3.password.string = passwords[i];
6780 status = dcerpc_samr_ValidatePassword(p, tctx, &r);
6781 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
6782 torture_comment(tctx, "Server %s password '%s' with code %i\n",
6783 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
6784 req.req3.password.string, repp->ctr3.status);
6787 return true;
6790 bool torture_rpc_samr(struct torture_context *torture)
6792 NTSTATUS status;
6793 struct dcerpc_pipe *p;
6794 bool ret = true;
6795 struct torture_samr_context *ctx;
6797 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 return false;
6802 ctx = talloc_zero(torture, struct torture_samr_context);
6804 ctx->choice = TORTURE_SAMR_OTHER;
6806 ret &= test_Connect(p, torture, &ctx->handle);
6808 if (!torture_setting_bool(torture, "samba3", false)) {
6809 ret &= test_QuerySecurity(p, torture, &ctx->handle);
6812 ret &= test_EnumDomains(p, torture, ctx);
6814 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
6816 ret &= test_Shutdown(p, torture, &ctx->handle);
6818 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6820 return ret;
6824 bool torture_rpc_samr_users(struct torture_context *torture)
6826 NTSTATUS status;
6827 struct dcerpc_pipe *p;
6828 bool ret = true;
6829 struct torture_samr_context *ctx;
6831 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6832 if (!NT_STATUS_IS_OK(status)) {
6833 return false;
6836 ctx = talloc_zero(torture, struct torture_samr_context);
6838 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
6840 ret &= test_Connect(p, torture, &ctx->handle);
6842 if (!torture_setting_bool(torture, "samba3", false)) {
6843 ret &= test_QuerySecurity(p, torture, &ctx->handle);
6846 ret &= test_EnumDomains(p, torture, ctx);
6848 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
6850 ret &= test_Shutdown(p, torture, &ctx->handle);
6852 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6854 return ret;
6858 bool torture_rpc_samr_passwords(struct torture_context *torture)
6860 NTSTATUS status;
6861 struct dcerpc_pipe *p;
6862 bool ret = true;
6863 struct torture_samr_context *ctx;
6865 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6866 if (!NT_STATUS_IS_OK(status)) {
6867 return false;
6870 ctx = talloc_zero(torture, struct torture_samr_context);
6872 ctx->choice = TORTURE_SAMR_PASSWORDS;
6874 ret &= test_Connect(p, torture, &ctx->handle);
6876 ret &= test_EnumDomains(p, torture, ctx);
6878 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6880 ret &= test_samr_ValidatePassword(p, torture);
6882 return ret;
6885 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6886 struct dcerpc_pipe *p2,
6887 struct cli_credentials *machine_credentials)
6889 NTSTATUS status;
6890 struct dcerpc_pipe *p;
6891 bool ret = true;
6892 struct torture_samr_context *ctx;
6894 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6895 if (!NT_STATUS_IS_OK(status)) {
6896 return false;
6899 ctx = talloc_zero(torture, struct torture_samr_context);
6901 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
6902 ctx->machine_credentials = machine_credentials;
6904 ret &= test_Connect(p, torture, &ctx->handle);
6906 ret &= test_EnumDomains(p, torture, ctx);
6908 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6910 return ret;
6913 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6915 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6916 struct torture_rpc_tcase *tcase;
6918 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6919 &ndr_table_samr,
6920 TEST_ACCOUNT_NAME_PWD);
6922 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6923 torture_rpc_samr_pwdlastset);
6925 return suite;
6928 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
6929 struct dcerpc_pipe *p2,
6930 struct cli_credentials *machine_credentials)
6932 NTSTATUS status;
6933 struct dcerpc_pipe *p;
6934 bool ret = true;
6935 struct torture_samr_context *ctx;
6937 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 return false;
6942 ctx = talloc_zero(torture, struct torture_samr_context);
6944 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
6945 ctx->machine_credentials = machine_credentials;
6947 ret &= test_Connect(p, torture, &ctx->handle);
6949 ret &= test_EnumDomains(p, torture, ctx);
6951 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6953 return ret;
6956 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
6958 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
6959 struct torture_rpc_tcase *tcase;
6961 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6962 &ndr_table_samr,
6963 TEST_ACCOUNT_NAME_PWD);
6965 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
6966 torture_rpc_samr_users_privileges_delete_user);
6968 return suite;
6971 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
6972 struct dcerpc_pipe *p2,
6973 struct cli_credentials *machine_credentials)
6975 NTSTATUS status;
6976 struct dcerpc_pipe *p;
6977 bool ret = true;
6978 struct torture_samr_context *ctx;
6980 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6981 if (!NT_STATUS_IS_OK(status)) {
6982 return false;
6985 ctx = talloc_zero(torture, struct torture_samr_context);
6987 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
6988 ctx->num_objects_large_dc = 1500;
6990 ret &= test_Connect(p, torture, &ctx->handle);
6992 ret &= test_EnumDomains(p, torture, ctx);
6994 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6996 return ret;
6999 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7000 struct dcerpc_pipe *p2,
7001 struct cli_credentials *machine_credentials)
7003 NTSTATUS status;
7004 struct dcerpc_pipe *p;
7005 bool ret = true;
7006 struct torture_samr_context *ctx;
7008 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 return false;
7013 ctx = talloc_zero(torture, struct torture_samr_context);
7015 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
7016 ctx->num_objects_large_dc = 1500;
7018 ret &= test_Connect(p, torture, &ctx->handle);
7020 ret &= test_EnumDomains(p, torture, ctx);
7022 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7024 return ret;
7027 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7028 struct dcerpc_pipe *p2,
7029 struct cli_credentials *machine_credentials)
7031 NTSTATUS status;
7032 struct dcerpc_pipe *p;
7033 bool ret = true;
7034 struct torture_samr_context *ctx;
7036 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 return false;
7041 ctx = talloc_zero(torture, struct torture_samr_context);
7043 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
7044 ctx->num_objects_large_dc = 1500;
7046 ret &= test_Connect(p, torture, &ctx->handle);
7048 ret &= test_EnumDomains(p, torture, ctx);
7050 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7052 return ret;
7055 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7057 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7058 struct torture_rpc_tcase *tcase;
7060 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7061 &ndr_table_samr,
7062 TEST_ACCOUNT_NAME);
7064 torture_rpc_tcase_add_test_creds(tcase, "many_aliases",
7065 torture_rpc_samr_many_aliases);
7066 torture_rpc_tcase_add_test_creds(tcase, "many_groups",
7067 torture_rpc_samr_many_groups);
7068 torture_rpc_tcase_add_test_creds(tcase, "many_accounts",
7069 torture_rpc_samr_many_accounts);
7071 return suite;