s4-smbtorture: add a samr_GetAliasMembership test to RPC-SAMR.
[Samba/bb.git] / source4 / torture / rpc / samr.c
blob903d5382a2a7d04706b33d305572d7d5cac9d67f
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 samr_ChangeReject *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->reason != SAMR_REJECT_OTHER)) {
2280 torture_warning(tctx, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2281 SAMR_REJECT_OTHER, reject->reason);
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->reason != SAMR_REJECT_OTHER) {
2299 torture_warning(tctx, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2300 SAMR_REJECT_OTHER, reject->reason);
2301 return false;
2304 } else if ((dominfo->min_password_length > 0) &&
2305 (strlen(newpass) < dominfo->min_password_length)) {
2307 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2308 torture_warning(tctx, "expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2309 SAMR_REJECT_TOO_SHORT, reject->reason);
2310 return false;
2313 } else if ((dominfo->password_history_length > 0) &&
2314 strequal(oldpass, newpass)) {
2316 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2317 torture_warning(tctx, "expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2318 SAMR_REJECT_IN_HISTORY, reject->reason);
2319 return false;
2321 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2323 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2324 torture_warning(tctx, "expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2325 SAMR_REJECT_COMPLEXITY, reject->reason);
2326 return false;
2331 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2332 /* retry with adjusted size */
2333 return test_ChangePasswordUser3(p, tctx, account_string,
2334 dominfo->min_password_length,
2335 password, NULL, 0, false);
2339 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2340 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2341 torture_warning(tctx, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2342 SAMR_REJECT_OTHER, reject->reason);
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 samr_ChangeReject *reject = NULL;
2381 new_random_pass = samr_very_rand_pass(tctx, 128);
2383 torture_assert(tctx, *password != NULL,
2384 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2386 oldpass = *password;
2387 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2388 init_lsa_String(&account, account_string);
2390 s.in.user_handle = handle;
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->reason != SAMR_REJECT_OTHER) {
2455 torture_warning(tctx, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2456 SAMR_REJECT_OTHER, reject->reason);
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->reason != SAMR_REJECT_OTHER) {
2493 torture_warning(tctx, "expected SAMR_REJECT_OTHER (%d), got %d\n",
2494 SAMR_REJECT_OTHER, reject->reason);
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_GetAliasMembership(struct dcerpc_pipe *p,
2597 struct torture_context *tctx,
2598 struct policy_handle *domain_handle)
2600 struct samr_GetAliasMembership r;
2601 struct lsa_SidArray sids;
2602 struct samr_Ids rids;
2603 NTSTATUS status;
2605 torture_comment(tctx, "Testing GetAliasMembership\n");
2607 r.in.domain_handle = domain_handle;
2608 r.in.sids = &sids;
2609 r.out.rids = &rids;
2611 sids.num_sids = 0;
2612 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2614 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2615 torture_assert_ntstatus_ok(tctx, status,
2616 "samr_GetAliasMembership failed");
2618 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2619 "protocol misbehaviour");
2621 sids.num_sids = 1;
2622 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2623 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2625 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2626 torture_assert_ntstatus_ok(tctx, status,
2627 "samr_GetAliasMembership failed");
2629 #if 0
2630 /* only true for w2k8 it seems
2631 * win7, xp, w2k3 will return a 0 length array pointer */
2633 torture_assert(tctx, (rids.ids && !rids.count),
2634 "samr_GetAliasMembership protocol misbehaviour");
2635 #endif
2636 torture_assert(tctx, (!rids.ids && rids.count),
2637 "samr_GetAliasMembership protocol misbehaviour");
2639 return true;
2642 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2643 struct policy_handle *user_handle)
2645 struct samr_TestPrivateFunctionsUser r;
2646 NTSTATUS status;
2648 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2650 r.in.user_handle = user_handle;
2652 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2653 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2655 return true;
2658 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2659 struct torture_context *tctx,
2660 struct policy_handle *handle,
2661 bool use_info2,
2662 NTTIME *pwdlastset)
2664 NTSTATUS status;
2665 uint16_t levels[] = { /* 3, */ 5, 21 };
2666 int i;
2667 NTTIME pwdlastset3 = 0;
2668 NTTIME pwdlastset5 = 0;
2669 NTTIME pwdlastset21 = 0;
2671 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2672 use_info2 ? "2":"");
2674 for (i=0; i<ARRAY_SIZE(levels); i++) {
2676 struct samr_QueryUserInfo r;
2677 struct samr_QueryUserInfo2 r2;
2678 union samr_UserInfo *info;
2680 if (use_info2) {
2681 r2.in.user_handle = handle;
2682 r2.in.level = levels[i];
2683 r2.out.info = &info;
2684 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2686 } else {
2687 r.in.user_handle = handle;
2688 r.in.level = levels[i];
2689 r.out.info = &info;
2690 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2693 if (!NT_STATUS_IS_OK(status) &&
2694 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2695 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2696 use_info2 ? "2":"", levels[i], nt_errstr(status));
2697 return false;
2700 switch (levels[i]) {
2701 case 3:
2702 pwdlastset3 = info->info3.last_password_change;
2703 break;
2704 case 5:
2705 pwdlastset5 = info->info5.last_password_change;
2706 break;
2707 case 21:
2708 pwdlastset21 = info->info21.last_password_change;
2709 break;
2710 default:
2711 return false;
2714 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2715 "pwdlastset mixup"); */
2716 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2717 "pwdlastset mixup");
2719 *pwdlastset = pwdlastset21;
2721 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2723 return true;
2726 static bool test_SamLogon(struct torture_context *tctx,
2727 struct dcerpc_pipe *p,
2728 struct cli_credentials *test_credentials,
2729 NTSTATUS expected_result)
2731 NTSTATUS status;
2732 struct netr_LogonSamLogonEx r;
2733 union netr_LogonLevel logon;
2734 union netr_Validation validation;
2735 uint8_t authoritative;
2736 struct netr_NetworkInfo ninfo;
2737 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2738 int flags = CLI_CRED_NTLM_AUTH;
2739 uint32_t samlogon_flags = 0;
2741 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2742 flags |= CLI_CRED_LANMAN_AUTH;
2745 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2746 flags |= CLI_CRED_NTLMv2_AUTH;
2749 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2750 &ninfo.identity_info.account_name.string,
2751 &ninfo.identity_info.domain_name.string);
2753 generate_random_buffer(ninfo.challenge,
2754 sizeof(ninfo.challenge));
2755 chal = data_blob_const(ninfo.challenge,
2756 sizeof(ninfo.challenge));
2758 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2759 cli_credentials_get_domain(test_credentials));
2761 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2762 &flags,
2763 chal,
2764 names_blob,
2765 &lm_resp, &nt_resp,
2766 NULL, NULL);
2767 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2769 ninfo.lm.data = lm_resp.data;
2770 ninfo.lm.length = lm_resp.length;
2772 ninfo.nt.data = nt_resp.data;
2773 ninfo.nt.length = nt_resp.length;
2775 ninfo.identity_info.parameter_control =
2776 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2777 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2778 ninfo.identity_info.logon_id_low = 0;
2779 ninfo.identity_info.logon_id_high = 0;
2780 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(test_credentials);
2782 logon.network = &ninfo;
2784 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2785 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2786 r.in.logon_level = NetlogonNetworkInformation;
2787 r.in.logon = &logon;
2788 r.in.flags = &samlogon_flags;
2789 r.out.flags = &samlogon_flags;
2790 r.out.validation = &validation;
2791 r.out.authoritative = &authoritative;
2793 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2795 r.in.validation_level = 6;
2797 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2798 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2799 r.in.validation_level = 3;
2800 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2804 return true;
2805 } else {
2806 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2809 return true;
2812 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2813 struct dcerpc_pipe *p,
2814 struct cli_credentials *machine_creds,
2815 const char *acct_name,
2816 char *password,
2817 NTSTATUS expected_samlogon_result)
2819 bool ret = true;
2820 struct cli_credentials *test_credentials;
2822 test_credentials = cli_credentials_init(tctx);
2824 cli_credentials_set_workstation(test_credentials,
2825 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2826 cli_credentials_set_domain(test_credentials,
2827 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2828 cli_credentials_set_username(test_credentials,
2829 acct_name, CRED_SPECIFIED);
2830 cli_credentials_set_password(test_credentials,
2831 password, CRED_SPECIFIED);
2833 torture_comment(tctx, "testing samlogon as %s password: %s\n",
2834 acct_name, password);
2836 if (!test_SamLogon(tctx, p, test_credentials,
2837 expected_samlogon_result)) {
2838 torture_warning(tctx, "new password did not work\n");
2839 ret = false;
2842 return ret;
2845 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2846 struct dcerpc_pipe *np,
2847 struct torture_context *tctx,
2848 struct policy_handle *handle,
2849 uint16_t level,
2850 uint32_t fields_present,
2851 uint8_t password_expired,
2852 bool *matched_expected_error,
2853 bool use_setinfo2,
2854 const char *acct_name,
2855 char **password,
2856 struct cli_credentials *machine_creds,
2857 bool use_queryinfo2,
2858 NTTIME *pwdlastset,
2859 NTSTATUS expected_samlogon_result)
2861 const char *fields = NULL;
2862 bool ret = true;
2864 switch (level) {
2865 case 21:
2866 case 23:
2867 case 25:
2868 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2869 fields_present);
2870 break;
2871 default:
2872 break;
2875 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2876 "(password_expired: %d) %s\n",
2877 use_setinfo2 ? "2":"", level, password_expired,
2878 fields ? fields : "");
2880 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2881 fields_present,
2882 password,
2883 password_expired,
2884 use_setinfo2,
2885 matched_expected_error)) {
2886 ret = false;
2889 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2890 use_queryinfo2,
2891 pwdlastset)) {
2892 ret = false;
2895 if (*matched_expected_error == true) {
2896 return ret;
2899 if (!test_SamLogon_with_creds(tctx, np,
2900 machine_creds,
2901 acct_name,
2902 *password,
2903 expected_samlogon_result)) {
2904 ret = false;
2907 return ret;
2910 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2911 struct torture_context *tctx,
2912 uint32_t acct_flags,
2913 const char *acct_name,
2914 struct policy_handle *handle,
2915 char **password,
2916 struct cli_credentials *machine_credentials)
2918 int s = 0, q = 0, f = 0, l = 0, z = 0;
2919 struct dcerpc_binding *b;
2920 bool ret = true;
2921 int delay = 50000;
2922 bool set_levels[] = { false, true };
2923 bool query_levels[] = { false, true };
2924 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2925 uint32_t nonzeros[] = { 1, 24 };
2926 uint32_t fields_present[] = {
2928 SAMR_FIELD_EXPIRED_FLAG,
2929 SAMR_FIELD_LAST_PWD_CHANGE,
2930 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2931 SAMR_FIELD_COMMENT,
2932 SAMR_FIELD_NT_PASSWORD_PRESENT,
2933 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2934 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2935 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2936 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2937 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2938 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2940 NTSTATUS status;
2941 struct dcerpc_pipe *np = NULL;
2943 if (torture_setting_bool(tctx, "samba3", false)) {
2944 delay = 999999;
2945 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
2946 delay);
2949 status = torture_rpc_binding(tctx, &b);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 ret = false;
2952 return ret;
2955 /* We have to use schannel, otherwise the SamLogonEx fails
2956 * with INTERNAL_ERROR */
2958 b->flags &= ~DCERPC_AUTH_OPTIONS;
2959 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2961 status = dcerpc_pipe_connect_b(tctx, &np, b,
2962 &ndr_table_netlogon,
2963 machine_credentials, tctx->ev, tctx->lp_ctx);
2965 if (!NT_STATUS_IS_OK(status)) {
2966 torture_warning(tctx, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
2967 ret = false;
2968 return ret;
2971 /* set to 1 to enable testing for all possible opcode
2972 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2973 combinations */
2974 #if 0
2975 #define TEST_ALL_LEVELS 1
2976 #define TEST_SET_LEVELS 1
2977 #define TEST_QUERY_LEVELS 1
2978 #endif
2979 #ifdef TEST_ALL_LEVELS
2980 for (l=0; l<ARRAY_SIZE(levels); l++) {
2981 #else
2982 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
2983 #endif
2984 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2985 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2986 #ifdef TEST_SET_LEVELS
2987 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2988 #endif
2989 #ifdef TEST_QUERY_LEVELS
2990 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2991 #endif
2992 NTTIME pwdlastset_old = 0;
2993 NTTIME pwdlastset_new = 0;
2994 bool matched_expected_error = false;
2995 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2997 torture_comment(tctx, "------------------------------\n"
2998 "Testing pwdLastSet attribute for flags: 0x%08x "
2999 "(s: %d (l: %d), q: %d)\n",
3000 acct_flags, s, levels[l], q);
3002 switch (levels[l]) {
3003 case 21:
3004 case 23:
3005 case 25:
3006 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3007 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3008 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3010 break;
3014 /* set #1 */
3016 /* set a password and force password change (pwdlastset 0) by
3017 * setting the password expired flag to a non-0 value */
3019 if (!test_SetPassword_level(p, np, tctx, handle,
3020 levels[l],
3021 fields_present[f],
3022 nonzeros[z],
3023 &matched_expected_error,
3024 set_levels[s],
3025 acct_name,
3026 password,
3027 machine_credentials,
3028 query_levels[q],
3029 &pwdlastset_old,
3030 expected_samlogon_result)) {
3031 ret = false;
3034 if (matched_expected_error == true) {
3035 /* skipping on expected failure */
3036 continue;
3039 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3040 * set without the SAMR_FIELD_EXPIRED_FLAG */
3042 switch (levels[l]) {
3043 case 21:
3044 case 23:
3045 case 25:
3046 if ((pwdlastset_new != 0) &&
3047 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3048 torture_comment(tctx, "not considering a non-0 "
3049 "pwdLastSet as a an error as the "
3050 "SAMR_FIELD_EXPIRED_FLAG has not "
3051 "been set\n");
3052 break;
3054 default:
3055 if (pwdlastset_new != 0) {
3056 torture_warning(tctx, "pwdLastSet test failed: "
3057 "expected pwdLastSet 0 but got %lld\n",
3058 pwdlastset_old);
3059 ret = false;
3061 break;
3064 switch (levels[l]) {
3065 case 21:
3066 case 23:
3067 case 25:
3068 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3069 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3070 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3071 (pwdlastset_old >= pwdlastset_new)) {
3072 torture_warning(tctx, "pwdlastset not increasing\n");
3073 ret = false;
3075 break;
3076 default:
3077 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3078 (pwdlastset_old >= pwdlastset_new)) {
3079 torture_warning(tctx, "pwdlastset not increasing\n");
3080 ret = false;
3082 break;
3085 usleep(delay);
3087 /* set #2 */
3089 /* set a password, pwdlastset needs to get updated (increased
3090 * value), password_expired value used here is 0 */
3092 if (!test_SetPassword_level(p, np, tctx, handle,
3093 levels[l],
3094 fields_present[f],
3096 &matched_expected_error,
3097 set_levels[s],
3098 acct_name,
3099 password,
3100 machine_credentials,
3101 query_levels[q],
3102 &pwdlastset_new,
3103 expected_samlogon_result)) {
3104 ret = false;
3107 /* when a password has been changed, pwdlastset must not be 0 afterwards
3108 * and must be larger then the old value */
3110 switch (levels[l]) {
3111 case 21:
3112 case 23:
3113 case 25:
3115 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3116 * password has been changed, old and new pwdlastset
3117 * need to be the same value */
3119 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3120 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3121 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3123 torture_assert_int_equal(tctx, pwdlastset_old,
3124 pwdlastset_new, "pwdlastset must be equal");
3125 break;
3127 default:
3128 if (pwdlastset_old >= pwdlastset_new) {
3129 torture_warning(tctx, "pwdLastSet test failed: "
3130 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3131 pwdlastset_old, pwdlastset_new);
3132 ret = false;
3134 if (pwdlastset_new == 0) {
3135 torture_warning(tctx, "pwdLastSet test failed: "
3136 "expected non-0 pwdlastset, got: %lld\n",
3137 pwdlastset_new);
3138 ret = false;
3142 switch (levels[l]) {
3143 case 21:
3144 case 23:
3145 case 25:
3146 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3147 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3148 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3149 (pwdlastset_old >= pwdlastset_new)) {
3150 torture_warning(tctx, "pwdlastset not increasing\n");
3151 ret = false;
3153 break;
3154 default:
3155 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3156 (pwdlastset_old >= pwdlastset_new)) {
3157 torture_warning(tctx, "pwdlastset not increasing\n");
3158 ret = false;
3160 break;
3163 pwdlastset_old = pwdlastset_new;
3165 usleep(delay);
3167 /* set #2b */
3169 /* set a password, pwdlastset needs to get updated (increased
3170 * value), password_expired value used here is 0 */
3172 if (!test_SetPassword_level(p, np, tctx, handle,
3173 levels[l],
3174 fields_present[f],
3176 &matched_expected_error,
3177 set_levels[s],
3178 acct_name,
3179 password,
3180 machine_credentials,
3181 query_levels[q],
3182 &pwdlastset_new,
3183 expected_samlogon_result)) {
3184 ret = false;
3187 /* when a password has been changed, pwdlastset must not be 0 afterwards
3188 * and must be larger then the old value */
3190 switch (levels[l]) {
3191 case 21:
3192 case 23:
3193 case 25:
3195 /* if no password has been changed, old and new pwdlastset
3196 * need to be the same value */
3198 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3199 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3201 torture_assert_int_equal(tctx, pwdlastset_old,
3202 pwdlastset_new, "pwdlastset must be equal");
3203 break;
3205 default:
3206 if (pwdlastset_old >= pwdlastset_new) {
3207 torture_warning(tctx, "pwdLastSet test failed: "
3208 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3209 pwdlastset_old, pwdlastset_new);
3210 ret = false;
3212 if (pwdlastset_new == 0) {
3213 torture_warning(tctx, "pwdLastSet test failed: "
3214 "expected non-0 pwdlastset, got: %lld\n",
3215 pwdlastset_new);
3216 ret = false;
3220 /* set #3 */
3222 /* set a password and force password change (pwdlastset 0) by
3223 * setting the password expired flag to a non-0 value */
3225 if (!test_SetPassword_level(p, np, tctx, handle,
3226 levels[l],
3227 fields_present[f],
3228 nonzeros[z],
3229 &matched_expected_error,
3230 set_levels[s],
3231 acct_name,
3232 password,
3233 machine_credentials,
3234 query_levels[q],
3235 &pwdlastset_new,
3236 expected_samlogon_result)) {
3237 ret = false;
3240 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3241 * set without the SAMR_FIELD_EXPIRED_FLAG */
3243 switch (levels[l]) {
3244 case 21:
3245 case 23:
3246 case 25:
3247 if ((pwdlastset_new != 0) &&
3248 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3249 torture_comment(tctx, "not considering a non-0 "
3250 "pwdLastSet as a an error as the "
3251 "SAMR_FIELD_EXPIRED_FLAG has not "
3252 "been set\n");
3253 break;
3256 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3257 * password has been changed, old and new pwdlastset
3258 * need to be the same value */
3260 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3261 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3262 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3264 torture_assert_int_equal(tctx, pwdlastset_old,
3265 pwdlastset_new, "pwdlastset must be equal");
3266 break;
3268 default:
3270 if (pwdlastset_old == pwdlastset_new) {
3271 torture_warning(tctx, "pwdLastSet test failed: "
3272 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3273 pwdlastset_old, pwdlastset_new);
3274 ret = false;
3277 if (pwdlastset_new != 0) {
3278 torture_warning(tctx, "pwdLastSet test failed: "
3279 "expected pwdLastSet 0, got %lld\n",
3280 pwdlastset_old);
3281 ret = false;
3283 break;
3286 switch (levels[l]) {
3287 case 21:
3288 case 23:
3289 case 25:
3290 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3291 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3292 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3293 (pwdlastset_old >= pwdlastset_new)) {
3294 torture_warning(tctx, "pwdlastset not increasing\n");
3295 ret = false;
3297 break;
3298 default:
3299 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3300 (pwdlastset_old >= pwdlastset_new)) {
3301 torture_warning(tctx, "pwdlastset not increasing\n");
3302 ret = false;
3304 break;
3307 /* if the level we are testing does not have a fields_present
3308 * field, skip all fields present tests by setting f to to
3309 * arraysize */
3310 switch (levels[l]) {
3311 case 18:
3312 case 24:
3313 case 26:
3314 f = ARRAY_SIZE(fields_present);
3315 break;
3318 #ifdef TEST_QUERY_LEVELS
3320 #endif
3321 #ifdef TEST_SET_LEVELS
3323 #endif
3324 } /* fields present */
3325 } /* nonzeros */
3326 } /* levels */
3328 #undef TEST_SET_LEVELS
3329 #undef TEST_QUERY_LEVELS
3331 talloc_free(np);
3333 return ret;
3336 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
3337 struct dcerpc_pipe *lp,
3338 struct torture_context *tctx,
3339 struct policy_handle *domain_handle,
3340 struct policy_handle *lsa_handle,
3341 struct policy_handle *user_handle,
3342 const struct dom_sid *domain_sid,
3343 uint32_t rid,
3344 struct cli_credentials *machine_credentials)
3346 NTSTATUS status;
3347 bool ret = true;
3349 struct policy_handle lsa_acct_handle;
3350 struct dom_sid *user_sid;
3352 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
3355 struct lsa_EnumAccountRights r;
3356 struct lsa_RightSet rights;
3358 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3360 r.in.handle = lsa_handle;
3361 r.in.sid = user_sid;
3362 r.out.rights = &rights;
3364 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3365 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3366 "Expected enum rights for account to fail");
3370 struct lsa_RightSet rights;
3371 struct lsa_StringLarge names[2];
3372 struct lsa_AddAccountRights r;
3374 torture_comment(tctx, "Testing LSA AddAccountRights\n");
3376 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
3377 init_lsa_StringLarge(&names[1], NULL);
3379 rights.count = 1;
3380 rights.names = names;
3382 r.in.handle = lsa_handle;
3383 r.in.sid = user_sid;
3384 r.in.rights = &rights;
3386 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
3387 torture_assert_ntstatus_ok(tctx, status,
3388 "Failed to add privileges");
3392 struct lsa_EnumAccounts r;
3393 uint32_t resume_handle = 0;
3394 struct lsa_SidArray lsa_sid_array;
3395 int i;
3396 bool found_sid = false;
3398 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3400 r.in.handle = lsa_handle;
3401 r.in.num_entries = 0x1000;
3402 r.in.resume_handle = &resume_handle;
3403 r.out.sids = &lsa_sid_array;
3404 r.out.resume_handle = &resume_handle;
3406 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3407 torture_assert_ntstatus_ok(tctx, status,
3408 "Failed to enum accounts");
3410 for (i=0; i < lsa_sid_array.num_sids; i++) {
3411 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3412 found_sid = true;
3416 torture_assert(tctx, found_sid,
3417 "failed to list privileged account");
3421 struct lsa_EnumAccountRights r;
3422 struct lsa_RightSet user_rights;
3424 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3426 r.in.handle = lsa_handle;
3427 r.in.sid = user_sid;
3428 r.out.rights = &user_rights;
3430 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3431 torture_assert_ntstatus_ok(tctx, status,
3432 "Failed to enum rights for account");
3434 if (user_rights.count < 1) {
3435 torture_warning(tctx, "failed to find newly added rights");
3436 return false;
3441 struct lsa_OpenAccount r;
3443 torture_comment(tctx, "Testing LSA OpenAccount\n");
3445 r.in.handle = lsa_handle;
3446 r.in.sid = user_sid;
3447 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3448 r.out.acct_handle = &lsa_acct_handle;
3450 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3451 torture_assert_ntstatus_ok(tctx, status,
3452 "Failed to open lsa account");
3456 struct lsa_GetSystemAccessAccount r;
3457 uint32_t access_mask;
3459 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3461 r.in.handle = &lsa_acct_handle;
3462 r.out.access_mask = &access_mask;
3464 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3465 torture_assert_ntstatus_ok(tctx, status,
3466 "Failed to get lsa system access account");
3470 struct lsa_Close r;
3472 torture_comment(tctx, "Testing LSA Close\n");
3474 r.in.handle = &lsa_acct_handle;
3475 r.out.handle = &lsa_acct_handle;
3477 status = dcerpc_lsa_Close(lp, tctx, &r);
3478 torture_assert_ntstatus_ok(tctx, status,
3479 "Failed to close lsa");
3483 struct samr_DeleteUser r;
3485 torture_comment(tctx, "Testing SAMR DeleteUser\n");
3487 r.in.user_handle = user_handle;
3488 r.out.user_handle = user_handle;
3490 status = dcerpc_samr_DeleteUser(p, tctx, &r);
3491 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
3495 struct lsa_EnumAccounts r;
3496 uint32_t resume_handle = 0;
3497 struct lsa_SidArray lsa_sid_array;
3498 int i;
3499 bool found_sid = false;
3501 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3503 r.in.handle = lsa_handle;
3504 r.in.num_entries = 0x1000;
3505 r.in.resume_handle = &resume_handle;
3506 r.out.sids = &lsa_sid_array;
3507 r.out.resume_handle = &resume_handle;
3509 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3510 torture_assert_ntstatus_ok(tctx, status,
3511 "Failed to enum accounts");
3513 for (i=0; i < lsa_sid_array.num_sids; i++) {
3514 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3515 found_sid = true;
3519 torture_assert(tctx, found_sid,
3520 "failed to list privileged account");
3524 struct lsa_EnumAccountRights r;
3525 struct lsa_RightSet user_rights;
3527 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3529 r.in.handle = lsa_handle;
3530 r.in.sid = user_sid;
3531 r.out.rights = &user_rights;
3533 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3534 torture_assert_ntstatus_ok(tctx, status,
3535 "Failed to enum rights for account");
3537 if (user_rights.count < 1) {
3538 torture_warning(tctx, "failed to find newly added rights");
3539 return false;
3544 struct lsa_OpenAccount r;
3546 torture_comment(tctx, "Testing LSA OpenAccount\n");
3548 r.in.handle = lsa_handle;
3549 r.in.sid = user_sid;
3550 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3551 r.out.acct_handle = &lsa_acct_handle;
3553 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3554 torture_assert_ntstatus_ok(tctx, status,
3555 "Failed to open lsa account");
3559 struct lsa_GetSystemAccessAccount r;
3560 uint32_t access_mask;
3562 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3564 r.in.handle = &lsa_acct_handle;
3565 r.out.access_mask = &access_mask;
3567 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3568 torture_assert_ntstatus_ok(tctx, status,
3569 "Failed to get lsa system access account");
3573 struct lsa_DeleteObject r;
3575 torture_comment(tctx, "Testing LSA DeleteObject\n");
3577 r.in.handle = &lsa_acct_handle;
3578 r.out.handle = &lsa_acct_handle;
3580 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
3581 torture_assert_ntstatus_ok(tctx, status,
3582 "Failed to delete object");
3586 struct lsa_EnumAccounts r;
3587 uint32_t resume_handle = 0;
3588 struct lsa_SidArray lsa_sid_array;
3589 int i;
3590 bool found_sid = false;
3592 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3594 r.in.handle = lsa_handle;
3595 r.in.num_entries = 0x1000;
3596 r.in.resume_handle = &resume_handle;
3597 r.out.sids = &lsa_sid_array;
3598 r.out.resume_handle = &resume_handle;
3600 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3601 torture_assert_ntstatus_ok(tctx, status,
3602 "Failed to enum accounts");
3604 for (i=0; i < lsa_sid_array.num_sids; i++) {
3605 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3606 found_sid = true;
3610 torture_assert(tctx, !found_sid,
3611 "should not have listed privileged account");
3615 struct lsa_EnumAccountRights r;
3616 struct lsa_RightSet user_rights;
3618 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3620 r.in.handle = lsa_handle;
3621 r.in.sid = user_sid;
3622 r.out.rights = &user_rights;
3624 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3625 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3626 "Failed to enum rights for account");
3629 return ret;
3632 static bool test_user_ops(struct dcerpc_pipe *p,
3633 struct torture_context *tctx,
3634 struct policy_handle *user_handle,
3635 struct policy_handle *domain_handle,
3636 const struct dom_sid *domain_sid,
3637 uint32_t base_acct_flags,
3638 const char *base_acct_name, enum torture_samr_choice which_ops,
3639 struct cli_credentials *machine_credentials)
3641 char *password = NULL;
3642 struct samr_QueryUserInfo q;
3643 union samr_UserInfo *info;
3644 NTSTATUS status;
3646 bool ret = true;
3647 int i;
3648 uint32_t rid;
3649 const uint32_t password_fields[] = {
3650 SAMR_FIELD_NT_PASSWORD_PRESENT,
3651 SAMR_FIELD_LM_PASSWORD_PRESENT,
3652 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3656 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3657 if (!NT_STATUS_IS_OK(status)) {
3658 ret = false;
3661 switch (which_ops) {
3662 case TORTURE_SAMR_USER_ATTRIBUTES:
3663 if (!test_QuerySecurity(p, tctx, user_handle)) {
3664 ret = false;
3667 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3668 ret = false;
3671 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3672 ret = false;
3675 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3676 base_acct_name)) {
3677 ret = false;
3680 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3681 ret = false;
3684 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3685 ret = false;
3688 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3689 ret = false;
3691 break;
3692 case TORTURE_SAMR_PASSWORDS:
3693 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3694 char simple_pass[9];
3695 char *v = generate_random_str(tctx, 1);
3697 ZERO_STRUCT(simple_pass);
3698 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3700 torture_comment(tctx, "Testing machine account password policy rules\n");
3702 /* Workstation trust accounts don't seem to need to honour password quality policy */
3703 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3704 ret = false;
3707 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3708 ret = false;
3711 /* reset again, to allow another 'user' password change */
3712 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3713 ret = false;
3716 /* Try a 'short' password */
3717 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3718 ret = false;
3721 /* Try a compleatly random password */
3722 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3723 ret = false;
3727 for (i = 0; password_fields[i]; i++) {
3728 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3729 ret = false;
3732 /* check it was set right */
3733 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3734 ret = false;
3738 for (i = 0; password_fields[i]; i++) {
3739 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3740 ret = false;
3743 /* check it was set right */
3744 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3745 ret = false;
3749 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3750 ret = false;
3753 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3754 ret = false;
3757 if (torture_setting_bool(tctx, "samba4", false)) {
3758 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
3759 } else {
3761 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3762 ret = false;
3765 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3766 ret = false;
3769 for (i = 0; password_fields[i]; i++) {
3771 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3772 /* we need to skip as that would break
3773 * the ChangePasswordUser3 verify */
3774 continue;
3777 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3778 ret = false;
3781 /* check it was set right */
3782 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3783 ret = false;
3788 q.in.user_handle = user_handle;
3789 q.in.level = 5;
3790 q.out.info = &info;
3792 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
3795 q.in.level, nt_errstr(status));
3796 ret = false;
3797 } else {
3798 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3799 if ((info->info5.acct_flags) != expected_flags) {
3800 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3801 info->info5.acct_flags,
3802 expected_flags);
3803 /* FIXME: GD */
3804 if (!torture_setting_bool(tctx, "samba3", false)) {
3805 ret = false;
3808 if (info->info5.rid != rid) {
3809 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3810 info->info5.rid, rid);
3815 break;
3817 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3819 /* test last password change timestamp behaviour */
3820 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3821 base_acct_name,
3822 user_handle, &password,
3823 machine_credentials)) {
3824 ret = false;
3827 if (ret == true) {
3828 torture_comment(tctx, "pwdLastSet test succeeded\n");
3829 } else {
3830 torture_warning(tctx, "pwdLastSet test failed\n");
3833 break;
3835 case TORTURE_SAMR_USER_PRIVILEGES: {
3837 struct dcerpc_pipe *lp;
3838 struct policy_handle *lsa_handle;
3840 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
3841 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
3843 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
3844 ret = false;
3847 if (!test_DeleteUser_with_privs(p, lp, tctx,
3848 domain_handle, lsa_handle, user_handle,
3849 domain_sid, rid,
3850 machine_credentials)) {
3851 ret = false;
3854 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
3855 ret = false;
3858 if (!ret) {
3859 torture_warning(tctx, "privileged user delete test failed\n");
3862 break;
3864 case TORTURE_SAMR_OTHER:
3865 /* We just need the account to exist */
3866 break;
3868 return ret;
3871 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3872 struct policy_handle *alias_handle,
3873 const struct dom_sid *domain_sid)
3875 bool ret = true;
3877 if (!torture_setting_bool(tctx, "samba3", false)) {
3878 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3879 ret = false;
3883 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3884 ret = false;
3887 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3888 ret = false;
3891 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3892 ret = false;
3895 if (torture_setting_bool(tctx, "samba3", false) ||
3896 torture_setting_bool(tctx, "samba4", false)) {
3897 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
3898 return ret;
3901 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3902 ret = false;
3905 return ret;
3909 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3910 struct policy_handle *user_handle)
3912 struct samr_DeleteUser d;
3913 NTSTATUS status;
3914 torture_comment(tctx, "Testing DeleteUser\n");
3916 d.in.user_handle = user_handle;
3917 d.out.user_handle = user_handle;
3919 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3920 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3922 return true;
3925 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
3926 struct torture_context *tctx,
3927 struct policy_handle *handle, const char *name)
3929 NTSTATUS status;
3930 struct samr_DeleteUser d;
3931 struct policy_handle user_handle;
3932 uint32_t rid;
3934 status = test_LookupName(p, tctx, handle, name, &rid);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 goto failed;
3939 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
3940 if (!NT_STATUS_IS_OK(status)) {
3941 goto failed;
3944 d.in.user_handle = &user_handle;
3945 d.out.user_handle = &user_handle;
3946 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 goto failed;
3951 return true;
3953 failed:
3954 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3955 return false;
3959 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
3960 struct torture_context *tctx,
3961 struct policy_handle *handle, const char *name)
3963 NTSTATUS status;
3964 struct samr_OpenGroup r;
3965 struct samr_DeleteDomainGroup d;
3966 struct policy_handle group_handle;
3967 uint32_t rid;
3969 status = test_LookupName(p, tctx, handle, name, &rid);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 goto failed;
3974 r.in.domain_handle = handle;
3975 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3976 r.in.rid = rid;
3977 r.out.group_handle = &group_handle;
3978 status = dcerpc_samr_OpenGroup(p, tctx, &r);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 goto failed;
3983 d.in.group_handle = &group_handle;
3984 d.out.group_handle = &group_handle;
3985 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 goto failed;
3990 return true;
3992 failed:
3993 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3994 return false;
3998 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
3999 struct torture_context *tctx,
4000 struct policy_handle *domain_handle,
4001 const char *name)
4003 NTSTATUS status;
4004 struct samr_OpenAlias r;
4005 struct samr_DeleteDomAlias d;
4006 struct policy_handle alias_handle;
4007 uint32_t rid;
4009 torture_comment(tctx, "testing DeleteAlias_byname\n");
4011 status = test_LookupName(p, tctx, domain_handle, name, &rid);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 goto failed;
4016 r.in.domain_handle = domain_handle;
4017 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4018 r.in.rid = rid;
4019 r.out.alias_handle = &alias_handle;
4020 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 goto failed;
4025 d.in.alias_handle = &alias_handle;
4026 d.out.alias_handle = &alias_handle;
4027 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4028 if (!NT_STATUS_IS_OK(status)) {
4029 goto failed;
4032 return true;
4034 failed:
4035 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
4036 return false;
4039 static bool test_DeleteAlias(struct dcerpc_pipe *p,
4040 struct torture_context *tctx,
4041 struct policy_handle *alias_handle)
4043 struct samr_DeleteDomAlias d;
4044 NTSTATUS status;
4045 bool ret = true;
4047 torture_comment(tctx, "Testing DeleteAlias\n");
4049 d.in.alias_handle = alias_handle;
4050 d.out.alias_handle = alias_handle;
4052 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4055 ret = false;
4058 return ret;
4061 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4062 struct policy_handle *domain_handle,
4063 const char *alias_name,
4064 struct policy_handle *alias_handle,
4065 const struct dom_sid *domain_sid,
4066 bool test_alias)
4068 NTSTATUS status;
4069 struct samr_CreateDomAlias r;
4070 struct lsa_String name;
4071 uint32_t rid;
4072 bool ret = true;
4074 init_lsa_String(&name, alias_name);
4075 r.in.domain_handle = domain_handle;
4076 r.in.alias_name = &name;
4077 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4078 r.out.alias_handle = alias_handle;
4079 r.out.rid = &rid;
4081 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4083 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4085 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4086 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4087 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4088 return true;
4089 } else {
4090 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4091 nt_errstr(status));
4092 return false;
4096 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4097 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4098 return false;
4100 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4105 return false;
4108 if (!test_alias) {
4109 return ret;
4112 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4113 ret = false;
4116 return ret;
4119 static bool test_ChangePassword(struct dcerpc_pipe *p,
4120 struct torture_context *tctx,
4121 const char *acct_name,
4122 struct policy_handle *domain_handle, char **password)
4124 bool ret = true;
4126 if (!*password) {
4127 return false;
4130 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4131 ret = false;
4134 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4135 ret = false;
4138 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4139 ret = false;
4142 /* test what happens when setting the old password again */
4143 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4144 ret = false;
4148 char simple_pass[9];
4149 char *v = generate_random_str(tctx, 1);
4151 ZERO_STRUCT(simple_pass);
4152 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4154 /* test what happens when picking a simple password */
4155 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4156 ret = false;
4160 /* set samr_SetDomainInfo level 1 with min_length 5 */
4162 struct samr_QueryDomainInfo r;
4163 union samr_DomainInfo *info = NULL;
4164 struct samr_SetDomainInfo s;
4165 uint16_t len_old, len;
4166 uint32_t pwd_prop_old;
4167 int64_t min_pwd_age_old;
4168 NTSTATUS status;
4170 len = 5;
4172 r.in.domain_handle = domain_handle;
4173 r.in.level = 1;
4174 r.out.info = &info;
4176 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
4177 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
4178 if (!NT_STATUS_IS_OK(status)) {
4179 return false;
4182 s.in.domain_handle = domain_handle;
4183 s.in.level = 1;
4184 s.in.info = info;
4186 /* remember the old min length, so we can reset it */
4187 len_old = s.in.info->info1.min_password_length;
4188 s.in.info->info1.min_password_length = len;
4189 pwd_prop_old = s.in.info->info1.password_properties;
4190 /* turn off password complexity checks for this test */
4191 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
4193 min_pwd_age_old = s.in.info->info1.min_password_age;
4194 s.in.info->info1.min_password_age = 0;
4196 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4197 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 return false;
4202 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
4204 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
4205 ret = false;
4208 s.in.info->info1.min_password_length = len_old;
4209 s.in.info->info1.password_properties = pwd_prop_old;
4210 s.in.info->info1.min_password_age = min_pwd_age_old;
4212 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4213 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4214 if (!NT_STATUS_IS_OK(status)) {
4215 return false;
4221 NTSTATUS status;
4222 struct samr_OpenUser r;
4223 struct samr_QueryUserInfo q;
4224 union samr_UserInfo *info;
4225 struct samr_LookupNames n;
4226 struct policy_handle user_handle;
4227 struct samr_Ids rids, types;
4229 n.in.domain_handle = domain_handle;
4230 n.in.num_names = 1;
4231 n.in.names = talloc_array(tctx, struct lsa_String, 1);
4232 n.in.names[0].string = acct_name;
4233 n.out.rids = &rids;
4234 n.out.types = &types;
4236 status = dcerpc_samr_LookupNames(p, tctx, &n);
4237 if (!NT_STATUS_IS_OK(status)) {
4238 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
4239 return false;
4242 r.in.domain_handle = domain_handle;
4243 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4244 r.in.rid = n.out.rids->ids[0];
4245 r.out.user_handle = &user_handle;
4247 status = dcerpc_samr_OpenUser(p, tctx, &r);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
4250 return false;
4253 q.in.user_handle = &user_handle;
4254 q.in.level = 5;
4255 q.out.info = &info;
4257 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4258 if (!NT_STATUS_IS_OK(status)) {
4259 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
4260 return false;
4263 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
4265 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
4266 info->info5.last_password_change, true)) {
4267 ret = false;
4271 /* we change passwords twice - this has the effect of verifying
4272 they were changed correctly for the final call */
4273 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4274 ret = false;
4277 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4278 ret = false;
4281 return ret;
4284 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4285 struct policy_handle *domain_handle,
4286 const char *user_name,
4287 struct policy_handle *user_handle_out,
4288 struct dom_sid *domain_sid,
4289 enum torture_samr_choice which_ops,
4290 struct cli_credentials *machine_credentials,
4291 bool test_user)
4294 TALLOC_CTX *user_ctx;
4296 NTSTATUS status;
4297 struct samr_CreateUser r;
4298 struct samr_QueryUserInfo q;
4299 union samr_UserInfo *info;
4300 struct samr_DeleteUser d;
4301 uint32_t rid;
4303 /* This call creates a 'normal' account - check that it really does */
4304 const uint32_t acct_flags = ACB_NORMAL;
4305 struct lsa_String name;
4306 bool ret = true;
4308 struct policy_handle user_handle;
4309 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4310 init_lsa_String(&name, user_name);
4312 r.in.domain_handle = domain_handle;
4313 r.in.account_name = &name;
4314 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4315 r.out.user_handle = &user_handle;
4316 r.out.rid = &rid;
4318 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
4320 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4322 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4323 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4324 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4325 return true;
4326 } else {
4327 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4328 nt_errstr(status));
4329 return false;
4333 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4334 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4335 talloc_free(user_ctx);
4336 return false;
4338 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4341 if (!NT_STATUS_IS_OK(status)) {
4342 talloc_free(user_ctx);
4343 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
4344 return false;
4347 if (!test_user) {
4348 if (user_handle_out) {
4349 *user_handle_out = user_handle;
4351 return ret;
4355 q.in.user_handle = &user_handle;
4356 q.in.level = 16;
4357 q.out.info = &info;
4359 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4360 if (!NT_STATUS_IS_OK(status)) {
4361 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4362 q.in.level, nt_errstr(status));
4363 ret = false;
4364 } else {
4365 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
4366 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4367 info->info16.acct_flags,
4368 acct_flags);
4369 ret = false;
4373 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4374 domain_sid, acct_flags, name.string, which_ops,
4375 machine_credentials)) {
4376 ret = false;
4379 if (user_handle_out) {
4380 *user_handle_out = user_handle;
4381 } else {
4382 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
4384 d.in.user_handle = &user_handle;
4385 d.out.user_handle = &user_handle;
4387 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4388 if (!NT_STATUS_IS_OK(status)) {
4389 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4390 ret = false;
4396 talloc_free(user_ctx);
4398 return ret;
4402 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
4403 struct policy_handle *domain_handle,
4404 struct dom_sid *domain_sid,
4405 enum torture_samr_choice which_ops,
4406 struct cli_credentials *machine_credentials)
4408 NTSTATUS status;
4409 struct samr_CreateUser2 r;
4410 struct samr_QueryUserInfo q;
4411 union samr_UserInfo *info;
4412 struct samr_DeleteUser d;
4413 struct policy_handle user_handle;
4414 uint32_t rid;
4415 struct lsa_String name;
4416 bool ret = true;
4417 int i;
4419 struct {
4420 uint32_t acct_flags;
4421 const char *account_name;
4422 NTSTATUS nt_status;
4423 } account_types[] = {
4424 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
4425 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4426 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4427 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4428 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4429 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4430 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4431 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4432 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4433 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
4434 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4435 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4436 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4437 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4438 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4441 for (i = 0; account_types[i].account_name; i++) {
4442 TALLOC_CTX *user_ctx;
4443 uint32_t acct_flags = account_types[i].acct_flags;
4444 uint32_t access_granted;
4445 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4446 init_lsa_String(&name, account_types[i].account_name);
4448 r.in.domain_handle = domain_handle;
4449 r.in.account_name = &name;
4450 r.in.acct_flags = acct_flags;
4451 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4452 r.out.user_handle = &user_handle;
4453 r.out.access_granted = &access_granted;
4454 r.out.rid = &rid;
4456 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4458 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4460 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4461 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4462 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4463 continue;
4464 } else {
4465 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4466 nt_errstr(status));
4467 ret = false;
4468 continue;
4472 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4473 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4474 talloc_free(user_ctx);
4475 ret = false;
4476 continue;
4478 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4481 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4482 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4483 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4484 ret = false;
4487 if (NT_STATUS_IS_OK(status)) {
4488 q.in.user_handle = &user_handle;
4489 q.in.level = 5;
4490 q.out.info = &info;
4492 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4495 q.in.level, nt_errstr(status));
4496 ret = false;
4497 } else {
4498 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4499 if (acct_flags == ACB_NORMAL) {
4500 expected_flags |= ACB_PW_EXPIRED;
4502 if ((info->info5.acct_flags) != expected_flags) {
4503 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4504 info->info5.acct_flags,
4505 expected_flags);
4506 ret = false;
4508 switch (acct_flags) {
4509 case ACB_SVRTRUST:
4510 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4511 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4512 DOMAIN_RID_DCS, info->info5.primary_gid);
4513 ret = false;
4515 break;
4516 case ACB_WSTRUST:
4517 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4518 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4519 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4520 ret = false;
4522 break;
4523 case ACB_NORMAL:
4524 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4525 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4526 DOMAIN_RID_USERS, info->info5.primary_gid);
4527 ret = false;
4529 break;
4533 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4534 domain_sid, acct_flags, name.string, which_ops,
4535 machine_credentials)) {
4536 ret = false;
4539 if (!policy_handle_empty(&user_handle)) {
4540 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
4542 d.in.user_handle = &user_handle;
4543 d.out.user_handle = &user_handle;
4545 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4548 ret = false;
4552 talloc_free(user_ctx);
4555 return ret;
4558 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
4559 struct torture_context *tctx,
4560 struct policy_handle *handle)
4562 NTSTATUS status;
4563 struct samr_QueryAliasInfo r;
4564 union samr_AliasInfo *info;
4565 uint16_t levels[] = {1, 2, 3};
4566 int i;
4567 bool ret = true;
4569 for (i=0;i<ARRAY_SIZE(levels);i++) {
4570 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
4572 r.in.alias_handle = handle;
4573 r.in.level = levels[i];
4574 r.out.info = &info;
4576 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
4579 levels[i], nt_errstr(status));
4580 ret = false;
4584 return ret;
4587 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
4588 struct torture_context *tctx,
4589 struct policy_handle *handle)
4591 NTSTATUS status;
4592 struct samr_QueryGroupInfo r;
4593 union samr_GroupInfo *info;
4594 uint16_t levels[] = {1, 2, 3, 4, 5};
4595 int i;
4596 bool ret = true;
4598 for (i=0;i<ARRAY_SIZE(levels);i++) {
4599 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4601 r.in.group_handle = handle;
4602 r.in.level = levels[i];
4603 r.out.info = &info;
4605 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4608 levels[i], nt_errstr(status));
4609 ret = false;
4613 return ret;
4616 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
4617 struct torture_context *tctx,
4618 struct policy_handle *handle)
4620 NTSTATUS status;
4621 struct samr_QueryGroupMember r;
4622 struct samr_RidTypeArray *rids = NULL;
4623 bool ret = true;
4625 torture_comment(tctx, "Testing QueryGroupMember\n");
4627 r.in.group_handle = handle;
4628 r.out.rids = &rids;
4630 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
4631 if (!NT_STATUS_IS_OK(status)) {
4632 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
4633 ret = false;
4636 return ret;
4640 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
4641 struct torture_context *tctx,
4642 struct policy_handle *handle)
4644 NTSTATUS status;
4645 struct samr_QueryGroupInfo r;
4646 union samr_GroupInfo *info;
4647 struct samr_SetGroupInfo s;
4648 uint16_t levels[] = {1, 2, 3, 4};
4649 uint16_t set_ok[] = {0, 1, 1, 1};
4650 int i;
4651 bool ret = true;
4653 for (i=0;i<ARRAY_SIZE(levels);i++) {
4654 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4656 r.in.group_handle = handle;
4657 r.in.level = levels[i];
4658 r.out.info = &info;
4660 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4663 levels[i], nt_errstr(status));
4664 ret = false;
4667 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
4669 s.in.group_handle = handle;
4670 s.in.level = levels[i];
4671 s.in.info = *r.out.info;
4673 #if 0
4674 /* disabled this, as it changes the name only from the point of view of samr,
4675 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4676 the name is still reserved, so creating the old name fails, but deleting by the old name
4677 also fails */
4678 if (s.in.level == 2) {
4679 init_lsa_String(&s.in.info->string, "NewName");
4681 #endif
4683 if (s.in.level == 4) {
4684 init_lsa_String(&s.in.info->description, "test description");
4687 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
4688 if (set_ok[i]) {
4689 if (!NT_STATUS_IS_OK(status)) {
4690 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
4691 r.in.level, nt_errstr(status));
4692 ret = false;
4693 continue;
4695 } else {
4696 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4697 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4698 r.in.level, nt_errstr(status));
4699 ret = false;
4700 continue;
4705 return ret;
4708 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
4709 struct torture_context *tctx,
4710 struct policy_handle *handle)
4712 NTSTATUS status;
4713 struct samr_QueryUserInfo r;
4714 union samr_UserInfo *info;
4715 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4716 11, 12, 13, 14, 16, 17, 20, 21};
4717 int i;
4718 bool ret = true;
4720 for (i=0;i<ARRAY_SIZE(levels);i++) {
4721 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
4723 r.in.user_handle = handle;
4724 r.in.level = levels[i];
4725 r.out.info = &info;
4727 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4730 levels[i], nt_errstr(status));
4731 ret = false;
4735 return ret;
4738 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
4739 struct torture_context *tctx,
4740 struct policy_handle *handle)
4742 NTSTATUS status;
4743 struct samr_QueryUserInfo2 r;
4744 union samr_UserInfo *info;
4745 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4746 11, 12, 13, 14, 16, 17, 20, 21};
4747 int i;
4748 bool ret = true;
4750 for (i=0;i<ARRAY_SIZE(levels);i++) {
4751 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
4753 r.in.user_handle = handle;
4754 r.in.level = levels[i];
4755 r.out.info = &info;
4757 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
4758 if (!NT_STATUS_IS_OK(status)) {
4759 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
4760 levels[i], nt_errstr(status));
4761 ret = false;
4765 return ret;
4768 static bool test_OpenUser(struct dcerpc_pipe *p,
4769 struct torture_context *tctx,
4770 struct policy_handle *handle, uint32_t rid)
4772 NTSTATUS status;
4773 struct samr_OpenUser r;
4774 struct policy_handle user_handle;
4775 bool ret = true;
4777 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4779 r.in.domain_handle = handle;
4780 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4781 r.in.rid = rid;
4782 r.out.user_handle = &user_handle;
4784 status = dcerpc_samr_OpenUser(p, tctx, &r);
4785 if (!NT_STATUS_IS_OK(status)) {
4786 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4787 return false;
4790 if (!test_QuerySecurity(p, tctx, &user_handle)) {
4791 ret = false;
4794 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
4795 ret = false;
4798 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
4799 ret = false;
4802 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
4803 ret = false;
4806 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
4807 ret = false;
4810 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4811 ret = false;
4814 return ret;
4817 static bool test_OpenGroup(struct dcerpc_pipe *p,
4818 struct torture_context *tctx,
4819 struct policy_handle *handle, uint32_t rid)
4821 NTSTATUS status;
4822 struct samr_OpenGroup r;
4823 struct policy_handle group_handle;
4824 bool ret = true;
4826 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
4828 r.in.domain_handle = handle;
4829 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4830 r.in.rid = rid;
4831 r.out.group_handle = &group_handle;
4833 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4836 return false;
4839 if (!torture_setting_bool(tctx, "samba3", false)) {
4840 if (!test_QuerySecurity(p, tctx, &group_handle)) {
4841 ret = false;
4845 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
4846 ret = false;
4849 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
4850 ret = false;
4853 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
4854 ret = false;
4857 return ret;
4860 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4861 struct policy_handle *handle, uint32_t rid)
4863 NTSTATUS status;
4864 struct samr_OpenAlias r;
4865 struct policy_handle alias_handle;
4866 bool ret = true;
4868 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4870 r.in.domain_handle = handle;
4871 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4872 r.in.rid = rid;
4873 r.out.alias_handle = &alias_handle;
4875 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4878 return false;
4881 if (!torture_setting_bool(tctx, "samba3", false)) {
4882 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4883 ret = false;
4887 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4888 ret = false;
4891 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4892 ret = false;
4895 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4896 ret = false;
4899 return ret;
4902 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4903 struct policy_handle *handle, uint32_t rid,
4904 uint32_t acct_flag_mask)
4906 NTSTATUS status;
4907 struct samr_OpenUser r;
4908 struct samr_QueryUserInfo q;
4909 union samr_UserInfo *info;
4910 struct policy_handle user_handle;
4911 bool ret = true;
4913 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4915 r.in.domain_handle = handle;
4916 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4917 r.in.rid = rid;
4918 r.out.user_handle = &user_handle;
4920 status = dcerpc_samr_OpenUser(p, tctx, &r);
4921 if (!NT_STATUS_IS_OK(status)) {
4922 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4923 return false;
4926 q.in.user_handle = &user_handle;
4927 q.in.level = 16;
4928 q.out.info = &info;
4930 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4931 if (!NT_STATUS_IS_OK(status)) {
4932 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
4933 nt_errstr(status));
4934 ret = false;
4935 } else {
4936 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4937 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4938 acct_flag_mask, info->info16.acct_flags, rid);
4939 ret = false;
4943 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4944 ret = false;
4947 return ret;
4950 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
4951 struct torture_context *tctx,
4952 struct policy_handle *handle)
4954 NTSTATUS status = STATUS_MORE_ENTRIES;
4955 struct samr_EnumDomainUsers r;
4956 uint32_t mask, resume_handle=0;
4957 int i, mask_idx;
4958 bool ret = true;
4959 struct samr_LookupNames n;
4960 struct samr_LookupRids lr ;
4961 struct lsa_Strings names;
4962 struct samr_Ids rids, types;
4963 struct samr_SamArray *sam = NULL;
4964 uint32_t num_entries = 0;
4966 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4967 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4968 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4969 ACB_PWNOEXP, 0};
4971 torture_comment(tctx, "Testing EnumDomainUsers\n");
4973 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4974 r.in.domain_handle = handle;
4975 r.in.resume_handle = &resume_handle;
4976 r.in.acct_flags = mask = masks[mask_idx];
4977 r.in.max_size = (uint32_t)-1;
4978 r.out.resume_handle = &resume_handle;
4979 r.out.num_entries = &num_entries;
4980 r.out.sam = &sam;
4982 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4983 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4984 !NT_STATUS_IS_OK(status)) {
4985 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
4986 return false;
4989 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4991 if (sam->count == 0) {
4992 continue;
4995 for (i=0;i<sam->count;i++) {
4996 if (mask) {
4997 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4998 ret = false;
5000 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
5001 ret = false;
5006 torture_comment(tctx, "Testing LookupNames\n");
5007 n.in.domain_handle = handle;
5008 n.in.num_names = sam->count;
5009 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
5010 n.out.rids = &rids;
5011 n.out.types = &types;
5012 for (i=0;i<sam->count;i++) {
5013 n.in.names[i].string = sam->entries[i].name.string;
5015 status = dcerpc_samr_LookupNames(p, tctx, &n);
5016 if (!NT_STATUS_IS_OK(status)) {
5017 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5018 ret = false;
5022 torture_comment(tctx, "Testing LookupRids\n");
5023 lr.in.domain_handle = handle;
5024 lr.in.num_rids = sam->count;
5025 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
5026 lr.out.names = &names;
5027 lr.out.types = &types;
5028 for (i=0;i<sam->count;i++) {
5029 lr.in.rids[i] = sam->entries[i].idx;
5031 status = dcerpc_samr_LookupRids(p, tctx, &lr);
5032 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
5034 return ret;
5038 try blasting the server with a bunch of sync requests
5040 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
5041 struct policy_handle *handle)
5043 NTSTATUS status;
5044 struct samr_EnumDomainUsers r;
5045 uint32_t resume_handle=0;
5046 int i;
5047 #define ASYNC_COUNT 100
5048 struct rpc_request *req[ASYNC_COUNT];
5050 if (!torture_setting_bool(tctx, "dangerous", false)) {
5051 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5054 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5056 r.in.domain_handle = handle;
5057 r.in.resume_handle = &resume_handle;
5058 r.in.acct_flags = 0;
5059 r.in.max_size = (uint32_t)-1;
5060 r.out.resume_handle = &resume_handle;
5062 for (i=0;i<ASYNC_COUNT;i++) {
5063 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5066 for (i=0;i<ASYNC_COUNT;i++) {
5067 status = dcerpc_ndr_request_recv(req[i]);
5068 if (!NT_STATUS_IS_OK(status)) {
5069 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5070 i, nt_errstr(status));
5071 return false;
5075 torture_comment(tctx, "%d async requests OK\n", i);
5077 return true;
5080 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5081 struct torture_context *tctx,
5082 struct policy_handle *handle)
5084 NTSTATUS status;
5085 struct samr_EnumDomainGroups r;
5086 uint32_t resume_handle=0;
5087 struct samr_SamArray *sam = NULL;
5088 uint32_t num_entries = 0;
5089 int i;
5090 bool ret = true;
5092 torture_comment(tctx, "Testing EnumDomainGroups\n");
5094 r.in.domain_handle = handle;
5095 r.in.resume_handle = &resume_handle;
5096 r.in.max_size = (uint32_t)-1;
5097 r.out.resume_handle = &resume_handle;
5098 r.out.num_entries = &num_entries;
5099 r.out.sam = &sam;
5101 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5102 if (!NT_STATUS_IS_OK(status)) {
5103 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5104 return false;
5107 if (!sam) {
5108 return false;
5111 for (i=0;i<sam->count;i++) {
5112 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5113 ret = false;
5117 return ret;
5120 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5121 struct torture_context *tctx,
5122 struct policy_handle *handle)
5124 NTSTATUS status;
5125 struct samr_EnumDomainAliases r;
5126 uint32_t resume_handle=0;
5127 struct samr_SamArray *sam = NULL;
5128 uint32_t num_entries = 0;
5129 int i;
5130 bool ret = true;
5132 torture_comment(tctx, "Testing EnumDomainAliases\n");
5134 r.in.domain_handle = handle;
5135 r.in.resume_handle = &resume_handle;
5136 r.in.max_size = (uint32_t)-1;
5137 r.out.sam = &sam;
5138 r.out.num_entries = &num_entries;
5139 r.out.resume_handle = &resume_handle;
5141 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5142 if (!NT_STATUS_IS_OK(status)) {
5143 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5144 return false;
5147 if (!sam) {
5148 return false;
5151 for (i=0;i<sam->count;i++) {
5152 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5153 ret = false;
5157 return ret;
5160 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5161 struct torture_context *tctx,
5162 struct policy_handle *handle)
5164 NTSTATUS status;
5165 struct samr_GetDisplayEnumerationIndex r;
5166 bool ret = true;
5167 uint16_t levels[] = {1, 2, 3, 4, 5};
5168 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5169 struct lsa_String name;
5170 uint32_t idx = 0;
5171 int i;
5173 for (i=0;i<ARRAY_SIZE(levels);i++) {
5174 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
5176 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5178 r.in.domain_handle = handle;
5179 r.in.level = levels[i];
5180 r.in.name = &name;
5181 r.out.idx = &idx;
5183 status = dcerpc_samr_GetDisplayEnumerationIndex(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, "GetDisplayEnumerationIndex level %u failed - %s\n",
5189 levels[i], nt_errstr(status));
5190 ret = false;
5193 init_lsa_String(&name, "zzzzzzzz");
5195 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5197 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5198 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
5199 levels[i], nt_errstr(status));
5200 ret = false;
5204 return ret;
5207 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
5208 struct torture_context *tctx,
5209 struct policy_handle *handle)
5211 NTSTATUS status;
5212 struct samr_GetDisplayEnumerationIndex2 r;
5213 bool ret = true;
5214 uint16_t levels[] = {1, 2, 3, 4, 5};
5215 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5216 struct lsa_String name;
5217 uint32_t idx = 0;
5218 int i;
5220 for (i=0;i<ARRAY_SIZE(levels);i++) {
5221 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
5223 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5225 r.in.domain_handle = handle;
5226 r.in.level = levels[i];
5227 r.in.name = &name;
5228 r.out.idx = &idx;
5230 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5231 if (ok_lvl[i] &&
5232 !NT_STATUS_IS_OK(status) &&
5233 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5234 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5235 levels[i], nt_errstr(status));
5236 ret = false;
5239 init_lsa_String(&name, "zzzzzzzz");
5241 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5242 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5243 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5244 levels[i], nt_errstr(status));
5245 ret = false;
5249 return ret;
5252 #define STRING_EQUAL_QUERY(s1, s2, user) \
5253 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
5254 /* odd, but valid */ \
5255 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
5256 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
5257 #s1, user.string, s1.string, s2.string, __location__); \
5258 ret = false; \
5260 #define INT_EQUAL_QUERY(s1, s2, user) \
5261 if (s1 != s2) { \
5262 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
5263 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
5264 ret = false; \
5267 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
5268 struct torture_context *tctx,
5269 struct samr_QueryDisplayInfo *querydisplayinfo,
5270 bool *seen_testuser)
5272 struct samr_OpenUser r;
5273 struct samr_QueryUserInfo q;
5274 union samr_UserInfo *info;
5275 struct policy_handle user_handle;
5276 int i, ret = true;
5277 NTSTATUS status;
5278 r.in.domain_handle = querydisplayinfo->in.domain_handle;
5279 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5280 for (i = 0; ; i++) {
5281 switch (querydisplayinfo->in.level) {
5282 case 1:
5283 if (i >= querydisplayinfo->out.info->info1.count) {
5284 return ret;
5286 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
5287 break;
5288 case 2:
5289 if (i >= querydisplayinfo->out.info->info2.count) {
5290 return ret;
5292 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
5293 break;
5294 case 3:
5295 /* Groups */
5296 case 4:
5297 case 5:
5298 /* Not interested in validating just the account name */
5299 return true;
5302 r.out.user_handle = &user_handle;
5304 switch (querydisplayinfo->in.level) {
5305 case 1:
5306 case 2:
5307 status = dcerpc_samr_OpenUser(p, tctx, &r);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5310 return false;
5314 q.in.user_handle = &user_handle;
5315 q.in.level = 21;
5316 q.out.info = &info;
5317 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5318 if (!NT_STATUS_IS_OK(status)) {
5319 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5320 return false;
5323 switch (querydisplayinfo->in.level) {
5324 case 1:
5325 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
5326 *seen_testuser = true;
5328 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
5329 info->info21.full_name, info->info21.account_name);
5330 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
5331 info->info21.account_name, info->info21.account_name);
5332 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
5333 info->info21.description, info->info21.account_name);
5334 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
5335 info->info21.rid, info->info21.account_name);
5336 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
5337 info->info21.acct_flags, info->info21.account_name);
5339 break;
5340 case 2:
5341 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
5342 info->info21.account_name, info->info21.account_name);
5343 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
5344 info->info21.description, info->info21.account_name);
5345 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
5346 info->info21.rid, info->info21.account_name);
5347 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
5348 info->info21.acct_flags, info->info21.account_name);
5350 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
5351 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
5352 info->info21.account_name.string);
5355 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
5356 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
5357 info->info21.account_name.string,
5358 querydisplayinfo->out.info->info2.entries[i].acct_flags,
5359 info->info21.acct_flags);
5360 return false;
5363 break;
5366 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5367 return false;
5370 return ret;
5373 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
5374 struct torture_context *tctx,
5375 struct policy_handle *handle)
5377 NTSTATUS status;
5378 struct samr_QueryDisplayInfo r;
5379 struct samr_QueryDomainInfo dom_info;
5380 union samr_DomainInfo *info = NULL;
5381 bool ret = true;
5382 uint16_t levels[] = {1, 2, 3, 4, 5};
5383 int i;
5384 bool seen_testuser = false;
5385 uint32_t total_size;
5386 uint32_t returned_size;
5387 union samr_DispInfo disp_info;
5390 for (i=0;i<ARRAY_SIZE(levels);i++) {
5391 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
5393 r.in.start_idx = 0;
5394 status = STATUS_MORE_ENTRIES;
5395 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5396 r.in.domain_handle = handle;
5397 r.in.level = levels[i];
5398 r.in.max_entries = 2;
5399 r.in.buf_size = (uint32_t)-1;
5400 r.out.total_size = &total_size;
5401 r.out.returned_size = &returned_size;
5402 r.out.info = &disp_info;
5404 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5405 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
5406 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5407 levels[i], nt_errstr(status));
5408 ret = false;
5410 switch (r.in.level) {
5411 case 1:
5412 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
5413 ret = false;
5415 r.in.start_idx += r.out.info->info1.count;
5416 break;
5417 case 2:
5418 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
5419 ret = false;
5421 r.in.start_idx += r.out.info->info2.count;
5422 break;
5423 case 3:
5424 r.in.start_idx += r.out.info->info3.count;
5425 break;
5426 case 4:
5427 r.in.start_idx += r.out.info->info4.count;
5428 break;
5429 case 5:
5430 r.in.start_idx += r.out.info->info5.count;
5431 break;
5434 dom_info.in.domain_handle = handle;
5435 dom_info.in.level = 2;
5436 dom_info.out.info = &info;
5438 /* Check number of users returned is correct */
5439 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5442 r.in.level, nt_errstr(status));
5443 ret = false;
5444 break;
5446 switch (r.in.level) {
5447 case 1:
5448 case 4:
5449 if (info->general.num_users < r.in.start_idx) {
5450 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5451 r.in.start_idx, info->general.num_groups,
5452 info->general.domain_name.string);
5453 ret = false;
5455 if (!seen_testuser) {
5456 struct policy_handle user_handle;
5457 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5458 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5459 info->general.domain_name.string);
5460 ret = false;
5461 test_samr_handle_Close(p, tctx, &user_handle);
5464 break;
5465 case 3:
5466 case 5:
5467 if (info->general.num_groups != r.in.start_idx) {
5468 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5469 r.in.start_idx, info->general.num_groups,
5470 info->general.domain_name.string);
5471 ret = false;
5474 break;
5479 return ret;
5482 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
5483 struct torture_context *tctx,
5484 struct policy_handle *handle)
5486 NTSTATUS status;
5487 struct samr_QueryDisplayInfo2 r;
5488 bool ret = true;
5489 uint16_t levels[] = {1, 2, 3, 4, 5};
5490 int i;
5491 uint32_t total_size;
5492 uint32_t returned_size;
5493 union samr_DispInfo info;
5495 for (i=0;i<ARRAY_SIZE(levels);i++) {
5496 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
5498 r.in.domain_handle = handle;
5499 r.in.level = levels[i];
5500 r.in.start_idx = 0;
5501 r.in.max_entries = 1000;
5502 r.in.buf_size = (uint32_t)-1;
5503 r.out.total_size = &total_size;
5504 r.out.returned_size = &returned_size;
5505 r.out.info = &info;
5507 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
5508 if (!NT_STATUS_IS_OK(status)) {
5509 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
5510 levels[i], nt_errstr(status));
5511 ret = false;
5515 return ret;
5518 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5519 struct policy_handle *handle)
5521 NTSTATUS status;
5522 struct samr_QueryDisplayInfo3 r;
5523 bool ret = true;
5524 uint16_t levels[] = {1, 2, 3, 4, 5};
5525 int i;
5526 uint32_t total_size;
5527 uint32_t returned_size;
5528 union samr_DispInfo info;
5530 for (i=0;i<ARRAY_SIZE(levels);i++) {
5531 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5533 r.in.domain_handle = handle;
5534 r.in.level = levels[i];
5535 r.in.start_idx = 0;
5536 r.in.max_entries = 1000;
5537 r.in.buf_size = (uint32_t)-1;
5538 r.out.total_size = &total_size;
5539 r.out.returned_size = &returned_size;
5540 r.out.info = &info;
5542 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
5545 levels[i], nt_errstr(status));
5546 ret = false;
5550 return ret;
5554 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
5555 struct torture_context *tctx,
5556 struct policy_handle *handle)
5558 NTSTATUS status;
5559 struct samr_QueryDisplayInfo r;
5560 bool ret = true;
5561 uint32_t total_size;
5562 uint32_t returned_size;
5563 union samr_DispInfo info;
5565 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
5567 r.in.domain_handle = handle;
5568 r.in.level = 1;
5569 r.in.start_idx = 0;
5570 r.in.max_entries = 1;
5571 r.in.buf_size = (uint32_t)-1;
5572 r.out.total_size = &total_size;
5573 r.out.returned_size = &returned_size;
5574 r.out.info = &info;
5576 do {
5577 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5578 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5579 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5580 torture_warning(tctx, "expected idx %d but got %d\n",
5581 r.in.start_idx + 1,
5582 r.out.info->info1.entries[0].idx);
5583 break;
5586 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5587 !NT_STATUS_IS_OK(status)) {
5588 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5589 r.in.level, nt_errstr(status));
5590 ret = false;
5591 break;
5593 r.in.start_idx++;
5594 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5595 NT_STATUS_IS_OK(status)) &&
5596 *r.out.returned_size != 0);
5598 return ret;
5601 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5602 struct policy_handle *handle)
5604 NTSTATUS status;
5605 struct samr_QueryDomainInfo r;
5606 union samr_DomainInfo *info = NULL;
5607 struct samr_SetDomainInfo s;
5608 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5609 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5610 int i;
5611 bool ret = true;
5612 const char *domain_comment = talloc_asprintf(tctx,
5613 "Tortured by Samba4 RPC-SAMR: %s",
5614 timestring(tctx, time(NULL)));
5616 s.in.domain_handle = handle;
5617 s.in.level = 4;
5618 s.in.info = talloc(tctx, union samr_DomainInfo);
5620 s.in.info->oem.oem_information.string = domain_comment;
5621 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
5624 s.in.level, nt_errstr(status));
5625 return false;
5628 for (i=0;i<ARRAY_SIZE(levels);i++) {
5629 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5631 r.in.domain_handle = handle;
5632 r.in.level = levels[i];
5633 r.out.info = &info;
5635 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5636 if (!NT_STATUS_IS_OK(status)) {
5637 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5638 r.in.level, nt_errstr(status));
5639 ret = false;
5640 continue;
5643 switch (levels[i]) {
5644 case 2:
5645 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5646 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5647 levels[i], info->general.oem_information.string, domain_comment);
5648 if (!torture_setting_bool(tctx, "samba3", false)) {
5649 ret = false;
5652 if (!info->general.primary.string) {
5653 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5654 levels[i]);
5655 ret = false;
5656 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5657 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5658 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5659 levels[i], info->general.primary.string, dcerpc_server_name(p));
5662 break;
5663 case 4:
5664 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5665 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5666 levels[i], info->oem.oem_information.string, domain_comment);
5667 if (!torture_setting_bool(tctx, "samba3", false)) {
5668 ret = false;
5671 break;
5672 case 6:
5673 if (!info->info6.primary.string) {
5674 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5675 levels[i]);
5676 ret = false;
5678 break;
5679 case 11:
5680 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5681 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5682 levels[i], info->general2.general.oem_information.string, domain_comment);
5683 if (!torture_setting_bool(tctx, "samba3", false)) {
5684 ret = false;
5687 break;
5690 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5692 s.in.domain_handle = handle;
5693 s.in.level = levels[i];
5694 s.in.info = info;
5696 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5697 if (set_ok[i]) {
5698 if (!NT_STATUS_IS_OK(status)) {
5699 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
5700 r.in.level, nt_errstr(status));
5701 ret = false;
5702 continue;
5704 } else {
5705 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5706 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5707 r.in.level, nt_errstr(status));
5708 ret = false;
5709 continue;
5713 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5714 if (!NT_STATUS_IS_OK(status)) {
5715 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5716 r.in.level, nt_errstr(status));
5717 ret = false;
5718 continue;
5722 return ret;
5726 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5727 struct policy_handle *handle)
5729 NTSTATUS status;
5730 struct samr_QueryDomainInfo2 r;
5731 union samr_DomainInfo *info = NULL;
5732 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5733 int i;
5734 bool ret = true;
5736 for (i=0;i<ARRAY_SIZE(levels);i++) {
5737 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
5739 r.in.domain_handle = handle;
5740 r.in.level = levels[i];
5741 r.out.info = &info;
5743 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5744 if (!NT_STATUS_IS_OK(status)) {
5745 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
5746 r.in.level, nt_errstr(status));
5747 ret = false;
5748 continue;
5752 return true;
5755 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5756 set of group names. */
5757 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5758 struct policy_handle *handle)
5760 struct samr_EnumDomainGroups q1;
5761 struct samr_QueryDisplayInfo q2;
5762 NTSTATUS status;
5763 uint32_t resume_handle=0;
5764 struct samr_SamArray *sam = NULL;
5765 uint32_t num_entries = 0;
5766 int i;
5767 bool ret = true;
5768 uint32_t total_size;
5769 uint32_t returned_size;
5770 union samr_DispInfo info;
5772 int num_names = 0;
5773 const char **names = NULL;
5775 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5777 q1.in.domain_handle = handle;
5778 q1.in.resume_handle = &resume_handle;
5779 q1.in.max_size = 5;
5780 q1.out.resume_handle = &resume_handle;
5781 q1.out.num_entries = &num_entries;
5782 q1.out.sam = &sam;
5784 status = STATUS_MORE_ENTRIES;
5785 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5786 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5788 if (!NT_STATUS_IS_OK(status) &&
5789 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5790 break;
5792 for (i=0; i<*q1.out.num_entries; i++) {
5793 add_string_to_array(tctx,
5794 sam->entries[i].name.string,
5795 &names, &num_names);
5799 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5801 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5803 q2.in.domain_handle = handle;
5804 q2.in.level = 5;
5805 q2.in.start_idx = 0;
5806 q2.in.max_entries = 5;
5807 q2.in.buf_size = (uint32_t)-1;
5808 q2.out.total_size = &total_size;
5809 q2.out.returned_size = &returned_size;
5810 q2.out.info = &info;
5812 status = STATUS_MORE_ENTRIES;
5813 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5814 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5816 if (!NT_STATUS_IS_OK(status) &&
5817 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5818 break;
5820 for (i=0; i<q2.out.info->info5.count; i++) {
5821 int j;
5822 const char *name = q2.out.info->info5.entries[i].account_name.string;
5823 bool found = false;
5824 for (j=0; j<num_names; j++) {
5825 if (names[j] == NULL)
5826 continue;
5827 if (strequal(names[j], name)) {
5828 names[j] = NULL;
5829 found = true;
5830 break;
5834 if (!found) {
5835 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5836 name);
5837 ret = false;
5840 q2.in.start_idx += q2.out.info->info5.count;
5843 if (!NT_STATUS_IS_OK(status)) {
5844 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
5845 nt_errstr(status));
5846 ret = false;
5849 for (i=0; i<num_names; i++) {
5850 if (names[i] != NULL) {
5851 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5852 names[i]);
5853 ret = false;
5857 return ret;
5860 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5861 struct policy_handle *group_handle)
5863 struct samr_DeleteDomainGroup d;
5864 NTSTATUS status;
5866 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5868 d.in.group_handle = group_handle;
5869 d.out.group_handle = group_handle;
5871 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5872 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5874 return true;
5877 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5878 struct policy_handle *domain_handle)
5880 struct samr_TestPrivateFunctionsDomain r;
5881 NTSTATUS status;
5882 bool ret = true;
5884 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5886 r.in.domain_handle = domain_handle;
5888 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5889 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
5891 return ret;
5894 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5895 struct dom_sid *domain_sid,
5896 struct policy_handle *domain_handle)
5898 struct samr_RidToSid r;
5899 NTSTATUS status;
5900 bool ret = true;
5901 struct dom_sid *calc_sid, *out_sid;
5902 int rids[] = { 0, 42, 512, 10200 };
5903 int i;
5905 for (i=0;i<ARRAY_SIZE(rids);i++) {
5906 torture_comment(tctx, "Testing RidToSid\n");
5908 calc_sid = dom_sid_dup(tctx, domain_sid);
5909 r.in.domain_handle = domain_handle;
5910 r.in.rid = rids[i];
5911 r.out.sid = &out_sid;
5913 status = dcerpc_samr_RidToSid(p, tctx, &r);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5916 ret = false;
5917 } else {
5918 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5920 if (!dom_sid_equal(calc_sid, out_sid)) {
5921 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
5922 dom_sid_string(tctx, out_sid),
5923 dom_sid_string(tctx, calc_sid));
5924 ret = false;
5929 return ret;
5932 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5933 struct policy_handle *domain_handle)
5935 struct samr_GetBootKeyInformation r;
5936 NTSTATUS status;
5937 bool ret = true;
5938 uint32_t unknown = 0;
5940 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5942 r.in.domain_handle = domain_handle;
5943 r.out.unknown = &unknown;
5945 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 /* w2k3 seems to fail this sometimes and pass it sometimes */
5948 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5951 return ret;
5954 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5955 struct policy_handle *domain_handle,
5956 struct policy_handle *group_handle)
5958 NTSTATUS status;
5959 struct samr_AddGroupMember r;
5960 struct samr_DeleteGroupMember d;
5961 struct samr_QueryGroupMember q;
5962 struct samr_RidTypeArray *rids = NULL;
5963 struct samr_SetMemberAttributesOfGroup s;
5964 uint32_t rid;
5965 bool found_member = false;
5966 int i;
5968 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5969 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5971 r.in.group_handle = group_handle;
5972 r.in.rid = rid;
5973 r.in.flags = 0; /* ??? */
5975 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
5977 d.in.group_handle = group_handle;
5978 d.in.rid = rid;
5980 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5981 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5983 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5984 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5986 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5987 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5989 if (torture_setting_bool(tctx, "samba4", false) ||
5990 torture_setting_bool(tctx, "samba3", false)) {
5991 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
5992 } else {
5993 /* this one is quite strange. I am using random inputs in the
5994 hope of triggering an error that might give us a clue */
5996 s.in.group_handle = group_handle;
5997 s.in.unknown1 = random();
5998 s.in.unknown2 = random();
6000 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
6001 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
6004 q.in.group_handle = group_handle;
6005 q.out.rids = &rids;
6007 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6008 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6009 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6011 for (i=0; i < rids->count; i++) {
6012 if (rids->rids[i] == rid) {
6013 found_member = true;
6017 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
6019 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6020 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
6022 rids = NULL;
6023 found_member = false;
6025 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6026 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6027 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6029 for (i=0; i < rids->count; i++) {
6030 if (rids->rids[i] == rid) {
6031 found_member = true;
6035 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
6037 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6038 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6040 return true;
6044 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
6045 struct torture_context *tctx,
6046 struct policy_handle *domain_handle,
6047 const char *group_name,
6048 struct policy_handle *group_handle,
6049 struct dom_sid *domain_sid,
6050 bool test_group)
6052 NTSTATUS status;
6053 struct samr_CreateDomainGroup r;
6054 uint32_t rid;
6055 struct lsa_String name;
6056 bool ret = true;
6058 init_lsa_String(&name, group_name);
6060 r.in.domain_handle = domain_handle;
6061 r.in.name = &name;
6062 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6063 r.out.group_handle = group_handle;
6064 r.out.rid = &rid;
6066 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6068 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6070 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6071 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6072 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6073 return true;
6074 } else {
6075 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6076 nt_errstr(status));
6077 return false;
6081 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6082 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6083 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6084 nt_errstr(status));
6085 return false;
6087 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6089 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6090 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6092 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6093 nt_errstr(status));
6094 return false;
6096 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6098 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6100 if (!test_group) {
6101 return ret;
6104 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6105 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6106 ret = false;
6109 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6110 ret = false;
6113 return ret;
6118 its not totally clear what this does. It seems to accept any sid you like.
6120 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6121 struct torture_context *tctx,
6122 struct policy_handle *domain_handle)
6124 NTSTATUS status;
6125 struct samr_RemoveMemberFromForeignDomain r;
6127 r.in.domain_handle = domain_handle;
6128 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6130 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6131 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6133 return true;
6136 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6137 struct torture_context *tctx,
6138 struct policy_handle *domain_handle,
6139 uint32_t *total_num_entries_p)
6141 NTSTATUS status;
6142 struct samr_EnumDomainUsers r;
6143 uint32_t resume_handle = 0;
6144 uint32_t num_entries = 0;
6145 uint32_t total_num_entries = 0;
6146 struct samr_SamArray *sam;
6148 r.in.domain_handle = domain_handle;
6149 r.in.acct_flags = 0;
6150 r.in.max_size = (uint32_t)-1;
6151 r.in.resume_handle = &resume_handle;
6153 r.out.sam = &sam;
6154 r.out.num_entries = &num_entries;
6155 r.out.resume_handle = &resume_handle;
6157 torture_comment(tctx, "Testing EnumDomainUsers\n");
6159 do {
6160 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6161 if (NT_STATUS_IS_ERR(status)) {
6162 torture_assert_ntstatus_ok(tctx, status,
6163 "failed to enumerate users");
6166 total_num_entries += num_entries;
6167 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6169 if (total_num_entries_p) {
6170 *total_num_entries_p = total_num_entries;
6173 return true;
6176 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
6177 struct torture_context *tctx,
6178 struct policy_handle *domain_handle,
6179 uint32_t *total_num_entries_p)
6181 NTSTATUS status;
6182 struct samr_EnumDomainGroups r;
6183 uint32_t resume_handle = 0;
6184 uint32_t num_entries = 0;
6185 uint32_t total_num_entries = 0;
6186 struct samr_SamArray *sam;
6188 r.in.domain_handle = domain_handle;
6189 r.in.max_size = (uint32_t)-1;
6190 r.in.resume_handle = &resume_handle;
6192 r.out.sam = &sam;
6193 r.out.num_entries = &num_entries;
6194 r.out.resume_handle = &resume_handle;
6196 torture_comment(tctx, "Testing EnumDomainGroups\n");
6198 do {
6199 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
6200 if (NT_STATUS_IS_ERR(status)) {
6201 torture_assert_ntstatus_ok(tctx, status,
6202 "failed to enumerate groups");
6205 total_num_entries += num_entries;
6206 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6208 if (total_num_entries_p) {
6209 *total_num_entries_p = total_num_entries;
6212 return true;
6215 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
6216 struct torture_context *tctx,
6217 struct policy_handle *domain_handle,
6218 uint32_t *total_num_entries_p)
6220 NTSTATUS status;
6221 struct samr_EnumDomainAliases r;
6222 uint32_t resume_handle = 0;
6223 uint32_t num_entries = 0;
6224 uint32_t total_num_entries = 0;
6225 struct samr_SamArray *sam;
6227 r.in.domain_handle = domain_handle;
6228 r.in.max_size = (uint32_t)-1;
6229 r.in.resume_handle = &resume_handle;
6231 r.out.sam = &sam;
6232 r.out.num_entries = &num_entries;
6233 r.out.resume_handle = &resume_handle;
6235 torture_comment(tctx, "Testing EnumDomainAliases\n");
6237 do {
6238 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
6239 if (NT_STATUS_IS_ERR(status)) {
6240 torture_assert_ntstatus_ok(tctx, status,
6241 "failed to enumerate aliases");
6244 total_num_entries += num_entries;
6245 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6247 if (total_num_entries_p) {
6248 *total_num_entries_p = total_num_entries;
6251 return true;
6254 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
6255 struct torture_context *tctx,
6256 struct policy_handle *handle,
6257 uint16_t level,
6258 uint32_t *total_num_entries_p)
6260 NTSTATUS status;
6261 struct samr_QueryDisplayInfo r;
6262 uint32_t total_num_entries = 0;
6264 r.in.domain_handle = handle;
6265 r.in.level = level;
6266 r.in.start_idx = 0;
6267 r.in.max_entries = (uint32_t)-1;
6268 r.in.buf_size = (uint32_t)-1;
6270 torture_comment(tctx, "Testing QueryDisplayInfo\n");
6272 do {
6273 uint32_t total_size;
6274 uint32_t returned_size;
6275 union samr_DispInfo info;
6277 r.out.total_size = &total_size;
6278 r.out.returned_size = &returned_size;
6279 r.out.info = &info;
6281 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6282 if (NT_STATUS_IS_ERR(status)) {
6283 torture_assert_ntstatus_ok(tctx, status,
6284 "failed to query displayinfo");
6287 if (*r.out.returned_size == 0) {
6288 break;
6291 switch (r.in.level) {
6292 case 1:
6293 total_num_entries += info.info1.count;
6294 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
6295 break;
6296 case 2:
6297 total_num_entries += info.info2.count;
6298 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
6299 break;
6300 case 3:
6301 total_num_entries += info.info3.count;
6302 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
6303 break;
6304 case 4:
6305 total_num_entries += info.info4.count;
6306 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
6307 break;
6308 case 5:
6309 total_num_entries += info.info5.count;
6310 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
6311 break;
6312 default:
6313 return false;
6316 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6318 if (total_num_entries_p) {
6319 *total_num_entries_p = total_num_entries;
6322 return true;
6325 static bool test_ManyObjects(struct dcerpc_pipe *p,
6326 struct torture_context *tctx,
6327 struct policy_handle *domain_handle,
6328 struct dom_sid *domain_sid,
6329 struct torture_samr_context *ctx)
6331 uint32_t num_total = ctx->num_objects_large_dc;
6332 uint32_t num_enum = 0;
6333 uint32_t num_disp = 0;
6334 uint32_t num_created = 0;
6335 uint32_t num_anounced = 0;
6336 bool ret = true;
6337 NTSTATUS status;
6338 uint32_t i;
6340 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
6342 /* query */
6345 struct samr_QueryDomainInfo2 r;
6346 union samr_DomainInfo *info;
6347 r.in.domain_handle = domain_handle;
6348 r.in.level = 2;
6349 r.out.info = &info;
6351 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6352 torture_assert_ntstatus_ok(tctx, status,
6353 "failed to query domain info");
6355 switch (ctx->choice) {
6356 case TORTURE_SAMR_MANY_ACCOUNTS:
6357 num_anounced = info->general.num_users;
6358 break;
6359 case TORTURE_SAMR_MANY_GROUPS:
6360 num_anounced = info->general.num_groups;
6361 break;
6362 case TORTURE_SAMR_MANY_ALIASES:
6363 num_anounced = info->general.num_aliases;
6364 break;
6365 default:
6366 return false;
6370 /* create */
6372 for (i=0; i < num_total; i++) {
6374 const char *name = NULL;
6376 switch (ctx->choice) {
6377 case TORTURE_SAMR_MANY_ACCOUNTS:
6378 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
6379 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
6380 break;
6381 case TORTURE_SAMR_MANY_GROUPS:
6382 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
6383 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6384 break;
6385 case TORTURE_SAMR_MANY_ALIASES:
6386 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
6387 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6388 break;
6389 default:
6390 return false;
6392 if (!policy_handle_empty(&handles[i])) {
6393 num_created++;
6397 /* enum */
6399 switch (ctx->choice) {
6400 case TORTURE_SAMR_MANY_ACCOUNTS:
6401 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
6402 break;
6403 case TORTURE_SAMR_MANY_GROUPS:
6404 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
6405 break;
6406 case TORTURE_SAMR_MANY_ALIASES:
6407 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
6408 break;
6409 default:
6410 return false;
6413 /* dispinfo */
6415 switch (ctx->choice) {
6416 case TORTURE_SAMR_MANY_ACCOUNTS:
6417 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
6418 break;
6419 case TORTURE_SAMR_MANY_GROUPS:
6420 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
6421 break;
6422 case TORTURE_SAMR_MANY_ALIASES:
6423 /* no aliases in dispinfo */
6424 break;
6425 default:
6426 return false;
6429 /* close or delete */
6431 for (i=0; i < num_total; i++) {
6433 if (policy_handle_empty(&handles[i])) {
6434 continue;
6437 if (torture_setting_bool(tctx, "samba3", false)) {
6438 ret &= test_samr_handle_Close(p, tctx, &handles[i]);
6439 } else {
6440 switch (ctx->choice) {
6441 case TORTURE_SAMR_MANY_ACCOUNTS:
6442 ret &= test_DeleteUser(p, tctx, &handles[i]);
6443 break;
6444 case TORTURE_SAMR_MANY_GROUPS:
6445 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
6446 break;
6447 case TORTURE_SAMR_MANY_ALIASES:
6448 ret &= test_DeleteAlias(p, tctx, &handles[i]);
6449 break;
6450 default:
6451 return false;
6456 talloc_free(handles);
6458 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
6459 torture_comment(tctx,
6460 "unexpected number of results (%u) returned in enum call, expected %u\n",
6461 num_enum, num_anounced + num_created);
6463 torture_comment(tctx,
6464 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
6465 num_disp, num_anounced + num_created);
6467 return ret;
6470 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6471 struct policy_handle *handle);
6473 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6474 struct torture_samr_context *ctx, struct dom_sid *sid)
6476 NTSTATUS status;
6477 struct samr_OpenDomain r;
6478 struct policy_handle domain_handle;
6479 struct policy_handle alias_handle;
6480 struct policy_handle user_handle;
6481 struct policy_handle group_handle;
6482 bool ret = true;
6484 ZERO_STRUCT(alias_handle);
6485 ZERO_STRUCT(user_handle);
6486 ZERO_STRUCT(group_handle);
6487 ZERO_STRUCT(domain_handle);
6489 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
6491 r.in.connect_handle = &ctx->handle;
6492 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6493 r.in.sid = sid;
6494 r.out.domain_handle = &domain_handle;
6496 status = dcerpc_samr_OpenDomain(p, tctx, &r);
6497 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
6499 /* run the domain tests with the main handle closed - this tests
6500 the servers reference counting */
6501 torture_assert(tctx, test_samr_handle_Close(p, tctx, &ctx->handle), "Failed to close SAMR handle");
6503 switch (ctx->choice) {
6504 case TORTURE_SAMR_PASSWORDS:
6505 case TORTURE_SAMR_USER_PRIVILEGES:
6506 if (!torture_setting_bool(tctx, "samba3", false)) {
6507 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
6509 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6510 if (!ret) {
6511 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
6513 break;
6514 case TORTURE_SAMR_USER_ATTRIBUTES:
6515 if (!torture_setting_bool(tctx, "samba3", false)) {
6516 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
6518 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6519 /* This test needs 'complex' users to validate */
6520 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
6521 if (!ret) {
6522 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
6524 break;
6525 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
6526 if (!torture_setting_bool(tctx, "samba3", false)) {
6527 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
6529 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
6530 if (!ret) {
6531 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
6533 break;
6534 case TORTURE_SAMR_MANY_ACCOUNTS:
6535 case TORTURE_SAMR_MANY_GROUPS:
6536 case TORTURE_SAMR_MANY_ALIASES:
6537 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
6538 if (!ret) {
6539 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
6541 break;
6542 case TORTURE_SAMR_OTHER:
6543 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
6544 if (!ret) {
6545 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
6547 if (!torture_setting_bool(tctx, "samba3", false)) {
6548 ret &= test_QuerySecurity(p, tctx, &domain_handle);
6550 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
6551 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
6552 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
6553 ret &= test_GetAliasMembership(p, tctx, &domain_handle);
6554 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
6555 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
6556 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
6557 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
6558 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
6559 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
6560 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
6561 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
6562 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
6564 if (torture_setting_bool(tctx, "samba4", false)) {
6565 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
6566 } else {
6567 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
6568 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
6570 ret &= test_GroupList(p, tctx, &domain_handle);
6571 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
6572 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
6573 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
6574 if (!ret) {
6575 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
6577 break;
6580 if (!policy_handle_empty(&user_handle) &&
6581 !test_DeleteUser(p, tctx, &user_handle)) {
6582 ret = false;
6585 if (!policy_handle_empty(&alias_handle) &&
6586 !test_DeleteAlias(p, tctx, &alias_handle)) {
6587 ret = false;
6590 if (!policy_handle_empty(&group_handle) &&
6591 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
6592 ret = false;
6595 torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
6597 torture_assert(tctx, test_Connect(p, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
6598 /* reconnect the main handle */
6600 if (!ret) {
6601 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
6604 return ret;
6607 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6608 struct torture_samr_context *ctx, const char *domain)
6610 NTSTATUS status;
6611 struct samr_LookupDomain r;
6612 struct dom_sid2 *sid = NULL;
6613 struct lsa_String n1;
6614 struct lsa_String n2;
6615 bool ret = true;
6617 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
6619 /* check for correct error codes */
6620 r.in.connect_handle = &ctx->handle;
6621 r.in.domain_name = &n2;
6622 r.out.sid = &sid;
6623 n2.string = NULL;
6625 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6626 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
6628 init_lsa_String(&n2, "xxNODOMAINxx");
6630 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6631 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
6633 r.in.connect_handle = &ctx->handle;
6635 init_lsa_String(&n1, domain);
6636 r.in.domain_name = &n1;
6638 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6639 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
6641 if (!test_GetDomPwInfo(p, tctx, &n1)) {
6642 ret = false;
6645 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
6646 ret = false;
6649 return ret;
6653 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
6654 struct torture_samr_context *ctx)
6656 NTSTATUS status;
6657 struct samr_EnumDomains r;
6658 uint32_t resume_handle = 0;
6659 uint32_t num_entries = 0;
6660 struct samr_SamArray *sam = NULL;
6661 int i;
6662 bool ret = true;
6664 r.in.connect_handle = &ctx->handle;
6665 r.in.resume_handle = &resume_handle;
6666 r.in.buf_size = (uint32_t)-1;
6667 r.out.resume_handle = &resume_handle;
6668 r.out.num_entries = &num_entries;
6669 r.out.sam = &sam;
6671 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6672 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6674 if (!*r.out.sam) {
6675 return false;
6678 for (i=0;i<sam->count;i++) {
6679 if (!test_LookupDomain(p, tctx, ctx,
6680 sam->entries[i].name.string)) {
6681 ret = false;
6685 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6686 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6688 return ret;
6692 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6693 struct policy_handle *handle)
6695 NTSTATUS status;
6696 struct samr_Connect r;
6697 struct samr_Connect2 r2;
6698 struct samr_Connect3 r3;
6699 struct samr_Connect4 r4;
6700 struct samr_Connect5 r5;
6701 union samr_ConnectInfo info;
6702 struct policy_handle h;
6703 uint32_t level_out = 0;
6704 bool ret = true, got_handle = false;
6706 torture_comment(tctx, "testing samr_Connect\n");
6708 r.in.system_name = 0;
6709 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6710 r.out.connect_handle = &h;
6712 status = dcerpc_samr_Connect(p, tctx, &r);
6713 if (!NT_STATUS_IS_OK(status)) {
6714 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
6715 ret = false;
6716 } else {
6717 got_handle = true;
6718 *handle = h;
6721 torture_comment(tctx, "testing samr_Connect2\n");
6723 r2.in.system_name = NULL;
6724 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6725 r2.out.connect_handle = &h;
6727 status = dcerpc_samr_Connect2(p, tctx, &r2);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
6730 ret = false;
6731 } else {
6732 if (got_handle) {
6733 test_samr_handle_Close(p, tctx, handle);
6735 got_handle = true;
6736 *handle = h;
6739 torture_comment(tctx, "testing samr_Connect3\n");
6741 r3.in.system_name = NULL;
6742 r3.in.unknown = 0;
6743 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6744 r3.out.connect_handle = &h;
6746 status = dcerpc_samr_Connect3(p, tctx, &r3);
6747 if (!NT_STATUS_IS_OK(status)) {
6748 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
6749 ret = false;
6750 } else {
6751 if (got_handle) {
6752 test_samr_handle_Close(p, tctx, handle);
6754 got_handle = true;
6755 *handle = h;
6758 torture_comment(tctx, "testing samr_Connect4\n");
6760 r4.in.system_name = "";
6761 r4.in.client_version = 0;
6762 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6763 r4.out.connect_handle = &h;
6765 status = dcerpc_samr_Connect4(p, tctx, &r4);
6766 if (!NT_STATUS_IS_OK(status)) {
6767 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
6768 ret = false;
6769 } else {
6770 if (got_handle) {
6771 test_samr_handle_Close(p, tctx, handle);
6773 got_handle = true;
6774 *handle = h;
6777 torture_comment(tctx, "testing samr_Connect5\n");
6779 info.info1.client_version = 0;
6780 info.info1.unknown2 = 0;
6782 r5.in.system_name = "";
6783 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6784 r5.in.level_in = 1;
6785 r5.out.level_out = &level_out;
6786 r5.in.info_in = &info;
6787 r5.out.info_out = &info;
6788 r5.out.connect_handle = &h;
6790 status = dcerpc_samr_Connect5(p, tctx, &r5);
6791 if (!NT_STATUS_IS_OK(status)) {
6792 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
6793 ret = false;
6794 } else {
6795 if (got_handle) {
6796 test_samr_handle_Close(p, tctx, handle);
6798 got_handle = true;
6799 *handle = h;
6802 return ret;
6806 bool torture_rpc_samr(struct torture_context *torture)
6808 NTSTATUS status;
6809 struct dcerpc_pipe *p;
6810 bool ret = true;
6811 struct torture_samr_context *ctx;
6813 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6814 if (!NT_STATUS_IS_OK(status)) {
6815 return false;
6818 ctx = talloc_zero(torture, struct torture_samr_context);
6820 ctx->choice = TORTURE_SAMR_OTHER;
6822 ret &= test_Connect(p, torture, &ctx->handle);
6824 if (!torture_setting_bool(torture, "samba3", false)) {
6825 ret &= test_QuerySecurity(p, torture, &ctx->handle);
6828 ret &= test_EnumDomains(p, torture, ctx);
6830 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
6832 ret &= test_Shutdown(p, torture, &ctx->handle);
6834 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6836 return ret;
6840 bool torture_rpc_samr_users(struct torture_context *torture)
6842 NTSTATUS status;
6843 struct dcerpc_pipe *p;
6844 bool ret = true;
6845 struct torture_samr_context *ctx;
6847 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6848 if (!NT_STATUS_IS_OK(status)) {
6849 return false;
6852 ctx = talloc_zero(torture, struct torture_samr_context);
6854 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
6856 ret &= test_Connect(p, torture, &ctx->handle);
6858 if (!torture_setting_bool(torture, "samba3", false)) {
6859 ret &= test_QuerySecurity(p, torture, &ctx->handle);
6862 ret &= test_EnumDomains(p, torture, ctx);
6864 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
6866 ret &= test_Shutdown(p, torture, &ctx->handle);
6868 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6870 return ret;
6874 bool torture_rpc_samr_passwords(struct torture_context *torture)
6876 NTSTATUS status;
6877 struct dcerpc_pipe *p;
6878 bool ret = true;
6879 struct torture_samr_context *ctx;
6881 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6882 if (!NT_STATUS_IS_OK(status)) {
6883 return false;
6886 ctx = talloc_zero(torture, struct torture_samr_context);
6888 ctx->choice = TORTURE_SAMR_PASSWORDS;
6890 ret &= test_Connect(p, torture, &ctx->handle);
6892 ret &= test_EnumDomains(p, torture, ctx);
6894 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6896 return ret;
6899 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6900 struct dcerpc_pipe *p2,
6901 struct cli_credentials *machine_credentials)
6903 NTSTATUS status;
6904 struct dcerpc_pipe *p;
6905 bool ret = true;
6906 struct torture_samr_context *ctx;
6908 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 return false;
6913 ctx = talloc_zero(torture, struct torture_samr_context);
6915 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
6916 ctx->machine_credentials = machine_credentials;
6918 ret &= test_Connect(p, torture, &ctx->handle);
6920 ret &= test_EnumDomains(p, torture, ctx);
6922 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6924 return ret;
6927 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6929 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6930 struct torture_rpc_tcase *tcase;
6932 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6933 &ndr_table_samr,
6934 TEST_ACCOUNT_NAME_PWD);
6936 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6937 torture_rpc_samr_pwdlastset);
6939 return suite;
6942 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
6943 struct dcerpc_pipe *p2,
6944 struct cli_credentials *machine_credentials)
6946 NTSTATUS status;
6947 struct dcerpc_pipe *p;
6948 bool ret = true;
6949 struct torture_samr_context *ctx;
6951 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 return false;
6956 ctx = talloc_zero(torture, struct torture_samr_context);
6958 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
6959 ctx->machine_credentials = machine_credentials;
6961 ret &= test_Connect(p, torture, &ctx->handle);
6963 ret &= test_EnumDomains(p, torture, ctx);
6965 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
6967 return ret;
6970 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
6972 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
6973 struct torture_rpc_tcase *tcase;
6975 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6976 &ndr_table_samr,
6977 TEST_ACCOUNT_NAME_PWD);
6979 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
6980 torture_rpc_samr_users_privileges_delete_user);
6982 return suite;
6985 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
6986 struct dcerpc_pipe *p2,
6987 void *data)
6989 NTSTATUS status;
6990 struct dcerpc_pipe *p;
6991 bool ret = true;
6992 struct torture_samr_context *ctx =
6993 talloc_get_type_abort(data, struct torture_samr_context);
6995 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6996 if (!NT_STATUS_IS_OK(status)) {
6997 return false;
7000 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
7001 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7002 ctx->num_objects_large_dc);
7004 ret &= test_Connect(p, torture, &ctx->handle);
7006 ret &= test_EnumDomains(p, torture, ctx);
7008 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7010 return ret;
7013 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7014 struct dcerpc_pipe *p2,
7015 void *data)
7017 NTSTATUS status;
7018 struct dcerpc_pipe *p;
7019 bool ret = true;
7020 struct torture_samr_context *ctx =
7021 talloc_get_type_abort(data, struct torture_samr_context);
7023 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 return false;
7028 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
7029 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7030 ctx->num_objects_large_dc);
7032 ret &= test_Connect(p, torture, &ctx->handle);
7034 ret &= test_EnumDomains(p, torture, ctx);
7036 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7038 return ret;
7041 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7042 struct dcerpc_pipe *p2,
7043 void *data)
7045 NTSTATUS status;
7046 struct dcerpc_pipe *p;
7047 bool ret = true;
7048 struct torture_samr_context *ctx =
7049 talloc_get_type_abort(data, struct torture_samr_context);
7051 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return false;
7056 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
7057 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7058 ctx->num_objects_large_dc);
7060 ret &= test_Connect(p, torture, &ctx->handle);
7062 ret &= test_EnumDomains(p, torture, ctx);
7064 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7066 return ret;
7069 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7071 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7072 struct torture_rpc_tcase *tcase;
7073 struct torture_samr_context *ctx;
7075 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
7077 ctx = talloc_zero(suite, struct torture_samr_context);
7078 ctx->num_objects_large_dc = 150;
7080 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
7081 torture_rpc_samr_many_aliases, ctx);
7082 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
7083 torture_rpc_samr_many_groups, ctx);
7084 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
7085 torture_rpc_samr_many_accounts, ctx);
7087 return suite;