s4:torture/samr - Activate "ValidatePassword" test per default
[Samba/ekacnet.git] / source4 / torture / rpc / samr.c
blobb26a4c6eee74f30909a487b7c73c2b4310480bc6
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 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
58 struct torture_context *tctx,
59 struct policy_handle *handle);
61 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
62 struct torture_context *tctx,
63 struct policy_handle *handle);
65 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
66 struct torture_context *tctx,
67 struct policy_handle *handle);
69 static bool test_ChangePassword(struct dcerpc_pipe *p,
70 struct torture_context *tctx,
71 const char *acct_name,
72 struct policy_handle *domain_handle, char **password);
74 static void init_lsa_String(struct lsa_String *string, const char *s)
76 string->string = s;
79 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
81 string->string = s;
84 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
86 string->length = length;
87 string->size = length;
88 string->array = (uint16_t *)discard_const(s);
91 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
92 struct policy_handle *handle)
94 NTSTATUS status;
95 struct samr_Close r;
97 r.in.handle = handle;
98 r.out.handle = handle;
100 status = dcerpc_samr_Close(p, tctx, &r);
101 torture_assert_ntstatus_ok(tctx, status, "Close");
103 return true;
106 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
107 struct policy_handle *handle)
109 NTSTATUS status;
110 struct samr_Shutdown r;
112 if (!torture_setting_bool(tctx, "dangerous", false)) {
113 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
114 return true;
117 r.in.connect_handle = handle;
119 torture_comment(tctx, "testing samr_Shutdown\n");
121 status = dcerpc_samr_Shutdown(p, tctx, &r);
122 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
124 return true;
127 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
128 struct policy_handle *handle)
130 NTSTATUS status;
131 struct samr_SetDsrmPassword r;
132 struct lsa_String string;
133 struct samr_Password hash;
135 if (!torture_setting_bool(tctx, "dangerous", false)) {
136 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
139 E_md4hash("TeSTDSRM123", hash.hash);
141 init_lsa_String(&string, "Administrator");
143 r.in.name = &string;
144 r.in.unknown = 0;
145 r.in.hash = &hash;
147 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
149 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
150 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
152 return true;
156 static bool test_QuerySecurity(struct dcerpc_pipe *p,
157 struct torture_context *tctx,
158 struct policy_handle *handle)
160 NTSTATUS status;
161 struct samr_QuerySecurity r;
162 struct samr_SetSecurity s;
163 struct sec_desc_buf *sdbuf = NULL;
165 r.in.handle = handle;
166 r.in.sec_info = 7;
167 r.out.sdbuf = &sdbuf;
169 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
170 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
172 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
174 s.in.handle = handle;
175 s.in.sec_info = 7;
176 s.in.sdbuf = sdbuf;
178 if (torture_setting_bool(tctx, "samba4", false)) {
179 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
182 status = dcerpc_samr_SetSecurity(p, tctx, &s);
183 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
185 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
186 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
188 return true;
192 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
193 struct policy_handle *handle, uint32_t base_acct_flags,
194 const char *base_account_name)
196 NTSTATUS status;
197 struct samr_SetUserInfo s;
198 struct samr_SetUserInfo2 s2;
199 struct samr_QueryUserInfo q;
200 struct samr_QueryUserInfo q0;
201 union samr_UserInfo u;
202 union samr_UserInfo *info;
203 bool ret = true;
204 const char *test_account_name;
206 uint32_t user_extra_flags = 0;
208 if (!torture_setting_bool(tctx, "samba3", false)) {
209 if (base_acct_flags == ACB_NORMAL) {
210 /* When created, accounts are expired by default */
211 user_extra_flags = ACB_PW_EXPIRED;
215 s.in.user_handle = handle;
216 s.in.info = &u;
218 s2.in.user_handle = handle;
219 s2.in.info = &u;
221 q.in.user_handle = handle;
222 q.out.info = &info;
223 q0 = q;
225 #define TESTCALL(call, r) \
226 status = dcerpc_samr_ ##call(p, tctx, &r); \
227 if (!NT_STATUS_IS_OK(status)) { \
228 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
229 r.in.level, nt_errstr(status), __location__); \
230 ret = false; \
231 break; \
234 #define STRING_EQUAL(s1, s2, field) \
235 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
236 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
237 #field, s2, __location__); \
238 ret = false; \
239 break; \
242 #define MEM_EQUAL(s1, s2, length, field) \
243 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
244 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
245 #field, (const char *)s2, __location__); \
246 ret = false; \
247 break; \
250 #define INT_EQUAL(i1, i2, field) \
251 if (i1 != i2) { \
252 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
253 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
254 ret = false; \
255 break; \
258 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
259 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
260 q.in.level = lvl1; \
261 TESTCALL(QueryUserInfo, q) \
262 s.in.level = lvl1; \
263 s2.in.level = lvl1; \
264 u = *info; \
265 if (lvl1 == 21) { \
266 ZERO_STRUCT(u.info21); \
267 u.info21.fields_present = fpval; \
269 init_lsa_String(&u.info ## lvl1.field1, value); \
270 TESTCALL(SetUserInfo, s) \
271 TESTCALL(SetUserInfo2, s2) \
272 init_lsa_String(&u.info ## lvl1.field1, ""); \
273 TESTCALL(QueryUserInfo, q); \
274 u = *info; \
275 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
276 q.in.level = lvl2; \
277 TESTCALL(QueryUserInfo, q) \
278 u = *info; \
279 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
280 } while (0)
282 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
283 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
284 q.in.level = lvl1; \
285 TESTCALL(QueryUserInfo, q) \
286 s.in.level = lvl1; \
287 s2.in.level = lvl1; \
288 u = *info; \
289 if (lvl1 == 21) { \
290 ZERO_STRUCT(u.info21); \
291 u.info21.fields_present = fpval; \
293 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
294 TESTCALL(SetUserInfo, s) \
295 TESTCALL(SetUserInfo2, s2) \
296 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
297 TESTCALL(QueryUserInfo, q); \
298 u = *info; \
299 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
300 q.in.level = lvl2; \
301 TESTCALL(QueryUserInfo, q) \
302 u = *info; \
303 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
304 } while (0)
306 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
307 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
308 q.in.level = lvl1; \
309 TESTCALL(QueryUserInfo, q) \
310 s.in.level = lvl1; \
311 s2.in.level = lvl1; \
312 u = *info; \
313 if (lvl1 == 21) { \
314 uint8_t *bits = u.info21.logon_hours.bits; \
315 ZERO_STRUCT(u.info21); \
316 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
317 u.info21.logon_hours.units_per_week = 168; \
318 u.info21.logon_hours.bits = bits; \
320 u.info21.fields_present = fpval; \
322 u.info ## lvl1.field1 = value; \
323 TESTCALL(SetUserInfo, s) \
324 TESTCALL(SetUserInfo2, s2) \
325 u.info ## lvl1.field1 = 0; \
326 TESTCALL(QueryUserInfo, q); \
327 u = *info; \
328 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
329 q.in.level = lvl2; \
330 TESTCALL(QueryUserInfo, q) \
331 u = *info; \
332 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
333 } while (0)
335 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
336 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
337 } while (0)
339 q0.in.level = 12;
340 do { TESTCALL(QueryUserInfo, q0) } while (0);
342 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
343 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
344 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
345 SAMR_FIELD_COMMENT);
347 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
348 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
349 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
350 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
351 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
352 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
353 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
354 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
355 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
356 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
357 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
358 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
359 test_account_name = base_account_name;
360 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
361 SAMR_FIELD_ACCOUNT_NAME);
363 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
364 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
365 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
366 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
367 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
368 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
369 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
370 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
371 SAMR_FIELD_FULL_NAME);
373 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
374 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
375 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
376 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
377 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
378 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
379 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
380 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
381 SAMR_FIELD_FULL_NAME);
383 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
384 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
385 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
386 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
387 SAMR_FIELD_LOGON_SCRIPT);
389 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
390 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
391 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
392 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
393 SAMR_FIELD_PROFILE_PATH);
395 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
396 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
397 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
398 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
399 SAMR_FIELD_HOME_DIRECTORY);
400 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
401 SAMR_FIELD_HOME_DIRECTORY);
403 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
404 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
405 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
406 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
407 SAMR_FIELD_HOME_DRIVE);
408 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
409 SAMR_FIELD_HOME_DRIVE);
411 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
412 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
413 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
414 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
415 SAMR_FIELD_DESCRIPTION);
417 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
418 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
419 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
420 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
421 SAMR_FIELD_WORKSTATIONS);
422 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
423 SAMR_FIELD_WORKSTATIONS);
424 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
425 SAMR_FIELD_WORKSTATIONS);
426 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
427 SAMR_FIELD_WORKSTATIONS);
429 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
430 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
431 SAMR_FIELD_PARAMETERS);
432 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
433 SAMR_FIELD_PARAMETERS);
434 /* also empty user parameters are allowed */
435 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
436 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
437 SAMR_FIELD_PARAMETERS);
438 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
439 SAMR_FIELD_PARAMETERS);
441 /* Samba 3 cannot store country_code and copy_page atm. - gd */
442 if (!torture_setting_bool(tctx, "samba3", false)) {
443 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
444 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
445 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
446 SAMR_FIELD_COUNTRY_CODE);
447 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
448 SAMR_FIELD_COUNTRY_CODE);
450 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
451 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
452 SAMR_FIELD_CODE_PAGE);
453 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
454 SAMR_FIELD_CODE_PAGE);
457 if (!torture_setting_bool(tctx, "samba3", false)) {
458 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
459 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
460 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
461 SAMR_FIELD_ACCT_EXPIRY);
462 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
463 SAMR_FIELD_ACCT_EXPIRY);
464 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
465 SAMR_FIELD_ACCT_EXPIRY);
466 } else {
467 /* Samba 3 can only store seconds / time_t in passdb - gd */
468 NTTIME nt;
469 unix_to_nt_time(&nt, time(NULL) + __LINE__);
470 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
471 unix_to_nt_time(&nt, time(NULL) + __LINE__);
472 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
473 unix_to_nt_time(&nt, time(NULL) + __LINE__);
474 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
475 unix_to_nt_time(&nt, time(NULL) + __LINE__);
476 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
477 unix_to_nt_time(&nt, time(NULL) + __LINE__);
478 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
481 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
482 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
483 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
484 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
485 SAMR_FIELD_LOGON_HOURS);
487 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
488 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
489 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
491 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
492 (base_acct_flags | ACB_DISABLED),
493 (base_acct_flags | ACB_DISABLED | user_extra_flags),
496 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
497 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
498 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
499 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
501 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
502 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
503 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
507 /* The 'autolock' flag doesn't stick - check this */
508 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
509 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
510 (base_acct_flags | ACB_DISABLED | user_extra_flags),
512 #if 0
513 /* Removing the 'disabled' flag doesn't stick - check this */
514 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
515 (base_acct_flags),
516 (base_acct_flags | ACB_DISABLED | user_extra_flags),
518 #endif
520 /* Samba3 cannot store these atm */
521 if (!torture_setting_bool(tctx, "samba3", false)) {
522 /* The 'store plaintext' flag does stick */
523 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
524 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
525 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
527 /* The 'use DES' flag does stick */
528 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
529 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
530 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
532 /* The 'don't require kerberos pre-authentication flag does stick */
533 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
534 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
535 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
537 /* The 'no kerberos PAC required' flag sticks */
538 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
539 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
540 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
543 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
544 (base_acct_flags | ACB_DISABLED),
545 (base_acct_flags | ACB_DISABLED | user_extra_flags),
546 SAMR_FIELD_ACCT_FLAGS);
548 #if 0
549 /* these fail with win2003 - it appears you can't set the primary gid?
550 the set succeeds, but the gid isn't changed. Very weird! */
551 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
552 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
553 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
554 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
555 #endif
557 return ret;
561 generate a random password for password change tests
563 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
565 size_t len = MAX(8, min_len) + (random() % 6);
566 char *s = generate_random_str(mem_ctx, len);
567 return s;
570 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
572 char *s = samr_rand_pass_silent(mem_ctx, min_len);
573 printf("Generated password '%s'\n", s);
574 return s;
579 generate a random password for password change tests
581 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
583 int i;
584 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
585 generate_random_buffer(password.data, password.length);
587 for (i=0; i < len; i++) {
588 if (((uint16_t *)password.data)[i] == 0) {
589 ((uint16_t *)password.data)[i] = 1;
593 return password;
597 generate a random password for password change tests (fixed length)
599 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
601 char *s = generate_random_str(mem_ctx, len);
602 printf("Generated password '%s'\n", s);
603 return s;
606 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
607 struct policy_handle *handle, char **password)
609 NTSTATUS status;
610 struct samr_SetUserInfo s;
611 union samr_UserInfo u;
612 bool ret = true;
613 DATA_BLOB session_key;
614 char *newpass;
615 struct samr_GetUserPwInfo pwp;
616 struct samr_PwInfo info;
617 int policy_min_pw_len = 0;
618 pwp.in.user_handle = handle;
619 pwp.out.info = &info;
621 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
622 if (NT_STATUS_IS_OK(status)) {
623 policy_min_pw_len = pwp.out.info->min_password_length;
625 newpass = samr_rand_pass(tctx, policy_min_pw_len);
627 s.in.user_handle = handle;
628 s.in.info = &u;
629 s.in.level = 24;
631 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
632 u.info24.password_expired = 0;
634 status = dcerpc_fetch_session_key(p, &session_key);
635 if (!NT_STATUS_IS_OK(status)) {
636 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
637 s.in.level, nt_errstr(status));
638 return false;
641 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
643 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
645 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
646 if (!NT_STATUS_IS_OK(status)) {
647 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
648 s.in.level, nt_errstr(status));
649 ret = false;
650 } else {
651 *password = newpass;
654 return ret;
658 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
659 struct policy_handle *handle, uint32_t fields_present,
660 char **password)
662 NTSTATUS status;
663 struct samr_SetUserInfo s;
664 union samr_UserInfo u;
665 bool ret = true;
666 DATA_BLOB session_key;
667 char *newpass;
668 struct samr_GetUserPwInfo pwp;
669 struct samr_PwInfo info;
670 int policy_min_pw_len = 0;
671 pwp.in.user_handle = handle;
672 pwp.out.info = &info;
674 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
675 if (NT_STATUS_IS_OK(status)) {
676 policy_min_pw_len = pwp.out.info->min_password_length;
678 newpass = samr_rand_pass(tctx, policy_min_pw_len);
680 s.in.user_handle = handle;
681 s.in.info = &u;
682 s.in.level = 23;
684 ZERO_STRUCT(u);
686 u.info23.info.fields_present = fields_present;
688 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
690 status = dcerpc_fetch_session_key(p, &session_key);
691 if (!NT_STATUS_IS_OK(status)) {
692 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
693 s.in.level, nt_errstr(status));
694 return false;
697 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
699 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
701 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
702 if (!NT_STATUS_IS_OK(status)) {
703 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
704 s.in.level, nt_errstr(status));
705 ret = false;
706 } else {
707 *password = newpass;
710 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
712 status = dcerpc_fetch_session_key(p, &session_key);
713 if (!NT_STATUS_IS_OK(status)) {
714 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
715 s.in.level, nt_errstr(status));
716 return false;
719 /* This should break the key nicely */
720 session_key.length--;
721 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
723 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
725 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
726 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
727 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
728 s.in.level, nt_errstr(status));
729 ret = false;
732 return ret;
736 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
737 struct policy_handle *handle, bool makeshort,
738 char **password)
740 NTSTATUS status;
741 struct samr_SetUserInfo s;
742 union samr_UserInfo u;
743 bool ret = true;
744 DATA_BLOB session_key;
745 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
746 uint8_t confounder[16];
747 char *newpass;
748 struct MD5Context ctx;
749 struct samr_GetUserPwInfo pwp;
750 struct samr_PwInfo info;
751 int policy_min_pw_len = 0;
752 pwp.in.user_handle = handle;
753 pwp.out.info = &info;
755 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
756 if (NT_STATUS_IS_OK(status)) {
757 policy_min_pw_len = pwp.out.info->min_password_length;
759 if (makeshort && policy_min_pw_len) {
760 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
761 } else {
762 newpass = samr_rand_pass(tctx, policy_min_pw_len);
765 s.in.user_handle = handle;
766 s.in.info = &u;
767 s.in.level = 26;
769 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
770 u.info26.password_expired = 0;
772 status = dcerpc_fetch_session_key(p, &session_key);
773 if (!NT_STATUS_IS_OK(status)) {
774 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
775 s.in.level, nt_errstr(status));
776 return false;
779 generate_random_buffer((uint8_t *)confounder, 16);
781 MD5Init(&ctx);
782 MD5Update(&ctx, confounder, 16);
783 MD5Update(&ctx, session_key.data, session_key.length);
784 MD5Final(confounded_session_key.data, &ctx);
786 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
787 memcpy(&u.info26.password.data[516], confounder, 16);
789 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
791 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
792 if (!NT_STATUS_IS_OK(status)) {
793 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
794 s.in.level, nt_errstr(status));
795 ret = false;
796 } else {
797 *password = newpass;
800 /* This should break the key nicely */
801 confounded_session_key.data[0]++;
803 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
804 memcpy(&u.info26.password.data[516], confounder, 16);
806 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
808 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
809 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
810 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
811 s.in.level, nt_errstr(status));
812 ret = false;
813 } else {
814 *password = newpass;
817 return ret;
820 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
821 struct policy_handle *handle, uint32_t fields_present,
822 char **password)
824 NTSTATUS status;
825 struct samr_SetUserInfo s;
826 union samr_UserInfo u;
827 bool ret = true;
828 DATA_BLOB session_key;
829 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
830 struct MD5Context ctx;
831 uint8_t confounder[16];
832 char *newpass;
833 struct samr_GetUserPwInfo pwp;
834 struct samr_PwInfo info;
835 int policy_min_pw_len = 0;
836 pwp.in.user_handle = handle;
837 pwp.out.info = &info;
839 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
840 if (NT_STATUS_IS_OK(status)) {
841 policy_min_pw_len = pwp.out.info->min_password_length;
843 newpass = samr_rand_pass(tctx, policy_min_pw_len);
845 s.in.user_handle = handle;
846 s.in.info = &u;
847 s.in.level = 25;
849 ZERO_STRUCT(u);
851 u.info25.info.fields_present = fields_present;
853 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
855 status = dcerpc_fetch_session_key(p, &session_key);
856 if (!NT_STATUS_IS_OK(status)) {
857 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
858 s.in.level, nt_errstr(status));
859 return false;
862 generate_random_buffer((uint8_t *)confounder, 16);
864 MD5Init(&ctx);
865 MD5Update(&ctx, confounder, 16);
866 MD5Update(&ctx, session_key.data, session_key.length);
867 MD5Final(confounded_session_key.data, &ctx);
869 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
870 memcpy(&u.info25.password.data[516], confounder, 16);
872 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
874 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
875 if (!NT_STATUS_IS_OK(status)) {
876 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
877 s.in.level, nt_errstr(status));
878 ret = false;
879 } else {
880 *password = newpass;
883 /* This should break the key nicely */
884 confounded_session_key.data[0]++;
886 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
887 memcpy(&u.info25.password.data[516], confounder, 16);
889 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
891 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
892 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
893 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
894 s.in.level, nt_errstr(status));
895 ret = false;
898 return ret;
901 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
902 struct policy_handle *handle, char **password)
904 NTSTATUS status;
905 struct samr_SetUserInfo s;
906 union samr_UserInfo u;
907 bool ret = true;
908 DATA_BLOB session_key;
909 char *newpass;
910 struct samr_GetUserPwInfo pwp;
911 struct samr_PwInfo info;
912 int policy_min_pw_len = 0;
913 uint8_t lm_hash[16], nt_hash[16];
915 pwp.in.user_handle = handle;
916 pwp.out.info = &info;
918 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
919 if (NT_STATUS_IS_OK(status)) {
920 policy_min_pw_len = pwp.out.info->min_password_length;
922 newpass = samr_rand_pass(tctx, policy_min_pw_len);
924 s.in.user_handle = handle;
925 s.in.info = &u;
926 s.in.level = 18;
928 ZERO_STRUCT(u);
930 u.info18.nt_pwd_active = true;
931 u.info18.lm_pwd_active = true;
933 E_md4hash(newpass, nt_hash);
934 E_deshash(newpass, lm_hash);
936 status = dcerpc_fetch_session_key(p, &session_key);
937 if (!NT_STATUS_IS_OK(status)) {
938 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
939 s.in.level, nt_errstr(status));
940 return false;
944 DATA_BLOB in,out;
945 in = data_blob_const(nt_hash, 16);
946 out = data_blob_talloc_zero(tctx, 16);
947 sess_crypt_blob(&out, &in, &session_key, true);
948 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
951 DATA_BLOB in,out;
952 in = data_blob_const(lm_hash, 16);
953 out = data_blob_talloc_zero(tctx, 16);
954 sess_crypt_blob(&out, &in, &session_key, true);
955 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
958 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
960 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
961 if (!NT_STATUS_IS_OK(status)) {
962 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
963 s.in.level, nt_errstr(status));
964 ret = false;
965 } else {
966 *password = newpass;
969 return ret;
972 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
973 struct policy_handle *handle, uint32_t fields_present,
974 char **password)
976 NTSTATUS status;
977 struct samr_SetUserInfo s;
978 union samr_UserInfo u;
979 bool ret = true;
980 DATA_BLOB session_key;
981 char *newpass;
982 struct samr_GetUserPwInfo pwp;
983 struct samr_PwInfo info;
984 int policy_min_pw_len = 0;
985 uint8_t lm_hash[16], nt_hash[16];
987 pwp.in.user_handle = handle;
988 pwp.out.info = &info;
990 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
991 if (NT_STATUS_IS_OK(status)) {
992 policy_min_pw_len = pwp.out.info->min_password_length;
994 newpass = samr_rand_pass(tctx, policy_min_pw_len);
996 s.in.user_handle = handle;
997 s.in.info = &u;
998 s.in.level = 21;
1000 E_md4hash(newpass, nt_hash);
1001 E_deshash(newpass, lm_hash);
1003 ZERO_STRUCT(u);
1005 u.info21.fields_present = fields_present;
1007 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1008 u.info21.lm_owf_password.length = 16;
1009 u.info21.lm_owf_password.size = 16;
1010 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1011 u.info21.lm_password_set = true;
1014 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1015 u.info21.nt_owf_password.length = 16;
1016 u.info21.nt_owf_password.size = 16;
1017 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1018 u.info21.nt_password_set = true;
1021 status = dcerpc_fetch_session_key(p, &session_key);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1024 s.in.level, nt_errstr(status));
1025 return false;
1028 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1029 DATA_BLOB in,out;
1030 in = data_blob_const(u.info21.lm_owf_password.array,
1031 u.info21.lm_owf_password.length);
1032 out = data_blob_talloc_zero(tctx, 16);
1033 sess_crypt_blob(&out, &in, &session_key, true);
1034 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1037 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1038 DATA_BLOB in,out;
1039 in = data_blob_const(u.info21.nt_owf_password.array,
1040 u.info21.nt_owf_password.length);
1041 out = data_blob_talloc_zero(tctx, 16);
1042 sess_crypt_blob(&out, &in, &session_key, true);
1043 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1046 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1048 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1051 s.in.level, nt_errstr(status));
1052 ret = false;
1053 } else {
1054 *password = newpass;
1057 /* try invalid length */
1058 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1060 u.info21.nt_owf_password.length++;
1062 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1064 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1065 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1066 s.in.level, nt_errstr(status));
1067 ret = false;
1071 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1073 u.info21.lm_owf_password.length++;
1075 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1077 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1078 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1079 s.in.level, nt_errstr(status));
1080 ret = false;
1084 return ret;
1087 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1088 struct torture_context *tctx,
1089 struct policy_handle *handle,
1090 uint16_t level,
1091 uint32_t fields_present,
1092 char **password, uint8_t password_expired,
1093 bool use_setinfo2,
1094 bool *matched_expected_error)
1096 NTSTATUS status;
1097 NTSTATUS expected_error = NT_STATUS_OK;
1098 struct samr_SetUserInfo s;
1099 struct samr_SetUserInfo2 s2;
1100 union samr_UserInfo u;
1101 bool ret = true;
1102 DATA_BLOB session_key;
1103 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1104 struct MD5Context ctx;
1105 uint8_t confounder[16];
1106 char *newpass;
1107 struct samr_GetUserPwInfo pwp;
1108 struct samr_PwInfo info;
1109 int policy_min_pw_len = 0;
1110 const char *comment = NULL;
1111 uint8_t lm_hash[16], nt_hash[16];
1113 pwp.in.user_handle = handle;
1114 pwp.out.info = &info;
1116 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1117 if (NT_STATUS_IS_OK(status)) {
1118 policy_min_pw_len = pwp.out.info->min_password_length;
1120 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1122 if (use_setinfo2) {
1123 s2.in.user_handle = handle;
1124 s2.in.info = &u;
1125 s2.in.level = level;
1126 } else {
1127 s.in.user_handle = handle;
1128 s.in.info = &u;
1129 s.in.level = level;
1132 if (fields_present & SAMR_FIELD_COMMENT) {
1133 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1136 ZERO_STRUCT(u);
1138 switch (level) {
1139 case 18:
1140 E_md4hash(newpass, nt_hash);
1141 E_deshash(newpass, lm_hash);
1143 u.info18.nt_pwd_active = true;
1144 u.info18.lm_pwd_active = true;
1145 u.info18.password_expired = password_expired;
1147 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1148 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1150 break;
1151 case 21:
1152 E_md4hash(newpass, nt_hash);
1153 E_deshash(newpass, lm_hash);
1155 u.info21.fields_present = fields_present;
1156 u.info21.password_expired = password_expired;
1157 u.info21.comment.string = comment;
1159 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1160 u.info21.lm_owf_password.length = 16;
1161 u.info21.lm_owf_password.size = 16;
1162 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1163 u.info21.lm_password_set = true;
1166 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1167 u.info21.nt_owf_password.length = 16;
1168 u.info21.nt_owf_password.size = 16;
1169 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1170 u.info21.nt_password_set = true;
1173 break;
1174 case 23:
1175 u.info23.info.fields_present = fields_present;
1176 u.info23.info.password_expired = password_expired;
1177 u.info23.info.comment.string = comment;
1179 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1181 break;
1182 case 24:
1183 u.info24.password_expired = password_expired;
1185 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1187 break;
1188 case 25:
1189 u.info25.info.fields_present = fields_present;
1190 u.info25.info.password_expired = password_expired;
1191 u.info25.info.comment.string = comment;
1193 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1195 break;
1196 case 26:
1197 u.info26.password_expired = password_expired;
1199 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1201 break;
1204 status = dcerpc_fetch_session_key(p, &session_key);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1207 s.in.level, nt_errstr(status));
1208 return false;
1211 generate_random_buffer((uint8_t *)confounder, 16);
1213 MD5Init(&ctx);
1214 MD5Update(&ctx, confounder, 16);
1215 MD5Update(&ctx, session_key.data, session_key.length);
1216 MD5Final(confounded_session_key.data, &ctx);
1218 switch (level) {
1219 case 18:
1221 DATA_BLOB in,out;
1222 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1223 out = data_blob_talloc_zero(tctx, 16);
1224 sess_crypt_blob(&out, &in, &session_key, true);
1225 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1228 DATA_BLOB in,out;
1229 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1230 out = data_blob_talloc_zero(tctx, 16);
1231 sess_crypt_blob(&out, &in, &session_key, true);
1232 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1235 break;
1236 case 21:
1237 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1238 DATA_BLOB in,out;
1239 in = data_blob_const(u.info21.lm_owf_password.array,
1240 u.info21.lm_owf_password.length);
1241 out = data_blob_talloc_zero(tctx, 16);
1242 sess_crypt_blob(&out, &in, &session_key, true);
1243 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1245 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1246 DATA_BLOB in,out;
1247 in = data_blob_const(u.info21.nt_owf_password.array,
1248 u.info21.nt_owf_password.length);
1249 out = data_blob_talloc_zero(tctx, 16);
1250 sess_crypt_blob(&out, &in, &session_key, true);
1251 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1253 break;
1254 case 23:
1255 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1256 break;
1257 case 24:
1258 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1259 break;
1260 case 25:
1261 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1262 memcpy(&u.info25.password.data[516], confounder, 16);
1263 break;
1264 case 26:
1265 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1266 memcpy(&u.info26.password.data[516], confounder, 16);
1267 break;
1270 if (use_setinfo2) {
1271 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1272 } else {
1273 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 if (fields_present == 0) {
1278 expected_error = NT_STATUS_INVALID_PARAMETER;
1280 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1281 expected_error = NT_STATUS_ACCESS_DENIED;
1285 if (!NT_STATUS_IS_OK(expected_error)) {
1286 if (use_setinfo2) {
1287 torture_assert_ntstatus_equal(tctx,
1288 s2.out.result,
1289 expected_error, "SetUserInfo2 failed");
1290 } else {
1291 torture_assert_ntstatus_equal(tctx,
1292 s.out.result,
1293 expected_error, "SetUserInfo failed");
1295 *matched_expected_error = true;
1296 return true;
1299 if (!NT_STATUS_IS_OK(status)) {
1300 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1301 use_setinfo2 ? "2":"", level, nt_errstr(status));
1302 ret = false;
1303 } else {
1304 *password = newpass;
1307 return ret;
1310 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1311 struct policy_handle *handle)
1313 NTSTATUS status;
1314 struct samr_SetAliasInfo r;
1315 struct samr_QueryAliasInfo q;
1316 union samr_AliasInfo *info;
1317 uint16_t levels[] = {2, 3};
1318 int i;
1319 bool ret = true;
1321 /* Ignoring switch level 1, as that includes the number of members for the alias
1322 * and setting this to a wrong value might have negative consequences
1325 for (i=0;i<ARRAY_SIZE(levels);i++) {
1326 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1328 r.in.alias_handle = handle;
1329 r.in.level = levels[i];
1330 r.in.info = talloc(tctx, union samr_AliasInfo);
1331 switch (r.in.level) {
1332 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1333 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1334 "Test Description, should test I18N as well"); break;
1335 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1338 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1339 if (!NT_STATUS_IS_OK(status)) {
1340 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1341 levels[i], nt_errstr(status));
1342 ret = false;
1345 q.in.alias_handle = handle;
1346 q.in.level = levels[i];
1347 q.out.info = &info;
1349 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1352 levels[i], nt_errstr(status));
1353 ret = false;
1357 return ret;
1360 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1361 struct policy_handle *user_handle)
1363 struct samr_GetGroupsForUser r;
1364 struct samr_RidWithAttributeArray *rids = NULL;
1365 NTSTATUS status;
1367 torture_comment(tctx, "testing GetGroupsForUser\n");
1369 r.in.user_handle = user_handle;
1370 r.out.rids = &rids;
1372 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1373 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1375 return true;
1379 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1380 struct lsa_String *domain_name)
1382 NTSTATUS status;
1383 struct samr_GetDomPwInfo r;
1384 struct samr_PwInfo info;
1386 r.in.domain_name = domain_name;
1387 r.out.info = &info;
1389 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1391 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1392 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1394 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1395 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1397 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1398 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1400 r.in.domain_name->string = "\\\\__NONAME__";
1401 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1403 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1404 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1406 r.in.domain_name->string = "\\\\Builtin";
1407 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1409 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1410 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1412 return true;
1415 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1416 struct policy_handle *handle)
1418 NTSTATUS status;
1419 struct samr_GetUserPwInfo r;
1420 struct samr_PwInfo info;
1422 torture_comment(tctx, "Testing GetUserPwInfo\n");
1424 r.in.user_handle = handle;
1425 r.out.info = &info;
1427 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1428 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1430 return true;
1433 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1434 struct policy_handle *domain_handle, const char *name,
1435 uint32_t *rid)
1437 NTSTATUS status;
1438 struct samr_LookupNames n;
1439 struct lsa_String sname[2];
1440 struct samr_Ids rids, types;
1442 init_lsa_String(&sname[0], name);
1444 n.in.domain_handle = domain_handle;
1445 n.in.num_names = 1;
1446 n.in.names = sname;
1447 n.out.rids = &rids;
1448 n.out.types = &types;
1449 status = dcerpc_samr_LookupNames(p, tctx, &n);
1450 if (NT_STATUS_IS_OK(status)) {
1451 *rid = n.out.rids->ids[0];
1452 } else {
1453 return status;
1456 init_lsa_String(&sname[1], "xxNONAMExx");
1457 n.in.num_names = 2;
1458 status = dcerpc_samr_LookupNames(p, tctx, &n);
1459 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1460 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(status));
1461 if (NT_STATUS_IS_OK(status)) {
1462 return NT_STATUS_UNSUCCESSFUL;
1464 return status;
1467 n.in.num_names = 0;
1468 status = dcerpc_samr_LookupNames(p, tctx, &n);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1471 return status;
1474 init_lsa_String(&sname[0], "xxNONAMExx");
1475 n.in.num_names = 1;
1476 status = dcerpc_samr_LookupNames(p, tctx, &n);
1477 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1478 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1479 if (NT_STATUS_IS_OK(status)) {
1480 return NT_STATUS_UNSUCCESSFUL;
1482 return status;
1485 init_lsa_String(&sname[0], "xxNONAMExx");
1486 init_lsa_String(&sname[1], "xxNONAME2xx");
1487 n.in.num_names = 2;
1488 status = dcerpc_samr_LookupNames(p, tctx, &n);
1489 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1490 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1491 if (NT_STATUS_IS_OK(status)) {
1492 return NT_STATUS_UNSUCCESSFUL;
1494 return status;
1497 return NT_STATUS_OK;
1500 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
1501 struct torture_context *tctx,
1502 struct policy_handle *domain_handle,
1503 const char *name, struct policy_handle *user_handle)
1505 NTSTATUS status;
1506 struct samr_OpenUser r;
1507 uint32_t rid;
1509 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return status;
1514 r.in.domain_handle = domain_handle;
1515 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1516 r.in.rid = rid;
1517 r.out.user_handle = user_handle;
1518 status = dcerpc_samr_OpenUser(p, tctx, &r);
1519 if (!NT_STATUS_IS_OK(status)) {
1520 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1523 return status;
1526 #if 0
1527 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1528 struct torture_context *tctx,
1529 struct policy_handle *handle)
1531 NTSTATUS status;
1532 struct samr_ChangePasswordUser r;
1533 bool ret = true;
1534 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1535 struct policy_handle user_handle;
1536 char *oldpass = "test";
1537 char *newpass = "test2";
1538 uint8_t old_nt_hash[16], new_nt_hash[16];
1539 uint8_t old_lm_hash[16], new_lm_hash[16];
1541 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 return false;
1546 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1548 torture_comment(tctx, "old password: %s\n", oldpass);
1549 torture_comment(tctx, "new password: %s\n", newpass);
1551 E_md4hash(oldpass, old_nt_hash);
1552 E_md4hash(newpass, new_nt_hash);
1553 E_deshash(oldpass, old_lm_hash);
1554 E_deshash(newpass, new_lm_hash);
1556 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1557 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1558 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1559 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1560 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1561 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1563 r.in.handle = &user_handle;
1564 r.in.lm_present = 1;
1565 r.in.old_lm_crypted = &hash1;
1566 r.in.new_lm_crypted = &hash2;
1567 r.in.nt_present = 1;
1568 r.in.old_nt_crypted = &hash3;
1569 r.in.new_nt_crypted = &hash4;
1570 r.in.cross1_present = 1;
1571 r.in.nt_cross = &hash5;
1572 r.in.cross2_present = 1;
1573 r.in.lm_cross = &hash6;
1575 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1578 ret = false;
1581 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1582 ret = false;
1585 return ret;
1587 #endif
1589 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1590 const char *acct_name,
1591 struct policy_handle *handle, char **password)
1593 NTSTATUS status;
1594 struct samr_ChangePasswordUser r;
1595 bool ret = true;
1596 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1597 struct policy_handle user_handle;
1598 char *oldpass;
1599 uint8_t old_nt_hash[16], new_nt_hash[16];
1600 uint8_t old_lm_hash[16], new_lm_hash[16];
1601 bool changed = true;
1603 char *newpass;
1604 struct samr_GetUserPwInfo pwp;
1605 struct samr_PwInfo info;
1606 int policy_min_pw_len = 0;
1608 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 return false;
1612 pwp.in.user_handle = &user_handle;
1613 pwp.out.info = &info;
1615 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1616 if (NT_STATUS_IS_OK(status)) {
1617 policy_min_pw_len = pwp.out.info->min_password_length;
1619 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1621 torture_comment(tctx, "Testing ChangePasswordUser\n");
1623 torture_assert(tctx, *password != NULL,
1624 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1626 oldpass = *password;
1628 E_md4hash(oldpass, old_nt_hash);
1629 E_md4hash(newpass, new_nt_hash);
1630 E_deshash(oldpass, old_lm_hash);
1631 E_deshash(newpass, new_lm_hash);
1633 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1634 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1635 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1636 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1637 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1638 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1640 r.in.user_handle = &user_handle;
1641 r.in.lm_present = 1;
1642 /* Break the LM hash */
1643 hash1.hash[0]++;
1644 r.in.old_lm_crypted = &hash1;
1645 r.in.new_lm_crypted = &hash2;
1646 r.in.nt_present = 1;
1647 r.in.old_nt_crypted = &hash3;
1648 r.in.new_nt_crypted = &hash4;
1649 r.in.cross1_present = 1;
1650 r.in.nt_cross = &hash5;
1651 r.in.cross2_present = 1;
1652 r.in.lm_cross = &hash6;
1654 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1655 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1656 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1658 /* Unbreak the LM hash */
1659 hash1.hash[0]--;
1661 r.in.user_handle = &user_handle;
1662 r.in.lm_present = 1;
1663 r.in.old_lm_crypted = &hash1;
1664 r.in.new_lm_crypted = &hash2;
1665 /* Break the NT hash */
1666 hash3.hash[0]--;
1667 r.in.nt_present = 1;
1668 r.in.old_nt_crypted = &hash3;
1669 r.in.new_nt_crypted = &hash4;
1670 r.in.cross1_present = 1;
1671 r.in.nt_cross = &hash5;
1672 r.in.cross2_present = 1;
1673 r.in.lm_cross = &hash6;
1675 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1676 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1677 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1679 /* Unbreak the NT hash */
1680 hash3.hash[0]--;
1682 r.in.user_handle = &user_handle;
1683 r.in.lm_present = 1;
1684 r.in.old_lm_crypted = &hash1;
1685 r.in.new_lm_crypted = &hash2;
1686 r.in.nt_present = 1;
1687 r.in.old_nt_crypted = &hash3;
1688 r.in.new_nt_crypted = &hash4;
1689 r.in.cross1_present = 1;
1690 r.in.nt_cross = &hash5;
1691 r.in.cross2_present = 1;
1692 /* Break the LM cross */
1693 hash6.hash[0]++;
1694 r.in.lm_cross = &hash6;
1696 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1697 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1698 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1699 ret = false;
1702 /* Unbreak the LM cross */
1703 hash6.hash[0]--;
1705 r.in.user_handle = &user_handle;
1706 r.in.lm_present = 1;
1707 r.in.old_lm_crypted = &hash1;
1708 r.in.new_lm_crypted = &hash2;
1709 r.in.nt_present = 1;
1710 r.in.old_nt_crypted = &hash3;
1711 r.in.new_nt_crypted = &hash4;
1712 r.in.cross1_present = 1;
1713 /* Break the NT cross */
1714 hash5.hash[0]++;
1715 r.in.nt_cross = &hash5;
1716 r.in.cross2_present = 1;
1717 r.in.lm_cross = &hash6;
1719 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1720 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1721 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1722 ret = false;
1725 /* Unbreak the NT cross */
1726 hash5.hash[0]--;
1729 /* Reset the hashes to not broken values */
1730 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1731 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1732 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1733 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1734 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1735 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1737 r.in.user_handle = &user_handle;
1738 r.in.lm_present = 1;
1739 r.in.old_lm_crypted = &hash1;
1740 r.in.new_lm_crypted = &hash2;
1741 r.in.nt_present = 1;
1742 r.in.old_nt_crypted = &hash3;
1743 r.in.new_nt_crypted = &hash4;
1744 r.in.cross1_present = 1;
1745 r.in.nt_cross = &hash5;
1746 r.in.cross2_present = 0;
1747 r.in.lm_cross = NULL;
1749 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1750 if (NT_STATUS_IS_OK(status)) {
1751 changed = true;
1752 *password = newpass;
1753 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1754 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1755 ret = false;
1758 oldpass = newpass;
1759 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1761 E_md4hash(oldpass, old_nt_hash);
1762 E_md4hash(newpass, new_nt_hash);
1763 E_deshash(oldpass, old_lm_hash);
1764 E_deshash(newpass, new_lm_hash);
1767 /* Reset the hashes to not broken values */
1768 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1769 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1770 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1771 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1772 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1773 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1775 r.in.user_handle = &user_handle;
1776 r.in.lm_present = 1;
1777 r.in.old_lm_crypted = &hash1;
1778 r.in.new_lm_crypted = &hash2;
1779 r.in.nt_present = 1;
1780 r.in.old_nt_crypted = &hash3;
1781 r.in.new_nt_crypted = &hash4;
1782 r.in.cross1_present = 0;
1783 r.in.nt_cross = NULL;
1784 r.in.cross2_present = 1;
1785 r.in.lm_cross = &hash6;
1787 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1788 if (NT_STATUS_IS_OK(status)) {
1789 changed = true;
1790 *password = newpass;
1791 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1792 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1793 ret = false;
1796 oldpass = newpass;
1797 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1799 E_md4hash(oldpass, old_nt_hash);
1800 E_md4hash(newpass, new_nt_hash);
1801 E_deshash(oldpass, old_lm_hash);
1802 E_deshash(newpass, new_lm_hash);
1805 /* Reset the hashes to not broken values */
1806 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1807 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1808 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1809 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1810 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1811 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1813 r.in.user_handle = &user_handle;
1814 r.in.lm_present = 1;
1815 r.in.old_lm_crypted = &hash1;
1816 r.in.new_lm_crypted = &hash2;
1817 r.in.nt_present = 1;
1818 r.in.old_nt_crypted = &hash3;
1819 r.in.new_nt_crypted = &hash4;
1820 r.in.cross1_present = 1;
1821 r.in.nt_cross = &hash5;
1822 r.in.cross2_present = 1;
1823 r.in.lm_cross = &hash6;
1825 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1826 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1827 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1828 } else if (!NT_STATUS_IS_OK(status)) {
1829 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1830 ret = false;
1831 } else {
1832 changed = true;
1833 *password = newpass;
1836 r.in.user_handle = &user_handle;
1837 r.in.lm_present = 1;
1838 r.in.old_lm_crypted = &hash1;
1839 r.in.new_lm_crypted = &hash2;
1840 r.in.nt_present = 1;
1841 r.in.old_nt_crypted = &hash3;
1842 r.in.new_nt_crypted = &hash4;
1843 r.in.cross1_present = 1;
1844 r.in.nt_cross = &hash5;
1845 r.in.cross2_present = 1;
1846 r.in.lm_cross = &hash6;
1848 if (changed) {
1849 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1850 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1851 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1852 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1853 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1854 ret = false;
1859 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1860 ret = false;
1863 return ret;
1867 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1868 const char *acct_name,
1869 struct policy_handle *handle, char **password)
1871 NTSTATUS status;
1872 struct samr_OemChangePasswordUser2 r;
1873 bool ret = true;
1874 struct samr_Password lm_verifier;
1875 struct samr_CryptPassword lm_pass;
1876 struct lsa_AsciiString server, account, account_bad;
1877 char *oldpass;
1878 char *newpass;
1879 uint8_t old_lm_hash[16], new_lm_hash[16];
1881 struct samr_GetDomPwInfo dom_pw_info;
1882 struct samr_PwInfo info;
1883 int policy_min_pw_len = 0;
1885 struct lsa_String domain_name;
1887 domain_name.string = "";
1888 dom_pw_info.in.domain_name = &domain_name;
1889 dom_pw_info.out.info = &info;
1891 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1893 torture_assert(tctx, *password != NULL,
1894 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1896 oldpass = *password;
1898 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1899 if (NT_STATUS_IS_OK(status)) {
1900 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1903 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1905 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1906 account.string = acct_name;
1908 E_deshash(oldpass, old_lm_hash);
1909 E_deshash(newpass, new_lm_hash);
1911 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1912 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1913 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1915 r.in.server = &server;
1916 r.in.account = &account;
1917 r.in.password = &lm_pass;
1918 r.in.hash = &lm_verifier;
1920 /* Break the verification */
1921 lm_verifier.hash[0]++;
1923 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1925 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1926 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1927 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1928 nt_errstr(status));
1929 ret = false;
1932 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1933 /* Break the old password */
1934 old_lm_hash[0]++;
1935 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1936 /* unbreak it for the next operation */
1937 old_lm_hash[0]--;
1938 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1940 r.in.server = &server;
1941 r.in.account = &account;
1942 r.in.password = &lm_pass;
1943 r.in.hash = &lm_verifier;
1945 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1947 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1948 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1949 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1950 nt_errstr(status));
1951 ret = false;
1954 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1955 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1957 r.in.server = &server;
1958 r.in.account = &account;
1959 r.in.password = &lm_pass;
1960 r.in.hash = NULL;
1962 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1964 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1965 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1966 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1967 nt_errstr(status));
1968 ret = false;
1971 /* This shouldn't be a valid name */
1972 account_bad.string = TEST_ACCOUNT_NAME "XX";
1973 r.in.account = &account_bad;
1975 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1977 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1978 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1979 nt_errstr(status));
1980 ret = false;
1983 /* This shouldn't be a valid name */
1984 account_bad.string = TEST_ACCOUNT_NAME "XX";
1985 r.in.account = &account_bad;
1986 r.in.password = &lm_pass;
1987 r.in.hash = &lm_verifier;
1989 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1991 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1992 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1993 nt_errstr(status));
1994 ret = false;
1997 /* This shouldn't be a valid name */
1998 account_bad.string = TEST_ACCOUNT_NAME "XX";
1999 r.in.account = &account_bad;
2000 r.in.password = NULL;
2001 r.in.hash = &lm_verifier;
2003 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2005 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2006 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2007 nt_errstr(status));
2008 ret = false;
2011 E_deshash(oldpass, old_lm_hash);
2012 E_deshash(newpass, new_lm_hash);
2014 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2015 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2016 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2018 r.in.server = &server;
2019 r.in.account = &account;
2020 r.in.password = &lm_pass;
2021 r.in.hash = &lm_verifier;
2023 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2024 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2025 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2026 } else if (!NT_STATUS_IS_OK(status)) {
2027 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2028 ret = false;
2029 } else {
2030 *password = newpass;
2033 return ret;
2037 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2038 const char *acct_name,
2039 char **password,
2040 char *newpass, bool allow_password_restriction)
2042 NTSTATUS status;
2043 struct samr_ChangePasswordUser2 r;
2044 bool ret = true;
2045 struct lsa_String server, account;
2046 struct samr_CryptPassword nt_pass, lm_pass;
2047 struct samr_Password nt_verifier, lm_verifier;
2048 char *oldpass;
2049 uint8_t old_nt_hash[16], new_nt_hash[16];
2050 uint8_t old_lm_hash[16], new_lm_hash[16];
2052 struct samr_GetDomPwInfo dom_pw_info;
2053 struct samr_PwInfo info;
2055 struct lsa_String domain_name;
2057 domain_name.string = "";
2058 dom_pw_info.in.domain_name = &domain_name;
2059 dom_pw_info.out.info = &info;
2061 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2063 torture_assert(tctx, *password != NULL,
2064 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2065 oldpass = *password;
2067 if (!newpass) {
2068 int policy_min_pw_len = 0;
2069 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2070 if (NT_STATUS_IS_OK(status)) {
2071 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2074 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2077 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2078 init_lsa_String(&account, acct_name);
2080 E_md4hash(oldpass, old_nt_hash);
2081 E_md4hash(newpass, new_nt_hash);
2083 E_deshash(oldpass, old_lm_hash);
2084 E_deshash(newpass, new_lm_hash);
2086 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2087 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2088 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2090 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2091 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2092 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2094 r.in.server = &server;
2095 r.in.account = &account;
2096 r.in.nt_password = &nt_pass;
2097 r.in.nt_verifier = &nt_verifier;
2098 r.in.lm_change = 1;
2099 r.in.lm_password = &lm_pass;
2100 r.in.lm_verifier = &lm_verifier;
2102 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2103 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2104 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2105 } else if (!NT_STATUS_IS_OK(status)) {
2106 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2107 ret = false;
2108 } else {
2109 *password = newpass;
2112 return ret;
2116 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2117 const char *account_string,
2118 int policy_min_pw_len,
2119 char **password,
2120 const char *newpass,
2121 NTTIME last_password_change,
2122 bool handle_reject_reason)
2124 NTSTATUS status;
2125 struct samr_ChangePasswordUser3 r;
2126 bool ret = true;
2127 struct lsa_String server, account, account_bad;
2128 struct samr_CryptPassword nt_pass, lm_pass;
2129 struct samr_Password nt_verifier, lm_verifier;
2130 char *oldpass;
2131 uint8_t old_nt_hash[16], new_nt_hash[16];
2132 uint8_t old_lm_hash[16], new_lm_hash[16];
2133 NTTIME t;
2134 struct samr_DomInfo1 *dominfo = NULL;
2135 struct userPwdChangeFailureInformation *reject = NULL;
2137 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2139 if (newpass == NULL) {
2140 do {
2141 if (policy_min_pw_len == 0) {
2142 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2143 } else {
2144 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2146 } while (check_password_quality(newpass) == false);
2147 } else {
2148 torture_comment(tctx, "Using password '%s'\n", newpass);
2151 torture_assert(tctx, *password != NULL,
2152 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2154 oldpass = *password;
2155 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2156 init_lsa_String(&account, account_string);
2158 E_md4hash(oldpass, old_nt_hash);
2159 E_md4hash(newpass, new_nt_hash);
2161 E_deshash(oldpass, old_lm_hash);
2162 E_deshash(newpass, new_lm_hash);
2164 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2165 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2166 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2168 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2169 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2170 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2172 /* Break the verification */
2173 nt_verifier.hash[0]++;
2175 r.in.server = &server;
2176 r.in.account = &account;
2177 r.in.nt_password = &nt_pass;
2178 r.in.nt_verifier = &nt_verifier;
2179 r.in.lm_change = 1;
2180 r.in.lm_password = &lm_pass;
2181 r.in.lm_verifier = &lm_verifier;
2182 r.in.password3 = NULL;
2183 r.out.dominfo = &dominfo;
2184 r.out.reject = &reject;
2186 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2187 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2188 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2189 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2190 nt_errstr(status));
2191 ret = false;
2194 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2195 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2196 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2198 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2199 /* Break the NT hash */
2200 old_nt_hash[0]++;
2201 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2202 /* Unbreak it again */
2203 old_nt_hash[0]--;
2204 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2206 r.in.server = &server;
2207 r.in.account = &account;
2208 r.in.nt_password = &nt_pass;
2209 r.in.nt_verifier = &nt_verifier;
2210 r.in.lm_change = 1;
2211 r.in.lm_password = &lm_pass;
2212 r.in.lm_verifier = &lm_verifier;
2213 r.in.password3 = NULL;
2214 r.out.dominfo = &dominfo;
2215 r.out.reject = &reject;
2217 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2218 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2219 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2220 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2221 nt_errstr(status));
2222 ret = false;
2225 /* This shouldn't be a valid name */
2226 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2228 r.in.account = &account_bad;
2229 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2230 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2231 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2232 nt_errstr(status));
2233 ret = false;
2236 E_md4hash(oldpass, old_nt_hash);
2237 E_md4hash(newpass, new_nt_hash);
2239 E_deshash(oldpass, old_lm_hash);
2240 E_deshash(newpass, new_lm_hash);
2242 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2243 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2244 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2246 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2247 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2248 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2250 r.in.server = &server;
2251 r.in.account = &account;
2252 r.in.nt_password = &nt_pass;
2253 r.in.nt_verifier = &nt_verifier;
2254 r.in.lm_change = 1;
2255 r.in.lm_password = &lm_pass;
2256 r.in.lm_verifier = &lm_verifier;
2257 r.in.password3 = NULL;
2258 r.out.dominfo = &dominfo;
2259 r.out.reject = &reject;
2261 unix_to_nt_time(&t, time(NULL));
2263 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2265 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2266 && dominfo
2267 && reject
2268 && handle_reject_reason
2269 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2270 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2272 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2273 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2274 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2275 return false;
2279 /* We tested the order of precendence which is as follows:
2281 * pwd min_age
2282 * pwd length
2283 * pwd complexity
2284 * pwd history
2286 Guenther */
2288 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2289 (last_password_change + dominfo->min_password_age > t)) {
2291 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2292 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2293 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2294 return false;
2297 } else if ((dominfo->min_password_length > 0) &&
2298 (strlen(newpass) < dominfo->min_password_length)) {
2300 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2301 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2302 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2303 return false;
2306 } else if ((dominfo->password_history_length > 0) &&
2307 strequal(oldpass, newpass)) {
2309 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2310 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2311 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2312 return false;
2314 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2316 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2317 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2318 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2319 return false;
2324 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2325 /* retry with adjusted size */
2326 return test_ChangePasswordUser3(p, tctx, account_string,
2327 dominfo->min_password_length,
2328 password, NULL, 0, false);
2332 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2333 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2334 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2335 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2336 return false;
2338 /* Perhaps the server has a 'min password age' set? */
2340 } else {
2341 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2342 *password = talloc_strdup(tctx, newpass);
2345 return ret;
2348 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2349 const char *account_string,
2350 struct policy_handle *handle,
2351 char **password)
2353 NTSTATUS status;
2354 struct samr_ChangePasswordUser3 r;
2355 struct samr_SetUserInfo s;
2356 union samr_UserInfo u;
2357 DATA_BLOB session_key;
2358 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2359 uint8_t confounder[16];
2360 struct MD5Context ctx;
2362 bool ret = true;
2363 struct lsa_String server, account;
2364 struct samr_CryptPassword nt_pass;
2365 struct samr_Password nt_verifier;
2366 DATA_BLOB new_random_pass;
2367 char *newpass;
2368 char *oldpass;
2369 uint8_t old_nt_hash[16], new_nt_hash[16];
2370 NTTIME t;
2371 struct samr_DomInfo1 *dominfo = NULL;
2372 struct userPwdChangeFailureInformation *reject = NULL;
2374 new_random_pass = samr_very_rand_pass(tctx, 128);
2376 torture_assert(tctx, *password != NULL,
2377 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2379 oldpass = *password;
2380 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2381 init_lsa_String(&account, account_string);
2383 s.in.user_handle = handle;
2384 s.in.info = &u;
2385 s.in.level = 25;
2387 ZERO_STRUCT(u);
2389 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2391 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2393 status = dcerpc_fetch_session_key(p, &session_key);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2396 s.in.level, nt_errstr(status));
2397 return false;
2400 generate_random_buffer((uint8_t *)confounder, 16);
2402 MD5Init(&ctx);
2403 MD5Update(&ctx, confounder, 16);
2404 MD5Update(&ctx, session_key.data, session_key.length);
2405 MD5Final(confounded_session_key.data, &ctx);
2407 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2408 memcpy(&u.info25.password.data[516], confounder, 16);
2410 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2412 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2413 if (!NT_STATUS_IS_OK(status)) {
2414 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2415 s.in.level, nt_errstr(status));
2416 ret = false;
2419 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2421 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2423 new_random_pass = samr_very_rand_pass(tctx, 128);
2425 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2427 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2428 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2429 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2431 r.in.server = &server;
2432 r.in.account = &account;
2433 r.in.nt_password = &nt_pass;
2434 r.in.nt_verifier = &nt_verifier;
2435 r.in.lm_change = 0;
2436 r.in.lm_password = NULL;
2437 r.in.lm_verifier = NULL;
2438 r.in.password3 = NULL;
2439 r.out.dominfo = &dominfo;
2440 r.out.reject = &reject;
2442 unix_to_nt_time(&t, time(NULL));
2444 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2446 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2447 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2448 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2449 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2450 return false;
2452 /* Perhaps the server has a 'min password age' set? */
2454 } else if (!NT_STATUS_IS_OK(status)) {
2455 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2456 ret = false;
2459 newpass = samr_rand_pass(tctx, 128);
2461 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2463 E_md4hash(newpass, new_nt_hash);
2465 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2466 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2467 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2469 r.in.server = &server;
2470 r.in.account = &account;
2471 r.in.nt_password = &nt_pass;
2472 r.in.nt_verifier = &nt_verifier;
2473 r.in.lm_change = 0;
2474 r.in.lm_password = NULL;
2475 r.in.lm_verifier = NULL;
2476 r.in.password3 = NULL;
2477 r.out.dominfo = &dominfo;
2478 r.out.reject = &reject;
2480 unix_to_nt_time(&t, time(NULL));
2482 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2484 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2485 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2486 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2487 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2488 return false;
2490 /* Perhaps the server has a 'min password age' set? */
2492 } else {
2493 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2494 *password = talloc_strdup(tctx, newpass);
2497 return ret;
2501 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2502 struct policy_handle *alias_handle)
2504 struct samr_GetMembersInAlias r;
2505 struct lsa_SidArray sids;
2506 NTSTATUS status;
2508 torture_comment(tctx, "Testing GetMembersInAlias\n");
2510 r.in.alias_handle = alias_handle;
2511 r.out.sids = &sids;
2513 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2514 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2516 return true;
2519 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2520 struct policy_handle *alias_handle,
2521 const struct dom_sid *domain_sid)
2523 struct samr_AddAliasMember r;
2524 struct samr_DeleteAliasMember d;
2525 NTSTATUS status;
2526 struct dom_sid *sid;
2528 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2530 torture_comment(tctx, "testing AddAliasMember\n");
2531 r.in.alias_handle = alias_handle;
2532 r.in.sid = sid;
2534 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2535 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2537 d.in.alias_handle = alias_handle;
2538 d.in.sid = sid;
2540 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2541 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2543 return true;
2546 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2547 struct policy_handle *alias_handle)
2549 struct samr_AddMultipleMembersToAlias a;
2550 struct samr_RemoveMultipleMembersFromAlias r;
2551 NTSTATUS status;
2552 struct lsa_SidArray sids;
2554 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2555 a.in.alias_handle = alias_handle;
2556 a.in.sids = &sids;
2558 sids.num_sids = 3;
2559 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2561 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2562 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2563 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2565 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2566 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2569 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2570 r.in.alias_handle = alias_handle;
2571 r.in.sids = &sids;
2573 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2574 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2576 /* strange! removing twice doesn't give any error */
2577 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2578 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2580 /* but removing an alias that isn't there does */
2581 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2583 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2584 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2586 return true;
2589 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2590 struct policy_handle *user_handle)
2592 struct samr_TestPrivateFunctionsUser r;
2593 NTSTATUS status;
2595 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2597 r.in.user_handle = user_handle;
2599 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2600 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2602 return true;
2605 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2606 struct torture_context *tctx,
2607 struct policy_handle *handle,
2608 bool use_info2,
2609 NTTIME *pwdlastset)
2611 NTSTATUS status;
2612 uint16_t levels[] = { /* 3, */ 5, 21 };
2613 int i;
2614 NTTIME pwdlastset3 = 0;
2615 NTTIME pwdlastset5 = 0;
2616 NTTIME pwdlastset21 = 0;
2618 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2619 use_info2 ? "2":"");
2621 for (i=0; i<ARRAY_SIZE(levels); i++) {
2623 struct samr_QueryUserInfo r;
2624 struct samr_QueryUserInfo2 r2;
2625 union samr_UserInfo *info;
2627 if (use_info2) {
2628 r2.in.user_handle = handle;
2629 r2.in.level = levels[i];
2630 r2.out.info = &info;
2631 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2633 } else {
2634 r.in.user_handle = handle;
2635 r.in.level = levels[i];
2636 r.out.info = &info;
2637 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2640 if (!NT_STATUS_IS_OK(status) &&
2641 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2642 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2643 use_info2 ? "2":"", levels[i], nt_errstr(status));
2644 return false;
2647 switch (levels[i]) {
2648 case 3:
2649 pwdlastset3 = info->info3.last_password_change;
2650 break;
2651 case 5:
2652 pwdlastset5 = info->info5.last_password_change;
2653 break;
2654 case 21:
2655 pwdlastset21 = info->info21.last_password_change;
2656 break;
2657 default:
2658 return false;
2661 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2662 "pwdlastset mixup"); */
2663 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2664 "pwdlastset mixup");
2666 *pwdlastset = pwdlastset21;
2668 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2670 return true;
2673 static bool test_SamLogon(struct torture_context *tctx,
2674 struct dcerpc_pipe *p,
2675 struct cli_credentials *test_credentials,
2676 NTSTATUS expected_result)
2678 NTSTATUS status;
2679 struct netr_LogonSamLogonEx r;
2680 union netr_LogonLevel logon;
2681 union netr_Validation validation;
2682 uint8_t authoritative;
2683 struct netr_NetworkInfo ninfo;
2684 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2685 int flags = CLI_CRED_NTLM_AUTH;
2686 uint32_t samlogon_flags = 0;
2688 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2689 flags |= CLI_CRED_LANMAN_AUTH;
2692 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2693 flags |= CLI_CRED_NTLMv2_AUTH;
2696 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2697 &ninfo.identity_info.account_name.string,
2698 &ninfo.identity_info.domain_name.string);
2700 generate_random_buffer(ninfo.challenge,
2701 sizeof(ninfo.challenge));
2702 chal = data_blob_const(ninfo.challenge,
2703 sizeof(ninfo.challenge));
2705 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2706 cli_credentials_get_domain(test_credentials));
2708 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2709 &flags,
2710 chal,
2711 names_blob,
2712 &lm_resp, &nt_resp,
2713 NULL, NULL);
2714 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2716 ninfo.lm.data = lm_resp.data;
2717 ninfo.lm.length = lm_resp.length;
2719 ninfo.nt.data = nt_resp.data;
2720 ninfo.nt.length = nt_resp.length;
2722 ninfo.identity_info.parameter_control =
2723 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2724 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2725 ninfo.identity_info.logon_id_low = 0;
2726 ninfo.identity_info.logon_id_high = 0;
2727 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(test_credentials);
2729 logon.network = &ninfo;
2731 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2732 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2733 r.in.logon_level = NetlogonNetworkInformation;
2734 r.in.logon = &logon;
2735 r.in.flags = &samlogon_flags;
2736 r.out.flags = &samlogon_flags;
2737 r.out.validation = &validation;
2738 r.out.authoritative = &authoritative;
2740 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2742 r.in.validation_level = 6;
2744 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2745 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2746 r.in.validation_level = 3;
2747 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2749 if (!NT_STATUS_IS_OK(status)) {
2750 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2751 return true;
2752 } else {
2753 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2756 return true;
2759 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2760 struct dcerpc_pipe *p,
2761 struct cli_credentials *machine_creds,
2762 const char *acct_name,
2763 char *password,
2764 NTSTATUS expected_samlogon_result)
2766 bool ret = true;
2767 struct cli_credentials *test_credentials;
2769 test_credentials = cli_credentials_init(tctx);
2771 cli_credentials_set_workstation(test_credentials,
2772 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2773 cli_credentials_set_domain(test_credentials,
2774 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2775 cli_credentials_set_username(test_credentials,
2776 acct_name, CRED_SPECIFIED);
2777 cli_credentials_set_password(test_credentials,
2778 password, CRED_SPECIFIED);
2780 torture_comment(tctx, "testing samlogon as %s password: %s\n",
2781 acct_name, password);
2783 if (!test_SamLogon(tctx, p, test_credentials,
2784 expected_samlogon_result)) {
2785 torture_warning(tctx, "new password did not work\n");
2786 ret = false;
2789 return ret;
2792 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2793 struct dcerpc_pipe *np,
2794 struct torture_context *tctx,
2795 struct policy_handle *handle,
2796 uint16_t level,
2797 uint32_t fields_present,
2798 uint8_t password_expired,
2799 bool *matched_expected_error,
2800 bool use_setinfo2,
2801 const char *acct_name,
2802 char **password,
2803 struct cli_credentials *machine_creds,
2804 bool use_queryinfo2,
2805 NTTIME *pwdlastset,
2806 NTSTATUS expected_samlogon_result)
2808 const char *fields = NULL;
2809 bool ret = true;
2811 switch (level) {
2812 case 21:
2813 case 23:
2814 case 25:
2815 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2816 fields_present);
2817 break;
2818 default:
2819 break;
2822 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2823 "(password_expired: %d) %s\n",
2824 use_setinfo2 ? "2":"", level, password_expired,
2825 fields ? fields : "");
2827 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2828 fields_present,
2829 password,
2830 password_expired,
2831 use_setinfo2,
2832 matched_expected_error)) {
2833 ret = false;
2836 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2837 use_queryinfo2,
2838 pwdlastset)) {
2839 ret = false;
2842 if (*matched_expected_error == true) {
2843 return ret;
2846 if (!test_SamLogon_with_creds(tctx, np,
2847 machine_creds,
2848 acct_name,
2849 *password,
2850 expected_samlogon_result)) {
2851 ret = false;
2854 return ret;
2857 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2858 struct torture_context *tctx,
2859 uint32_t acct_flags,
2860 const char *acct_name,
2861 struct policy_handle *handle,
2862 char **password,
2863 struct cli_credentials *machine_credentials)
2865 int s = 0, q = 0, f = 0, l = 0, z = 0;
2866 struct dcerpc_binding *b;
2867 bool ret = true;
2868 int delay = 50000;
2869 bool set_levels[] = { false, true };
2870 bool query_levels[] = { false, true };
2871 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2872 uint32_t nonzeros[] = { 1, 24 };
2873 uint32_t fields_present[] = {
2875 SAMR_FIELD_EXPIRED_FLAG,
2876 SAMR_FIELD_LAST_PWD_CHANGE,
2877 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2878 SAMR_FIELD_COMMENT,
2879 SAMR_FIELD_NT_PASSWORD_PRESENT,
2880 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2881 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2882 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2883 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2884 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2885 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2887 NTSTATUS status;
2888 struct dcerpc_pipe *np = NULL;
2890 if (torture_setting_bool(tctx, "samba3", false)) {
2891 delay = 999999;
2892 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
2893 delay);
2896 status = torture_rpc_binding(tctx, &b);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 ret = false;
2899 return ret;
2902 /* We have to use schannel, otherwise the SamLogonEx fails
2903 * with INTERNAL_ERROR */
2905 b->flags &= ~DCERPC_AUTH_OPTIONS;
2906 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2908 status = dcerpc_pipe_connect_b(tctx, &np, b,
2909 &ndr_table_netlogon,
2910 machine_credentials, tctx->ev, tctx->lp_ctx);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 torture_warning(tctx, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
2914 ret = false;
2915 return ret;
2918 /* set to 1 to enable testing for all possible opcode
2919 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2920 combinations */
2921 #if 0
2922 #define TEST_ALL_LEVELS 1
2923 #define TEST_SET_LEVELS 1
2924 #define TEST_QUERY_LEVELS 1
2925 #endif
2926 #ifdef TEST_ALL_LEVELS
2927 for (l=0; l<ARRAY_SIZE(levels); l++) {
2928 #else
2929 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
2930 #endif
2931 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2932 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2933 #ifdef TEST_SET_LEVELS
2934 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2935 #endif
2936 #ifdef TEST_QUERY_LEVELS
2937 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2938 #endif
2939 NTTIME pwdlastset_old = 0;
2940 NTTIME pwdlastset_new = 0;
2941 bool matched_expected_error = false;
2942 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2944 torture_comment(tctx, "------------------------------\n"
2945 "Testing pwdLastSet attribute for flags: 0x%08x "
2946 "(s: %d (l: %d), q: %d)\n",
2947 acct_flags, s, levels[l], q);
2949 switch (levels[l]) {
2950 case 21:
2951 case 23:
2952 case 25:
2953 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2954 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2955 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2957 break;
2961 /* set #1 */
2963 /* set a password and force password change (pwdlastset 0) by
2964 * setting the password expired flag to a non-0 value */
2966 if (!test_SetPassword_level(p, np, tctx, handle,
2967 levels[l],
2968 fields_present[f],
2969 nonzeros[z],
2970 &matched_expected_error,
2971 set_levels[s],
2972 acct_name,
2973 password,
2974 machine_credentials,
2975 query_levels[q],
2976 &pwdlastset_old,
2977 expected_samlogon_result)) {
2978 ret = false;
2981 if (matched_expected_error == true) {
2982 /* skipping on expected failure */
2983 continue;
2986 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2987 * set without the SAMR_FIELD_EXPIRED_FLAG */
2989 switch (levels[l]) {
2990 case 21:
2991 case 23:
2992 case 25:
2993 if ((pwdlastset_new != 0) &&
2994 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2995 torture_comment(tctx, "not considering a non-0 "
2996 "pwdLastSet as a an error as the "
2997 "SAMR_FIELD_EXPIRED_FLAG has not "
2998 "been set\n");
2999 break;
3001 default:
3002 if (pwdlastset_new != 0) {
3003 torture_warning(tctx, "pwdLastSet test failed: "
3004 "expected pwdLastSet 0 but got %lld\n",
3005 pwdlastset_old);
3006 ret = false;
3008 break;
3011 switch (levels[l]) {
3012 case 21:
3013 case 23:
3014 case 25:
3015 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3016 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3017 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3018 (pwdlastset_old >= pwdlastset_new)) {
3019 torture_warning(tctx, "pwdlastset not increasing\n");
3020 ret = false;
3022 break;
3023 default:
3024 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3025 (pwdlastset_old >= pwdlastset_new)) {
3026 torture_warning(tctx, "pwdlastset not increasing\n");
3027 ret = false;
3029 break;
3032 usleep(delay);
3034 /* set #2 */
3036 /* set a password, pwdlastset needs to get updated (increased
3037 * value), password_expired value used here is 0 */
3039 if (!test_SetPassword_level(p, np, tctx, handle,
3040 levels[l],
3041 fields_present[f],
3043 &matched_expected_error,
3044 set_levels[s],
3045 acct_name,
3046 password,
3047 machine_credentials,
3048 query_levels[q],
3049 &pwdlastset_new,
3050 expected_samlogon_result)) {
3051 ret = false;
3054 /* when a password has been changed, pwdlastset must not be 0 afterwards
3055 * and must be larger then the old value */
3057 switch (levels[l]) {
3058 case 21:
3059 case 23:
3060 case 25:
3062 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3063 * password has been changed, old and new pwdlastset
3064 * need to be the same value */
3066 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3067 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3068 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3070 torture_assert_int_equal(tctx, pwdlastset_old,
3071 pwdlastset_new, "pwdlastset must be equal");
3072 break;
3074 default:
3075 if (pwdlastset_old >= pwdlastset_new) {
3076 torture_warning(tctx, "pwdLastSet test failed: "
3077 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3078 pwdlastset_old, pwdlastset_new);
3079 ret = false;
3081 if (pwdlastset_new == 0) {
3082 torture_warning(tctx, "pwdLastSet test failed: "
3083 "expected non-0 pwdlastset, got: %lld\n",
3084 pwdlastset_new);
3085 ret = false;
3089 switch (levels[l]) {
3090 case 21:
3091 case 23:
3092 case 25:
3093 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3094 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3095 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3096 (pwdlastset_old >= pwdlastset_new)) {
3097 torture_warning(tctx, "pwdlastset not increasing\n");
3098 ret = false;
3100 break;
3101 default:
3102 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3103 (pwdlastset_old >= pwdlastset_new)) {
3104 torture_warning(tctx, "pwdlastset not increasing\n");
3105 ret = false;
3107 break;
3110 pwdlastset_old = pwdlastset_new;
3112 usleep(delay);
3114 /* set #2b */
3116 /* set a password, pwdlastset needs to get updated (increased
3117 * value), password_expired value used here is 0 */
3119 if (!test_SetPassword_level(p, np, tctx, handle,
3120 levels[l],
3121 fields_present[f],
3123 &matched_expected_error,
3124 set_levels[s],
3125 acct_name,
3126 password,
3127 machine_credentials,
3128 query_levels[q],
3129 &pwdlastset_new,
3130 expected_samlogon_result)) {
3131 ret = false;
3134 /* when a password has been changed, pwdlastset must not be 0 afterwards
3135 * and must be larger then the old value */
3137 switch (levels[l]) {
3138 case 21:
3139 case 23:
3140 case 25:
3142 /* if no password has been changed, old and new pwdlastset
3143 * need to be the same value */
3145 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3146 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3148 torture_assert_int_equal(tctx, pwdlastset_old,
3149 pwdlastset_new, "pwdlastset must be equal");
3150 break;
3152 default:
3153 if (pwdlastset_old >= pwdlastset_new) {
3154 torture_warning(tctx, "pwdLastSet test failed: "
3155 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3156 pwdlastset_old, pwdlastset_new);
3157 ret = false;
3159 if (pwdlastset_new == 0) {
3160 torture_warning(tctx, "pwdLastSet test failed: "
3161 "expected non-0 pwdlastset, got: %lld\n",
3162 pwdlastset_new);
3163 ret = false;
3167 /* set #3 */
3169 /* set a password and force password change (pwdlastset 0) by
3170 * setting the password expired flag to a non-0 value */
3172 if (!test_SetPassword_level(p, np, tctx, handle,
3173 levels[l],
3174 fields_present[f],
3175 nonzeros[z],
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 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3188 * set without the SAMR_FIELD_EXPIRED_FLAG */
3190 switch (levels[l]) {
3191 case 21:
3192 case 23:
3193 case 25:
3194 if ((pwdlastset_new != 0) &&
3195 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3196 torture_comment(tctx, "not considering a non-0 "
3197 "pwdLastSet as a an error as the "
3198 "SAMR_FIELD_EXPIRED_FLAG has not "
3199 "been set\n");
3200 break;
3203 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3204 * password has been changed, old and new pwdlastset
3205 * need to be the same value */
3207 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3208 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3209 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3211 torture_assert_int_equal(tctx, pwdlastset_old,
3212 pwdlastset_new, "pwdlastset must be equal");
3213 break;
3215 default:
3217 if (pwdlastset_old == pwdlastset_new) {
3218 torture_warning(tctx, "pwdLastSet test failed: "
3219 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3220 pwdlastset_old, pwdlastset_new);
3221 ret = false;
3224 if (pwdlastset_new != 0) {
3225 torture_warning(tctx, "pwdLastSet test failed: "
3226 "expected pwdLastSet 0, got %lld\n",
3227 pwdlastset_old);
3228 ret = false;
3230 break;
3233 switch (levels[l]) {
3234 case 21:
3235 case 23:
3236 case 25:
3237 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3238 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3239 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3240 (pwdlastset_old >= pwdlastset_new)) {
3241 torture_warning(tctx, "pwdlastset not increasing\n");
3242 ret = false;
3244 break;
3245 default:
3246 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3247 (pwdlastset_old >= pwdlastset_new)) {
3248 torture_warning(tctx, "pwdlastset not increasing\n");
3249 ret = false;
3251 break;
3254 /* if the level we are testing does not have a fields_present
3255 * field, skip all fields present tests by setting f to to
3256 * arraysize */
3257 switch (levels[l]) {
3258 case 18:
3259 case 24:
3260 case 26:
3261 f = ARRAY_SIZE(fields_present);
3262 break;
3265 #ifdef TEST_QUERY_LEVELS
3267 #endif
3268 #ifdef TEST_SET_LEVELS
3270 #endif
3271 } /* fields present */
3272 } /* nonzeros */
3273 } /* levels */
3275 #undef TEST_SET_LEVELS
3276 #undef TEST_QUERY_LEVELS
3278 talloc_free(np);
3280 return ret;
3283 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
3284 struct dcerpc_pipe *lp,
3285 struct torture_context *tctx,
3286 struct policy_handle *domain_handle,
3287 struct policy_handle *lsa_handle,
3288 struct policy_handle *user_handle,
3289 const struct dom_sid *domain_sid,
3290 uint32_t rid,
3291 struct cli_credentials *machine_credentials)
3293 NTSTATUS status;
3294 bool ret = true;
3296 struct policy_handle lsa_acct_handle;
3297 struct dom_sid *user_sid;
3299 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
3302 struct lsa_EnumAccountRights r;
3303 struct lsa_RightSet rights;
3305 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3307 r.in.handle = lsa_handle;
3308 r.in.sid = user_sid;
3309 r.out.rights = &rights;
3311 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3312 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3313 "Expected enum rights for account to fail");
3317 struct lsa_RightSet rights;
3318 struct lsa_StringLarge names[2];
3319 struct lsa_AddAccountRights r;
3321 torture_comment(tctx, "Testing LSA AddAccountRights\n");
3323 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
3324 init_lsa_StringLarge(&names[1], NULL);
3326 rights.count = 1;
3327 rights.names = names;
3329 r.in.handle = lsa_handle;
3330 r.in.sid = user_sid;
3331 r.in.rights = &rights;
3333 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
3334 torture_assert_ntstatus_ok(tctx, status,
3335 "Failed to add privileges");
3339 struct lsa_EnumAccounts r;
3340 uint32_t resume_handle = 0;
3341 struct lsa_SidArray lsa_sid_array;
3342 int i;
3343 bool found_sid = false;
3345 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3347 r.in.handle = lsa_handle;
3348 r.in.num_entries = 0x1000;
3349 r.in.resume_handle = &resume_handle;
3350 r.out.sids = &lsa_sid_array;
3351 r.out.resume_handle = &resume_handle;
3353 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3354 torture_assert_ntstatus_ok(tctx, status,
3355 "Failed to enum accounts");
3357 for (i=0; i < lsa_sid_array.num_sids; i++) {
3358 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3359 found_sid = true;
3363 torture_assert(tctx, found_sid,
3364 "failed to list privileged account");
3368 struct lsa_EnumAccountRights r;
3369 struct lsa_RightSet user_rights;
3371 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3373 r.in.handle = lsa_handle;
3374 r.in.sid = user_sid;
3375 r.out.rights = &user_rights;
3377 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3378 torture_assert_ntstatus_ok(tctx, status,
3379 "Failed to enum rights for account");
3381 if (user_rights.count < 1) {
3382 torture_warning(tctx, "failed to find newly added rights");
3383 return false;
3388 struct lsa_OpenAccount r;
3390 torture_comment(tctx, "Testing LSA OpenAccount\n");
3392 r.in.handle = lsa_handle;
3393 r.in.sid = user_sid;
3394 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3395 r.out.acct_handle = &lsa_acct_handle;
3397 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3398 torture_assert_ntstatus_ok(tctx, status,
3399 "Failed to open lsa account");
3403 struct lsa_GetSystemAccessAccount r;
3404 uint32_t access_mask;
3406 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3408 r.in.handle = &lsa_acct_handle;
3409 r.out.access_mask = &access_mask;
3411 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3412 torture_assert_ntstatus_ok(tctx, status,
3413 "Failed to get lsa system access account");
3417 struct lsa_Close r;
3419 torture_comment(tctx, "Testing LSA Close\n");
3421 r.in.handle = &lsa_acct_handle;
3422 r.out.handle = &lsa_acct_handle;
3424 status = dcerpc_lsa_Close(lp, tctx, &r);
3425 torture_assert_ntstatus_ok(tctx, status,
3426 "Failed to close lsa");
3430 struct samr_DeleteUser r;
3432 torture_comment(tctx, "Testing SAMR DeleteUser\n");
3434 r.in.user_handle = user_handle;
3435 r.out.user_handle = user_handle;
3437 status = dcerpc_samr_DeleteUser(p, tctx, &r);
3438 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
3442 struct lsa_EnumAccounts r;
3443 uint32_t resume_handle = 0;
3444 struct lsa_SidArray lsa_sid_array;
3445 int i;
3446 bool found_sid = false;
3448 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3450 r.in.handle = lsa_handle;
3451 r.in.num_entries = 0x1000;
3452 r.in.resume_handle = &resume_handle;
3453 r.out.sids = &lsa_sid_array;
3454 r.out.resume_handle = &resume_handle;
3456 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3457 torture_assert_ntstatus_ok(tctx, status,
3458 "Failed to enum accounts");
3460 for (i=0; i < lsa_sid_array.num_sids; i++) {
3461 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3462 found_sid = true;
3466 torture_assert(tctx, found_sid,
3467 "failed to list privileged account");
3471 struct lsa_EnumAccountRights r;
3472 struct lsa_RightSet user_rights;
3474 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3476 r.in.handle = lsa_handle;
3477 r.in.sid = user_sid;
3478 r.out.rights = &user_rights;
3480 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3481 torture_assert_ntstatus_ok(tctx, status,
3482 "Failed to enum rights for account");
3484 if (user_rights.count < 1) {
3485 torture_warning(tctx, "failed to find newly added rights");
3486 return false;
3491 struct lsa_OpenAccount r;
3493 torture_comment(tctx, "Testing LSA OpenAccount\n");
3495 r.in.handle = lsa_handle;
3496 r.in.sid = user_sid;
3497 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3498 r.out.acct_handle = &lsa_acct_handle;
3500 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3501 torture_assert_ntstatus_ok(tctx, status,
3502 "Failed to open lsa account");
3506 struct lsa_GetSystemAccessAccount r;
3507 uint32_t access_mask;
3509 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
3511 r.in.handle = &lsa_acct_handle;
3512 r.out.access_mask = &access_mask;
3514 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3515 torture_assert_ntstatus_ok(tctx, status,
3516 "Failed to get lsa system access account");
3520 struct lsa_DeleteObject r;
3522 torture_comment(tctx, "Testing LSA DeleteObject\n");
3524 r.in.handle = &lsa_acct_handle;
3525 r.out.handle = &lsa_acct_handle;
3527 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
3528 torture_assert_ntstatus_ok(tctx, status,
3529 "Failed to delete object");
3533 struct lsa_EnumAccounts r;
3534 uint32_t resume_handle = 0;
3535 struct lsa_SidArray lsa_sid_array;
3536 int i;
3537 bool found_sid = false;
3539 torture_comment(tctx, "Testing LSA EnumAccounts\n");
3541 r.in.handle = lsa_handle;
3542 r.in.num_entries = 0x1000;
3543 r.in.resume_handle = &resume_handle;
3544 r.out.sids = &lsa_sid_array;
3545 r.out.resume_handle = &resume_handle;
3547 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3548 torture_assert_ntstatus_ok(tctx, status,
3549 "Failed to enum accounts");
3551 for (i=0; i < lsa_sid_array.num_sids; i++) {
3552 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3553 found_sid = true;
3557 torture_assert(tctx, !found_sid,
3558 "should not have listed privileged account");
3562 struct lsa_EnumAccountRights r;
3563 struct lsa_RightSet user_rights;
3565 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
3567 r.in.handle = lsa_handle;
3568 r.in.sid = user_sid;
3569 r.out.rights = &user_rights;
3571 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3572 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3573 "Failed to enum rights for account");
3576 return ret;
3579 static bool test_user_ops(struct dcerpc_pipe *p,
3580 struct torture_context *tctx,
3581 struct policy_handle *user_handle,
3582 struct policy_handle *domain_handle,
3583 const struct dom_sid *domain_sid,
3584 uint32_t base_acct_flags,
3585 const char *base_acct_name, enum torture_samr_choice which_ops,
3586 struct cli_credentials *machine_credentials)
3588 char *password = NULL;
3589 struct samr_QueryUserInfo q;
3590 union samr_UserInfo *info;
3591 NTSTATUS status;
3593 bool ret = true;
3594 int i;
3595 uint32_t rid;
3596 const uint32_t password_fields[] = {
3597 SAMR_FIELD_NT_PASSWORD_PRESENT,
3598 SAMR_FIELD_LM_PASSWORD_PRESENT,
3599 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3603 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 ret = false;
3608 switch (which_ops) {
3609 case TORTURE_SAMR_USER_ATTRIBUTES:
3610 if (!test_QuerySecurity(p, tctx, user_handle)) {
3611 ret = false;
3614 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3615 ret = false;
3618 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3619 ret = false;
3622 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3623 base_acct_name)) {
3624 ret = false;
3627 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3628 ret = false;
3631 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3632 ret = false;
3635 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3636 ret = false;
3638 break;
3639 case TORTURE_SAMR_PASSWORDS:
3640 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3641 char simple_pass[9];
3642 char *v = generate_random_str(tctx, 1);
3644 ZERO_STRUCT(simple_pass);
3645 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3647 torture_comment(tctx, "Testing machine account password policy rules\n");
3649 /* Workstation trust accounts don't seem to need to honour password quality policy */
3650 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3651 ret = false;
3654 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3655 ret = false;
3658 /* reset again, to allow another 'user' password change */
3659 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3660 ret = false;
3663 /* Try a 'short' password */
3664 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3665 ret = false;
3668 /* Try a compleatly random password */
3669 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3670 ret = false;
3674 for (i = 0; password_fields[i]; i++) {
3675 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3676 ret = false;
3679 /* check it was set right */
3680 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3681 ret = false;
3685 for (i = 0; password_fields[i]; i++) {
3686 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3687 ret = false;
3690 /* check it was set right */
3691 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3692 ret = false;
3696 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3697 ret = false;
3700 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3701 ret = false;
3704 if (torture_setting_bool(tctx, "samba4", false)) {
3705 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
3706 } else {
3708 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3709 ret = false;
3712 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3713 ret = false;
3716 for (i = 0; password_fields[i]; i++) {
3718 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3719 /* we need to skip as that would break
3720 * the ChangePasswordUser3 verify */
3721 continue;
3724 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3725 ret = false;
3728 /* check it was set right */
3729 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3730 ret = false;
3735 q.in.user_handle = user_handle;
3736 q.in.level = 5;
3737 q.out.info = &info;
3739 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
3742 q.in.level, nt_errstr(status));
3743 ret = false;
3744 } else {
3745 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3746 if ((info->info5.acct_flags) != expected_flags) {
3747 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3748 info->info5.acct_flags,
3749 expected_flags);
3750 /* FIXME: GD */
3751 if (!torture_setting_bool(tctx, "samba3", false)) {
3752 ret = false;
3755 if (info->info5.rid != rid) {
3756 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3757 info->info5.rid, rid);
3762 break;
3764 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3766 /* test last password change timestamp behaviour */
3767 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3768 base_acct_name,
3769 user_handle, &password,
3770 machine_credentials)) {
3771 ret = false;
3774 if (ret == true) {
3775 torture_comment(tctx, "pwdLastSet test succeeded\n");
3776 } else {
3777 torture_warning(tctx, "pwdLastSet test failed\n");
3780 break;
3782 case TORTURE_SAMR_USER_PRIVILEGES: {
3784 struct dcerpc_pipe *lp;
3785 struct policy_handle *lsa_handle;
3787 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
3788 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
3790 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
3791 ret = false;
3794 if (!test_DeleteUser_with_privs(p, lp, tctx,
3795 domain_handle, lsa_handle, user_handle,
3796 domain_sid, rid,
3797 machine_credentials)) {
3798 ret = false;
3801 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
3802 ret = false;
3805 if (!ret) {
3806 torture_warning(tctx, "privileged user delete test failed\n");
3809 break;
3811 case TORTURE_SAMR_OTHER:
3812 /* We just need the account to exist */
3813 break;
3815 return ret;
3818 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3819 struct policy_handle *alias_handle,
3820 const struct dom_sid *domain_sid)
3822 bool ret = true;
3824 if (!torture_setting_bool(tctx, "samba3", false)) {
3825 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3826 ret = false;
3830 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3831 ret = false;
3834 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3835 ret = false;
3838 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3839 ret = false;
3842 if (torture_setting_bool(tctx, "samba3", false) ||
3843 torture_setting_bool(tctx, "samba4", false)) {
3844 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
3845 return ret;
3848 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3849 ret = false;
3852 return ret;
3856 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3857 struct policy_handle *user_handle)
3859 struct samr_DeleteUser d;
3860 NTSTATUS status;
3861 torture_comment(tctx, "Testing DeleteUser\n");
3863 d.in.user_handle = user_handle;
3864 d.out.user_handle = user_handle;
3866 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3867 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3869 return true;
3872 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
3873 struct torture_context *tctx,
3874 struct policy_handle *handle, const char *name)
3876 NTSTATUS status;
3877 struct samr_DeleteUser d;
3878 struct policy_handle user_handle;
3879 uint32_t rid;
3881 status = test_LookupName(p, tctx, handle, name, &rid);
3882 if (!NT_STATUS_IS_OK(status)) {
3883 goto failed;
3886 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 goto failed;
3891 d.in.user_handle = &user_handle;
3892 d.out.user_handle = &user_handle;
3893 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 goto failed;
3898 return true;
3900 failed:
3901 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3902 return false;
3906 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
3907 struct torture_context *tctx,
3908 struct policy_handle *handle, const char *name)
3910 NTSTATUS status;
3911 struct samr_OpenGroup r;
3912 struct samr_DeleteDomainGroup d;
3913 struct policy_handle group_handle;
3914 uint32_t rid;
3916 status = test_LookupName(p, tctx, handle, name, &rid);
3917 if (!NT_STATUS_IS_OK(status)) {
3918 goto failed;
3921 r.in.domain_handle = handle;
3922 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3923 r.in.rid = rid;
3924 r.out.group_handle = &group_handle;
3925 status = dcerpc_samr_OpenGroup(p, tctx, &r);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 goto failed;
3930 d.in.group_handle = &group_handle;
3931 d.out.group_handle = &group_handle;
3932 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 goto failed;
3937 return true;
3939 failed:
3940 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3941 return false;
3945 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
3946 struct torture_context *tctx,
3947 struct policy_handle *domain_handle,
3948 const char *name)
3950 NTSTATUS status;
3951 struct samr_OpenAlias r;
3952 struct samr_DeleteDomAlias d;
3953 struct policy_handle alias_handle;
3954 uint32_t rid;
3956 torture_comment(tctx, "testing DeleteAlias_byname\n");
3958 status = test_LookupName(p, tctx, domain_handle, name, &rid);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 goto failed;
3963 r.in.domain_handle = domain_handle;
3964 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3965 r.in.rid = rid;
3966 r.out.alias_handle = &alias_handle;
3967 status = dcerpc_samr_OpenAlias(p, tctx, &r);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 goto failed;
3972 d.in.alias_handle = &alias_handle;
3973 d.out.alias_handle = &alias_handle;
3974 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 goto failed;
3979 return true;
3981 failed:
3982 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3983 return false;
3986 static bool test_DeleteAlias(struct dcerpc_pipe *p,
3987 struct torture_context *tctx,
3988 struct policy_handle *alias_handle)
3990 struct samr_DeleteDomAlias d;
3991 NTSTATUS status;
3992 bool ret = true;
3994 torture_comment(tctx, "Testing DeleteAlias\n");
3996 d.in.alias_handle = alias_handle;
3997 d.out.alias_handle = alias_handle;
3999 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4002 ret = false;
4005 return ret;
4008 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4009 struct policy_handle *domain_handle,
4010 const char *alias_name,
4011 struct policy_handle *alias_handle,
4012 const struct dom_sid *domain_sid,
4013 bool test_alias)
4015 NTSTATUS status;
4016 struct samr_CreateDomAlias r;
4017 struct lsa_String name;
4018 uint32_t rid;
4019 bool ret = true;
4021 init_lsa_String(&name, alias_name);
4022 r.in.domain_handle = domain_handle;
4023 r.in.alias_name = &name;
4024 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4025 r.out.alias_handle = alias_handle;
4026 r.out.rid = &rid;
4028 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4030 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4032 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4033 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4034 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4035 return true;
4036 } else {
4037 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4038 nt_errstr(status));
4039 return false;
4043 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4044 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4045 return false;
4047 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4052 return false;
4055 if (!test_alias) {
4056 return ret;
4059 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4060 ret = false;
4063 return ret;
4066 static bool test_ChangePassword(struct dcerpc_pipe *p,
4067 struct torture_context *tctx,
4068 const char *acct_name,
4069 struct policy_handle *domain_handle, char **password)
4071 bool ret = true;
4073 if (!*password) {
4074 return false;
4077 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4078 ret = false;
4081 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4082 ret = false;
4085 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4086 ret = false;
4089 /* test what happens when setting the old password again */
4090 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4091 ret = false;
4095 char simple_pass[9];
4096 char *v = generate_random_str(tctx, 1);
4098 ZERO_STRUCT(simple_pass);
4099 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4101 /* test what happens when picking a simple password */
4102 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4103 ret = false;
4107 /* set samr_SetDomainInfo level 1 with min_length 5 */
4109 struct samr_QueryDomainInfo r;
4110 union samr_DomainInfo *info = NULL;
4111 struct samr_SetDomainInfo s;
4112 uint16_t len_old, len;
4113 uint32_t pwd_prop_old;
4114 int64_t min_pwd_age_old;
4115 NTSTATUS status;
4117 len = 5;
4119 r.in.domain_handle = domain_handle;
4120 r.in.level = 1;
4121 r.out.info = &info;
4123 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
4124 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
4125 if (!NT_STATUS_IS_OK(status)) {
4126 return false;
4129 s.in.domain_handle = domain_handle;
4130 s.in.level = 1;
4131 s.in.info = info;
4133 /* remember the old min length, so we can reset it */
4134 len_old = s.in.info->info1.min_password_length;
4135 s.in.info->info1.min_password_length = len;
4136 pwd_prop_old = s.in.info->info1.password_properties;
4137 /* turn off password complexity checks for this test */
4138 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
4140 min_pwd_age_old = s.in.info->info1.min_password_age;
4141 s.in.info->info1.min_password_age = 0;
4143 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4144 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4145 if (!NT_STATUS_IS_OK(status)) {
4146 return false;
4149 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
4151 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
4152 ret = false;
4155 s.in.info->info1.min_password_length = len_old;
4156 s.in.info->info1.password_properties = pwd_prop_old;
4157 s.in.info->info1.min_password_age = min_pwd_age_old;
4159 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
4160 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4161 if (!NT_STATUS_IS_OK(status)) {
4162 return false;
4168 NTSTATUS status;
4169 struct samr_OpenUser r;
4170 struct samr_QueryUserInfo q;
4171 union samr_UserInfo *info;
4172 struct samr_LookupNames n;
4173 struct policy_handle user_handle;
4174 struct samr_Ids rids, types;
4176 n.in.domain_handle = domain_handle;
4177 n.in.num_names = 1;
4178 n.in.names = talloc_array(tctx, struct lsa_String, 1);
4179 n.in.names[0].string = acct_name;
4180 n.out.rids = &rids;
4181 n.out.types = &types;
4183 status = dcerpc_samr_LookupNames(p, tctx, &n);
4184 if (!NT_STATUS_IS_OK(status)) {
4185 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
4186 return false;
4189 r.in.domain_handle = domain_handle;
4190 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4191 r.in.rid = n.out.rids->ids[0];
4192 r.out.user_handle = &user_handle;
4194 status = dcerpc_samr_OpenUser(p, tctx, &r);
4195 if (!NT_STATUS_IS_OK(status)) {
4196 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
4197 return false;
4200 q.in.user_handle = &user_handle;
4201 q.in.level = 5;
4202 q.out.info = &info;
4204 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4205 if (!NT_STATUS_IS_OK(status)) {
4206 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
4207 return false;
4210 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
4212 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
4213 info->info5.last_password_change, true)) {
4214 ret = false;
4218 /* we change passwords twice - this has the effect of verifying
4219 they were changed correctly for the final call */
4220 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4221 ret = false;
4224 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4225 ret = false;
4228 return ret;
4231 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4232 struct policy_handle *domain_handle,
4233 const char *user_name,
4234 struct policy_handle *user_handle_out,
4235 struct dom_sid *domain_sid,
4236 enum torture_samr_choice which_ops,
4237 struct cli_credentials *machine_credentials,
4238 bool test_user)
4241 TALLOC_CTX *user_ctx;
4243 NTSTATUS status;
4244 struct samr_CreateUser r;
4245 struct samr_QueryUserInfo q;
4246 union samr_UserInfo *info;
4247 struct samr_DeleteUser d;
4248 uint32_t rid;
4250 /* This call creates a 'normal' account - check that it really does */
4251 const uint32_t acct_flags = ACB_NORMAL;
4252 struct lsa_String name;
4253 bool ret = true;
4255 struct policy_handle user_handle;
4256 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4257 init_lsa_String(&name, user_name);
4259 r.in.domain_handle = domain_handle;
4260 r.in.account_name = &name;
4261 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4262 r.out.user_handle = &user_handle;
4263 r.out.rid = &rid;
4265 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
4267 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4269 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4270 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4271 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4272 return true;
4273 } else {
4274 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4275 nt_errstr(status));
4276 return false;
4280 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4281 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4282 talloc_free(user_ctx);
4283 return false;
4285 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4288 if (!NT_STATUS_IS_OK(status)) {
4289 talloc_free(user_ctx);
4290 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
4291 return false;
4294 if (!test_user) {
4295 if (user_handle_out) {
4296 *user_handle_out = user_handle;
4298 return ret;
4302 q.in.user_handle = &user_handle;
4303 q.in.level = 16;
4304 q.out.info = &info;
4306 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4307 if (!NT_STATUS_IS_OK(status)) {
4308 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4309 q.in.level, nt_errstr(status));
4310 ret = false;
4311 } else {
4312 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
4313 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4314 info->info16.acct_flags,
4315 acct_flags);
4316 ret = false;
4320 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4321 domain_sid, acct_flags, name.string, which_ops,
4322 machine_credentials)) {
4323 ret = false;
4326 if (user_handle_out) {
4327 *user_handle_out = user_handle;
4328 } else {
4329 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
4331 d.in.user_handle = &user_handle;
4332 d.out.user_handle = &user_handle;
4334 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4335 if (!NT_STATUS_IS_OK(status)) {
4336 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4337 ret = false;
4343 talloc_free(user_ctx);
4345 return ret;
4349 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
4350 struct policy_handle *domain_handle,
4351 struct dom_sid *domain_sid,
4352 enum torture_samr_choice which_ops,
4353 struct cli_credentials *machine_credentials)
4355 NTSTATUS status;
4356 struct samr_CreateUser2 r;
4357 struct samr_QueryUserInfo q;
4358 union samr_UserInfo *info;
4359 struct samr_DeleteUser d;
4360 struct policy_handle user_handle;
4361 uint32_t rid;
4362 struct lsa_String name;
4363 bool ret = true;
4364 int i;
4366 struct {
4367 uint32_t acct_flags;
4368 const char *account_name;
4369 NTSTATUS nt_status;
4370 } account_types[] = {
4371 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
4372 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4373 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4374 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4375 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4376 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4377 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4378 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4379 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4380 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
4381 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4382 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4383 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4384 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4385 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4388 for (i = 0; account_types[i].account_name; i++) {
4389 TALLOC_CTX *user_ctx;
4390 uint32_t acct_flags = account_types[i].acct_flags;
4391 uint32_t access_granted;
4392 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4393 init_lsa_String(&name, account_types[i].account_name);
4395 r.in.domain_handle = domain_handle;
4396 r.in.account_name = &name;
4397 r.in.acct_flags = acct_flags;
4398 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4399 r.out.user_handle = &user_handle;
4400 r.out.access_granted = &access_granted;
4401 r.out.rid = &rid;
4403 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4405 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4407 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4408 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4409 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
4410 continue;
4411 } else {
4412 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4413 nt_errstr(status));
4414 ret = false;
4415 continue;
4419 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4420 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4421 talloc_free(user_ctx);
4422 ret = false;
4423 continue;
4425 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4428 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4429 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4430 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4431 ret = false;
4434 if (NT_STATUS_IS_OK(status)) {
4435 q.in.user_handle = &user_handle;
4436 q.in.level = 5;
4437 q.out.info = &info;
4439 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4442 q.in.level, nt_errstr(status));
4443 ret = false;
4444 } else {
4445 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4446 if (acct_flags == ACB_NORMAL) {
4447 expected_flags |= ACB_PW_EXPIRED;
4449 if ((info->info5.acct_flags) != expected_flags) {
4450 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4451 info->info5.acct_flags,
4452 expected_flags);
4453 ret = false;
4455 switch (acct_flags) {
4456 case ACB_SVRTRUST:
4457 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4458 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4459 DOMAIN_RID_DCS, info->info5.primary_gid);
4460 ret = false;
4462 break;
4463 case ACB_WSTRUST:
4464 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4465 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4466 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4467 ret = false;
4469 break;
4470 case ACB_NORMAL:
4471 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4472 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4473 DOMAIN_RID_USERS, info->info5.primary_gid);
4474 ret = false;
4476 break;
4480 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4481 domain_sid, acct_flags, name.string, which_ops,
4482 machine_credentials)) {
4483 ret = false;
4486 if (!policy_handle_empty(&user_handle)) {
4487 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
4489 d.in.user_handle = &user_handle;
4490 d.out.user_handle = &user_handle;
4492 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
4495 ret = false;
4499 talloc_free(user_ctx);
4502 return ret;
4505 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
4506 struct torture_context *tctx,
4507 struct policy_handle *handle)
4509 NTSTATUS status;
4510 struct samr_QueryAliasInfo r;
4511 union samr_AliasInfo *info;
4512 uint16_t levels[] = {1, 2, 3};
4513 int i;
4514 bool ret = true;
4516 for (i=0;i<ARRAY_SIZE(levels);i++) {
4517 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
4519 r.in.alias_handle = handle;
4520 r.in.level = levels[i];
4521 r.out.info = &info;
4523 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
4526 levels[i], nt_errstr(status));
4527 ret = false;
4531 return ret;
4534 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
4535 struct torture_context *tctx,
4536 struct policy_handle *handle)
4538 NTSTATUS status;
4539 struct samr_QueryGroupInfo r;
4540 union samr_GroupInfo *info;
4541 uint16_t levels[] = {1, 2, 3, 4, 5};
4542 int i;
4543 bool ret = true;
4545 for (i=0;i<ARRAY_SIZE(levels);i++) {
4546 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4548 r.in.group_handle = handle;
4549 r.in.level = levels[i];
4550 r.out.info = &info;
4552 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4553 if (!NT_STATUS_IS_OK(status)) {
4554 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4555 levels[i], nt_errstr(status));
4556 ret = false;
4560 return ret;
4563 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
4564 struct torture_context *tctx,
4565 struct policy_handle *handle)
4567 NTSTATUS status;
4568 struct samr_QueryGroupMember r;
4569 struct samr_RidTypeArray *rids = NULL;
4570 bool ret = true;
4572 torture_comment(tctx, "Testing QueryGroupMember\n");
4574 r.in.group_handle = handle;
4575 r.out.rids = &rids;
4577 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
4578 if (!NT_STATUS_IS_OK(status)) {
4579 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
4580 ret = false;
4583 return ret;
4587 static bool test_SetGroupInfo(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 struct samr_SetGroupInfo s;
4595 uint16_t levels[] = {1, 2, 3, 4};
4596 uint16_t set_ok[] = {0, 1, 1, 1};
4597 int i;
4598 bool ret = true;
4600 for (i=0;i<ARRAY_SIZE(levels);i++) {
4601 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
4603 r.in.group_handle = handle;
4604 r.in.level = levels[i];
4605 r.out.info = &info;
4607 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4608 if (!NT_STATUS_IS_OK(status)) {
4609 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
4610 levels[i], nt_errstr(status));
4611 ret = false;
4614 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
4616 s.in.group_handle = handle;
4617 s.in.level = levels[i];
4618 s.in.info = *r.out.info;
4620 #if 0
4621 /* disabled this, as it changes the name only from the point of view of samr,
4622 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4623 the name is still reserved, so creating the old name fails, but deleting by the old name
4624 also fails */
4625 if (s.in.level == 2) {
4626 init_lsa_String(&s.in.info->string, "NewName");
4628 #endif
4630 if (s.in.level == 4) {
4631 init_lsa_String(&s.in.info->description, "test description");
4634 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
4635 if (set_ok[i]) {
4636 if (!NT_STATUS_IS_OK(status)) {
4637 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
4638 r.in.level, nt_errstr(status));
4639 ret = false;
4640 continue;
4642 } else {
4643 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4644 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4645 r.in.level, nt_errstr(status));
4646 ret = false;
4647 continue;
4652 return ret;
4655 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
4656 struct torture_context *tctx,
4657 struct policy_handle *handle)
4659 NTSTATUS status;
4660 struct samr_QueryUserInfo r;
4661 union samr_UserInfo *info;
4662 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4663 11, 12, 13, 14, 16, 17, 20, 21};
4664 int i;
4665 bool ret = true;
4667 for (i=0;i<ARRAY_SIZE(levels);i++) {
4668 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
4670 r.in.user_handle = handle;
4671 r.in.level = levels[i];
4672 r.out.info = &info;
4674 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4677 levels[i], nt_errstr(status));
4678 ret = false;
4682 return ret;
4685 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
4686 struct torture_context *tctx,
4687 struct policy_handle *handle)
4689 NTSTATUS status;
4690 struct samr_QueryUserInfo2 r;
4691 union samr_UserInfo *info;
4692 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4693 11, 12, 13, 14, 16, 17, 20, 21};
4694 int i;
4695 bool ret = true;
4697 for (i=0;i<ARRAY_SIZE(levels);i++) {
4698 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
4700 r.in.user_handle = handle;
4701 r.in.level = levels[i];
4702 r.out.info = &info;
4704 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
4705 if (!NT_STATUS_IS_OK(status)) {
4706 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
4707 levels[i], nt_errstr(status));
4708 ret = false;
4712 return ret;
4715 static bool test_OpenUser(struct dcerpc_pipe *p,
4716 struct torture_context *tctx,
4717 struct policy_handle *handle, uint32_t rid)
4719 NTSTATUS status;
4720 struct samr_OpenUser r;
4721 struct policy_handle user_handle;
4722 bool ret = true;
4724 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4726 r.in.domain_handle = handle;
4727 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4728 r.in.rid = rid;
4729 r.out.user_handle = &user_handle;
4731 status = dcerpc_samr_OpenUser(p, tctx, &r);
4732 if (!NT_STATUS_IS_OK(status)) {
4733 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4734 return false;
4737 if (!test_QuerySecurity(p, tctx, &user_handle)) {
4738 ret = false;
4741 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
4742 ret = false;
4745 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
4746 ret = false;
4749 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
4750 ret = false;
4753 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
4754 ret = false;
4757 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4758 ret = false;
4761 return ret;
4764 static bool test_OpenGroup(struct dcerpc_pipe *p,
4765 struct torture_context *tctx,
4766 struct policy_handle *handle, uint32_t rid)
4768 NTSTATUS status;
4769 struct samr_OpenGroup r;
4770 struct policy_handle group_handle;
4771 bool ret = true;
4773 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
4775 r.in.domain_handle = handle;
4776 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4777 r.in.rid = rid;
4778 r.out.group_handle = &group_handle;
4780 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4783 return false;
4786 if (!torture_setting_bool(tctx, "samba3", false)) {
4787 if (!test_QuerySecurity(p, tctx, &group_handle)) {
4788 ret = false;
4792 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
4793 ret = false;
4796 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
4797 ret = false;
4800 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
4801 ret = false;
4804 return ret;
4807 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4808 struct policy_handle *handle, uint32_t rid)
4810 NTSTATUS status;
4811 struct samr_OpenAlias r;
4812 struct policy_handle alias_handle;
4813 bool ret = true;
4815 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4817 r.in.domain_handle = handle;
4818 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4819 r.in.rid = rid;
4820 r.out.alias_handle = &alias_handle;
4822 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4825 return false;
4828 if (!torture_setting_bool(tctx, "samba3", false)) {
4829 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4830 ret = false;
4834 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4835 ret = false;
4838 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4839 ret = false;
4842 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4843 ret = false;
4846 return ret;
4849 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4850 struct policy_handle *handle, uint32_t rid,
4851 uint32_t acct_flag_mask)
4853 NTSTATUS status;
4854 struct samr_OpenUser r;
4855 struct samr_QueryUserInfo q;
4856 union samr_UserInfo *info;
4857 struct policy_handle user_handle;
4858 bool ret = true;
4860 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4862 r.in.domain_handle = handle;
4863 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4864 r.in.rid = rid;
4865 r.out.user_handle = &user_handle;
4867 status = dcerpc_samr_OpenUser(p, tctx, &r);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4870 return false;
4873 q.in.user_handle = &user_handle;
4874 q.in.level = 16;
4875 q.out.info = &info;
4877 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
4880 nt_errstr(status));
4881 ret = false;
4882 } else {
4883 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4884 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4885 acct_flag_mask, info->info16.acct_flags, rid);
4886 ret = false;
4890 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4891 ret = false;
4894 return ret;
4897 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
4898 struct torture_context *tctx,
4899 struct policy_handle *handle)
4901 NTSTATUS status = STATUS_MORE_ENTRIES;
4902 struct samr_EnumDomainUsers r;
4903 uint32_t mask, resume_handle=0;
4904 int i, mask_idx;
4905 bool ret = true;
4906 struct samr_LookupNames n;
4907 struct samr_LookupRids lr ;
4908 struct lsa_Strings names;
4909 struct samr_Ids rids, types;
4910 struct samr_SamArray *sam = NULL;
4911 uint32_t num_entries = 0;
4913 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4914 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4915 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4916 ACB_PWNOEXP, 0};
4918 torture_comment(tctx, "Testing EnumDomainUsers\n");
4920 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4921 r.in.domain_handle = handle;
4922 r.in.resume_handle = &resume_handle;
4923 r.in.acct_flags = mask = masks[mask_idx];
4924 r.in.max_size = (uint32_t)-1;
4925 r.out.resume_handle = &resume_handle;
4926 r.out.num_entries = &num_entries;
4927 r.out.sam = &sam;
4929 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4930 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4931 !NT_STATUS_IS_OK(status)) {
4932 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
4933 return false;
4936 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4938 if (sam->count == 0) {
4939 continue;
4942 for (i=0;i<sam->count;i++) {
4943 if (mask) {
4944 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4945 ret = false;
4947 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4948 ret = false;
4953 torture_comment(tctx, "Testing LookupNames\n");
4954 n.in.domain_handle = handle;
4955 n.in.num_names = sam->count;
4956 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4957 n.out.rids = &rids;
4958 n.out.types = &types;
4959 for (i=0;i<sam->count;i++) {
4960 n.in.names[i].string = sam->entries[i].name.string;
4962 status = dcerpc_samr_LookupNames(p, tctx, &n);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
4965 ret = false;
4969 torture_comment(tctx, "Testing LookupRids\n");
4970 lr.in.domain_handle = handle;
4971 lr.in.num_rids = sam->count;
4972 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4973 lr.out.names = &names;
4974 lr.out.types = &types;
4975 for (i=0;i<sam->count;i++) {
4976 lr.in.rids[i] = sam->entries[i].idx;
4978 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4979 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4981 return ret;
4985 try blasting the server with a bunch of sync requests
4987 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4988 struct policy_handle *handle)
4990 NTSTATUS status;
4991 struct samr_EnumDomainUsers r;
4992 uint32_t resume_handle=0;
4993 int i;
4994 #define ASYNC_COUNT 100
4995 struct rpc_request *req[ASYNC_COUNT];
4997 if (!torture_setting_bool(tctx, "dangerous", false)) {
4998 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5001 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5003 r.in.domain_handle = handle;
5004 r.in.resume_handle = &resume_handle;
5005 r.in.acct_flags = 0;
5006 r.in.max_size = (uint32_t)-1;
5007 r.out.resume_handle = &resume_handle;
5009 for (i=0;i<ASYNC_COUNT;i++) {
5010 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5013 for (i=0;i<ASYNC_COUNT;i++) {
5014 status = dcerpc_ndr_request_recv(req[i]);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5017 i, nt_errstr(status));
5018 return false;
5022 torture_comment(tctx, "%d async requests OK\n", i);
5024 return true;
5027 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5028 struct torture_context *tctx,
5029 struct policy_handle *handle)
5031 NTSTATUS status;
5032 struct samr_EnumDomainGroups r;
5033 uint32_t resume_handle=0;
5034 struct samr_SamArray *sam = NULL;
5035 uint32_t num_entries = 0;
5036 int i;
5037 bool ret = true;
5039 torture_comment(tctx, "Testing EnumDomainGroups\n");
5041 r.in.domain_handle = handle;
5042 r.in.resume_handle = &resume_handle;
5043 r.in.max_size = (uint32_t)-1;
5044 r.out.resume_handle = &resume_handle;
5045 r.out.num_entries = &num_entries;
5046 r.out.sam = &sam;
5048 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5049 if (!NT_STATUS_IS_OK(status)) {
5050 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5051 return false;
5054 if (!sam) {
5055 return false;
5058 for (i=0;i<sam->count;i++) {
5059 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5060 ret = false;
5064 return ret;
5067 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5068 struct torture_context *tctx,
5069 struct policy_handle *handle)
5071 NTSTATUS status;
5072 struct samr_EnumDomainAliases r;
5073 uint32_t resume_handle=0;
5074 struct samr_SamArray *sam = NULL;
5075 uint32_t num_entries = 0;
5076 int i;
5077 bool ret = true;
5079 torture_comment(tctx, "Testing EnumDomainAliases\n");
5081 r.in.domain_handle = handle;
5082 r.in.resume_handle = &resume_handle;
5083 r.in.max_size = (uint32_t)-1;
5084 r.out.sam = &sam;
5085 r.out.num_entries = &num_entries;
5086 r.out.resume_handle = &resume_handle;
5088 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5089 if (!NT_STATUS_IS_OK(status)) {
5090 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5091 return false;
5094 if (!sam) {
5095 return false;
5098 for (i=0;i<sam->count;i++) {
5099 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5100 ret = false;
5104 return ret;
5107 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5108 struct torture_context *tctx,
5109 struct policy_handle *handle)
5111 NTSTATUS status;
5112 struct samr_GetDisplayEnumerationIndex r;
5113 bool ret = true;
5114 uint16_t levels[] = {1, 2, 3, 4, 5};
5115 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5116 struct lsa_String name;
5117 uint32_t idx = 0;
5118 int i;
5120 for (i=0;i<ARRAY_SIZE(levels);i++) {
5121 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
5123 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5125 r.in.domain_handle = handle;
5126 r.in.level = levels[i];
5127 r.in.name = &name;
5128 r.out.idx = &idx;
5130 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5132 if (ok_lvl[i] &&
5133 !NT_STATUS_IS_OK(status) &&
5134 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5135 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
5136 levels[i], nt_errstr(status));
5137 ret = false;
5140 init_lsa_String(&name, "zzzzzzzz");
5142 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5144 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5145 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
5146 levels[i], nt_errstr(status));
5147 ret = false;
5151 return ret;
5154 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
5155 struct torture_context *tctx,
5156 struct policy_handle *handle)
5158 NTSTATUS status;
5159 struct samr_GetDisplayEnumerationIndex2 r;
5160 bool ret = true;
5161 uint16_t levels[] = {1, 2, 3, 4, 5};
5162 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5163 struct lsa_String name;
5164 uint32_t idx = 0;
5165 int i;
5167 for (i=0;i<ARRAY_SIZE(levels);i++) {
5168 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
5170 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5172 r.in.domain_handle = handle;
5173 r.in.level = levels[i];
5174 r.in.name = &name;
5175 r.out.idx = &idx;
5177 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5178 if (ok_lvl[i] &&
5179 !NT_STATUS_IS_OK(status) &&
5180 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5181 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5182 levels[i], nt_errstr(status));
5183 ret = false;
5186 init_lsa_String(&name, "zzzzzzzz");
5188 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5189 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5190 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
5191 levels[i], nt_errstr(status));
5192 ret = false;
5196 return ret;
5199 #define STRING_EQUAL_QUERY(s1, s2, user) \
5200 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
5201 /* odd, but valid */ \
5202 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
5203 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
5204 #s1, user.string, s1.string, s2.string, __location__); \
5205 ret = false; \
5207 #define INT_EQUAL_QUERY(s1, s2, user) \
5208 if (s1 != s2) { \
5209 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
5210 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
5211 ret = false; \
5214 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
5215 struct torture_context *tctx,
5216 struct samr_QueryDisplayInfo *querydisplayinfo,
5217 bool *seen_testuser)
5219 struct samr_OpenUser r;
5220 struct samr_QueryUserInfo q;
5221 union samr_UserInfo *info;
5222 struct policy_handle user_handle;
5223 int i, ret = true;
5224 NTSTATUS status;
5225 r.in.domain_handle = querydisplayinfo->in.domain_handle;
5226 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5227 for (i = 0; ; i++) {
5228 switch (querydisplayinfo->in.level) {
5229 case 1:
5230 if (i >= querydisplayinfo->out.info->info1.count) {
5231 return ret;
5233 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
5234 break;
5235 case 2:
5236 if (i >= querydisplayinfo->out.info->info2.count) {
5237 return ret;
5239 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
5240 break;
5241 case 3:
5242 /* Groups */
5243 case 4:
5244 case 5:
5245 /* Not interested in validating just the account name */
5246 return true;
5249 r.out.user_handle = &user_handle;
5251 switch (querydisplayinfo->in.level) {
5252 case 1:
5253 case 2:
5254 status = dcerpc_samr_OpenUser(p, tctx, &r);
5255 if (!NT_STATUS_IS_OK(status)) {
5256 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5257 return false;
5261 q.in.user_handle = &user_handle;
5262 q.in.level = 21;
5263 q.out.info = &info;
5264 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5267 return false;
5270 switch (querydisplayinfo->in.level) {
5271 case 1:
5272 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
5273 *seen_testuser = true;
5275 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
5276 info->info21.full_name, info->info21.account_name);
5277 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
5278 info->info21.account_name, info->info21.account_name);
5279 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
5280 info->info21.description, info->info21.account_name);
5281 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
5282 info->info21.rid, info->info21.account_name);
5283 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
5284 info->info21.acct_flags, info->info21.account_name);
5286 break;
5287 case 2:
5288 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
5289 info->info21.account_name, info->info21.account_name);
5290 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
5291 info->info21.description, info->info21.account_name);
5292 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
5293 info->info21.rid, info->info21.account_name);
5294 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
5295 info->info21.acct_flags, info->info21.account_name);
5297 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
5298 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
5299 info->info21.account_name.string);
5302 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
5303 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
5304 info->info21.account_name.string,
5305 querydisplayinfo->out.info->info2.entries[i].acct_flags,
5306 info->info21.acct_flags);
5307 return false;
5310 break;
5313 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5314 return false;
5317 return ret;
5320 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
5321 struct torture_context *tctx,
5322 struct policy_handle *handle)
5324 NTSTATUS status;
5325 struct samr_QueryDisplayInfo r;
5326 struct samr_QueryDomainInfo dom_info;
5327 union samr_DomainInfo *info = NULL;
5328 bool ret = true;
5329 uint16_t levels[] = {1, 2, 3, 4, 5};
5330 int i;
5331 bool seen_testuser = false;
5332 uint32_t total_size;
5333 uint32_t returned_size;
5334 union samr_DispInfo disp_info;
5337 for (i=0;i<ARRAY_SIZE(levels);i++) {
5338 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
5340 r.in.start_idx = 0;
5341 status = STATUS_MORE_ENTRIES;
5342 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5343 r.in.domain_handle = handle;
5344 r.in.level = levels[i];
5345 r.in.max_entries = 2;
5346 r.in.buf_size = (uint32_t)-1;
5347 r.out.total_size = &total_size;
5348 r.out.returned_size = &returned_size;
5349 r.out.info = &disp_info;
5351 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5352 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
5353 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5354 levels[i], nt_errstr(status));
5355 ret = false;
5357 switch (r.in.level) {
5358 case 1:
5359 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
5360 ret = false;
5362 r.in.start_idx += r.out.info->info1.count;
5363 break;
5364 case 2:
5365 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
5366 ret = false;
5368 r.in.start_idx += r.out.info->info2.count;
5369 break;
5370 case 3:
5371 r.in.start_idx += r.out.info->info3.count;
5372 break;
5373 case 4:
5374 r.in.start_idx += r.out.info->info4.count;
5375 break;
5376 case 5:
5377 r.in.start_idx += r.out.info->info5.count;
5378 break;
5381 dom_info.in.domain_handle = handle;
5382 dom_info.in.level = 2;
5383 dom_info.out.info = &info;
5385 /* Check number of users returned is correct */
5386 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
5387 if (!NT_STATUS_IS_OK(status)) {
5388 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5389 r.in.level, nt_errstr(status));
5390 ret = false;
5391 break;
5393 switch (r.in.level) {
5394 case 1:
5395 case 4:
5396 if (info->general.num_users < r.in.start_idx) {
5397 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5398 r.in.start_idx, info->general.num_groups,
5399 info->general.domain_name.string);
5400 ret = false;
5402 if (!seen_testuser) {
5403 struct policy_handle user_handle;
5404 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5405 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5406 info->general.domain_name.string);
5407 ret = false;
5408 test_samr_handle_Close(p, tctx, &user_handle);
5411 break;
5412 case 3:
5413 case 5:
5414 if (info->general.num_groups != r.in.start_idx) {
5415 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5416 r.in.start_idx, info->general.num_groups,
5417 info->general.domain_name.string);
5418 ret = false;
5421 break;
5426 return ret;
5429 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
5430 struct torture_context *tctx,
5431 struct policy_handle *handle)
5433 NTSTATUS status;
5434 struct samr_QueryDisplayInfo2 r;
5435 bool ret = true;
5436 uint16_t levels[] = {1, 2, 3, 4, 5};
5437 int i;
5438 uint32_t total_size;
5439 uint32_t returned_size;
5440 union samr_DispInfo info;
5442 for (i=0;i<ARRAY_SIZE(levels);i++) {
5443 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
5445 r.in.domain_handle = handle;
5446 r.in.level = levels[i];
5447 r.in.start_idx = 0;
5448 r.in.max_entries = 1000;
5449 r.in.buf_size = (uint32_t)-1;
5450 r.out.total_size = &total_size;
5451 r.out.returned_size = &returned_size;
5452 r.out.info = &info;
5454 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
5455 if (!NT_STATUS_IS_OK(status)) {
5456 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
5457 levels[i], nt_errstr(status));
5458 ret = false;
5462 return ret;
5465 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5466 struct policy_handle *handle)
5468 NTSTATUS status;
5469 struct samr_QueryDisplayInfo3 r;
5470 bool ret = true;
5471 uint16_t levels[] = {1, 2, 3, 4, 5};
5472 int i;
5473 uint32_t total_size;
5474 uint32_t returned_size;
5475 union samr_DispInfo info;
5477 for (i=0;i<ARRAY_SIZE(levels);i++) {
5478 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5480 r.in.domain_handle = handle;
5481 r.in.level = levels[i];
5482 r.in.start_idx = 0;
5483 r.in.max_entries = 1000;
5484 r.in.buf_size = (uint32_t)-1;
5485 r.out.total_size = &total_size;
5486 r.out.returned_size = &returned_size;
5487 r.out.info = &info;
5489 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
5492 levels[i], nt_errstr(status));
5493 ret = false;
5497 return ret;
5501 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
5502 struct torture_context *tctx,
5503 struct policy_handle *handle)
5505 NTSTATUS status;
5506 struct samr_QueryDisplayInfo r;
5507 bool ret = true;
5508 uint32_t total_size;
5509 uint32_t returned_size;
5510 union samr_DispInfo info;
5512 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
5514 r.in.domain_handle = handle;
5515 r.in.level = 1;
5516 r.in.start_idx = 0;
5517 r.in.max_entries = 1;
5518 r.in.buf_size = (uint32_t)-1;
5519 r.out.total_size = &total_size;
5520 r.out.returned_size = &returned_size;
5521 r.out.info = &info;
5523 do {
5524 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5525 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5526 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5527 torture_warning(tctx, "expected idx %d but got %d\n",
5528 r.in.start_idx + 1,
5529 r.out.info->info1.entries[0].idx);
5530 break;
5533 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5534 !NT_STATUS_IS_OK(status)) {
5535 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
5536 r.in.level, nt_errstr(status));
5537 ret = false;
5538 break;
5540 r.in.start_idx++;
5541 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5542 NT_STATUS_IS_OK(status)) &&
5543 *r.out.returned_size != 0);
5545 return ret;
5548 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5549 struct policy_handle *handle)
5551 NTSTATUS status;
5552 struct samr_QueryDomainInfo r;
5553 union samr_DomainInfo *info = NULL;
5554 struct samr_SetDomainInfo s;
5555 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5556 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5557 int i;
5558 bool ret = true;
5559 const char *domain_comment = talloc_asprintf(tctx,
5560 "Tortured by Samba4 RPC-SAMR: %s",
5561 timestring(tctx, time(NULL)));
5563 s.in.domain_handle = handle;
5564 s.in.level = 4;
5565 s.in.info = talloc(tctx, union samr_DomainInfo);
5567 s.in.info->oem.oem_information.string = domain_comment;
5568 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
5571 s.in.level, nt_errstr(status));
5572 return false;
5575 for (i=0;i<ARRAY_SIZE(levels);i++) {
5576 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5578 r.in.domain_handle = handle;
5579 r.in.level = levels[i];
5580 r.out.info = &info;
5582 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5585 r.in.level, nt_errstr(status));
5586 ret = false;
5587 continue;
5590 switch (levels[i]) {
5591 case 2:
5592 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5593 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5594 levels[i], info->general.oem_information.string, domain_comment);
5595 if (!torture_setting_bool(tctx, "samba3", false)) {
5596 ret = false;
5599 if (!info->general.primary.string) {
5600 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5601 levels[i]);
5602 ret = false;
5603 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5604 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5605 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5606 levels[i], info->general.primary.string, dcerpc_server_name(p));
5609 break;
5610 case 4:
5611 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5612 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5613 levels[i], info->oem.oem_information.string, domain_comment);
5614 if (!torture_setting_bool(tctx, "samba3", false)) {
5615 ret = false;
5618 break;
5619 case 6:
5620 if (!info->info6.primary.string) {
5621 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
5622 levels[i]);
5623 ret = false;
5625 break;
5626 case 11:
5627 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5628 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5629 levels[i], info->general2.general.oem_information.string, domain_comment);
5630 if (!torture_setting_bool(tctx, "samba3", false)) {
5631 ret = false;
5634 break;
5637 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5639 s.in.domain_handle = handle;
5640 s.in.level = levels[i];
5641 s.in.info = info;
5643 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5644 if (set_ok[i]) {
5645 if (!NT_STATUS_IS_OK(status)) {
5646 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
5647 r.in.level, nt_errstr(status));
5648 ret = false;
5649 continue;
5651 } else {
5652 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5653 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5654 r.in.level, nt_errstr(status));
5655 ret = false;
5656 continue;
5660 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
5663 r.in.level, nt_errstr(status));
5664 ret = false;
5665 continue;
5669 return ret;
5673 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5674 struct policy_handle *handle)
5676 NTSTATUS status;
5677 struct samr_QueryDomainInfo2 r;
5678 union samr_DomainInfo *info = NULL;
5679 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5680 int i;
5681 bool ret = true;
5683 for (i=0;i<ARRAY_SIZE(levels);i++) {
5684 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
5686 r.in.domain_handle = handle;
5687 r.in.level = levels[i];
5688 r.out.info = &info;
5690 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
5693 r.in.level, nt_errstr(status));
5694 ret = false;
5695 continue;
5699 return true;
5702 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5703 set of group names. */
5704 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5705 struct policy_handle *handle)
5707 struct samr_EnumDomainGroups q1;
5708 struct samr_QueryDisplayInfo q2;
5709 NTSTATUS status;
5710 uint32_t resume_handle=0;
5711 struct samr_SamArray *sam = NULL;
5712 uint32_t num_entries = 0;
5713 int i;
5714 bool ret = true;
5715 uint32_t total_size;
5716 uint32_t returned_size;
5717 union samr_DispInfo info;
5719 int num_names = 0;
5720 const char **names = NULL;
5722 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5724 q1.in.domain_handle = handle;
5725 q1.in.resume_handle = &resume_handle;
5726 q1.in.max_size = 5;
5727 q1.out.resume_handle = &resume_handle;
5728 q1.out.num_entries = &num_entries;
5729 q1.out.sam = &sam;
5731 status = STATUS_MORE_ENTRIES;
5732 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5733 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5735 if (!NT_STATUS_IS_OK(status) &&
5736 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5737 break;
5739 for (i=0; i<*q1.out.num_entries; i++) {
5740 add_string_to_array(tctx,
5741 sam->entries[i].name.string,
5742 &names, &num_names);
5746 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5748 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5750 q2.in.domain_handle = handle;
5751 q2.in.level = 5;
5752 q2.in.start_idx = 0;
5753 q2.in.max_entries = 5;
5754 q2.in.buf_size = (uint32_t)-1;
5755 q2.out.total_size = &total_size;
5756 q2.out.returned_size = &returned_size;
5757 q2.out.info = &info;
5759 status = STATUS_MORE_ENTRIES;
5760 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5761 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5763 if (!NT_STATUS_IS_OK(status) &&
5764 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5765 break;
5767 for (i=0; i<q2.out.info->info5.count; i++) {
5768 int j;
5769 const char *name = q2.out.info->info5.entries[i].account_name.string;
5770 bool found = false;
5771 for (j=0; j<num_names; j++) {
5772 if (names[j] == NULL)
5773 continue;
5774 if (strequal(names[j], name)) {
5775 names[j] = NULL;
5776 found = true;
5777 break;
5781 if (!found) {
5782 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5783 name);
5784 ret = false;
5787 q2.in.start_idx += q2.out.info->info5.count;
5790 if (!NT_STATUS_IS_OK(status)) {
5791 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
5792 nt_errstr(status));
5793 ret = false;
5796 for (i=0; i<num_names; i++) {
5797 if (names[i] != NULL) {
5798 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5799 names[i]);
5800 ret = false;
5804 return ret;
5807 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5808 struct policy_handle *group_handle)
5810 struct samr_DeleteDomainGroup d;
5811 NTSTATUS status;
5813 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5815 d.in.group_handle = group_handle;
5816 d.out.group_handle = group_handle;
5818 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5819 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5821 return true;
5824 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5825 struct policy_handle *domain_handle)
5827 struct samr_TestPrivateFunctionsDomain r;
5828 NTSTATUS status;
5829 bool ret = true;
5831 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5833 r.in.domain_handle = domain_handle;
5835 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5836 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
5838 return ret;
5841 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5842 struct dom_sid *domain_sid,
5843 struct policy_handle *domain_handle)
5845 struct samr_RidToSid r;
5846 NTSTATUS status;
5847 bool ret = true;
5848 struct dom_sid *calc_sid, *out_sid;
5849 int rids[] = { 0, 42, 512, 10200 };
5850 int i;
5852 for (i=0;i<ARRAY_SIZE(rids);i++) {
5853 torture_comment(tctx, "Testing RidToSid\n");
5855 calc_sid = dom_sid_dup(tctx, domain_sid);
5856 r.in.domain_handle = domain_handle;
5857 r.in.rid = rids[i];
5858 r.out.sid = &out_sid;
5860 status = dcerpc_samr_RidToSid(p, tctx, &r);
5861 if (!NT_STATUS_IS_OK(status)) {
5862 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5863 ret = false;
5864 } else {
5865 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5867 if (!dom_sid_equal(calc_sid, out_sid)) {
5868 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
5869 dom_sid_string(tctx, out_sid),
5870 dom_sid_string(tctx, calc_sid));
5871 ret = false;
5876 return ret;
5879 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5880 struct policy_handle *domain_handle)
5882 struct samr_GetBootKeyInformation r;
5883 NTSTATUS status;
5884 bool ret = true;
5885 uint32_t unknown = 0;
5887 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5889 r.in.domain_handle = domain_handle;
5890 r.out.unknown = &unknown;
5892 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 /* w2k3 seems to fail this sometimes and pass it sometimes */
5895 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5898 return ret;
5901 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5902 struct policy_handle *domain_handle,
5903 struct policy_handle *group_handle)
5905 NTSTATUS status;
5906 struct samr_AddGroupMember r;
5907 struct samr_DeleteGroupMember d;
5908 struct samr_QueryGroupMember q;
5909 struct samr_RidTypeArray *rids = NULL;
5910 struct samr_SetMemberAttributesOfGroup s;
5911 uint32_t rid;
5912 bool found_member = false;
5913 int i;
5915 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5916 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5918 r.in.group_handle = group_handle;
5919 r.in.rid = rid;
5920 r.in.flags = 0; /* ??? */
5922 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
5924 d.in.group_handle = group_handle;
5925 d.in.rid = rid;
5927 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5928 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5930 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5931 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5933 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5934 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5936 if (torture_setting_bool(tctx, "samba4", false) ||
5937 torture_setting_bool(tctx, "samba3", false)) {
5938 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
5939 } else {
5940 /* this one is quite strange. I am using random inputs in the
5941 hope of triggering an error that might give us a clue */
5943 s.in.group_handle = group_handle;
5944 s.in.unknown1 = random();
5945 s.in.unknown2 = random();
5947 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5948 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5951 q.in.group_handle = group_handle;
5952 q.out.rids = &rids;
5954 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5955 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5956 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
5958 for (i=0; i < rids->count; i++) {
5959 if (rids->rids[i] == rid) {
5960 found_member = true;
5964 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
5966 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5967 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5969 rids = NULL;
5970 found_member = false;
5972 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5973 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5974 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
5976 for (i=0; i < rids->count; i++) {
5977 if (rids->rids[i] == rid) {
5978 found_member = true;
5982 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
5984 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5985 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5987 return true;
5991 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5992 struct torture_context *tctx,
5993 struct policy_handle *domain_handle,
5994 const char *group_name,
5995 struct policy_handle *group_handle,
5996 struct dom_sid *domain_sid,
5997 bool test_group)
5999 NTSTATUS status;
6000 struct samr_CreateDomainGroup r;
6001 uint32_t rid;
6002 struct lsa_String name;
6003 bool ret = true;
6005 init_lsa_String(&name, group_name);
6007 r.in.domain_handle = domain_handle;
6008 r.in.name = &name;
6009 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6010 r.out.group_handle = group_handle;
6011 r.out.rid = &rid;
6013 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6015 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6017 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6018 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6019 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6020 return true;
6021 } else {
6022 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6023 nt_errstr(status));
6024 return false;
6028 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6029 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6030 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6031 nt_errstr(status));
6032 return false;
6034 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6036 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6037 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6039 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6040 nt_errstr(status));
6041 return false;
6043 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6045 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6047 if (!test_group) {
6048 return ret;
6051 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6052 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6053 ret = false;
6056 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6057 ret = false;
6060 return ret;
6065 its not totally clear what this does. It seems to accept any sid you like.
6067 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6068 struct torture_context *tctx,
6069 struct policy_handle *domain_handle)
6071 NTSTATUS status;
6072 struct samr_RemoveMemberFromForeignDomain r;
6074 r.in.domain_handle = domain_handle;
6075 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6077 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6078 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6080 return true;
6083 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6084 struct torture_context *tctx,
6085 struct policy_handle *domain_handle,
6086 uint32_t *total_num_entries_p)
6088 NTSTATUS status;
6089 struct samr_EnumDomainUsers r;
6090 uint32_t resume_handle = 0;
6091 uint32_t num_entries = 0;
6092 uint32_t total_num_entries = 0;
6093 struct samr_SamArray *sam;
6095 r.in.domain_handle = domain_handle;
6096 r.in.acct_flags = 0;
6097 r.in.max_size = (uint32_t)-1;
6098 r.in.resume_handle = &resume_handle;
6100 r.out.sam = &sam;
6101 r.out.num_entries = &num_entries;
6102 r.out.resume_handle = &resume_handle;
6104 torture_comment(tctx, "Testing EnumDomainUsers\n");
6106 do {
6107 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6108 if (NT_STATUS_IS_ERR(status)) {
6109 torture_assert_ntstatus_ok(tctx, status,
6110 "failed to enumerate users");
6113 total_num_entries += num_entries;
6114 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6116 if (total_num_entries_p) {
6117 *total_num_entries_p = total_num_entries;
6120 return true;
6123 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
6124 struct torture_context *tctx,
6125 struct policy_handle *domain_handle,
6126 uint32_t *total_num_entries_p)
6128 NTSTATUS status;
6129 struct samr_EnumDomainGroups r;
6130 uint32_t resume_handle = 0;
6131 uint32_t num_entries = 0;
6132 uint32_t total_num_entries = 0;
6133 struct samr_SamArray *sam;
6135 r.in.domain_handle = domain_handle;
6136 r.in.max_size = (uint32_t)-1;
6137 r.in.resume_handle = &resume_handle;
6139 r.out.sam = &sam;
6140 r.out.num_entries = &num_entries;
6141 r.out.resume_handle = &resume_handle;
6143 torture_comment(tctx, "Testing EnumDomainGroups\n");
6145 do {
6146 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
6147 if (NT_STATUS_IS_ERR(status)) {
6148 torture_assert_ntstatus_ok(tctx, status,
6149 "failed to enumerate groups");
6152 total_num_entries += num_entries;
6153 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6155 if (total_num_entries_p) {
6156 *total_num_entries_p = total_num_entries;
6159 return true;
6162 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
6163 struct torture_context *tctx,
6164 struct policy_handle *domain_handle,
6165 uint32_t *total_num_entries_p)
6167 NTSTATUS status;
6168 struct samr_EnumDomainAliases r;
6169 uint32_t resume_handle = 0;
6170 uint32_t num_entries = 0;
6171 uint32_t total_num_entries = 0;
6172 struct samr_SamArray *sam;
6174 r.in.domain_handle = domain_handle;
6175 r.in.max_size = (uint32_t)-1;
6176 r.in.resume_handle = &resume_handle;
6178 r.out.sam = &sam;
6179 r.out.num_entries = &num_entries;
6180 r.out.resume_handle = &resume_handle;
6182 torture_comment(tctx, "Testing EnumDomainAliases\n");
6184 do {
6185 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
6186 if (NT_STATUS_IS_ERR(status)) {
6187 torture_assert_ntstatus_ok(tctx, status,
6188 "failed to enumerate aliases");
6191 total_num_entries += num_entries;
6192 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6194 if (total_num_entries_p) {
6195 *total_num_entries_p = total_num_entries;
6198 return true;
6201 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
6202 struct torture_context *tctx,
6203 struct policy_handle *handle,
6204 uint16_t level,
6205 uint32_t *total_num_entries_p)
6207 NTSTATUS status;
6208 struct samr_QueryDisplayInfo r;
6209 uint32_t total_num_entries = 0;
6211 r.in.domain_handle = handle;
6212 r.in.level = level;
6213 r.in.start_idx = 0;
6214 r.in.max_entries = (uint32_t)-1;
6215 r.in.buf_size = (uint32_t)-1;
6217 torture_comment(tctx, "Testing QueryDisplayInfo\n");
6219 do {
6220 uint32_t total_size;
6221 uint32_t returned_size;
6222 union samr_DispInfo info;
6224 r.out.total_size = &total_size;
6225 r.out.returned_size = &returned_size;
6226 r.out.info = &info;
6228 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6229 if (NT_STATUS_IS_ERR(status)) {
6230 torture_assert_ntstatus_ok(tctx, status,
6231 "failed to query displayinfo");
6234 if (*r.out.returned_size == 0) {
6235 break;
6238 switch (r.in.level) {
6239 case 1:
6240 total_num_entries += info.info1.count;
6241 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
6242 break;
6243 case 2:
6244 total_num_entries += info.info2.count;
6245 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
6246 break;
6247 case 3:
6248 total_num_entries += info.info3.count;
6249 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
6250 break;
6251 case 4:
6252 total_num_entries += info.info4.count;
6253 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
6254 break;
6255 case 5:
6256 total_num_entries += info.info5.count;
6257 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
6258 break;
6259 default:
6260 return false;
6263 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6265 if (total_num_entries_p) {
6266 *total_num_entries_p = total_num_entries;
6269 return true;
6272 static bool test_ManyObjects(struct dcerpc_pipe *p,
6273 struct torture_context *tctx,
6274 struct policy_handle *domain_handle,
6275 struct dom_sid *domain_sid,
6276 enum torture_samr_choice which_ops)
6278 uint32_t num_total = 1500;
6279 uint32_t num_enum = 0;
6280 uint32_t num_disp = 0;
6281 uint32_t num_created = 0;
6282 uint32_t num_anounced = 0;
6283 bool ret = true;
6284 NTSTATUS status;
6285 uint32_t i;
6287 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
6289 /* query */
6292 struct samr_QueryDomainInfo2 r;
6293 union samr_DomainInfo *info;
6294 r.in.domain_handle = domain_handle;
6295 r.in.level = 2;
6296 r.out.info = &info;
6298 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6299 torture_assert_ntstatus_ok(tctx, status,
6300 "failed to query domain info");
6302 switch (which_ops) {
6303 case TORTURE_SAMR_MANY_ACCOUNTS:
6304 num_anounced = info->general.num_users;
6305 break;
6306 case TORTURE_SAMR_MANY_GROUPS:
6307 num_anounced = info->general.num_groups;
6308 break;
6309 case TORTURE_SAMR_MANY_ALIASES:
6310 num_anounced = info->general.num_aliases;
6311 break;
6312 default:
6313 return false;
6317 /* create */
6319 for (i=0; i < num_total; i++) {
6321 const char *name = NULL;
6323 switch (which_ops) {
6324 case TORTURE_SAMR_MANY_ACCOUNTS:
6325 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
6326 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
6327 break;
6328 case TORTURE_SAMR_MANY_GROUPS:
6329 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
6330 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6331 break;
6332 case TORTURE_SAMR_MANY_ALIASES:
6333 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
6334 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6335 break;
6336 default:
6337 return false;
6339 if (!policy_handle_empty(&handles[i])) {
6340 num_created++;
6344 /* enum */
6346 switch (which_ops) {
6347 case TORTURE_SAMR_MANY_ACCOUNTS:
6348 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
6349 break;
6350 case TORTURE_SAMR_MANY_GROUPS:
6351 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
6352 break;
6353 case TORTURE_SAMR_MANY_ALIASES:
6354 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
6355 break;
6356 default:
6357 return false;
6360 /* dispinfo */
6362 switch (which_ops) {
6363 case TORTURE_SAMR_MANY_ACCOUNTS:
6364 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
6365 break;
6366 case TORTURE_SAMR_MANY_GROUPS:
6367 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
6368 break;
6369 case TORTURE_SAMR_MANY_ALIASES:
6370 /* no aliases in dispinfo */
6371 break;
6372 default:
6373 return false;
6376 /* close or delete */
6378 for (i=0; i < num_total; i++) {
6380 if (policy_handle_empty(&handles[i])) {
6381 continue;
6384 if (torture_setting_bool(tctx, "samba3", false)) {
6385 ret &= test_samr_handle_Close(p, tctx, &handles[i]);
6386 } else {
6387 switch (which_ops) {
6388 case TORTURE_SAMR_MANY_ACCOUNTS:
6389 ret &= test_DeleteUser(p, tctx, &handles[i]);
6390 break;
6391 case TORTURE_SAMR_MANY_GROUPS:
6392 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
6393 break;
6394 case TORTURE_SAMR_MANY_ALIASES:
6395 ret &= test_DeleteAlias(p, tctx, &handles[i]);
6396 break;
6397 default:
6398 return false;
6403 talloc_free(handles);
6405 if (which_ops == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
6406 torture_comment(tctx,
6407 "unexpected number of results (%u) returned in enum call, expected %u\n",
6408 num_enum, num_anounced + num_created);
6410 torture_comment(tctx,
6411 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
6412 num_disp, num_anounced + num_created);
6414 return ret;
6417 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6418 struct policy_handle *handle);
6420 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6421 struct policy_handle *handle, struct dom_sid *sid,
6422 enum torture_samr_choice which_ops,
6423 struct cli_credentials *machine_credentials)
6425 NTSTATUS status;
6426 struct samr_OpenDomain r;
6427 struct policy_handle domain_handle;
6428 struct policy_handle alias_handle;
6429 struct policy_handle user_handle;
6430 struct policy_handle group_handle;
6431 bool ret = true;
6433 ZERO_STRUCT(alias_handle);
6434 ZERO_STRUCT(user_handle);
6435 ZERO_STRUCT(group_handle);
6436 ZERO_STRUCT(domain_handle);
6438 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
6440 r.in.connect_handle = handle;
6441 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6442 r.in.sid = sid;
6443 r.out.domain_handle = &domain_handle;
6445 status = dcerpc_samr_OpenDomain(p, tctx, &r);
6446 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
6448 /* run the domain tests with the main handle closed - this tests
6449 the servers reference counting */
6450 torture_assert(tctx, test_samr_handle_Close(p, tctx, handle), "Failed to close SAMR handle");
6452 switch (which_ops) {
6453 case TORTURE_SAMR_PASSWORDS:
6454 case TORTURE_SAMR_USER_PRIVILEGES:
6455 if (!torture_setting_bool(tctx, "samba3", false)) {
6456 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
6458 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6459 if (!ret) {
6460 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
6462 break;
6463 case TORTURE_SAMR_USER_ATTRIBUTES:
6464 if (!torture_setting_bool(tctx, "samba3", false)) {
6465 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
6467 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6468 /* This test needs 'complex' users to validate */
6469 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
6470 if (!ret) {
6471 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
6473 break;
6474 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
6475 if (!torture_setting_bool(tctx, "samba3", false)) {
6476 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
6478 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, machine_credentials, true);
6479 if (!ret) {
6480 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
6482 break;
6483 case TORTURE_SAMR_MANY_ACCOUNTS:
6484 case TORTURE_SAMR_MANY_GROUPS:
6485 case TORTURE_SAMR_MANY_ALIASES:
6486 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, which_ops);
6487 if (!ret) {
6488 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
6490 break;
6491 case TORTURE_SAMR_OTHER:
6492 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6493 if (!ret) {
6494 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
6496 if (!torture_setting_bool(tctx, "samba3", false)) {
6497 ret &= test_QuerySecurity(p, tctx, &domain_handle);
6499 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
6500 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
6501 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
6502 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
6503 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
6504 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
6505 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
6506 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
6507 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
6508 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
6509 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
6510 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
6512 if (torture_setting_bool(tctx, "samba4", false)) {
6513 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
6514 } else {
6515 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
6516 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
6518 ret &= test_GroupList(p, tctx, &domain_handle);
6519 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
6520 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
6521 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
6522 if (!ret) {
6523 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
6525 break;
6528 if (!policy_handle_empty(&user_handle) &&
6529 !test_DeleteUser(p, tctx, &user_handle)) {
6530 ret = false;
6533 if (!policy_handle_empty(&alias_handle) &&
6534 !test_DeleteAlias(p, tctx, &alias_handle)) {
6535 ret = false;
6538 if (!policy_handle_empty(&group_handle) &&
6539 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
6540 ret = false;
6543 torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
6545 torture_assert(tctx, test_Connect(p, tctx, handle), "Faile to re-connect SAMR handle");
6546 /* reconnect the main handle */
6548 if (!ret) {
6549 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
6552 return ret;
6555 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6556 struct policy_handle *handle, const char *domain,
6557 enum torture_samr_choice which_ops,
6558 struct cli_credentials *machine_credentials)
6560 NTSTATUS status;
6561 struct samr_LookupDomain r;
6562 struct dom_sid2 *sid = NULL;
6563 struct lsa_String n1;
6564 struct lsa_String n2;
6565 bool ret = true;
6567 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
6569 /* check for correct error codes */
6570 r.in.connect_handle = handle;
6571 r.in.domain_name = &n2;
6572 r.out.sid = &sid;
6573 n2.string = NULL;
6575 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6576 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
6578 init_lsa_String(&n2, "xxNODOMAINxx");
6580 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6581 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
6583 r.in.connect_handle = handle;
6585 init_lsa_String(&n1, domain);
6586 r.in.domain_name = &n1;
6588 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6589 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
6591 if (!test_GetDomPwInfo(p, tctx, &n1)) {
6592 ret = false;
6595 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
6596 machine_credentials)) {
6597 ret = false;
6600 return ret;
6604 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
6605 struct policy_handle *handle, enum torture_samr_choice which_ops,
6606 struct cli_credentials *machine_credentials)
6608 NTSTATUS status;
6609 struct samr_EnumDomains r;
6610 uint32_t resume_handle = 0;
6611 uint32_t num_entries = 0;
6612 struct samr_SamArray *sam = NULL;
6613 int i;
6614 bool ret = true;
6616 r.in.connect_handle = handle;
6617 r.in.resume_handle = &resume_handle;
6618 r.in.buf_size = (uint32_t)-1;
6619 r.out.resume_handle = &resume_handle;
6620 r.out.num_entries = &num_entries;
6621 r.out.sam = &sam;
6623 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6624 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6626 if (!*r.out.sam) {
6627 return false;
6630 for (i=0;i<sam->count;i++) {
6631 if (!test_LookupDomain(p, tctx, handle,
6632 sam->entries[i].name.string, which_ops,
6633 machine_credentials)) {
6634 ret = false;
6638 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6639 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6641 return ret;
6645 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6646 struct policy_handle *handle)
6648 NTSTATUS status;
6649 struct samr_Connect r;
6650 struct samr_Connect2 r2;
6651 struct samr_Connect3 r3;
6652 struct samr_Connect4 r4;
6653 struct samr_Connect5 r5;
6654 union samr_ConnectInfo info;
6655 struct policy_handle h;
6656 uint32_t level_out = 0;
6657 bool ret = true, got_handle = false;
6659 torture_comment(tctx, "testing samr_Connect\n");
6661 r.in.system_name = 0;
6662 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6663 r.out.connect_handle = &h;
6665 status = dcerpc_samr_Connect(p, tctx, &r);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
6668 ret = false;
6669 } else {
6670 got_handle = true;
6671 *handle = h;
6674 torture_comment(tctx, "testing samr_Connect2\n");
6676 r2.in.system_name = NULL;
6677 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6678 r2.out.connect_handle = &h;
6680 status = dcerpc_samr_Connect2(p, tctx, &r2);
6681 if (!NT_STATUS_IS_OK(status)) {
6682 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
6683 ret = false;
6684 } else {
6685 if (got_handle) {
6686 test_samr_handle_Close(p, tctx, handle);
6688 got_handle = true;
6689 *handle = h;
6692 torture_comment(tctx, "testing samr_Connect3\n");
6694 r3.in.system_name = NULL;
6695 r3.in.unknown = 0;
6696 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6697 r3.out.connect_handle = &h;
6699 status = dcerpc_samr_Connect3(p, tctx, &r3);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
6702 ret = false;
6703 } else {
6704 if (got_handle) {
6705 test_samr_handle_Close(p, tctx, handle);
6707 got_handle = true;
6708 *handle = h;
6711 torture_comment(tctx, "testing samr_Connect4\n");
6713 r4.in.system_name = "";
6714 r4.in.client_version = 0;
6715 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6716 r4.out.connect_handle = &h;
6718 status = dcerpc_samr_Connect4(p, tctx, &r4);
6719 if (!NT_STATUS_IS_OK(status)) {
6720 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
6721 ret = false;
6722 } else {
6723 if (got_handle) {
6724 test_samr_handle_Close(p, tctx, handle);
6726 got_handle = true;
6727 *handle = h;
6730 torture_comment(tctx, "testing samr_Connect5\n");
6732 info.info1.client_version = 0;
6733 info.info1.unknown2 = 0;
6735 r5.in.system_name = "";
6736 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6737 r5.in.level_in = 1;
6738 r5.out.level_out = &level_out;
6739 r5.in.info_in = &info;
6740 r5.out.info_out = &info;
6741 r5.out.connect_handle = &h;
6743 status = dcerpc_samr_Connect5(p, tctx, &r5);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
6746 ret = false;
6747 } else {
6748 if (got_handle) {
6749 test_samr_handle_Close(p, tctx, handle);
6751 got_handle = true;
6752 *handle = h;
6755 return ret;
6759 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_context *tctx)
6761 struct samr_ValidatePassword r;
6762 union samr_ValidatePasswordReq req;
6763 union samr_ValidatePasswordRep *repp = NULL;
6764 NTSTATUS status;
6765 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
6766 int i;
6768 torture_comment(tctx, "testing samr_ValidatePassword\n");
6770 ZERO_STRUCT(r);
6771 r.in.level = NetValidatePasswordReset;
6772 r.in.req = &req;
6773 r.out.rep = &repp;
6775 ZERO_STRUCT(req);
6776 req.req3.account.string = "non-existant-account-aklsdji";
6778 for (i=0; passwords[i]; i++) {
6779 req.req3.password.string = passwords[i];
6780 status = dcerpc_samr_ValidatePassword(p, tctx, &r);
6781 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
6782 torture_comment(tctx, "Server %s password '%s'\n",
6783 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
6784 req.req3.password.string);
6787 return true;
6790 bool torture_rpc_samr(struct torture_context *torture)
6792 NTSTATUS status;
6793 struct dcerpc_pipe *p;
6794 bool ret = true;
6795 struct policy_handle handle;
6797 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6798 if (!NT_STATUS_IS_OK(status)) {
6799 return false;
6802 ret &= test_Connect(p, torture, &handle);
6804 if (!torture_setting_bool(torture, "samba3", false)) {
6805 ret &= test_QuerySecurity(p, torture, &handle);
6808 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
6810 ret &= test_SetDsrmPassword(p, torture, &handle);
6812 ret &= test_Shutdown(p, torture, &handle);
6814 ret &= test_samr_handle_Close(p, torture, &handle);
6816 return ret;
6820 bool torture_rpc_samr_users(struct torture_context *torture)
6822 NTSTATUS status;
6823 struct dcerpc_pipe *p;
6824 bool ret = true;
6825 struct policy_handle handle;
6827 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6828 if (!NT_STATUS_IS_OK(status)) {
6829 return false;
6832 ret &= test_Connect(p, torture, &handle);
6834 if (!torture_setting_bool(torture, "samba3", false)) {
6835 ret &= test_QuerySecurity(p, torture, &handle);
6838 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
6840 ret &= test_SetDsrmPassword(p, torture, &handle);
6842 ret &= test_Shutdown(p, torture, &handle);
6844 ret &= test_samr_handle_Close(p, torture, &handle);
6846 return ret;
6850 bool torture_rpc_samr_passwords(struct torture_context *torture)
6852 NTSTATUS status;
6853 struct dcerpc_pipe *p;
6854 bool ret = true;
6855 struct policy_handle handle;
6857 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 return false;
6862 ret &= test_Connect(p, torture, &handle);
6864 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6866 ret &= test_samr_handle_Close(p, torture, &handle);
6868 ret &= test_samr_ValidatePassword(p, torture);
6870 return ret;
6873 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6874 struct dcerpc_pipe *p2,
6875 struct cli_credentials *machine_credentials)
6877 NTSTATUS status;
6878 struct dcerpc_pipe *p;
6879 bool ret = true;
6880 struct policy_handle handle;
6882 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6883 if (!NT_STATUS_IS_OK(status)) {
6884 return false;
6887 ret &= test_Connect(p, torture, &handle);
6889 ret &= test_EnumDomains(p, torture, &handle,
6890 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6891 machine_credentials);
6893 ret &= test_samr_handle_Close(p, torture, &handle);
6895 return ret;
6898 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6900 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6901 struct torture_rpc_tcase *tcase;
6903 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6904 &ndr_table_samr,
6905 TEST_ACCOUNT_NAME_PWD);
6907 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6908 torture_rpc_samr_pwdlastset);
6910 return suite;
6913 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
6914 struct dcerpc_pipe *p2,
6915 struct cli_credentials *machine_credentials)
6917 NTSTATUS status;
6918 struct dcerpc_pipe *p;
6919 bool ret = true;
6920 struct policy_handle handle;
6922 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6923 if (!NT_STATUS_IS_OK(status)) {
6924 return false;
6927 ret &= test_Connect(p, torture, &handle);
6929 ret &= test_EnumDomains(p, torture, &handle,
6930 TORTURE_SAMR_USER_PRIVILEGES,
6931 machine_credentials);
6933 ret &= test_samr_handle_Close(p, torture, &handle);
6935 return ret;
6938 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
6940 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
6941 struct torture_rpc_tcase *tcase;
6943 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
6944 &ndr_table_samr,
6945 TEST_ACCOUNT_NAME_PWD);
6947 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
6948 torture_rpc_samr_users_privileges_delete_user);
6950 return suite;
6953 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
6954 struct dcerpc_pipe *p2,
6955 struct cli_credentials *machine_credentials)
6957 NTSTATUS status;
6958 struct dcerpc_pipe *p;
6959 bool ret = true;
6960 struct policy_handle handle;
6962 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 return false;
6967 ret &= test_Connect(p, torture, &handle);
6969 ret &= test_EnumDomains(p, torture, &handle,
6970 TORTURE_SAMR_MANY_ACCOUNTS,
6971 machine_credentials);
6973 ret &= test_samr_handle_Close(p, torture, &handle);
6975 return ret;
6978 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
6979 struct dcerpc_pipe *p2,
6980 struct cli_credentials *machine_credentials)
6982 NTSTATUS status;
6983 struct dcerpc_pipe *p;
6984 bool ret = true;
6985 struct policy_handle handle;
6987 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6988 if (!NT_STATUS_IS_OK(status)) {
6989 return false;
6992 ret &= test_Connect(p, torture, &handle);
6994 ret &= test_EnumDomains(p, torture, &handle,
6995 TORTURE_SAMR_MANY_GROUPS,
6996 machine_credentials);
6998 ret &= test_samr_handle_Close(p, torture, &handle);
7000 return ret;
7003 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7004 struct dcerpc_pipe *p2,
7005 struct cli_credentials *machine_credentials)
7007 NTSTATUS status;
7008 struct dcerpc_pipe *p;
7009 bool ret = true;
7010 struct policy_handle handle;
7012 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7013 if (!NT_STATUS_IS_OK(status)) {
7014 return false;
7017 ret &= test_Connect(p, torture, &handle);
7019 ret &= test_EnumDomains(p, torture, &handle,
7020 TORTURE_SAMR_MANY_ALIASES,
7021 machine_credentials);
7023 ret &= test_samr_handle_Close(p, torture, &handle);
7025 return ret;
7028 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7030 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7031 struct torture_rpc_tcase *tcase;
7033 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7034 &ndr_table_samr,
7035 TEST_ACCOUNT_NAME);
7037 torture_rpc_tcase_add_test_creds(tcase, "many_aliases",
7038 torture_rpc_samr_many_aliases);
7039 torture_rpc_tcase_add_test_creds(tcase, "many_groups",
7040 torture_rpc_samr_many_groups);
7041 torture_rpc_tcase_add_test_creds(tcase, "many_accounts",
7042 torture_rpc_samr_many_accounts);
7044 return suite;