s4:torture/rpc/samr.c - fix typos in outputs
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blob7212f1eb7dc65af2c71b55f41b8455e868de9fc6
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-2010
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 <tevent.h>
26 #include "system/time.h"
27 #include "librpc/gen_ndr/lsa.h"
28 #include "librpc/gen_ndr/ndr_netlogon.h"
29 #include "librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "../lib/crypto/crypto.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "libcli/security/security.h"
35 #include "torture/rpc/torture_rpc.h"
36 #include "param/param.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/gensec/gensec_proto.h"
39 #include "../libcli/auth/schannel.h"
41 #include <unistd.h>
43 #define TEST_ACCOUNT_NAME "samrtorturetest"
44 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
45 #define TEST_ALIASNAME "samrtorturetestalias"
46 #define TEST_GROUPNAME "samrtorturetestgroup"
47 #define TEST_MACHINENAME "samrtestmach$"
48 #define TEST_DOMAINNAME "samrtestdom$"
50 enum torture_samr_choice {
51 TORTURE_SAMR_PASSWORDS,
52 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
53 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
54 TORTURE_SAMR_PASSWORDS_LOCKOUT,
55 TORTURE_SAMR_USER_ATTRIBUTES,
56 TORTURE_SAMR_USER_PRIVILEGES,
57 TORTURE_SAMR_OTHER,
58 TORTURE_SAMR_MANY_ACCOUNTS,
59 TORTURE_SAMR_MANY_GROUPS,
60 TORTURE_SAMR_MANY_ALIASES
63 struct torture_samr_context {
64 struct policy_handle handle;
65 struct cli_credentials *machine_credentials;
66 enum torture_samr_choice choice;
67 uint32_t num_objects_large_dc;
70 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
71 struct torture_context *tctx,
72 struct policy_handle *handle);
74 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
75 struct torture_context *tctx,
76 struct policy_handle *handle);
78 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
79 struct torture_context *tctx,
80 struct policy_handle *handle);
82 static bool test_ChangePassword(struct dcerpc_pipe *p,
83 struct torture_context *tctx,
84 const char *acct_name,
85 struct policy_handle *domain_handle, char **password);
87 static void init_lsa_String(struct lsa_String *string, const char *s)
89 string->string = s;
92 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
94 string->string = s;
97 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
99 string->length = length;
100 string->size = length;
101 string->array = (uint16_t *)discard_const(s);
104 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
105 struct torture_context *tctx,
106 struct policy_handle *handle)
108 struct samr_Close r;
110 r.in.handle = handle;
111 r.out.handle = handle;
113 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
114 "Close failed");
115 torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
117 return true;
120 static bool test_Shutdown(struct dcerpc_binding_handle *b,
121 struct torture_context *tctx,
122 struct policy_handle *handle)
124 struct samr_Shutdown r;
126 if (!torture_setting_bool(tctx, "dangerous", false)) {
127 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
128 return true;
131 r.in.connect_handle = handle;
133 torture_comment(tctx, "Testing samr_Shutdown\n");
135 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
136 "Shutdown failed");
137 torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
139 return true;
142 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
143 struct torture_context *tctx,
144 struct policy_handle *handle)
146 struct samr_SetDsrmPassword r;
147 struct lsa_String string;
148 struct samr_Password hash;
150 if (!torture_setting_bool(tctx, "dangerous", false)) {
151 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
154 E_md4hash("TeSTDSRM123", hash.hash);
156 init_lsa_String(&string, "Administrator");
158 r.in.name = &string;
159 r.in.unknown = 0;
160 r.in.hash = &hash;
162 torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
164 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
165 "SetDsrmPassword failed");
166 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
168 return true;
172 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
173 struct torture_context *tctx,
174 struct policy_handle *handle)
176 struct samr_QuerySecurity r;
177 struct samr_SetSecurity s;
178 struct sec_desc_buf *sdbuf = NULL;
180 r.in.handle = handle;
181 r.in.sec_info = 7;
182 r.out.sdbuf = &sdbuf;
184 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
185 "QuerySecurity failed");
186 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
188 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
190 s.in.handle = handle;
191 s.in.sec_info = 7;
192 s.in.sdbuf = sdbuf;
194 if (torture_setting_bool(tctx, "samba4", false)) {
195 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
199 "SetSecurity failed");
200 torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
202 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
203 "QuerySecurity failed");
204 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
206 return true;
210 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
211 struct policy_handle *handle, uint32_t base_acct_flags,
212 const char *base_account_name)
214 struct samr_SetUserInfo s;
215 struct samr_SetUserInfo2 s2;
216 struct samr_QueryUserInfo q;
217 struct samr_QueryUserInfo q0;
218 union samr_UserInfo u;
219 union samr_UserInfo *info;
220 bool ret = true;
221 const char *test_account_name;
223 uint32_t user_extra_flags = 0;
225 if (!torture_setting_bool(tctx, "samba3", false)) {
226 if (base_acct_flags == ACB_NORMAL) {
227 /* When created, accounts are expired by default */
228 user_extra_flags = ACB_PW_EXPIRED;
232 s.in.user_handle = handle;
233 s.in.info = &u;
235 s2.in.user_handle = handle;
236 s2.in.info = &u;
238 q.in.user_handle = handle;
239 q.out.info = &info;
240 q0 = q;
242 #define TESTCALL(call, r) \
243 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
244 #call " failed"); \
245 if (!NT_STATUS_IS_OK(r.out.result)) { \
246 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
247 r.in.level, nt_errstr(r.out.result), __location__); \
248 ret = false; \
249 break; \
252 #define STRING_EQUAL(s1, s2, field) \
253 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
254 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
255 #field, s2, __location__); \
256 ret = false; \
257 break; \
260 #define MEM_EQUAL(s1, s2, length, field) \
261 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
262 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
263 #field, (const char *)s2, __location__); \
264 ret = false; \
265 break; \
268 #define INT_EQUAL(i1, i2, field) \
269 if (i1 != i2) { \
270 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
271 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
272 ret = false; \
273 break; \
276 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
277 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
278 q.in.level = lvl1; \
279 TESTCALL(QueryUserInfo, q) \
280 s.in.level = lvl1; \
281 s2.in.level = lvl1; \
282 u = *info; \
283 if (lvl1 == 21) { \
284 ZERO_STRUCT(u.info21); \
285 u.info21.fields_present = fpval; \
287 init_lsa_String(&u.info ## lvl1.field1, value); \
288 TESTCALL(SetUserInfo, s) \
289 TESTCALL(SetUserInfo2, s2) \
290 init_lsa_String(&u.info ## lvl1.field1, ""); \
291 TESTCALL(QueryUserInfo, q); \
292 u = *info; \
293 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
294 q.in.level = lvl2; \
295 TESTCALL(QueryUserInfo, q) \
296 u = *info; \
297 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
298 } while (0)
300 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
301 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
302 q.in.level = lvl1; \
303 TESTCALL(QueryUserInfo, q) \
304 s.in.level = lvl1; \
305 s2.in.level = lvl1; \
306 u = *info; \
307 if (lvl1 == 21) { \
308 ZERO_STRUCT(u.info21); \
309 u.info21.fields_present = fpval; \
311 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
312 TESTCALL(SetUserInfo, s) \
313 TESTCALL(SetUserInfo2, s2) \
314 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
315 TESTCALL(QueryUserInfo, q); \
316 u = *info; \
317 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
318 q.in.level = lvl2; \
319 TESTCALL(QueryUserInfo, q) \
320 u = *info; \
321 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
322 } while (0)
324 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
325 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
326 q.in.level = lvl1; \
327 TESTCALL(QueryUserInfo, q) \
328 s.in.level = lvl1; \
329 s2.in.level = lvl1; \
330 u = *info; \
331 if (lvl1 == 21) { \
332 uint8_t *bits = u.info21.logon_hours.bits; \
333 ZERO_STRUCT(u.info21); \
334 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
335 u.info21.logon_hours.units_per_week = 168; \
336 u.info21.logon_hours.bits = bits; \
338 u.info21.fields_present = fpval; \
340 u.info ## lvl1.field1 = value; \
341 TESTCALL(SetUserInfo, s) \
342 TESTCALL(SetUserInfo2, s2) \
343 u.info ## lvl1.field1 = 0; \
344 TESTCALL(QueryUserInfo, q); \
345 u = *info; \
346 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
347 q.in.level = lvl2; \
348 TESTCALL(QueryUserInfo, q) \
349 u = *info; \
350 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
351 } while (0)
353 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
354 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
355 } while (0)
357 q0.in.level = 12;
358 do { TESTCALL(QueryUserInfo, q0) } while (0);
360 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
361 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
362 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
363 SAMR_FIELD_COMMENT);
365 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
366 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
367 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
368 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
369 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
370 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
371 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
372 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
373 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
374 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
375 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
376 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
377 test_account_name = base_account_name;
378 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
379 SAMR_FIELD_ACCOUNT_NAME);
381 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
382 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
383 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
384 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
385 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
386 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
387 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
388 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
389 SAMR_FIELD_FULL_NAME);
391 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
392 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
393 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
394 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
395 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
396 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
397 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
398 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
399 SAMR_FIELD_FULL_NAME);
401 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
402 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
403 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
404 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
405 SAMR_FIELD_LOGON_SCRIPT);
407 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
408 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
409 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
410 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
411 SAMR_FIELD_PROFILE_PATH);
413 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
414 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
415 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
416 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
417 SAMR_FIELD_HOME_DIRECTORY);
418 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
419 SAMR_FIELD_HOME_DIRECTORY);
421 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
422 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
423 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
424 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
425 SAMR_FIELD_HOME_DRIVE);
426 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
427 SAMR_FIELD_HOME_DRIVE);
429 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
430 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
431 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
432 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
433 SAMR_FIELD_DESCRIPTION);
435 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
436 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
437 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
438 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
439 SAMR_FIELD_WORKSTATIONS);
440 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
441 SAMR_FIELD_WORKSTATIONS);
442 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
443 SAMR_FIELD_WORKSTATIONS);
444 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
445 SAMR_FIELD_WORKSTATIONS);
447 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
448 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
449 SAMR_FIELD_PARAMETERS);
450 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
451 SAMR_FIELD_PARAMETERS);
452 /* also empty user parameters are allowed */
453 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
454 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
455 SAMR_FIELD_PARAMETERS);
456 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
457 SAMR_FIELD_PARAMETERS);
459 /* Samba 3 cannot store country_code and copy_page atm. - gd */
460 if (!torture_setting_bool(tctx, "samba3", false)) {
461 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
462 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
463 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
464 SAMR_FIELD_COUNTRY_CODE);
465 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
466 SAMR_FIELD_COUNTRY_CODE);
468 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
469 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
470 SAMR_FIELD_CODE_PAGE);
471 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
472 SAMR_FIELD_CODE_PAGE);
475 if (!torture_setting_bool(tctx, "samba3", false)) {
476 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
477 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
478 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
479 SAMR_FIELD_ACCT_EXPIRY);
480 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
481 SAMR_FIELD_ACCT_EXPIRY);
482 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
483 SAMR_FIELD_ACCT_EXPIRY);
484 } else {
485 /* Samba 3 can only store seconds / time_t in passdb - gd */
486 NTTIME nt;
487 unix_to_nt_time(&nt, time(NULL) + __LINE__);
488 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
489 unix_to_nt_time(&nt, time(NULL) + __LINE__);
490 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
491 unix_to_nt_time(&nt, time(NULL) + __LINE__);
492 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
493 unix_to_nt_time(&nt, time(NULL) + __LINE__);
494 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
495 unix_to_nt_time(&nt, time(NULL) + __LINE__);
496 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
499 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
500 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
501 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
502 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
503 SAMR_FIELD_LOGON_HOURS);
505 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
506 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
507 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
509 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
510 (base_acct_flags | ACB_DISABLED),
511 (base_acct_flags | ACB_DISABLED | user_extra_flags),
514 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
515 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
516 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
517 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
519 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
520 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
521 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
525 /* The 'autolock' flag doesn't stick - check this */
526 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
527 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
528 (base_acct_flags | ACB_DISABLED | user_extra_flags),
530 #if 0
531 /* Removing the 'disabled' flag doesn't stick - check this */
532 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
533 (base_acct_flags),
534 (base_acct_flags | ACB_DISABLED | user_extra_flags),
536 #endif
538 /* Samba3 cannot store these atm */
539 if (!torture_setting_bool(tctx, "samba3", false)) {
540 /* The 'store plaintext' flag does stick */
541 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
542 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
543 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
545 /* The 'use DES' flag does stick */
546 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
547 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
548 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
550 /* The 'don't require kerberos pre-authentication flag does stick */
551 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
552 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
553 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
555 /* The 'no kerberos PAC required' flag sticks */
556 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
557 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
558 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
561 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
562 (base_acct_flags | ACB_DISABLED),
563 (base_acct_flags | ACB_DISABLED | user_extra_flags),
564 SAMR_FIELD_ACCT_FLAGS);
566 #if 0
567 /* these fail with win2003 - it appears you can't set the primary gid?
568 the set succeeds, but the gid isn't changed. Very weird! */
569 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
570 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
571 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
572 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
573 #endif
575 return ret;
579 generate a random password for password change tests
581 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
583 size_t len = MAX(8, min_len);
584 char *s = generate_random_password(mem_ctx, len, len+6);
585 return s;
588 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
590 char *s = samr_rand_pass_silent(mem_ctx, min_len);
591 printf("Generated password '%s'\n", s);
592 return s;
597 generate a random password for password change tests
599 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
601 int i;
602 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
603 generate_random_buffer(password.data, password.length);
605 for (i=0; i < len; i++) {
606 if (((uint16_t *)password.data)[i] == 0) {
607 ((uint16_t *)password.data)[i] = 1;
611 return password;
615 generate a random password for password change tests (fixed length)
617 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
619 char *s = generate_random_password(mem_ctx, len, len);
620 printf("Generated password '%s'\n", s);
621 return s;
624 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
625 struct policy_handle *handle, char **password)
627 NTSTATUS status;
628 struct samr_SetUserInfo s;
629 union samr_UserInfo u;
630 bool ret = true;
631 DATA_BLOB session_key;
632 char *newpass;
633 struct dcerpc_binding_handle *b = p->binding_handle;
634 struct samr_GetUserPwInfo pwp;
635 struct samr_PwInfo info;
636 int policy_min_pw_len = 0;
637 pwp.in.user_handle = handle;
638 pwp.out.info = &info;
640 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
641 "GetUserPwInfo failed");
642 if (NT_STATUS_IS_OK(pwp.out.result)) {
643 policy_min_pw_len = pwp.out.info->min_password_length;
645 newpass = samr_rand_pass(tctx, policy_min_pw_len);
647 s.in.user_handle = handle;
648 s.in.info = &u;
649 s.in.level = 24;
651 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
652 u.info24.password_expired = 0;
654 status = dcerpc_fetch_session_key(p, &session_key);
655 if (!NT_STATUS_IS_OK(status)) {
656 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
657 s.in.level, nt_errstr(status));
658 return false;
661 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
663 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
665 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
666 "SetUserInfo failed");
667 if (!NT_STATUS_IS_OK(s.out.result)) {
668 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
669 s.in.level, nt_errstr(s.out.result));
670 ret = false;
671 } else {
672 *password = newpass;
675 return ret;
679 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
680 struct policy_handle *handle, uint32_t fields_present,
681 char **password)
683 NTSTATUS status;
684 struct samr_SetUserInfo s;
685 union samr_UserInfo u;
686 bool ret = true;
687 DATA_BLOB session_key;
688 struct dcerpc_binding_handle *b = p->binding_handle;
689 char *newpass;
690 struct samr_GetUserPwInfo pwp;
691 struct samr_PwInfo info;
692 int policy_min_pw_len = 0;
693 pwp.in.user_handle = handle;
694 pwp.out.info = &info;
696 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
697 "GetUserPwInfo failed");
698 if (NT_STATUS_IS_OK(pwp.out.result)) {
699 policy_min_pw_len = pwp.out.info->min_password_length;
701 newpass = samr_rand_pass(tctx, policy_min_pw_len);
703 s.in.user_handle = handle;
704 s.in.info = &u;
705 s.in.level = 23;
707 ZERO_STRUCT(u);
709 u.info23.info.fields_present = fields_present;
711 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
713 status = dcerpc_fetch_session_key(p, &session_key);
714 if (!NT_STATUS_IS_OK(status)) {
715 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
716 s.in.level, nt_errstr(status));
717 return false;
720 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
722 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
724 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
725 "SetUserInfo failed");
726 if (!NT_STATUS_IS_OK(s.out.result)) {
727 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
728 s.in.level, nt_errstr(s.out.result));
729 ret = false;
730 } else {
731 *password = newpass;
734 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
736 status = dcerpc_fetch_session_key(p, &session_key);
737 if (!NT_STATUS_IS_OK(status)) {
738 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
739 s.in.level, nt_errstr(status));
740 return false;
743 /* This should break the key nicely */
744 session_key.length--;
745 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
747 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
749 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
750 "SetUserInfo failed");
751 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
752 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
753 s.in.level, nt_errstr(s.out.result));
754 ret = false;
757 return ret;
761 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
762 struct policy_handle *handle, bool makeshort,
763 char **password)
765 NTSTATUS status;
766 struct samr_SetUserInfo s;
767 union samr_UserInfo u;
768 bool ret = true;
769 DATA_BLOB session_key;
770 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
771 uint8_t confounder[16];
772 char *newpass;
773 struct dcerpc_binding_handle *b = p->binding_handle;
774 struct MD5Context ctx;
775 struct samr_GetUserPwInfo pwp;
776 struct samr_PwInfo info;
777 int policy_min_pw_len = 0;
778 pwp.in.user_handle = handle;
779 pwp.out.info = &info;
781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
782 "GetUserPwInfo failed");
783 if (NT_STATUS_IS_OK(pwp.out.result)) {
784 policy_min_pw_len = pwp.out.info->min_password_length;
786 if (makeshort && policy_min_pw_len) {
787 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
788 } else {
789 newpass = samr_rand_pass(tctx, policy_min_pw_len);
792 s.in.user_handle = handle;
793 s.in.info = &u;
794 s.in.level = 26;
796 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
797 u.info26.password_expired = 0;
799 status = dcerpc_fetch_session_key(p, &session_key);
800 if (!NT_STATUS_IS_OK(status)) {
801 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
802 s.in.level, nt_errstr(status));
803 return false;
806 generate_random_buffer((uint8_t *)confounder, 16);
808 MD5Init(&ctx);
809 MD5Update(&ctx, confounder, 16);
810 MD5Update(&ctx, session_key.data, session_key.length);
811 MD5Final(confounded_session_key.data, &ctx);
813 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
814 memcpy(&u.info26.password.data[516], confounder, 16);
816 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
818 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
819 "SetUserInfo failed");
820 if (!NT_STATUS_IS_OK(s.out.result)) {
821 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
822 s.in.level, nt_errstr(s.out.result));
823 ret = false;
824 } else {
825 *password = newpass;
828 /* This should break the key nicely */
829 confounded_session_key.data[0]++;
831 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
832 memcpy(&u.info26.password.data[516], confounder, 16);
834 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
836 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
837 "SetUserInfo failed");
838 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
839 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
840 s.in.level, nt_errstr(s.out.result));
841 ret = false;
842 } else {
843 *password = newpass;
846 return ret;
849 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
850 struct policy_handle *handle, uint32_t fields_present,
851 char **password)
853 NTSTATUS status;
854 struct samr_SetUserInfo s;
855 union samr_UserInfo u;
856 bool ret = true;
857 DATA_BLOB session_key;
858 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
859 struct MD5Context ctx;
860 uint8_t confounder[16];
861 char *newpass;
862 struct dcerpc_binding_handle *b = p->binding_handle;
863 struct samr_GetUserPwInfo pwp;
864 struct samr_PwInfo info;
865 int policy_min_pw_len = 0;
866 pwp.in.user_handle = handle;
867 pwp.out.info = &info;
869 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
870 "GetUserPwInfo failed");
871 if (NT_STATUS_IS_OK(pwp.out.result)) {
872 policy_min_pw_len = pwp.out.info->min_password_length;
874 newpass = samr_rand_pass(tctx, policy_min_pw_len);
876 s.in.user_handle = handle;
877 s.in.info = &u;
878 s.in.level = 25;
880 ZERO_STRUCT(u);
882 u.info25.info.fields_present = fields_present;
884 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
886 status = dcerpc_fetch_session_key(p, &session_key);
887 if (!NT_STATUS_IS_OK(status)) {
888 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
889 s.in.level, nt_errstr(status));
890 return false;
893 generate_random_buffer((uint8_t *)confounder, 16);
895 MD5Init(&ctx);
896 MD5Update(&ctx, confounder, 16);
897 MD5Update(&ctx, session_key.data, session_key.length);
898 MD5Final(confounded_session_key.data, &ctx);
900 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
901 memcpy(&u.info25.password.data[516], confounder, 16);
903 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
905 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
906 "SetUserInfo failed");
907 if (!NT_STATUS_IS_OK(s.out.result)) {
908 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
909 s.in.level, nt_errstr(s.out.result));
910 ret = false;
911 } else {
912 *password = newpass;
915 /* This should break the key nicely */
916 confounded_session_key.data[0]++;
918 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
919 memcpy(&u.info25.password.data[516], confounder, 16);
921 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
923 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
924 "SetUserInfo failed");
925 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
926 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
927 s.in.level, nt_errstr(s.out.result));
928 ret = false;
931 return ret;
934 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
935 struct policy_handle *handle, char **password)
937 NTSTATUS status;
938 struct samr_SetUserInfo s;
939 union samr_UserInfo u;
940 bool ret = true;
941 DATA_BLOB session_key;
942 char *newpass;
943 struct dcerpc_binding_handle *b = p->binding_handle;
944 struct samr_GetUserPwInfo pwp;
945 struct samr_PwInfo info;
946 int policy_min_pw_len = 0;
947 uint8_t lm_hash[16], nt_hash[16];
949 pwp.in.user_handle = handle;
950 pwp.out.info = &info;
952 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
953 "GetUserPwInfo failed");
954 if (NT_STATUS_IS_OK(pwp.out.result)) {
955 policy_min_pw_len = pwp.out.info->min_password_length;
957 newpass = samr_rand_pass(tctx, policy_min_pw_len);
959 s.in.user_handle = handle;
960 s.in.info = &u;
961 s.in.level = 18;
963 ZERO_STRUCT(u);
965 u.info18.nt_pwd_active = true;
966 u.info18.lm_pwd_active = true;
968 E_md4hash(newpass, nt_hash);
969 E_deshash(newpass, lm_hash);
971 status = dcerpc_fetch_session_key(p, &session_key);
972 if (!NT_STATUS_IS_OK(status)) {
973 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
974 s.in.level, nt_errstr(status));
975 return false;
979 DATA_BLOB in,out;
980 in = data_blob_const(nt_hash, 16);
981 out = data_blob_talloc_zero(tctx, 16);
982 sess_crypt_blob(&out, &in, &session_key, true);
983 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
986 DATA_BLOB in,out;
987 in = data_blob_const(lm_hash, 16);
988 out = data_blob_talloc_zero(tctx, 16);
989 sess_crypt_blob(&out, &in, &session_key, true);
990 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
993 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
995 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
996 "SetUserInfo failed");
997 if (!NT_STATUS_IS_OK(s.out.result)) {
998 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
999 s.in.level, nt_errstr(s.out.result));
1000 ret = false;
1001 } else {
1002 *password = newpass;
1005 return ret;
1008 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1009 struct policy_handle *handle, uint32_t fields_present,
1010 char **password)
1012 NTSTATUS status;
1013 struct samr_SetUserInfo s;
1014 union samr_UserInfo u;
1015 bool ret = true;
1016 DATA_BLOB session_key;
1017 char *newpass;
1018 struct dcerpc_binding_handle *b = p->binding_handle;
1019 struct samr_GetUserPwInfo pwp;
1020 struct samr_PwInfo info;
1021 int policy_min_pw_len = 0;
1022 uint8_t lm_hash[16], nt_hash[16];
1024 pwp.in.user_handle = handle;
1025 pwp.out.info = &info;
1027 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1028 "GetUserPwInfo failed");
1029 if (NT_STATUS_IS_OK(pwp.out.result)) {
1030 policy_min_pw_len = pwp.out.info->min_password_length;
1032 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1034 s.in.user_handle = handle;
1035 s.in.info = &u;
1036 s.in.level = 21;
1038 E_md4hash(newpass, nt_hash);
1039 E_deshash(newpass, lm_hash);
1041 ZERO_STRUCT(u);
1043 u.info21.fields_present = fields_present;
1045 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1046 u.info21.lm_owf_password.length = 16;
1047 u.info21.lm_owf_password.size = 16;
1048 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1049 u.info21.lm_password_set = true;
1052 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1053 u.info21.nt_owf_password.length = 16;
1054 u.info21.nt_owf_password.size = 16;
1055 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1056 u.info21.nt_password_set = true;
1059 status = dcerpc_fetch_session_key(p, &session_key);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1062 s.in.level, nt_errstr(status));
1063 return false;
1066 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1067 DATA_BLOB in,out;
1068 in = data_blob_const(u.info21.lm_owf_password.array,
1069 u.info21.lm_owf_password.length);
1070 out = data_blob_talloc_zero(tctx, 16);
1071 sess_crypt_blob(&out, &in, &session_key, true);
1072 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1075 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1076 DATA_BLOB in,out;
1077 in = data_blob_const(u.info21.nt_owf_password.array,
1078 u.info21.nt_owf_password.length);
1079 out = data_blob_talloc_zero(tctx, 16);
1080 sess_crypt_blob(&out, &in, &session_key, true);
1081 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1084 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1086 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1087 "SetUserInfo failed");
1088 if (!NT_STATUS_IS_OK(s.out.result)) {
1089 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1090 s.in.level, nt_errstr(s.out.result));
1091 ret = false;
1092 } else {
1093 *password = newpass;
1096 /* try invalid length */
1097 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1099 u.info21.nt_owf_password.length++;
1101 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1102 "SetUserInfo failed");
1103 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1104 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1105 s.in.level, nt_errstr(s.out.result));
1106 ret = false;
1110 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1112 u.info21.lm_owf_password.length++;
1114 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1115 "SetUserInfo failed");
1116 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1117 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1118 s.in.level, nt_errstr(s.out.result));
1119 ret = false;
1123 return ret;
1126 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1127 struct torture_context *tctx,
1128 struct policy_handle *handle,
1129 uint16_t level,
1130 uint32_t fields_present,
1131 char **password, uint8_t password_expired,
1132 bool use_setinfo2,
1133 bool *matched_expected_error)
1135 NTSTATUS status;
1136 NTSTATUS expected_error = NT_STATUS_OK;
1137 struct samr_SetUserInfo s;
1138 struct samr_SetUserInfo2 s2;
1139 union samr_UserInfo u;
1140 bool ret = true;
1141 DATA_BLOB session_key;
1142 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1143 struct MD5Context ctx;
1144 uint8_t confounder[16];
1145 char *newpass;
1146 struct dcerpc_binding_handle *b = p->binding_handle;
1147 struct samr_GetUserPwInfo pwp;
1148 struct samr_PwInfo info;
1149 int policy_min_pw_len = 0;
1150 const char *comment = NULL;
1151 uint8_t lm_hash[16], nt_hash[16];
1153 pwp.in.user_handle = handle;
1154 pwp.out.info = &info;
1156 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1157 "GetUserPwInfo failed");
1158 if (NT_STATUS_IS_OK(pwp.out.result)) {
1159 policy_min_pw_len = pwp.out.info->min_password_length;
1161 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1163 if (use_setinfo2) {
1164 s2.in.user_handle = handle;
1165 s2.in.info = &u;
1166 s2.in.level = level;
1167 } else {
1168 s.in.user_handle = handle;
1169 s.in.info = &u;
1170 s.in.level = level;
1173 if (fields_present & SAMR_FIELD_COMMENT) {
1174 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1177 ZERO_STRUCT(u);
1179 switch (level) {
1180 case 18:
1181 E_md4hash(newpass, nt_hash);
1182 E_deshash(newpass, lm_hash);
1184 u.info18.nt_pwd_active = true;
1185 u.info18.lm_pwd_active = true;
1186 u.info18.password_expired = password_expired;
1188 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1189 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1191 break;
1192 case 21:
1193 E_md4hash(newpass, nt_hash);
1194 E_deshash(newpass, lm_hash);
1196 u.info21.fields_present = fields_present;
1197 u.info21.password_expired = password_expired;
1198 u.info21.comment.string = comment;
1200 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1201 u.info21.lm_owf_password.length = 16;
1202 u.info21.lm_owf_password.size = 16;
1203 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1204 u.info21.lm_password_set = true;
1207 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1208 u.info21.nt_owf_password.length = 16;
1209 u.info21.nt_owf_password.size = 16;
1210 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1211 u.info21.nt_password_set = true;
1214 break;
1215 case 23:
1216 u.info23.info.fields_present = fields_present;
1217 u.info23.info.password_expired = password_expired;
1218 u.info23.info.comment.string = comment;
1220 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1222 break;
1223 case 24:
1224 u.info24.password_expired = password_expired;
1226 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1228 break;
1229 case 25:
1230 u.info25.info.fields_present = fields_present;
1231 u.info25.info.password_expired = password_expired;
1232 u.info25.info.comment.string = comment;
1234 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1236 break;
1237 case 26:
1238 u.info26.password_expired = password_expired;
1240 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1242 break;
1245 status = dcerpc_fetch_session_key(p, &session_key);
1246 if (!NT_STATUS_IS_OK(status)) {
1247 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1248 s.in.level, nt_errstr(status));
1249 return false;
1252 generate_random_buffer((uint8_t *)confounder, 16);
1254 MD5Init(&ctx);
1255 MD5Update(&ctx, confounder, 16);
1256 MD5Update(&ctx, session_key.data, session_key.length);
1257 MD5Final(confounded_session_key.data, &ctx);
1259 switch (level) {
1260 case 18:
1262 DATA_BLOB in,out;
1263 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1264 out = data_blob_talloc_zero(tctx, 16);
1265 sess_crypt_blob(&out, &in, &session_key, true);
1266 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1269 DATA_BLOB in,out;
1270 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1271 out = data_blob_talloc_zero(tctx, 16);
1272 sess_crypt_blob(&out, &in, &session_key, true);
1273 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1276 break;
1277 case 21:
1278 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1279 DATA_BLOB in,out;
1280 in = data_blob_const(u.info21.lm_owf_password.array,
1281 u.info21.lm_owf_password.length);
1282 out = data_blob_talloc_zero(tctx, 16);
1283 sess_crypt_blob(&out, &in, &session_key, true);
1284 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1286 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1287 DATA_BLOB in,out;
1288 in = data_blob_const(u.info21.nt_owf_password.array,
1289 u.info21.nt_owf_password.length);
1290 out = data_blob_talloc_zero(tctx, 16);
1291 sess_crypt_blob(&out, &in, &session_key, true);
1292 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1294 break;
1295 case 23:
1296 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1297 break;
1298 case 24:
1299 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1300 break;
1301 case 25:
1302 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1303 memcpy(&u.info25.password.data[516], confounder, 16);
1304 break;
1305 case 26:
1306 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1307 memcpy(&u.info26.password.data[516], confounder, 16);
1308 break;
1311 if (use_setinfo2) {
1312 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1313 "SetUserInfo2 failed");
1314 status = s2.out.result;
1315 } else {
1316 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1317 "SetUserInfo failed");
1318 status = s.out.result;
1321 if (!NT_STATUS_IS_OK(status)) {
1322 if (fields_present == 0) {
1323 expected_error = NT_STATUS_INVALID_PARAMETER;
1325 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1326 expected_error = NT_STATUS_ACCESS_DENIED;
1330 if (!NT_STATUS_IS_OK(expected_error)) {
1331 if (use_setinfo2) {
1332 torture_assert_ntstatus_equal(tctx,
1333 s2.out.result,
1334 expected_error, "SetUserInfo2 failed");
1335 } else {
1336 torture_assert_ntstatus_equal(tctx,
1337 s.out.result,
1338 expected_error, "SetUserInfo failed");
1340 *matched_expected_error = true;
1341 return true;
1344 if (!NT_STATUS_IS_OK(status)) {
1345 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1346 use_setinfo2 ? "2":"", level, nt_errstr(status));
1347 ret = false;
1348 } else {
1349 *password = newpass;
1352 return ret;
1355 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1356 struct torture_context *tctx,
1357 struct policy_handle *handle)
1359 struct samr_SetAliasInfo r;
1360 struct samr_QueryAliasInfo q;
1361 union samr_AliasInfo *info;
1362 uint16_t levels[] = {2, 3};
1363 int i;
1364 bool ret = true;
1366 /* Ignoring switch level 1, as that includes the number of members for the alias
1367 * and setting this to a wrong value might have negative consequences
1370 for (i=0;i<ARRAY_SIZE(levels);i++) {
1371 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1373 r.in.alias_handle = handle;
1374 r.in.level = levels[i];
1375 r.in.info = talloc(tctx, union samr_AliasInfo);
1376 switch (r.in.level) {
1377 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1378 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1379 "Test Description, should test I18N as well"); break;
1380 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1383 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1384 "SetAliasInfo failed");
1385 if (!NT_STATUS_IS_OK(r.out.result)) {
1386 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1387 levels[i], nt_errstr(r.out.result));
1388 ret = false;
1391 q.in.alias_handle = handle;
1392 q.in.level = levels[i];
1393 q.out.info = &info;
1395 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1396 "QueryAliasInfo failed");
1397 if (!NT_STATUS_IS_OK(q.out.result)) {
1398 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1399 levels[i], nt_errstr(q.out.result));
1400 ret = false;
1404 return ret;
1407 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1408 struct torture_context *tctx,
1409 struct policy_handle *user_handle)
1411 struct samr_GetGroupsForUser r;
1412 struct samr_RidWithAttributeArray *rids = NULL;
1414 torture_comment(tctx, "Testing GetGroupsForUser\n");
1416 r.in.user_handle = user_handle;
1417 r.out.rids = &rids;
1419 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1420 "GetGroupsForUser failed");
1421 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1423 return true;
1427 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1428 struct lsa_String *domain_name)
1430 struct samr_GetDomPwInfo r;
1431 struct samr_PwInfo info;
1432 struct dcerpc_binding_handle *b = p->binding_handle;
1434 r.in.domain_name = domain_name;
1435 r.out.info = &info;
1437 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1439 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1440 "GetDomPwInfo failed");
1441 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1443 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1444 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1446 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1447 "GetDomPwInfo failed");
1448 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1450 r.in.domain_name->string = "\\\\__NONAME__";
1451 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1453 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1454 "GetDomPwInfo failed");
1455 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1457 r.in.domain_name->string = "\\\\Builtin";
1458 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1460 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1461 "GetDomPwInfo failed");
1462 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1464 return true;
1467 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1468 struct torture_context *tctx,
1469 struct policy_handle *handle)
1471 struct samr_GetUserPwInfo r;
1472 struct samr_PwInfo info;
1474 torture_comment(tctx, "Testing GetUserPwInfo\n");
1476 r.in.user_handle = handle;
1477 r.out.info = &info;
1479 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1480 "GetUserPwInfo failed");
1481 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1483 return true;
1486 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1487 struct torture_context *tctx,
1488 struct policy_handle *domain_handle, const char *name,
1489 uint32_t *rid)
1491 NTSTATUS status;
1492 struct samr_LookupNames n;
1493 struct lsa_String sname[2];
1494 struct samr_Ids rids, types;
1496 init_lsa_String(&sname[0], name);
1498 n.in.domain_handle = domain_handle;
1499 n.in.num_names = 1;
1500 n.in.names = sname;
1501 n.out.rids = &rids;
1502 n.out.types = &types;
1503 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 return status;
1507 if (NT_STATUS_IS_OK(n.out.result)) {
1508 *rid = n.out.rids->ids[0];
1509 } else {
1510 return n.out.result;
1513 init_lsa_String(&sname[1], "xxNONAMExx");
1514 n.in.num_names = 2;
1515 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 return status;
1519 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1520 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1521 if (NT_STATUS_IS_OK(n.out.result)) {
1522 return NT_STATUS_UNSUCCESSFUL;
1524 return n.out.result;
1527 n.in.num_names = 0;
1528 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 return status;
1532 if (!NT_STATUS_IS_OK(n.out.result)) {
1533 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1534 return n.out.result;
1537 init_lsa_String(&sname[0], "xxNONAMExx");
1538 n.in.num_names = 1;
1539 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 return status;
1543 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1544 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1545 if (NT_STATUS_IS_OK(n.out.result)) {
1546 return NT_STATUS_UNSUCCESSFUL;
1548 return n.out.result;
1551 init_lsa_String(&sname[0], "xxNONAMExx");
1552 init_lsa_String(&sname[1], "xxNONAME2xx");
1553 n.in.num_names = 2;
1554 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 return status;
1558 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1559 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1560 if (NT_STATUS_IS_OK(n.out.result)) {
1561 return NT_STATUS_UNSUCCESSFUL;
1563 return n.out.result;
1566 return NT_STATUS_OK;
1569 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1570 struct torture_context *tctx,
1571 struct policy_handle *domain_handle,
1572 const char *name, struct policy_handle *user_handle)
1574 NTSTATUS status;
1575 struct samr_OpenUser r;
1576 uint32_t rid;
1578 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 return status;
1583 r.in.domain_handle = domain_handle;
1584 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1585 r.in.rid = rid;
1586 r.out.user_handle = user_handle;
1587 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 return status;
1591 if (!NT_STATUS_IS_OK(r.out.result)) {
1592 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1595 return r.out.result;
1598 #if 0
1599 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1600 struct torture_context *tctx,
1601 struct policy_handle *handle)
1603 NTSTATUS status;
1604 struct samr_ChangePasswordUser r;
1605 bool ret = true;
1606 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1607 struct policy_handle user_handle;
1608 char *oldpass = "test";
1609 char *newpass = "test2";
1610 uint8_t old_nt_hash[16], new_nt_hash[16];
1611 uint8_t old_lm_hash[16], new_lm_hash[16];
1613 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 return false;
1618 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1620 torture_comment(tctx, "old password: %s\n", oldpass);
1621 torture_comment(tctx, "new password: %s\n", newpass);
1623 E_md4hash(oldpass, old_nt_hash);
1624 E_md4hash(newpass, new_nt_hash);
1625 E_deshash(oldpass, old_lm_hash);
1626 E_deshash(newpass, new_lm_hash);
1628 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1629 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1630 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1631 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1632 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1633 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1635 r.in.handle = &user_handle;
1636 r.in.lm_present = 1;
1637 r.in.old_lm_crypted = &hash1;
1638 r.in.new_lm_crypted = &hash2;
1639 r.in.nt_present = 1;
1640 r.in.old_nt_crypted = &hash3;
1641 r.in.new_nt_crypted = &hash4;
1642 r.in.cross1_present = 1;
1643 r.in.nt_cross = &hash5;
1644 r.in.cross2_present = 1;
1645 r.in.lm_cross = &hash6;
1647 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1648 "ChangePasswordUser failed");
1649 if (!NT_STATUS_IS_OK(r.out.result)) {
1650 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1651 ret = false;
1654 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1655 ret = false;
1658 return ret;
1660 #endif
1662 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1663 struct torture_context *tctx,
1664 const char *acct_name,
1665 struct policy_handle *handle, char **password)
1667 NTSTATUS status;
1668 struct samr_ChangePasswordUser r;
1669 bool ret = true;
1670 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1671 struct policy_handle user_handle;
1672 char *oldpass;
1673 uint8_t old_nt_hash[16], new_nt_hash[16];
1674 uint8_t old_lm_hash[16], new_lm_hash[16];
1675 bool changed = true;
1677 char *newpass;
1678 struct samr_GetUserPwInfo pwp;
1679 struct samr_PwInfo info;
1680 int policy_min_pw_len = 0;
1682 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 return false;
1686 pwp.in.user_handle = &user_handle;
1687 pwp.out.info = &info;
1689 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1690 "GetUserPwInfo failed");
1691 if (NT_STATUS_IS_OK(pwp.out.result)) {
1692 policy_min_pw_len = pwp.out.info->min_password_length;
1694 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1696 torture_comment(tctx, "Testing ChangePasswordUser\n");
1698 torture_assert(tctx, *password != NULL,
1699 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1701 oldpass = *password;
1703 E_md4hash(oldpass, old_nt_hash);
1704 E_md4hash(newpass, new_nt_hash);
1705 E_deshash(oldpass, old_lm_hash);
1706 E_deshash(newpass, new_lm_hash);
1708 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1709 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1710 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1711 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1712 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1713 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1715 r.in.user_handle = &user_handle;
1716 r.in.lm_present = 1;
1717 /* Break the LM hash */
1718 hash1.hash[0]++;
1719 r.in.old_lm_crypted = &hash1;
1720 r.in.new_lm_crypted = &hash2;
1721 r.in.nt_present = 1;
1722 r.in.old_nt_crypted = &hash3;
1723 r.in.new_nt_crypted = &hash4;
1724 r.in.cross1_present = 1;
1725 r.in.nt_cross = &hash5;
1726 r.in.cross2_present = 1;
1727 r.in.lm_cross = &hash6;
1729 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1730 "ChangePasswordUser failed");
1731 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1732 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1734 /* Unbreak the LM hash */
1735 hash1.hash[0]--;
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 /* Break the NT hash */
1742 hash3.hash[0]--;
1743 r.in.nt_present = 1;
1744 r.in.old_nt_crypted = &hash3;
1745 r.in.new_nt_crypted = &hash4;
1746 r.in.cross1_present = 1;
1747 r.in.nt_cross = &hash5;
1748 r.in.cross2_present = 1;
1749 r.in.lm_cross = &hash6;
1751 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1752 "ChangePasswordUser failed");
1753 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1754 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1756 /* Unbreak the NT hash */
1757 hash3.hash[0]--;
1759 r.in.user_handle = &user_handle;
1760 r.in.lm_present = 1;
1761 r.in.old_lm_crypted = &hash1;
1762 r.in.new_lm_crypted = &hash2;
1763 r.in.nt_present = 1;
1764 r.in.old_nt_crypted = &hash3;
1765 r.in.new_nt_crypted = &hash4;
1766 r.in.cross1_present = 1;
1767 r.in.nt_cross = &hash5;
1768 r.in.cross2_present = 1;
1769 /* Break the LM cross */
1770 hash6.hash[0]++;
1771 r.in.lm_cross = &hash6;
1773 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1774 "ChangePasswordUser failed");
1775 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1776 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1777 ret = false;
1780 /* Unbreak the LM cross */
1781 hash6.hash[0]--;
1783 r.in.user_handle = &user_handle;
1784 r.in.lm_present = 1;
1785 r.in.old_lm_crypted = &hash1;
1786 r.in.new_lm_crypted = &hash2;
1787 r.in.nt_present = 1;
1788 r.in.old_nt_crypted = &hash3;
1789 r.in.new_nt_crypted = &hash4;
1790 r.in.cross1_present = 1;
1791 /* Break the NT cross */
1792 hash5.hash[0]++;
1793 r.in.nt_cross = &hash5;
1794 r.in.cross2_present = 1;
1795 r.in.lm_cross = &hash6;
1797 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1798 "ChangePasswordUser failed");
1799 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1800 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1801 ret = false;
1804 /* Unbreak the NT cross */
1805 hash5.hash[0]--;
1808 /* Reset the hashes to not broken values */
1809 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1810 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1811 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1812 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1813 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1814 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1816 r.in.user_handle = &user_handle;
1817 r.in.lm_present = 1;
1818 r.in.old_lm_crypted = &hash1;
1819 r.in.new_lm_crypted = &hash2;
1820 r.in.nt_present = 1;
1821 r.in.old_nt_crypted = &hash3;
1822 r.in.new_nt_crypted = &hash4;
1823 r.in.cross1_present = 1;
1824 r.in.nt_cross = &hash5;
1825 r.in.cross2_present = 0;
1826 r.in.lm_cross = NULL;
1828 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1829 "ChangePasswordUser failed");
1830 if (NT_STATUS_IS_OK(r.out.result)) {
1831 changed = true;
1832 *password = newpass;
1833 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1834 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1835 ret = false;
1838 oldpass = newpass;
1839 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1841 E_md4hash(oldpass, old_nt_hash);
1842 E_md4hash(newpass, new_nt_hash);
1843 E_deshash(oldpass, old_lm_hash);
1844 E_deshash(newpass, new_lm_hash);
1847 /* Reset the hashes to not broken values */
1848 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1849 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1850 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1851 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1852 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1853 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1855 r.in.user_handle = &user_handle;
1856 r.in.lm_present = 1;
1857 r.in.old_lm_crypted = &hash1;
1858 r.in.new_lm_crypted = &hash2;
1859 r.in.nt_present = 1;
1860 r.in.old_nt_crypted = &hash3;
1861 r.in.new_nt_crypted = &hash4;
1862 r.in.cross1_present = 0;
1863 r.in.nt_cross = NULL;
1864 r.in.cross2_present = 1;
1865 r.in.lm_cross = &hash6;
1867 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1868 "ChangePasswordUser failed");
1869 if (NT_STATUS_IS_OK(r.out.result)) {
1870 changed = true;
1871 *password = newpass;
1872 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1873 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1874 ret = false;
1877 oldpass = newpass;
1878 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1880 E_md4hash(oldpass, old_nt_hash);
1881 E_md4hash(newpass, new_nt_hash);
1882 E_deshash(oldpass, old_lm_hash);
1883 E_deshash(newpass, new_lm_hash);
1886 /* Reset the hashes to not broken values */
1887 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1888 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1889 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1890 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1891 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1892 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1894 r.in.user_handle = &user_handle;
1895 r.in.lm_present = 1;
1896 r.in.old_lm_crypted = &hash1;
1897 r.in.new_lm_crypted = &hash2;
1898 r.in.nt_present = 1;
1899 r.in.old_nt_crypted = &hash3;
1900 r.in.new_nt_crypted = &hash4;
1901 r.in.cross1_present = 1;
1902 r.in.nt_cross = &hash5;
1903 r.in.cross2_present = 1;
1904 r.in.lm_cross = &hash6;
1906 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1907 "ChangePasswordUser failed");
1908 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1909 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1910 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1911 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1912 ret = false;
1913 } else {
1914 changed = true;
1915 *password = newpass;
1918 r.in.user_handle = &user_handle;
1919 r.in.lm_present = 1;
1920 r.in.old_lm_crypted = &hash1;
1921 r.in.new_lm_crypted = &hash2;
1922 r.in.nt_present = 1;
1923 r.in.old_nt_crypted = &hash3;
1924 r.in.new_nt_crypted = &hash4;
1925 r.in.cross1_present = 1;
1926 r.in.nt_cross = &hash5;
1927 r.in.cross2_present = 1;
1928 r.in.lm_cross = &hash6;
1930 if (changed) {
1931 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1932 "ChangePasswordUser failed");
1933 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1934 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1935 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1936 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1937 ret = false;
1942 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1943 ret = false;
1946 return ret;
1950 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
1951 struct torture_context *tctx,
1952 const char *acct_name,
1953 struct policy_handle *handle, char **password)
1955 struct samr_OemChangePasswordUser2 r;
1956 bool ret = true;
1957 struct samr_Password lm_verifier;
1958 struct samr_CryptPassword lm_pass;
1959 struct lsa_AsciiString server, account, account_bad;
1960 char *oldpass;
1961 char *newpass;
1962 struct dcerpc_binding_handle *b = p->binding_handle;
1963 uint8_t old_lm_hash[16], new_lm_hash[16];
1965 struct samr_GetDomPwInfo dom_pw_info;
1966 struct samr_PwInfo info;
1967 int policy_min_pw_len = 0;
1969 struct lsa_String domain_name;
1971 domain_name.string = "";
1972 dom_pw_info.in.domain_name = &domain_name;
1973 dom_pw_info.out.info = &info;
1975 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1977 torture_assert(tctx, *password != NULL,
1978 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1980 oldpass = *password;
1982 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
1983 "GetDomPwInfo failed");
1984 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
1985 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1988 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1990 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1991 account.string = acct_name;
1993 E_deshash(oldpass, old_lm_hash);
1994 E_deshash(newpass, new_lm_hash);
1996 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1997 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1998 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2000 r.in.server = &server;
2001 r.in.account = &account;
2002 r.in.password = &lm_pass;
2003 r.in.hash = &lm_verifier;
2005 /* Break the verification */
2006 lm_verifier.hash[0]++;
2008 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2009 "OemChangePasswordUser2 failed");
2011 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2012 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2013 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2014 nt_errstr(r.out.result));
2015 ret = false;
2018 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2019 /* Break the old password */
2020 old_lm_hash[0]++;
2021 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2022 /* unbreak it for the next operation */
2023 old_lm_hash[0]--;
2024 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2026 r.in.server = &server;
2027 r.in.account = &account;
2028 r.in.password = &lm_pass;
2029 r.in.hash = &lm_verifier;
2031 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2032 "OemChangePasswordUser2 failed");
2034 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2035 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2036 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2037 nt_errstr(r.out.result));
2038 ret = false;
2041 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2042 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2044 r.in.server = &server;
2045 r.in.account = &account;
2046 r.in.password = &lm_pass;
2047 r.in.hash = NULL;
2049 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2050 "OemChangePasswordUser2 failed");
2052 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2053 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2054 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2055 nt_errstr(r.out.result));
2056 ret = false;
2059 /* This shouldn't be a valid name */
2060 account_bad.string = TEST_ACCOUNT_NAME "XX";
2061 r.in.account = &account_bad;
2063 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2064 "OemChangePasswordUser2 failed");
2066 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2067 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2068 nt_errstr(r.out.result));
2069 ret = false;
2072 /* This shouldn't be a valid name */
2073 account_bad.string = TEST_ACCOUNT_NAME "XX";
2074 r.in.account = &account_bad;
2075 r.in.password = &lm_pass;
2076 r.in.hash = &lm_verifier;
2078 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2079 "OemChangePasswordUser2 failed");
2081 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2082 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2083 nt_errstr(r.out.result));
2084 ret = false;
2087 /* This shouldn't be a valid name */
2088 account_bad.string = TEST_ACCOUNT_NAME "XX";
2089 r.in.account = &account_bad;
2090 r.in.password = NULL;
2091 r.in.hash = &lm_verifier;
2093 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2094 "OemChangePasswordUser2 failed");
2096 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2097 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2098 nt_errstr(r.out.result));
2099 ret = false;
2102 E_deshash(oldpass, old_lm_hash);
2103 E_deshash(newpass, new_lm_hash);
2105 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2106 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2107 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2109 r.in.server = &server;
2110 r.in.account = &account;
2111 r.in.password = &lm_pass;
2112 r.in.hash = &lm_verifier;
2114 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2115 "OemChangePasswordUser2 failed");
2117 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2118 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2119 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2120 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2121 ret = false;
2122 } else {
2123 *password = newpass;
2126 return ret;
2130 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2131 const char *acct_name,
2132 char **password,
2133 char *newpass, bool allow_password_restriction)
2135 struct samr_ChangePasswordUser2 r;
2136 bool ret = true;
2137 struct lsa_String server, account;
2138 struct samr_CryptPassword nt_pass, lm_pass;
2139 struct samr_Password nt_verifier, lm_verifier;
2140 char *oldpass;
2141 struct dcerpc_binding_handle *b = p->binding_handle;
2142 uint8_t old_nt_hash[16], new_nt_hash[16];
2143 uint8_t old_lm_hash[16], new_lm_hash[16];
2145 struct samr_GetDomPwInfo dom_pw_info;
2146 struct samr_PwInfo info;
2148 struct lsa_String domain_name;
2150 domain_name.string = "";
2151 dom_pw_info.in.domain_name = &domain_name;
2152 dom_pw_info.out.info = &info;
2154 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2156 torture_assert(tctx, *password != NULL,
2157 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2158 oldpass = *password;
2160 if (!newpass) {
2161 int policy_min_pw_len = 0;
2162 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2163 "GetDomPwInfo failed");
2164 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2165 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2168 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2171 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2172 init_lsa_String(&account, acct_name);
2174 E_md4hash(oldpass, old_nt_hash);
2175 E_md4hash(newpass, new_nt_hash);
2177 E_deshash(oldpass, old_lm_hash);
2178 E_deshash(newpass, new_lm_hash);
2180 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2181 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2182 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2184 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2185 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2186 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2188 r.in.server = &server;
2189 r.in.account = &account;
2190 r.in.nt_password = &nt_pass;
2191 r.in.nt_verifier = &nt_verifier;
2192 r.in.lm_change = 1;
2193 r.in.lm_password = &lm_pass;
2194 r.in.lm_verifier = &lm_verifier;
2196 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2197 "ChangePasswordUser2 failed");
2199 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2200 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2201 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2202 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2203 ret = false;
2204 } else {
2205 *password = newpass;
2208 return ret;
2212 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2213 const char *account_string,
2214 int policy_min_pw_len,
2215 char **password,
2216 const char *newpass,
2217 NTTIME last_password_change,
2218 bool handle_reject_reason)
2220 struct samr_ChangePasswordUser3 r;
2221 bool ret = true;
2222 struct lsa_String server, account, account_bad;
2223 struct samr_CryptPassword nt_pass, lm_pass;
2224 struct samr_Password nt_verifier, lm_verifier;
2225 char *oldpass;
2226 struct dcerpc_binding_handle *b = p->binding_handle;
2227 uint8_t old_nt_hash[16], new_nt_hash[16];
2228 uint8_t old_lm_hash[16], new_lm_hash[16];
2229 NTTIME t;
2230 struct samr_DomInfo1 *dominfo = NULL;
2231 struct userPwdChangeFailureInformation *reject = NULL;
2233 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2235 if (newpass == NULL) {
2236 do {
2237 if (policy_min_pw_len == 0) {
2238 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2239 } else {
2240 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2242 } while (check_password_quality(newpass) == false);
2243 } else {
2244 torture_comment(tctx, "Using password '%s'\n", newpass);
2247 torture_assert(tctx, *password != NULL,
2248 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2250 oldpass = *password;
2251 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2252 init_lsa_String(&account, account_string);
2254 E_md4hash(oldpass, old_nt_hash);
2255 E_md4hash(newpass, new_nt_hash);
2257 E_deshash(oldpass, old_lm_hash);
2258 E_deshash(newpass, new_lm_hash);
2260 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2261 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2262 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2264 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2265 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2266 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2268 /* Break the verification */
2269 nt_verifier.hash[0]++;
2271 r.in.server = &server;
2272 r.in.account = &account;
2273 r.in.nt_password = &nt_pass;
2274 r.in.nt_verifier = &nt_verifier;
2275 r.in.lm_change = 1;
2276 r.in.lm_password = &lm_pass;
2277 r.in.lm_verifier = &lm_verifier;
2278 r.in.password3 = NULL;
2279 r.out.dominfo = &dominfo;
2280 r.out.reject = &reject;
2282 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2283 "ChangePasswordUser3 failed");
2284 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2285 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2286 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2287 nt_errstr(r.out.result));
2288 ret = false;
2291 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2292 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2293 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2295 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2296 /* Break the NT hash */
2297 old_nt_hash[0]++;
2298 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2299 /* Unbreak it again */
2300 old_nt_hash[0]--;
2301 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2303 r.in.server = &server;
2304 r.in.account = &account;
2305 r.in.nt_password = &nt_pass;
2306 r.in.nt_verifier = &nt_verifier;
2307 r.in.lm_change = 1;
2308 r.in.lm_password = &lm_pass;
2309 r.in.lm_verifier = &lm_verifier;
2310 r.in.password3 = NULL;
2311 r.out.dominfo = &dominfo;
2312 r.out.reject = &reject;
2314 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2315 "ChangePasswordUser3 failed");
2316 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2317 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2318 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2319 nt_errstr(r.out.result));
2320 ret = false;
2323 /* This shouldn't be a valid name */
2324 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2326 r.in.account = &account_bad;
2327 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2328 "ChangePasswordUser3 failed");
2329 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2330 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2331 nt_errstr(r.out.result));
2332 ret = false;
2335 E_md4hash(oldpass, old_nt_hash);
2336 E_md4hash(newpass, new_nt_hash);
2338 E_deshash(oldpass, old_lm_hash);
2339 E_deshash(newpass, new_lm_hash);
2341 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2342 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2343 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2345 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2346 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2347 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2349 r.in.server = &server;
2350 r.in.account = &account;
2351 r.in.nt_password = &nt_pass;
2352 r.in.nt_verifier = &nt_verifier;
2353 r.in.lm_change = 1;
2354 r.in.lm_password = &lm_pass;
2355 r.in.lm_verifier = &lm_verifier;
2356 r.in.password3 = NULL;
2357 r.out.dominfo = &dominfo;
2358 r.out.reject = &reject;
2360 unix_to_nt_time(&t, time(NULL));
2362 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2363 "ChangePasswordUser3 failed");
2365 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2366 && dominfo
2367 && reject
2368 && handle_reject_reason
2369 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2370 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2372 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2373 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2374 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2375 return false;
2379 /* We tested the order of precendence which is as follows:
2381 * pwd min_age
2382 * pwd length
2383 * pwd complexity
2384 * pwd history
2386 Guenther */
2388 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2389 (last_password_change + dominfo->min_password_age > t)) {
2391 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2392 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2393 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2394 return false;
2397 } else if ((dominfo->min_password_length > 0) &&
2398 (strlen(newpass) < dominfo->min_password_length)) {
2400 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2401 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2402 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2403 return false;
2406 } else if ((dominfo->password_history_length > 0) &&
2407 strequal(oldpass, newpass)) {
2409 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2410 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2411 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2412 return false;
2414 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2416 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2417 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2418 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2419 return false;
2424 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2425 /* retry with adjusted size */
2426 return test_ChangePasswordUser3(p, tctx, account_string,
2427 dominfo->min_password_length,
2428 password, NULL, 0, false);
2432 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2433 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2434 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2435 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2436 return false;
2438 /* Perhaps the server has a 'min password age' set? */
2440 } else {
2441 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2443 *password = talloc_strdup(tctx, newpass);
2446 return ret;
2449 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2450 const char *account_string,
2451 struct policy_handle *handle,
2452 char **password)
2454 NTSTATUS status;
2455 struct samr_ChangePasswordUser3 r;
2456 struct samr_SetUserInfo s;
2457 union samr_UserInfo u;
2458 DATA_BLOB session_key;
2459 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2460 uint8_t confounder[16];
2461 struct MD5Context ctx;
2463 bool ret = true;
2464 struct lsa_String server, account;
2465 struct samr_CryptPassword nt_pass;
2466 struct samr_Password nt_verifier;
2467 DATA_BLOB new_random_pass;
2468 char *newpass;
2469 char *oldpass;
2470 struct dcerpc_binding_handle *b = p->binding_handle;
2471 uint8_t old_nt_hash[16], new_nt_hash[16];
2472 NTTIME t;
2473 struct samr_DomInfo1 *dominfo = NULL;
2474 struct userPwdChangeFailureInformation *reject = NULL;
2476 new_random_pass = samr_very_rand_pass(tctx, 128);
2478 torture_assert(tctx, *password != NULL,
2479 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2481 oldpass = *password;
2482 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2483 init_lsa_String(&account, account_string);
2485 s.in.user_handle = handle;
2486 s.in.info = &u;
2487 s.in.level = 25;
2489 ZERO_STRUCT(u);
2491 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2493 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2495 status = dcerpc_fetch_session_key(p, &session_key);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2498 s.in.level, nt_errstr(status));
2499 return false;
2502 generate_random_buffer((uint8_t *)confounder, 16);
2504 MD5Init(&ctx);
2505 MD5Update(&ctx, confounder, 16);
2506 MD5Update(&ctx, session_key.data, session_key.length);
2507 MD5Final(confounded_session_key.data, &ctx);
2509 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2510 memcpy(&u.info25.password.data[516], confounder, 16);
2512 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2514 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2515 "SetUserInfo failed");
2516 if (!NT_STATUS_IS_OK(s.out.result)) {
2517 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2518 s.in.level, nt_errstr(s.out.result));
2519 ret = false;
2522 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2524 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2526 new_random_pass = samr_very_rand_pass(tctx, 128);
2528 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2530 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2531 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2532 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2534 r.in.server = &server;
2535 r.in.account = &account;
2536 r.in.nt_password = &nt_pass;
2537 r.in.nt_verifier = &nt_verifier;
2538 r.in.lm_change = 0;
2539 r.in.lm_password = NULL;
2540 r.in.lm_verifier = NULL;
2541 r.in.password3 = NULL;
2542 r.out.dominfo = &dominfo;
2543 r.out.reject = &reject;
2545 unix_to_nt_time(&t, time(NULL));
2547 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2548 "ChangePasswordUser3 failed");
2550 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2551 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2552 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2553 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2554 return false;
2556 /* Perhaps the server has a 'min password age' set? */
2558 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2559 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2560 ret = false;
2563 newpass = samr_rand_pass(tctx, 128);
2565 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2567 E_md4hash(newpass, new_nt_hash);
2569 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2570 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2571 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2573 r.in.server = &server;
2574 r.in.account = &account;
2575 r.in.nt_password = &nt_pass;
2576 r.in.nt_verifier = &nt_verifier;
2577 r.in.lm_change = 0;
2578 r.in.lm_password = NULL;
2579 r.in.lm_verifier = NULL;
2580 r.in.password3 = NULL;
2581 r.out.dominfo = &dominfo;
2582 r.out.reject = &reject;
2584 unix_to_nt_time(&t, time(NULL));
2586 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2587 "ChangePasswordUser3 failed");
2589 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2590 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2591 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2592 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2593 return false;
2595 /* Perhaps the server has a 'min password age' set? */
2597 } else {
2598 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2599 *password = talloc_strdup(tctx, newpass);
2602 return ret;
2606 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2607 struct torture_context *tctx,
2608 struct policy_handle *alias_handle)
2610 struct samr_GetMembersInAlias r;
2611 struct lsa_SidArray sids;
2613 torture_comment(tctx, "Testing GetMembersInAlias\n");
2615 r.in.alias_handle = alias_handle;
2616 r.out.sids = &sids;
2618 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2619 "GetMembersInAlias failed");
2620 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2622 return true;
2625 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2626 struct torture_context *tctx,
2627 struct policy_handle *alias_handle,
2628 const struct dom_sid *domain_sid)
2630 struct samr_AddAliasMember r;
2631 struct samr_DeleteAliasMember d;
2632 struct dom_sid *sid;
2634 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2636 torture_comment(tctx, "Testing AddAliasMember\n");
2637 r.in.alias_handle = alias_handle;
2638 r.in.sid = sid;
2640 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2641 "AddAliasMember failed");
2642 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2644 d.in.alias_handle = alias_handle;
2645 d.in.sid = sid;
2647 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2648 "DeleteAliasMember failed");
2649 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2651 return true;
2654 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2655 struct torture_context *tctx,
2656 struct policy_handle *alias_handle)
2658 struct samr_AddMultipleMembersToAlias a;
2659 struct samr_RemoveMultipleMembersFromAlias r;
2660 struct lsa_SidArray sids;
2662 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2663 a.in.alias_handle = alias_handle;
2664 a.in.sids = &sids;
2666 sids.num_sids = 3;
2667 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2669 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2670 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2671 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2673 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2674 "AddMultipleMembersToAlias failed");
2675 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2678 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2679 r.in.alias_handle = alias_handle;
2680 r.in.sids = &sids;
2682 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2683 "RemoveMultipleMembersFromAlias failed");
2684 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2686 /* strange! removing twice doesn't give any error */
2687 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2688 "RemoveMultipleMembersFromAlias failed");
2689 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2691 /* but removing an alias that isn't there does */
2692 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2694 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2695 "RemoveMultipleMembersFromAlias failed");
2696 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2698 return true;
2701 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2702 struct torture_context *tctx,
2703 struct policy_handle *domain_handle)
2705 struct samr_GetAliasMembership r;
2706 struct lsa_SidArray sids;
2707 struct samr_Ids rids;
2709 torture_comment(tctx, "Testing GetAliasMembership\n");
2711 r.in.domain_handle = domain_handle;
2712 r.in.sids = &sids;
2713 r.out.rids = &rids;
2715 sids.num_sids = 0;
2716 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2718 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2719 "GetAliasMembership failed");
2720 torture_assert_ntstatus_ok(tctx, r.out.result,
2721 "samr_GetAliasMembership failed");
2723 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2724 "protocol misbehaviour");
2726 sids.num_sids = 1;
2727 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2728 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2730 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2731 "samr_GetAliasMembership failed");
2732 torture_assert_ntstatus_ok(tctx, r.out.result,
2733 "samr_GetAliasMembership failed");
2735 #if 0
2736 /* only true for w2k8 it seems
2737 * win7, xp, w2k3 will return a 0 length array pointer */
2739 if (rids.ids && (rids.count == 0)) {
2740 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2742 #endif
2743 if (!rids.ids && rids.count) {
2744 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2747 return true;
2750 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2751 struct torture_context *tctx,
2752 struct policy_handle *user_handle)
2754 struct samr_TestPrivateFunctionsUser r;
2756 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2758 r.in.user_handle = user_handle;
2760 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2761 "TestPrivateFunctionsUser failed");
2762 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2764 return true;
2767 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2768 struct torture_context *tctx,
2769 struct policy_handle *handle,
2770 bool use_info2,
2771 NTTIME *pwdlastset)
2773 NTSTATUS status;
2774 uint16_t levels[] = { /* 3, */ 5, 21 };
2775 int i;
2776 NTTIME pwdlastset3 = 0;
2777 NTTIME pwdlastset5 = 0;
2778 NTTIME pwdlastset21 = 0;
2780 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2781 use_info2 ? "2":"");
2783 for (i=0; i<ARRAY_SIZE(levels); i++) {
2785 struct samr_QueryUserInfo r;
2786 struct samr_QueryUserInfo2 r2;
2787 union samr_UserInfo *info;
2789 if (use_info2) {
2790 r2.in.user_handle = handle;
2791 r2.in.level = levels[i];
2792 r2.out.info = &info;
2793 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2794 "QueryUserInfo2 failed");
2795 status = r2.out.result;
2797 } else {
2798 r.in.user_handle = handle;
2799 r.in.level = levels[i];
2800 r.out.info = &info;
2801 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2802 "QueryUserInfo failed");
2803 status = r.out.result;
2806 if (!NT_STATUS_IS_OK(status) &&
2807 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2808 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2809 use_info2 ? "2":"", levels[i], nt_errstr(status));
2810 return false;
2813 switch (levels[i]) {
2814 case 3:
2815 pwdlastset3 = info->info3.last_password_change;
2816 break;
2817 case 5:
2818 pwdlastset5 = info->info5.last_password_change;
2819 break;
2820 case 21:
2821 pwdlastset21 = info->info21.last_password_change;
2822 break;
2823 default:
2824 return false;
2827 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2828 "pwdlastset mixup"); */
2829 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2830 "pwdlastset mixup");
2832 *pwdlastset = pwdlastset21;
2834 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2836 return true;
2839 static bool test_SamLogon(struct torture_context *tctx,
2840 struct dcerpc_pipe *p,
2841 struct cli_credentials *test_credentials,
2842 NTSTATUS expected_result,
2843 bool interactive)
2845 NTSTATUS status;
2846 struct netr_LogonSamLogonEx r;
2847 union netr_LogonLevel logon;
2848 union netr_Validation validation;
2849 uint8_t authoritative;
2850 struct netr_IdentityInfo identity;
2851 struct netr_NetworkInfo ninfo;
2852 struct netr_PasswordInfo pinfo;
2853 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2854 int flags = CLI_CRED_NTLM_AUTH;
2855 uint32_t samlogon_flags = 0;
2856 struct netlogon_creds_CredentialState *creds;
2857 struct netr_Authenticator a;
2858 struct dcerpc_binding_handle *b = p->binding_handle;
2860 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2862 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2863 flags |= CLI_CRED_LANMAN_AUTH;
2866 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2867 flags |= CLI_CRED_NTLMv2_AUTH;
2870 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2871 &identity.account_name.string,
2872 &identity.domain_name.string);
2874 identity.parameter_control =
2875 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2876 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2877 identity.logon_id_low = 0;
2878 identity.logon_id_high = 0;
2879 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2881 if (interactive) {
2882 netlogon_creds_client_authenticator(creds, &a);
2884 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2885 ZERO_STRUCT(pinfo.lmpassword.hash);
2887 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2889 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2890 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2891 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2892 } else {
2893 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2894 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2897 pinfo.identity_info = identity;
2898 logon.password = &pinfo;
2900 r.in.logon_level = NetlogonInteractiveInformation;
2901 } else {
2902 generate_random_buffer(ninfo.challenge,
2903 sizeof(ninfo.challenge));
2904 chal = data_blob_const(ninfo.challenge,
2905 sizeof(ninfo.challenge));
2907 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2908 cli_credentials_get_domain(test_credentials));
2910 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2911 &flags,
2912 chal,
2913 names_blob,
2914 &lm_resp, &nt_resp,
2915 NULL, NULL);
2916 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2918 ninfo.lm.data = lm_resp.data;
2919 ninfo.lm.length = lm_resp.length;
2921 ninfo.nt.data = nt_resp.data;
2922 ninfo.nt.length = nt_resp.length;
2924 ninfo.identity_info = identity;
2925 logon.network = &ninfo;
2927 r.in.logon_level = NetlogonNetworkInformation;
2930 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2931 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2932 r.in.logon = &logon;
2933 r.in.flags = &samlogon_flags;
2934 r.out.flags = &samlogon_flags;
2935 r.out.validation = &validation;
2936 r.out.authoritative = &authoritative;
2938 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2940 r.in.validation_level = 6;
2942 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2943 "netr_LogonSamLogonEx failed");
2944 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
2945 r.in.validation_level = 3;
2946 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2947 "netr_LogonSamLogonEx failed");
2949 if (!NT_STATUS_IS_OK(r.out.result)) {
2950 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
2951 return true;
2952 } else {
2953 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
2956 return true;
2959 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2960 struct dcerpc_pipe *p,
2961 struct cli_credentials *machine_creds,
2962 const char *acct_name,
2963 const char *password,
2964 NTSTATUS expected_samlogon_result,
2965 bool interactive)
2967 bool ret = true;
2968 struct cli_credentials *test_credentials;
2970 test_credentials = cli_credentials_init(tctx);
2972 cli_credentials_set_workstation(test_credentials,
2973 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2974 cli_credentials_set_domain(test_credentials,
2975 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2976 cli_credentials_set_username(test_credentials,
2977 acct_name, CRED_SPECIFIED);
2978 cli_credentials_set_password(test_credentials,
2979 password, CRED_SPECIFIED);
2981 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
2982 interactive ? "interactive" : "network", acct_name, password);
2984 if (!test_SamLogon(tctx, p, test_credentials,
2985 expected_samlogon_result, interactive)) {
2986 torture_warning(tctx, "new password did not work\n");
2987 ret = false;
2990 return ret;
2993 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2994 struct dcerpc_pipe *np,
2995 struct torture_context *tctx,
2996 struct policy_handle *handle,
2997 uint16_t level,
2998 uint32_t fields_present,
2999 uint8_t password_expired,
3000 bool *matched_expected_error,
3001 bool use_setinfo2,
3002 const char *acct_name,
3003 char **password,
3004 struct cli_credentials *machine_creds,
3005 bool use_queryinfo2,
3006 NTTIME *pwdlastset,
3007 NTSTATUS expected_samlogon_result)
3009 const char *fields = NULL;
3010 bool ret = true;
3011 struct dcerpc_binding_handle *b = p->binding_handle;
3013 switch (level) {
3014 case 21:
3015 case 23:
3016 case 25:
3017 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3018 fields_present);
3019 break;
3020 default:
3021 break;
3024 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3025 "(password_expired: %d) %s\n",
3026 use_setinfo2 ? "2":"", level, password_expired,
3027 fields ? fields : "");
3029 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3030 fields_present,
3031 password,
3032 password_expired,
3033 use_setinfo2,
3034 matched_expected_error)) {
3035 ret = false;
3038 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3039 use_queryinfo2,
3040 pwdlastset)) {
3041 ret = false;
3044 if (*matched_expected_error == true) {
3045 return ret;
3048 if (!test_SamLogon_with_creds(tctx, np,
3049 machine_creds,
3050 acct_name,
3051 *password,
3052 expected_samlogon_result,
3053 false)) {
3054 ret = false;
3057 return ret;
3060 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3061 struct cli_credentials *credentials,
3062 struct dcerpc_pipe **p)
3064 struct dcerpc_binding *b;
3066 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3067 "failed to get rpc binding");
3069 /* We have to use schannel, otherwise the SamLogonEx fails
3070 * with INTERNAL_ERROR */
3072 b->flags &= ~DCERPC_AUTH_OPTIONS;
3073 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
3075 torture_assert_ntstatus_ok(tctx,
3076 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3077 credentials, tctx->ev, tctx->lp_ctx),
3078 "failed to bind to netlogon");
3080 return true;
3083 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3084 struct torture_context *tctx,
3085 uint32_t acct_flags,
3086 const char *acct_name,
3087 struct policy_handle *handle,
3088 char **password,
3089 struct cli_credentials *machine_credentials)
3091 int s = 0, q = 0, f = 0, l = 0, z = 0;
3092 bool ret = true;
3093 int delay = 50000;
3094 bool set_levels[] = { false, true };
3095 bool query_levels[] = { false, true };
3096 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3097 uint32_t nonzeros[] = { 1, 24 };
3098 uint32_t fields_present[] = {
3100 SAMR_FIELD_EXPIRED_FLAG,
3101 SAMR_FIELD_LAST_PWD_CHANGE,
3102 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3103 SAMR_FIELD_COMMENT,
3104 SAMR_FIELD_NT_PASSWORD_PRESENT,
3105 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3106 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3107 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3108 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3109 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3110 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3112 struct dcerpc_pipe *np = NULL;
3114 if (torture_setting_bool(tctx, "samba3", false) ||
3115 torture_setting_bool(tctx, "samba4", false)) {
3116 delay = 999999;
3117 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3118 delay);
3121 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3123 /* set to 1 to enable testing for all possible opcode
3124 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3125 combinations */
3126 #if 0
3127 #define TEST_ALL_LEVELS 1
3128 #define TEST_SET_LEVELS 1
3129 #define TEST_QUERY_LEVELS 1
3130 #endif
3131 #ifdef TEST_ALL_LEVELS
3132 for (l=0; l<ARRAY_SIZE(levels); l++) {
3133 #else
3134 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3135 #endif
3136 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3137 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3138 #ifdef TEST_SET_LEVELS
3139 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3140 #endif
3141 #ifdef TEST_QUERY_LEVELS
3142 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3143 #endif
3144 NTTIME pwdlastset_old = 0;
3145 NTTIME pwdlastset_new = 0;
3146 bool matched_expected_error = false;
3147 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3149 torture_comment(tctx, "------------------------------\n"
3150 "Testing pwdLastSet attribute for flags: 0x%08x "
3151 "(s: %d (l: %d), q: %d)\n",
3152 acct_flags, s, levels[l], q);
3154 switch (levels[l]) {
3155 case 21:
3156 case 23:
3157 case 25:
3158 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3159 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3160 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3162 break;
3166 /* set #1 */
3168 /* set a password and force password change (pwdlastset 0) by
3169 * setting the password expired flag to a non-0 value */
3171 if (!test_SetPassword_level(p, np, tctx, handle,
3172 levels[l],
3173 fields_present[f],
3174 nonzeros[z],
3175 &matched_expected_error,
3176 set_levels[s],
3177 acct_name,
3178 password,
3179 machine_credentials,
3180 query_levels[q],
3181 &pwdlastset_new,
3182 expected_samlogon_result)) {
3183 ret = false;
3186 if (matched_expected_error == true) {
3187 /* skipping on expected failure */
3188 continue;
3191 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3192 * set without the SAMR_FIELD_EXPIRED_FLAG */
3194 switch (levels[l]) {
3195 case 21:
3196 case 23:
3197 case 25:
3198 if ((pwdlastset_new != 0) &&
3199 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3200 torture_comment(tctx, "not considering a non-0 "
3201 "pwdLastSet as a an error as the "
3202 "SAMR_FIELD_EXPIRED_FLAG has not "
3203 "been set\n");
3204 break;
3206 break;
3207 default:
3208 if (pwdlastset_new != 0) {
3209 torture_warning(tctx, "pwdLastSet test failed: "
3210 "expected pwdLastSet 0 but got %lld\n",
3211 pwdlastset_old);
3212 ret = false;
3214 break;
3217 switch (levels[l]) {
3218 case 21:
3219 case 23:
3220 case 25:
3221 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3222 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3223 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3224 (pwdlastset_old >= pwdlastset_new)) {
3225 torture_warning(tctx, "pwdlastset not increasing\n");
3226 ret = false;
3228 break;
3231 pwdlastset_old = pwdlastset_new;
3233 usleep(delay);
3235 /* set #2 */
3237 /* set a password, pwdlastset needs to get updated (increased
3238 * value), password_expired value used here is 0 */
3240 if (!test_SetPassword_level(p, np, tctx, handle,
3241 levels[l],
3242 fields_present[f],
3244 &matched_expected_error,
3245 set_levels[s],
3246 acct_name,
3247 password,
3248 machine_credentials,
3249 query_levels[q],
3250 &pwdlastset_new,
3251 expected_samlogon_result)) {
3252 ret = false;
3255 /* when a password has been changed, pwdlastset must not be 0 afterwards
3256 * and must be larger then the old value */
3258 switch (levels[l]) {
3259 case 21:
3260 case 23:
3261 case 25:
3262 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3263 * password has been changed, old and new pwdlastset
3264 * need to be the same value */
3266 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3267 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3268 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3270 torture_assert_int_equal(tctx, pwdlastset_old,
3271 pwdlastset_new, "pwdlastset must be equal");
3272 break;
3274 break;
3275 default:
3276 if (pwdlastset_old >= pwdlastset_new) {
3277 torture_warning(tctx, "pwdLastSet test failed: "
3278 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3279 pwdlastset_old, pwdlastset_new);
3280 ret = false;
3282 if (pwdlastset_new == 0) {
3283 torture_warning(tctx, "pwdLastSet test failed: "
3284 "expected non-0 pwdlastset, got: %lld\n",
3285 pwdlastset_new);
3286 ret = false;
3288 break;
3291 switch (levels[l]) {
3292 case 21:
3293 case 23:
3294 case 25:
3295 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3296 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3297 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3298 (pwdlastset_old >= pwdlastset_new)) {
3299 torture_warning(tctx, "pwdlastset not increasing\n");
3300 ret = false;
3302 break;
3305 pwdlastset_old = pwdlastset_new;
3307 usleep(delay);
3309 /* set #2b */
3311 /* set a password, pwdlastset needs to get updated (increased
3312 * value), password_expired value used here is 0 */
3314 if (!test_SetPassword_level(p, np, tctx, handle,
3315 levels[l],
3316 fields_present[f],
3318 &matched_expected_error,
3319 set_levels[s],
3320 acct_name,
3321 password,
3322 machine_credentials,
3323 query_levels[q],
3324 &pwdlastset_new,
3325 expected_samlogon_result)) {
3326 ret = false;
3329 /* when a password has been changed, pwdlastset must not be 0 afterwards
3330 * and must be larger then the old value */
3332 switch (levels[l]) {
3333 case 21:
3334 case 23:
3335 case 25:
3337 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3338 * password has been changed, old and new pwdlastset
3339 * need to be the same value */
3341 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3342 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3343 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3345 torture_assert_int_equal(tctx, pwdlastset_old,
3346 pwdlastset_new, "pwdlastset must be equal");
3347 break;
3349 break;
3350 default:
3351 if (pwdlastset_old >= pwdlastset_new) {
3352 torture_warning(tctx, "pwdLastSet test failed: "
3353 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3354 pwdlastset_old, pwdlastset_new);
3355 ret = false;
3357 if (pwdlastset_new == 0) {
3358 torture_warning(tctx, "pwdLastSet test failed: "
3359 "expected non-0 pwdlastset, got: %lld\n",
3360 pwdlastset_new);
3361 ret = false;
3363 break;
3366 switch (levels[l]) {
3367 case 21:
3368 case 23:
3369 case 25:
3370 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3371 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3372 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3373 (pwdlastset_old >= pwdlastset_new)) {
3374 torture_warning(tctx, "pwdlastset not increasing\n");
3375 ret = false;
3377 break;
3380 pwdlastset_old = pwdlastset_new;
3382 usleep(delay);
3384 /* set #3 */
3386 /* set a password and force password change (pwdlastset 0) by
3387 * setting the password expired flag to a non-0 value */
3389 if (!test_SetPassword_level(p, np, tctx, handle,
3390 levels[l],
3391 fields_present[f],
3392 nonzeros[z],
3393 &matched_expected_error,
3394 set_levels[s],
3395 acct_name,
3396 password,
3397 machine_credentials,
3398 query_levels[q],
3399 &pwdlastset_new,
3400 expected_samlogon_result)) {
3401 ret = false;
3404 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3405 * set without the SAMR_FIELD_EXPIRED_FLAG */
3407 switch (levels[l]) {
3408 case 21:
3409 case 23:
3410 case 25:
3411 if ((pwdlastset_new != 0) &&
3412 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3413 torture_comment(tctx, "not considering a non-0 "
3414 "pwdLastSet as a an error as the "
3415 "SAMR_FIELD_EXPIRED_FLAG has not "
3416 "been set\n");
3417 break;
3420 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3421 * password has been changed, old and new pwdlastset
3422 * need to be the same value */
3424 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3425 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3426 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3428 torture_assert_int_equal(tctx, pwdlastset_old,
3429 pwdlastset_new, "pwdlastset must be equal");
3430 break;
3432 break;
3433 default:
3434 if (pwdlastset_new != 0) {
3435 torture_warning(tctx, "pwdLastSet test failed: "
3436 "expected pwdLastSet 0, got %lld\n",
3437 pwdlastset_old);
3438 ret = false;
3440 break;
3443 switch (levels[l]) {
3444 case 21:
3445 case 23:
3446 case 25:
3447 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3448 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3449 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3450 (pwdlastset_old >= pwdlastset_new)) {
3451 torture_warning(tctx, "pwdlastset not increasing\n");
3452 ret = false;
3454 break;
3457 /* if the level we are testing does not have a fields_present
3458 * field, skip all fields present tests by setting f to to
3459 * arraysize */
3460 switch (levels[l]) {
3461 case 18:
3462 case 24:
3463 case 26:
3464 f = ARRAY_SIZE(fields_present);
3465 break;
3468 #ifdef TEST_QUERY_LEVELS
3470 #endif
3471 #ifdef TEST_SET_LEVELS
3473 #endif
3474 } /* fields present */
3475 } /* nonzeros */
3476 } /* levels */
3478 #undef TEST_SET_LEVELS
3479 #undef TEST_QUERY_LEVELS
3481 talloc_free(np);
3483 return ret;
3486 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3487 struct torture_context *tctx,
3488 struct policy_handle *handle,
3489 uint32_t *badpwdcount)
3491 union samr_UserInfo *info;
3492 struct samr_QueryUserInfo r;
3494 r.in.user_handle = handle;
3495 r.in.level = 3;
3496 r.out.info = &info;
3498 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3500 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3501 "failed to query userinfo");
3502 torture_assert_ntstatus_ok(tctx, r.out.result,
3503 "failed to query userinfo");
3505 *badpwdcount = info->info3.bad_password_count;
3507 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3509 return true;
3512 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3513 struct torture_context *tctx,
3514 struct policy_handle *user_handle,
3515 uint32_t acct_flags)
3517 struct samr_SetUserInfo r;
3518 union samr_UserInfo user_info;
3520 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3522 user_info.info16.acct_flags = acct_flags;
3524 r.in.user_handle = user_handle;
3525 r.in.level = 16;
3526 r.in.info = &user_info;
3528 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3529 "failed to set account flags");
3530 torture_assert_ntstatus_ok(tctx, r.out.result,
3531 "failed to set account flags");
3533 return true;
3536 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3537 struct torture_context *tctx,
3538 struct policy_handle *user_handle,
3539 uint32_t acct_flags,
3540 char **password)
3542 struct dcerpc_binding_handle *b = p->binding_handle;
3544 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3545 "failed to set password");
3547 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3549 torture_assert(tctx,
3550 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3551 acct_flags & ~ACB_DISABLED),
3552 "failed to enable user");
3554 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3555 "failed to set password");
3557 return true;
3560 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3561 struct torture_context *tctx,
3562 struct policy_handle *domain_handle,
3563 enum samr_DomainInfoClass level,
3564 union samr_DomainInfo *info)
3566 struct samr_SetDomainInfo r;
3568 r.in.domain_handle = domain_handle;
3569 r.in.level = level;
3570 r.in.info = info;
3572 torture_assert_ntstatus_ok(tctx,
3573 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3574 "failed to set domain info");
3575 torture_assert_ntstatus_ok(tctx, r.out.result,
3576 "failed to set domain info");
3578 return true;
3581 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3582 struct torture_context *tctx,
3583 struct policy_handle *domain_handle,
3584 enum samr_DomainInfoClass level,
3585 union samr_DomainInfo *info,
3586 NTSTATUS expected)
3588 struct samr_SetDomainInfo r;
3590 r.in.domain_handle = domain_handle;
3591 r.in.level = level;
3592 r.in.info = info;
3594 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3595 "SetDomainInfo failed");
3596 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3598 return true;
3601 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3602 struct torture_context *tctx,
3603 struct policy_handle *domain_handle,
3604 enum samr_DomainInfoClass level,
3605 union samr_DomainInfo **q_info)
3607 struct samr_QueryDomainInfo2 r;
3609 r.in.domain_handle = domain_handle;
3610 r.in.level = level;
3611 r.out.info = q_info;
3613 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3614 "failed to query domain info");
3615 torture_assert_ntstatus_ok(tctx, r.out.result,
3616 "failed to query domain info");
3618 return true;
3621 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3622 struct dcerpc_pipe *np,
3623 struct torture_context *tctx,
3624 uint32_t acct_flags,
3625 const char *acct_name,
3626 struct policy_handle *domain_handle,
3627 struct policy_handle *user_handle,
3628 char **password,
3629 struct cli_credentials *machine_credentials,
3630 const char *comment,
3631 bool disable,
3632 bool interactive,
3633 NTSTATUS expected_success_status,
3634 struct samr_DomInfo1 *info1,
3635 struct samr_DomInfo12 *info12)
3637 union samr_DomainInfo info;
3638 char **passwords;
3639 int i;
3640 uint32_t badpwdcount, tmp;
3641 uint32_t password_history_length = 12;
3642 uint32_t lockout_threshold = 15;
3643 struct dcerpc_binding_handle *b = p->binding_handle;
3645 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3647 torture_assert(tctx, password_history_length < lockout_threshold,
3648 "password history length needs to be smaller than account lockout threshold for this test");
3651 /* set policies */
3653 info.info1 = *info1;
3654 info.info1.password_history_length = password_history_length;
3656 torture_assert(tctx,
3657 test_SetDomainInfo(b, tctx, domain_handle,
3658 DomainPasswordInformation, &info),
3659 "failed to set password history length");
3661 info.info12 = *info12;
3662 info.info12.lockout_threshold = lockout_threshold;
3664 torture_assert(tctx,
3665 test_SetDomainInfo(b, tctx, domain_handle,
3666 DomainLockoutInformation, &info),
3667 "failed to set lockout threshold");
3669 /* reset bad pwd count */
3671 torture_assert(tctx,
3672 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3675 /* enable or disable account */
3676 if (disable) {
3677 torture_assert(tctx,
3678 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3679 acct_flags | ACB_DISABLED),
3680 "failed to disable user");
3681 } else {
3682 torture_assert(tctx,
3683 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3684 acct_flags & ~ACB_DISABLED),
3685 "failed to enable user");
3689 /* setup password history */
3691 passwords = talloc_array(tctx, char *, password_history_length);
3693 for (i=0; i < password_history_length; i++) {
3695 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3696 "failed to set password");
3697 passwords[i] = talloc_strdup(tctx, *password);
3699 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3700 acct_name, passwords[i],
3701 expected_success_status, interactive)) {
3702 torture_fail(tctx, "failed to auth with latest password");
3705 torture_assert(tctx,
3706 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3708 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3712 /* test with wrong password */
3714 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3715 acct_name, "random_crap",
3716 NT_STATUS_WRONG_PASSWORD, interactive)) {
3717 torture_fail(tctx, "succeeded to authenticate with wrong password");
3720 torture_assert(tctx,
3721 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3723 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3726 /* test with latest good password */
3728 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3729 passwords[password_history_length-1],
3730 expected_success_status, interactive)) {
3731 torture_fail(tctx, "succeeded to authenticate with wrong password");
3734 torture_assert(tctx,
3735 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3737 if (disable) {
3738 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3739 } else {
3740 /* only enabled accounts get the bad pwd count reset upon
3741 * successful logon */
3742 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3745 tmp = badpwdcount;
3748 /* test password history */
3750 for (i=0; i < password_history_length; i++) {
3752 torture_comment(tctx, "Testing bad password count behavior with "
3753 "password #%d of #%d\n", i, password_history_length);
3755 /* - network samlogon will succeed auth and not
3756 * increase badpwdcount for 2 last entries
3757 * - interactive samlogon only for the last one */
3759 if (i == password_history_length - 1 ||
3760 (i == password_history_length - 2 && !interactive)) {
3762 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3763 acct_name, passwords[i],
3764 expected_success_status, interactive)) {
3765 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3768 torture_assert(tctx,
3769 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3771 if (disable) {
3772 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3773 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3774 } else {
3775 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3776 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3779 tmp = badpwdcount;
3781 continue;
3784 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3785 acct_name, passwords[i],
3786 NT_STATUS_WRONG_PASSWORD, interactive)) {
3787 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3790 torture_assert(tctx,
3791 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3793 /* - network samlogon will fail auth but not increase
3794 * badpwdcount for 3rd last entry
3795 * - interactive samlogon for 3rd and 2nd last entry */
3797 if (i == password_history_length - 3 ||
3798 (i == password_history_length - 2 && interactive)) {
3799 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3800 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3801 } else {
3802 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3803 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3806 tmp = badpwdcount;
3809 return true;
3812 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3813 struct torture_context *tctx,
3814 uint32_t acct_flags,
3815 const char *acct_name,
3816 struct policy_handle *domain_handle,
3817 struct policy_handle *user_handle,
3818 char **password,
3819 struct cli_credentials *machine_credentials)
3821 union samr_DomainInfo *q_info, s_info;
3822 struct samr_DomInfo1 info1, _info1;
3823 struct samr_DomInfo12 info12, _info12;
3824 bool ret = true;
3825 struct dcerpc_binding_handle *b = p->binding_handle;
3826 struct dcerpc_pipe *np;
3827 int i;
3829 struct {
3830 const char *comment;
3831 bool disabled;
3832 bool interactive;
3833 NTSTATUS expected_success_status;
3834 } creds[] = {
3836 .comment = "network logon (disabled account)",
3837 .disabled = true,
3838 .interactive = false,
3839 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3842 .comment = "network logon (enabled account)",
3843 .disabled = false,
3844 .interactive = false,
3845 .expected_success_status= NT_STATUS_OK
3848 .comment = "interactive logon (disabled account)",
3849 .disabled = true,
3850 .interactive = true,
3851 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3854 .comment = "interactive logon (enabled account)",
3855 .disabled = false,
3856 .interactive = true,
3857 .expected_success_status= NT_STATUS_OK
3861 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3863 /* backup old policies */
3865 torture_assert(tctx,
3866 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3867 DomainPasswordInformation, &q_info),
3868 "failed to query domain info level 1");
3870 info1 = q_info->info1;
3871 _info1 = info1;
3873 torture_assert(tctx,
3874 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3875 DomainLockoutInformation, &q_info),
3876 "failed to query domain info level 12");
3878 info12 = q_info->info12;
3879 _info12 = info12;
3881 /* run tests */
3883 for (i=0; i < ARRAY_SIZE(creds); i++) {
3885 /* skip trust tests for now */
3886 if (acct_flags & ACB_WSTRUST ||
3887 acct_flags & ACB_SVRTRUST ||
3888 acct_flags & ACB_DOMTRUST) {
3889 continue;
3892 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3893 domain_handle, user_handle, password,
3894 machine_credentials,
3895 creds[i].comment,
3896 creds[i].disabled,
3897 creds[i].interactive,
3898 creds[i].expected_success_status,
3899 &_info1, &_info12);
3900 if (!ret) {
3901 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3902 } else {
3903 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3907 /* restore policies */
3909 s_info.info1 = info1;
3911 torture_assert(tctx,
3912 test_SetDomainInfo(b, tctx, domain_handle,
3913 DomainPasswordInformation, &s_info),
3914 "failed to set password information");
3916 s_info.info12 = info12;
3918 torture_assert(tctx,
3919 test_SetDomainInfo(b, tctx, domain_handle,
3920 DomainLockoutInformation, &s_info),
3921 "failed to set lockout information");
3923 return ret;
3926 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3927 struct torture_context *tctx,
3928 struct policy_handle *handle,
3929 uint32_t *acct_flags)
3931 union samr_UserInfo *info;
3932 struct samr_QueryUserInfo r;
3934 r.in.user_handle = handle;
3935 r.in.level = 16;
3936 r.out.info = &info;
3938 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3940 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3941 "failed to query userinfo");
3942 torture_assert_ntstatus_ok(tctx, r.out.result,
3943 "failed to query userinfo");
3945 *acct_flags = info->info16.acct_flags;
3947 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
3949 return true;
3952 static bool test_Password_lockout(struct dcerpc_pipe *p,
3953 struct dcerpc_pipe *np,
3954 struct torture_context *tctx,
3955 uint32_t acct_flags,
3956 const char *acct_name,
3957 struct policy_handle *domain_handle,
3958 struct policy_handle *user_handle,
3959 char **password,
3960 struct cli_credentials *machine_credentials,
3961 const char *comment,
3962 bool disable,
3963 bool interactive,
3964 NTSTATUS expected_success_status,
3965 struct samr_DomInfo1 *info1,
3966 struct samr_DomInfo12 *info12)
3968 union samr_DomainInfo info;
3969 uint32_t badpwdcount;
3970 uint32_t password_history_length = 1;
3971 uint64_t lockout_threshold = 1;
3972 uint32_t lockout_seconds = 5;
3973 uint64_t delta_time_factor = 10 * 1000 * 1000;
3974 struct dcerpc_binding_handle *b = p->binding_handle;
3976 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3978 /* set policies */
3980 info.info1 = *info1;
3982 torture_comment(tctx, "setting password history length.\n");
3983 info.info1.password_history_length = password_history_length;
3985 torture_assert(tctx,
3986 test_SetDomainInfo(b, tctx, domain_handle,
3987 DomainPasswordInformation, &info),
3988 "failed to set password history length");
3990 info.info12 = *info12;
3991 info.info12.lockout_threshold = lockout_threshold;
3993 /* set lockout duration < lockout window: should fail */
3994 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3995 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3997 torture_assert(tctx,
3998 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
3999 DomainLockoutInformation, &info,
4000 NT_STATUS_INVALID_PARAMETER),
4001 "setting lockout duration < lockout window gave unexpected result");
4003 info.info12.lockout_duration = 0;
4004 info.info12.lockout_window = 0;
4006 torture_assert(tctx,
4007 test_SetDomainInfo(b, tctx, domain_handle,
4008 DomainLockoutInformation, &info),
4009 "failed to set lockout window and duration to 0");
4012 /* set lockout duration of 5 seconds */
4013 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4014 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4016 torture_assert(tctx,
4017 test_SetDomainInfo(b, tctx, domain_handle,
4018 DomainLockoutInformation, &info),
4019 "failed to set lockout window and duration to 5 seconds");
4021 /* reset bad pwd count */
4023 torture_assert(tctx,
4024 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4027 /* enable or disable account */
4029 if (disable) {
4030 torture_assert(tctx,
4031 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4032 acct_flags | ACB_DISABLED),
4033 "failed to disable user");
4034 } else {
4035 torture_assert(tctx,
4036 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4037 acct_flags & ~ACB_DISABLED),
4038 "failed to enable user");
4042 /* test logon with right password */
4044 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4045 acct_name, *password,
4046 expected_success_status, interactive)) {
4047 torture_fail(tctx, "failed to auth with latest password");
4050 torture_assert(tctx,
4051 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4052 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4055 /* test with wrong password ==> lockout */
4057 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4058 acct_name, "random_crap",
4059 NT_STATUS_WRONG_PASSWORD, interactive)) {
4060 torture_fail(tctx, "succeeded to authenticate with wrong password");
4063 torture_assert(tctx,
4064 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4065 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4067 torture_assert(tctx,
4068 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4069 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4070 "expected account to be locked");
4073 /* test with good password */
4075 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4076 *password,
4077 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4079 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4082 /* bad pwd count should not get updated */
4083 torture_assert(tctx,
4084 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4085 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4087 /* curiously, windows does _not_ set the autlock flag */
4088 torture_assert(tctx,
4089 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4090 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4091 "expected account to be locked");
4094 /* with bad password */
4096 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4097 acct_name, "random_crap2",
4098 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4100 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4103 /* bad pwd count should not get updated */
4104 torture_assert(tctx,
4105 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4106 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4108 /* curiously, windows does _not_ set the autlock flag */
4109 torture_assert(tctx,
4110 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4111 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4112 "expected account to be locked");
4115 /* let lockout duration expire ==> unlock */
4117 torture_comment(tctx, "let lockout duration expire...\n");
4118 sleep(lockout_seconds + 1);
4120 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4121 *password,
4122 expected_success_status, interactive))
4124 torture_fail(tctx, "failed to authenticate after lockout expired");
4127 torture_assert(tctx,
4128 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4129 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4130 "expected account not to be locked");
4132 return true;
4135 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4136 struct torture_context *tctx,
4137 uint32_t acct_flags,
4138 const char *acct_name,
4139 struct policy_handle *domain_handle,
4140 struct policy_handle *user_handle,
4141 char **password,
4142 struct cli_credentials *machine_credentials)
4144 union samr_DomainInfo *q_info, s_info;
4145 struct samr_DomInfo1 info1, _info1;
4146 struct samr_DomInfo12 info12, _info12;
4147 bool ret = true;
4148 struct dcerpc_binding_handle *b = p->binding_handle;
4149 struct dcerpc_pipe *np;
4150 int i;
4152 struct {
4153 const char *comment;
4154 bool disabled;
4155 bool interactive;
4156 NTSTATUS expected_success_status;
4157 } creds[] = {
4159 .comment = "network logon (disabled account)",
4160 .disabled = true,
4161 .interactive = false,
4162 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4165 .comment = "network logon (enabled account)",
4166 .disabled = false,
4167 .interactive = false,
4168 .expected_success_status= NT_STATUS_OK
4171 .comment = "interactive logon (disabled account)",
4172 .disabled = true,
4173 .interactive = true,
4174 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4177 .comment = "interactive logon (enabled account)",
4178 .disabled = false,
4179 .interactive = true,
4180 .expected_success_status= NT_STATUS_OK
4184 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4186 /* backup old policies */
4188 torture_assert(tctx,
4189 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4190 DomainPasswordInformation, &q_info),
4191 "failed to query domain info level 1");
4193 info1 = q_info->info1;
4194 _info1 = info1;
4196 torture_assert(tctx,
4197 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4198 DomainLockoutInformation, &q_info),
4199 "failed to query domain info level 12");
4201 info12 = q_info->info12;
4202 _info12 = info12;
4204 /* run tests */
4206 for (i=0; i < ARRAY_SIZE(creds); i++) {
4208 /* skip trust tests for now */
4209 if (acct_flags & ACB_WSTRUST ||
4210 acct_flags & ACB_SVRTRUST ||
4211 acct_flags & ACB_DOMTRUST) {
4212 continue;
4215 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4216 domain_handle, user_handle, password,
4217 machine_credentials,
4218 creds[i].comment,
4219 creds[i].disabled,
4220 creds[i].interactive,
4221 creds[i].expected_success_status,
4222 &_info1, &_info12);
4223 if (!ret) {
4224 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4225 } else {
4226 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4230 /* restore policies */
4232 s_info.info1 = info1;
4234 torture_assert(tctx,
4235 test_SetDomainInfo(b, tctx, domain_handle,
4236 DomainPasswordInformation, &s_info),
4237 "failed to set password information");
4239 s_info.info12 = info12;
4241 torture_assert(tctx,
4242 test_SetDomainInfo(b, tctx, domain_handle,
4243 DomainLockoutInformation, &s_info),
4244 "failed to set lockout information");
4246 return ret;
4249 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4250 struct dcerpc_pipe *lp,
4251 struct torture_context *tctx,
4252 struct policy_handle *domain_handle,
4253 struct policy_handle *lsa_handle,
4254 struct policy_handle *user_handle,
4255 const struct dom_sid *domain_sid,
4256 uint32_t rid,
4257 struct cli_credentials *machine_credentials)
4259 bool ret = true;
4260 struct dcerpc_binding_handle *b = p->binding_handle;
4261 struct dcerpc_binding_handle *lb = lp->binding_handle;
4263 struct policy_handle lsa_acct_handle;
4264 struct dom_sid *user_sid;
4266 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4269 struct lsa_EnumAccountRights r;
4270 struct lsa_RightSet rights;
4272 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4274 r.in.handle = lsa_handle;
4275 r.in.sid = user_sid;
4276 r.out.rights = &rights;
4278 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4279 "lsa_EnumAccountRights failed");
4280 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4281 "Expected enum rights for account to fail");
4285 struct lsa_RightSet rights;
4286 struct lsa_StringLarge names[2];
4287 struct lsa_AddAccountRights r;
4289 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4291 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4292 init_lsa_StringLarge(&names[1], NULL);
4294 rights.count = 1;
4295 rights.names = names;
4297 r.in.handle = lsa_handle;
4298 r.in.sid = user_sid;
4299 r.in.rights = &rights;
4301 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4302 "lsa_AddAccountRights failed");
4303 torture_assert_ntstatus_ok(tctx, r.out.result,
4304 "Failed to add privileges");
4308 struct lsa_EnumAccounts r;
4309 uint32_t resume_handle = 0;
4310 struct lsa_SidArray lsa_sid_array;
4311 int i;
4312 bool found_sid = false;
4314 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4316 r.in.handle = lsa_handle;
4317 r.in.num_entries = 0x1000;
4318 r.in.resume_handle = &resume_handle;
4319 r.out.sids = &lsa_sid_array;
4320 r.out.resume_handle = &resume_handle;
4322 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4323 "lsa_EnumAccounts failed");
4324 torture_assert_ntstatus_ok(tctx, r.out.result,
4325 "Failed to enum accounts");
4327 for (i=0; i < lsa_sid_array.num_sids; i++) {
4328 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4329 found_sid = true;
4333 torture_assert(tctx, found_sid,
4334 "failed to list privileged account");
4338 struct lsa_EnumAccountRights r;
4339 struct lsa_RightSet user_rights;
4341 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4343 r.in.handle = lsa_handle;
4344 r.in.sid = user_sid;
4345 r.out.rights = &user_rights;
4347 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4348 "lsa_EnumAccountRights failed");
4349 torture_assert_ntstatus_ok(tctx, r.out.result,
4350 "Failed to enum rights for account");
4352 if (user_rights.count < 1) {
4353 torture_warning(tctx, "failed to find newly added rights");
4354 return false;
4359 struct lsa_OpenAccount r;
4361 torture_comment(tctx, "Testing LSA OpenAccount\n");
4363 r.in.handle = lsa_handle;
4364 r.in.sid = user_sid;
4365 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4366 r.out.acct_handle = &lsa_acct_handle;
4368 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4369 "lsa_OpenAccount failed");
4370 torture_assert_ntstatus_ok(tctx, r.out.result,
4371 "Failed to open lsa account");
4375 struct lsa_GetSystemAccessAccount r;
4376 uint32_t access_mask;
4378 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4380 r.in.handle = &lsa_acct_handle;
4381 r.out.access_mask = &access_mask;
4383 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4384 "lsa_GetSystemAccessAccount failed");
4385 torture_assert_ntstatus_ok(tctx, r.out.result,
4386 "Failed to get lsa system access account");
4390 struct lsa_Close r;
4392 torture_comment(tctx, "Testing LSA Close\n");
4394 r.in.handle = &lsa_acct_handle;
4395 r.out.handle = &lsa_acct_handle;
4397 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4398 "lsa_Close failed");
4399 torture_assert_ntstatus_ok(tctx, r.out.result,
4400 "Failed to close lsa");
4404 struct samr_DeleteUser r;
4406 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4408 r.in.user_handle = user_handle;
4409 r.out.user_handle = user_handle;
4411 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4412 "DeleteUser failed");
4413 torture_assert_ntstatus_ok(tctx, r.out.result,
4414 "DeleteUser failed");
4418 struct lsa_EnumAccounts r;
4419 uint32_t resume_handle = 0;
4420 struct lsa_SidArray lsa_sid_array;
4421 int i;
4422 bool found_sid = false;
4424 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4426 r.in.handle = lsa_handle;
4427 r.in.num_entries = 0x1000;
4428 r.in.resume_handle = &resume_handle;
4429 r.out.sids = &lsa_sid_array;
4430 r.out.resume_handle = &resume_handle;
4432 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4433 "lsa_EnumAccounts failed");
4434 torture_assert_ntstatus_ok(tctx, r.out.result,
4435 "Failed to enum accounts");
4437 for (i=0; i < lsa_sid_array.num_sids; i++) {
4438 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4439 found_sid = true;
4443 torture_assert(tctx, found_sid,
4444 "failed to list privileged account");
4448 struct lsa_EnumAccountRights r;
4449 struct lsa_RightSet user_rights;
4451 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4453 r.in.handle = lsa_handle;
4454 r.in.sid = user_sid;
4455 r.out.rights = &user_rights;
4457 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4458 "lsa_EnumAccountRights failed");
4459 torture_assert_ntstatus_ok(tctx, r.out.result,
4460 "Failed to enum rights for account");
4462 if (user_rights.count < 1) {
4463 torture_warning(tctx, "failed to find newly added rights");
4464 return false;
4469 struct lsa_OpenAccount r;
4471 torture_comment(tctx, "Testing LSA OpenAccount\n");
4473 r.in.handle = lsa_handle;
4474 r.in.sid = user_sid;
4475 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4476 r.out.acct_handle = &lsa_acct_handle;
4478 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4479 "lsa_OpenAccount failed");
4480 torture_assert_ntstatus_ok(tctx, r.out.result,
4481 "Failed to open lsa account");
4485 struct lsa_GetSystemAccessAccount r;
4486 uint32_t access_mask;
4488 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4490 r.in.handle = &lsa_acct_handle;
4491 r.out.access_mask = &access_mask;
4493 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4494 "lsa_GetSystemAccessAccount failed");
4495 torture_assert_ntstatus_ok(tctx, r.out.result,
4496 "Failed to get lsa system access account");
4500 struct lsa_DeleteObject r;
4502 torture_comment(tctx, "Testing LSA DeleteObject\n");
4504 r.in.handle = &lsa_acct_handle;
4505 r.out.handle = &lsa_acct_handle;
4507 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4508 "lsa_DeleteObject failed");
4509 torture_assert_ntstatus_ok(tctx, r.out.result,
4510 "Failed to delete object");
4514 struct lsa_EnumAccounts r;
4515 uint32_t resume_handle = 0;
4516 struct lsa_SidArray lsa_sid_array;
4517 int i;
4518 bool found_sid = false;
4520 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4522 r.in.handle = lsa_handle;
4523 r.in.num_entries = 0x1000;
4524 r.in.resume_handle = &resume_handle;
4525 r.out.sids = &lsa_sid_array;
4526 r.out.resume_handle = &resume_handle;
4528 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4529 "lsa_EnumAccounts failed");
4530 torture_assert_ntstatus_ok(tctx, r.out.result,
4531 "Failed to enum accounts");
4533 for (i=0; i < lsa_sid_array.num_sids; i++) {
4534 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4535 found_sid = true;
4539 torture_assert(tctx, !found_sid,
4540 "should not have listed privileged account");
4544 struct lsa_EnumAccountRights r;
4545 struct lsa_RightSet user_rights;
4547 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4549 r.in.handle = lsa_handle;
4550 r.in.sid = user_sid;
4551 r.out.rights = &user_rights;
4553 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4554 "lsa_EnumAccountRights failed");
4555 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4556 "Failed to enum rights for account");
4559 return ret;
4562 static bool test_user_ops(struct dcerpc_pipe *p,
4563 struct torture_context *tctx,
4564 struct policy_handle *user_handle,
4565 struct policy_handle *domain_handle,
4566 const struct dom_sid *domain_sid,
4567 uint32_t base_acct_flags,
4568 const char *base_acct_name, enum torture_samr_choice which_ops,
4569 struct cli_credentials *machine_credentials)
4571 char *password = NULL;
4572 struct samr_QueryUserInfo q;
4573 union samr_UserInfo *info;
4574 NTSTATUS status;
4575 struct dcerpc_binding_handle *b = p->binding_handle;
4577 bool ret = true;
4578 int i;
4579 uint32_t rid;
4580 const uint32_t password_fields[] = {
4581 SAMR_FIELD_NT_PASSWORD_PRESENT,
4582 SAMR_FIELD_LM_PASSWORD_PRESENT,
4583 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4587 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4588 if (!NT_STATUS_IS_OK(status)) {
4589 ret = false;
4592 switch (which_ops) {
4593 case TORTURE_SAMR_USER_ATTRIBUTES:
4594 if (!test_QuerySecurity(b, tctx, user_handle)) {
4595 ret = false;
4598 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4599 ret = false;
4602 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4603 ret = false;
4606 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4607 base_acct_name)) {
4608 ret = false;
4611 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4612 ret = false;
4615 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4616 ret = false;
4619 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4620 ret = false;
4622 break;
4623 case TORTURE_SAMR_PASSWORDS:
4624 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4625 char simple_pass[9];
4626 char *v = generate_random_str(tctx, 1);
4628 ZERO_STRUCT(simple_pass);
4629 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4631 torture_comment(tctx, "Testing machine account password policy rules\n");
4633 /* Workstation trust accounts don't seem to need to honour password quality policy */
4634 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4635 ret = false;
4638 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4639 ret = false;
4642 /* reset again, to allow another 'user' password change */
4643 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4644 ret = false;
4647 /* Try a 'short' password */
4648 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4649 ret = false;
4652 /* Try a compleatly random password */
4653 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4654 ret = false;
4658 for (i = 0; password_fields[i]; i++) {
4659 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4660 ret = false;
4663 /* check it was set right */
4664 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4665 ret = false;
4669 for (i = 0; password_fields[i]; i++) {
4670 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4671 ret = false;
4674 /* check it was set right */
4675 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4676 ret = false;
4680 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4681 ret = false;
4684 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4685 ret = false;
4688 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4689 ret = false;
4692 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4693 ret = false;
4696 for (i = 0; password_fields[i]; i++) {
4698 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4699 /* we need to skip as that would break
4700 * the ChangePasswordUser3 verify */
4701 continue;
4704 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4705 ret = false;
4708 /* check it was set right */
4709 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4710 ret = false;
4714 q.in.user_handle = user_handle;
4715 q.in.level = 5;
4716 q.out.info = &info;
4718 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4719 "QueryUserInfo failed");
4720 if (!NT_STATUS_IS_OK(q.out.result)) {
4721 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4722 q.in.level, nt_errstr(q.out.result));
4723 ret = false;
4724 } else {
4725 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4726 if ((info->info5.acct_flags) != expected_flags) {
4727 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4728 info->info5.acct_flags,
4729 expected_flags);
4730 /* FIXME: GD */
4731 if (!torture_setting_bool(tctx, "samba3", false)) {
4732 ret = false;
4735 if (info->info5.rid != rid) {
4736 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4737 info->info5.rid, rid);
4742 break;
4744 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4746 /* test last password change timestamp behaviour */
4747 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4748 base_acct_name,
4749 user_handle, &password,
4750 machine_credentials)) {
4751 ret = false;
4754 if (ret == true) {
4755 torture_comment(tctx, "pwdLastSet test succeeded\n");
4756 } else {
4757 torture_warning(tctx, "pwdLastSet test failed\n");
4760 break;
4762 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4764 /* test bad pwd count change behaviour */
4765 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4766 base_acct_name,
4767 domain_handle,
4768 user_handle, &password,
4769 machine_credentials)) {
4770 ret = false;
4773 if (ret == true) {
4774 torture_comment(tctx, "badPwdCount test succeeded\n");
4775 } else {
4776 torture_warning(tctx, "badPwdCount test failed\n");
4779 break;
4781 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4783 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4784 base_acct_name,
4785 domain_handle,
4786 user_handle, &password,
4787 machine_credentials))
4789 ret = false;
4792 if (ret == true) {
4793 torture_comment(tctx, "lockout test succeeded\n");
4794 } else {
4795 torture_warning(tctx, "lockout test failed\n");
4798 break;
4801 case TORTURE_SAMR_USER_PRIVILEGES: {
4803 struct dcerpc_pipe *lp;
4804 struct policy_handle *lsa_handle;
4805 struct dcerpc_binding_handle *lb;
4807 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4808 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4809 lb = lp->binding_handle;
4811 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4812 ret = false;
4815 if (!test_DeleteUser_with_privs(p, lp, tctx,
4816 domain_handle, lsa_handle, user_handle,
4817 domain_sid, rid,
4818 machine_credentials)) {
4819 ret = false;
4822 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4823 ret = false;
4826 if (!ret) {
4827 torture_warning(tctx, "privileged user delete test failed\n");
4830 break;
4832 case TORTURE_SAMR_OTHER:
4833 case TORTURE_SAMR_MANY_ACCOUNTS:
4834 case TORTURE_SAMR_MANY_GROUPS:
4835 case TORTURE_SAMR_MANY_ALIASES:
4836 /* We just need the account to exist */
4837 break;
4839 return ret;
4842 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4843 struct torture_context *tctx,
4844 struct policy_handle *alias_handle,
4845 const struct dom_sid *domain_sid)
4847 bool ret = true;
4849 if (!torture_setting_bool(tctx, "samba3", false)) {
4850 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4851 ret = false;
4855 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4856 ret = false;
4859 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4860 ret = false;
4863 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4864 ret = false;
4867 if (torture_setting_bool(tctx, "samba3", false) ||
4868 torture_setting_bool(tctx, "samba4", false)) {
4869 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4870 return ret;
4873 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4874 ret = false;
4877 return ret;
4881 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4882 struct torture_context *tctx,
4883 struct policy_handle *user_handle)
4885 struct samr_DeleteUser d;
4886 torture_comment(tctx, "Testing DeleteUser\n");
4888 d.in.user_handle = user_handle;
4889 d.out.user_handle = user_handle;
4891 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4892 "DeleteUser failed");
4893 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
4895 return true;
4898 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
4899 struct torture_context *tctx,
4900 struct policy_handle *handle, const char *name)
4902 NTSTATUS status;
4903 struct samr_DeleteUser d;
4904 struct policy_handle user_handle;
4905 uint32_t rid;
4907 status = test_LookupName(b, tctx, handle, name, &rid);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 goto failed;
4912 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
4913 if (!NT_STATUS_IS_OK(status)) {
4914 goto failed;
4917 d.in.user_handle = &user_handle;
4918 d.out.user_handle = &user_handle;
4919 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4920 "DeleteUser failed");
4921 if (!NT_STATUS_IS_OK(d.out.result)) {
4922 status = d.out.result;
4923 goto failed;
4926 return true;
4928 failed:
4929 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4930 return false;
4934 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
4935 struct torture_context *tctx,
4936 struct policy_handle *handle, const char *name)
4938 NTSTATUS status;
4939 struct samr_OpenGroup r;
4940 struct samr_DeleteDomainGroup d;
4941 struct policy_handle group_handle;
4942 uint32_t rid;
4944 status = test_LookupName(b, tctx, handle, name, &rid);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 goto failed;
4949 r.in.domain_handle = handle;
4950 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4951 r.in.rid = rid;
4952 r.out.group_handle = &group_handle;
4953 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
4954 "OpenGroup failed");
4955 if (!NT_STATUS_IS_OK(r.out.result)) {
4956 status = r.out.result;
4957 goto failed;
4960 d.in.group_handle = &group_handle;
4961 d.out.group_handle = &group_handle;
4962 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
4963 "DeleteDomainGroup failed");
4964 if (!NT_STATUS_IS_OK(d.out.result)) {
4965 status = d.out.result;
4966 goto failed;
4969 return true;
4971 failed:
4972 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4973 return false;
4977 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
4978 struct torture_context *tctx,
4979 struct policy_handle *domain_handle,
4980 const char *name)
4982 NTSTATUS status;
4983 struct samr_OpenAlias r;
4984 struct samr_DeleteDomAlias d;
4985 struct policy_handle alias_handle;
4986 uint32_t rid;
4988 torture_comment(tctx, "Testing DeleteAlias_byname\n");
4990 status = test_LookupName(b, tctx, domain_handle, name, &rid);
4991 if (!NT_STATUS_IS_OK(status)) {
4992 goto failed;
4995 r.in.domain_handle = domain_handle;
4996 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4997 r.in.rid = rid;
4998 r.out.alias_handle = &alias_handle;
4999 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5000 "OpenAlias failed");
5001 if (!NT_STATUS_IS_OK(r.out.result)) {
5002 status = r.out.result;
5003 goto failed;
5006 d.in.alias_handle = &alias_handle;
5007 d.out.alias_handle = &alias_handle;
5008 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5009 "DeleteDomAlias failed");
5010 if (!NT_STATUS_IS_OK(d.out.result)) {
5011 status = d.out.result;
5012 goto failed;
5015 return true;
5017 failed:
5018 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5019 return false;
5022 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5023 struct torture_context *tctx,
5024 struct policy_handle *alias_handle)
5026 struct samr_DeleteDomAlias d;
5027 bool ret = true;
5029 torture_comment(tctx, "Testing DeleteAlias\n");
5031 d.in.alias_handle = alias_handle;
5032 d.out.alias_handle = alias_handle;
5034 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5035 "DeleteDomAlias failed");
5036 if (!NT_STATUS_IS_OK(d.out.result)) {
5037 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5038 ret = false;
5041 return ret;
5044 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5045 struct torture_context *tctx,
5046 struct policy_handle *domain_handle,
5047 const char *alias_name,
5048 struct policy_handle *alias_handle,
5049 const struct dom_sid *domain_sid,
5050 bool test_alias)
5052 struct samr_CreateDomAlias r;
5053 struct lsa_String name;
5054 uint32_t rid;
5055 bool ret = true;
5057 init_lsa_String(&name, alias_name);
5058 r.in.domain_handle = domain_handle;
5059 r.in.alias_name = &name;
5060 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5061 r.out.alias_handle = alias_handle;
5062 r.out.rid = &rid;
5064 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5066 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5067 "CreateDomAlias failed");
5069 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5070 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5071 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5072 return true;
5073 } else {
5074 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5075 nt_errstr(r.out.result));
5076 return false;
5080 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5081 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5082 return false;
5084 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5085 "CreateDomAlias failed");
5088 if (!NT_STATUS_IS_OK(r.out.result)) {
5089 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5090 return false;
5093 if (!test_alias) {
5094 return ret;
5097 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5098 ret = false;
5101 return ret;
5104 static bool test_ChangePassword(struct dcerpc_pipe *p,
5105 struct torture_context *tctx,
5106 const char *acct_name,
5107 struct policy_handle *domain_handle, char **password)
5109 bool ret = true;
5110 struct dcerpc_binding_handle *b = p->binding_handle;
5112 if (!*password) {
5113 return false;
5116 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5117 ret = false;
5120 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5121 ret = false;
5124 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5125 ret = false;
5128 /* test what happens when setting the old password again */
5129 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5130 ret = false;
5134 char simple_pass[9];
5135 char *v = generate_random_str(tctx, 1);
5137 ZERO_STRUCT(simple_pass);
5138 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5140 /* test what happens when picking a simple password */
5141 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5142 ret = false;
5146 /* set samr_SetDomainInfo level 1 with min_length 5 */
5148 struct samr_QueryDomainInfo r;
5149 union samr_DomainInfo *info = NULL;
5150 struct samr_SetDomainInfo s;
5151 uint16_t len_old, len;
5152 uint32_t pwd_prop_old;
5153 int64_t min_pwd_age_old;
5155 len = 5;
5157 r.in.domain_handle = domain_handle;
5158 r.in.level = 1;
5159 r.out.info = &info;
5161 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5162 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5163 "QueryDomainInfo failed");
5164 if (!NT_STATUS_IS_OK(r.out.result)) {
5165 return false;
5168 s.in.domain_handle = domain_handle;
5169 s.in.level = 1;
5170 s.in.info = info;
5172 /* remember the old min length, so we can reset it */
5173 len_old = s.in.info->info1.min_password_length;
5174 s.in.info->info1.min_password_length = len;
5175 pwd_prop_old = s.in.info->info1.password_properties;
5176 /* turn off password complexity checks for this test */
5177 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5179 min_pwd_age_old = s.in.info->info1.min_password_age;
5180 s.in.info->info1.min_password_age = 0;
5182 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5183 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5184 "SetDomainInfo failed");
5185 if (!NT_STATUS_IS_OK(s.out.result)) {
5186 return false;
5189 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5191 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5192 ret = false;
5195 s.in.info->info1.min_password_length = len_old;
5196 s.in.info->info1.password_properties = pwd_prop_old;
5197 s.in.info->info1.min_password_age = min_pwd_age_old;
5199 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5200 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5201 "SetDomainInfo failed");
5202 if (!NT_STATUS_IS_OK(s.out.result)) {
5203 return false;
5209 struct samr_OpenUser r;
5210 struct samr_QueryUserInfo q;
5211 union samr_UserInfo *info;
5212 struct samr_LookupNames n;
5213 struct policy_handle user_handle;
5214 struct samr_Ids rids, types;
5216 n.in.domain_handle = domain_handle;
5217 n.in.num_names = 1;
5218 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5219 n.in.names[0].string = acct_name;
5220 n.out.rids = &rids;
5221 n.out.types = &types;
5223 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5224 "LookupNames failed");
5225 if (!NT_STATUS_IS_OK(n.out.result)) {
5226 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5227 return false;
5230 r.in.domain_handle = domain_handle;
5231 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5232 r.in.rid = n.out.rids->ids[0];
5233 r.out.user_handle = &user_handle;
5235 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5236 "OpenUser failed");
5237 if (!NT_STATUS_IS_OK(r.out.result)) {
5238 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5239 return false;
5242 q.in.user_handle = &user_handle;
5243 q.in.level = 5;
5244 q.out.info = &info;
5246 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5247 "QueryUserInfo failed");
5248 if (!NT_STATUS_IS_OK(q.out.result)) {
5249 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5250 return false;
5253 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5255 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5256 info->info5.last_password_change, true)) {
5257 ret = false;
5261 /* we change passwords twice - this has the effect of verifying
5262 they were changed correctly for the final call */
5263 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5264 ret = false;
5267 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5268 ret = false;
5271 return ret;
5274 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5275 struct policy_handle *domain_handle,
5276 const char *user_name,
5277 struct policy_handle *user_handle_out,
5278 struct dom_sid *domain_sid,
5279 enum torture_samr_choice which_ops,
5280 struct cli_credentials *machine_credentials,
5281 bool test_user)
5284 TALLOC_CTX *user_ctx;
5286 struct samr_CreateUser r;
5287 struct samr_QueryUserInfo q;
5288 union samr_UserInfo *info;
5289 struct samr_DeleteUser d;
5290 uint32_t rid;
5292 /* This call creates a 'normal' account - check that it really does */
5293 const uint32_t acct_flags = ACB_NORMAL;
5294 struct lsa_String name;
5295 bool ret = true;
5296 struct dcerpc_binding_handle *b = p->binding_handle;
5298 struct policy_handle user_handle;
5299 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5300 init_lsa_String(&name, user_name);
5302 r.in.domain_handle = domain_handle;
5303 r.in.account_name = &name;
5304 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5305 r.out.user_handle = &user_handle;
5306 r.out.rid = &rid;
5308 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5310 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5311 "CreateUser failed");
5313 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5314 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5315 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5316 return true;
5317 } else {
5318 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5319 nt_errstr(r.out.result));
5320 return false;
5324 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5325 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5326 talloc_free(user_ctx);
5327 return false;
5329 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5330 "CreateUser failed");
5333 if (!NT_STATUS_IS_OK(r.out.result)) {
5334 talloc_free(user_ctx);
5335 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5336 return false;
5339 if (!test_user) {
5340 if (user_handle_out) {
5341 *user_handle_out = user_handle;
5343 return ret;
5347 q.in.user_handle = &user_handle;
5348 q.in.level = 16;
5349 q.out.info = &info;
5351 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5352 "QueryUserInfo failed");
5353 if (!NT_STATUS_IS_OK(q.out.result)) {
5354 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5355 q.in.level, nt_errstr(q.out.result));
5356 ret = false;
5357 } else {
5358 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5359 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5360 info->info16.acct_flags,
5361 acct_flags);
5362 ret = false;
5366 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5367 domain_sid, acct_flags, name.string, which_ops,
5368 machine_credentials)) {
5369 ret = false;
5372 if (user_handle_out) {
5373 *user_handle_out = user_handle;
5374 } else {
5375 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5377 d.in.user_handle = &user_handle;
5378 d.out.user_handle = &user_handle;
5380 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5381 "DeleteUser failed");
5382 if (!NT_STATUS_IS_OK(d.out.result)) {
5383 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5384 ret = false;
5390 talloc_free(user_ctx);
5392 return ret;
5396 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5397 struct policy_handle *domain_handle,
5398 struct dom_sid *domain_sid,
5399 enum torture_samr_choice which_ops,
5400 struct cli_credentials *machine_credentials)
5402 struct samr_CreateUser2 r;
5403 struct samr_QueryUserInfo q;
5404 union samr_UserInfo *info;
5405 struct samr_DeleteUser d;
5406 struct policy_handle user_handle;
5407 uint32_t rid;
5408 struct lsa_String name;
5409 bool ret = true;
5410 int i;
5411 struct dcerpc_binding_handle *b = p->binding_handle;
5413 struct {
5414 uint32_t acct_flags;
5415 const char *account_name;
5416 NTSTATUS nt_status;
5417 } account_types[] = {
5418 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5419 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5420 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5421 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5422 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5423 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5424 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5425 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5426 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5427 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5428 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5429 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5430 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5431 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5432 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5435 for (i = 0; account_types[i].account_name; i++) {
5436 TALLOC_CTX *user_ctx;
5437 uint32_t acct_flags = account_types[i].acct_flags;
5438 uint32_t access_granted;
5439 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5440 init_lsa_String(&name, account_types[i].account_name);
5442 r.in.domain_handle = domain_handle;
5443 r.in.account_name = &name;
5444 r.in.acct_flags = acct_flags;
5445 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5446 r.out.user_handle = &user_handle;
5447 r.out.access_granted = &access_granted;
5448 r.out.rid = &rid;
5450 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5452 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5453 "CreateUser2 failed");
5455 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5456 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5457 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5458 continue;
5459 } else {
5460 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5461 nt_errstr(r.out.result));
5462 ret = false;
5463 continue;
5467 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5468 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5469 talloc_free(user_ctx);
5470 ret = false;
5471 continue;
5473 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5474 "CreateUser2 failed");
5477 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5478 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5479 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5480 ret = false;
5483 if (NT_STATUS_IS_OK(r.out.result)) {
5484 q.in.user_handle = &user_handle;
5485 q.in.level = 5;
5486 q.out.info = &info;
5488 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5489 "QueryUserInfo failed");
5490 if (!NT_STATUS_IS_OK(q.out.result)) {
5491 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5492 q.in.level, nt_errstr(q.out.result));
5493 ret = false;
5494 } else {
5495 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5496 if (acct_flags == ACB_NORMAL) {
5497 expected_flags |= ACB_PW_EXPIRED;
5499 if ((info->info5.acct_flags) != expected_flags) {
5500 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5501 info->info5.acct_flags,
5502 expected_flags);
5503 ret = false;
5505 switch (acct_flags) {
5506 case ACB_SVRTRUST:
5507 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5508 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5509 DOMAIN_RID_DCS, info->info5.primary_gid);
5510 ret = false;
5512 break;
5513 case ACB_WSTRUST:
5514 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5515 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5516 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5517 ret = false;
5519 break;
5520 case ACB_NORMAL:
5521 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5522 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5523 DOMAIN_RID_USERS, info->info5.primary_gid);
5524 ret = false;
5526 break;
5530 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5531 domain_sid, acct_flags, name.string, which_ops,
5532 machine_credentials)) {
5533 ret = false;
5536 if (!policy_handle_empty(&user_handle)) {
5537 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5539 d.in.user_handle = &user_handle;
5540 d.out.user_handle = &user_handle;
5542 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5543 "DeleteUser failed");
5544 if (!NT_STATUS_IS_OK(d.out.result)) {
5545 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5546 ret = false;
5550 talloc_free(user_ctx);
5553 return ret;
5556 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5557 struct torture_context *tctx,
5558 struct policy_handle *handle)
5560 struct samr_QueryAliasInfo r;
5561 union samr_AliasInfo *info;
5562 uint16_t levels[] = {1, 2, 3};
5563 int i;
5564 bool ret = true;
5566 for (i=0;i<ARRAY_SIZE(levels);i++) {
5567 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5569 r.in.alias_handle = handle;
5570 r.in.level = levels[i];
5571 r.out.info = &info;
5573 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5574 "QueryAliasInfo failed");
5575 if (!NT_STATUS_IS_OK(r.out.result)) {
5576 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5577 levels[i], nt_errstr(r.out.result));
5578 ret = false;
5582 return ret;
5585 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5586 struct torture_context *tctx,
5587 struct policy_handle *handle)
5589 struct samr_QueryGroupInfo r;
5590 union samr_GroupInfo *info;
5591 uint16_t levels[] = {1, 2, 3, 4, 5};
5592 int i;
5593 bool ret = true;
5595 for (i=0;i<ARRAY_SIZE(levels);i++) {
5596 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5598 r.in.group_handle = handle;
5599 r.in.level = levels[i];
5600 r.out.info = &info;
5602 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5603 "QueryGroupInfo failed");
5604 if (!NT_STATUS_IS_OK(r.out.result)) {
5605 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5606 levels[i], nt_errstr(r.out.result));
5607 ret = false;
5611 return ret;
5614 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5615 struct torture_context *tctx,
5616 struct policy_handle *handle)
5618 struct samr_QueryGroupMember r;
5619 struct samr_RidTypeArray *rids = NULL;
5620 bool ret = true;
5622 torture_comment(tctx, "Testing QueryGroupMember\n");
5624 r.in.group_handle = handle;
5625 r.out.rids = &rids;
5627 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5628 "QueryGroupMember failed");
5629 if (!NT_STATUS_IS_OK(r.out.result)) {
5630 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(r.out.result));
5631 ret = false;
5634 return ret;
5638 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5639 struct torture_context *tctx,
5640 struct policy_handle *handle)
5642 struct samr_QueryGroupInfo r;
5643 union samr_GroupInfo *info;
5644 struct samr_SetGroupInfo s;
5645 uint16_t levels[] = {1, 2, 3, 4};
5646 uint16_t set_ok[] = {0, 1, 1, 1};
5647 int i;
5648 bool ret = true;
5650 for (i=0;i<ARRAY_SIZE(levels);i++) {
5651 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5653 r.in.group_handle = handle;
5654 r.in.level = levels[i];
5655 r.out.info = &info;
5657 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5658 "QueryGroupInfo failed");
5659 if (!NT_STATUS_IS_OK(r.out.result)) {
5660 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5661 levels[i], nt_errstr(r.out.result));
5662 ret = false;
5665 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5667 s.in.group_handle = handle;
5668 s.in.level = levels[i];
5669 s.in.info = *r.out.info;
5671 #if 0
5672 /* disabled this, as it changes the name only from the point of view of samr,
5673 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5674 the name is still reserved, so creating the old name fails, but deleting by the old name
5675 also fails */
5676 if (s.in.level == 2) {
5677 init_lsa_String(&s.in.info->string, "NewName");
5679 #endif
5681 if (s.in.level == 4) {
5682 init_lsa_String(&s.in.info->description, "test description");
5685 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5686 "SetGroupInfo failed");
5687 if (set_ok[i]) {
5688 if (!NT_STATUS_IS_OK(s.out.result)) {
5689 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5690 r.in.level, nt_errstr(s.out.result));
5691 ret = false;
5692 continue;
5694 } else {
5695 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5696 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5697 r.in.level, nt_errstr(s.out.result));
5698 ret = false;
5699 continue;
5704 return ret;
5707 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5708 struct torture_context *tctx,
5709 struct policy_handle *handle)
5711 struct samr_QueryUserInfo r;
5712 union samr_UserInfo *info;
5713 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5714 11, 12, 13, 14, 16, 17, 20, 21};
5715 int i;
5716 bool ret = true;
5718 for (i=0;i<ARRAY_SIZE(levels);i++) {
5719 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5721 r.in.user_handle = handle;
5722 r.in.level = levels[i];
5723 r.out.info = &info;
5725 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5726 "QueryUserInfo failed");
5727 if (!NT_STATUS_IS_OK(r.out.result)) {
5728 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5729 levels[i], nt_errstr(r.out.result));
5730 ret = false;
5734 return ret;
5737 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5738 struct torture_context *tctx,
5739 struct policy_handle *handle)
5741 struct samr_QueryUserInfo2 r;
5742 union samr_UserInfo *info;
5743 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5744 11, 12, 13, 14, 16, 17, 20, 21};
5745 int i;
5746 bool ret = true;
5748 for (i=0;i<ARRAY_SIZE(levels);i++) {
5749 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5751 r.in.user_handle = handle;
5752 r.in.level = levels[i];
5753 r.out.info = &info;
5755 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5756 "QueryUserInfo2 failed");
5757 if (!NT_STATUS_IS_OK(r.out.result)) {
5758 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5759 levels[i], nt_errstr(r.out.result));
5760 ret = false;
5764 return ret;
5767 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5768 struct torture_context *tctx,
5769 struct policy_handle *handle, uint32_t rid)
5771 struct samr_OpenUser r;
5772 struct policy_handle user_handle;
5773 bool ret = true;
5775 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5777 r.in.domain_handle = handle;
5778 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5779 r.in.rid = rid;
5780 r.out.user_handle = &user_handle;
5782 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5783 "OpenUser failed");
5784 if (!NT_STATUS_IS_OK(r.out.result)) {
5785 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5786 return false;
5789 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5790 ret = false;
5793 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5794 ret = false;
5797 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5798 ret = false;
5801 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5802 ret = false;
5805 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5806 ret = false;
5809 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5810 ret = false;
5813 return ret;
5816 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5817 struct torture_context *tctx,
5818 struct policy_handle *handle, uint32_t rid)
5820 struct samr_OpenGroup r;
5821 struct policy_handle group_handle;
5822 bool ret = true;
5824 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5826 r.in.domain_handle = handle;
5827 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5828 r.in.rid = rid;
5829 r.out.group_handle = &group_handle;
5831 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5832 "OpenGroup failed");
5833 if (!NT_STATUS_IS_OK(r.out.result)) {
5834 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5835 return false;
5838 if (!torture_setting_bool(tctx, "samba3", false)) {
5839 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5840 ret = false;
5844 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5845 ret = false;
5848 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5849 ret = false;
5852 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5853 ret = false;
5856 return ret;
5859 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5860 struct torture_context *tctx,
5861 struct policy_handle *handle, uint32_t rid)
5863 struct samr_OpenAlias r;
5864 struct policy_handle alias_handle;
5865 bool ret = true;
5867 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5869 r.in.domain_handle = handle;
5870 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5871 r.in.rid = rid;
5872 r.out.alias_handle = &alias_handle;
5874 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5875 "OpenAlias failed");
5876 if (!NT_STATUS_IS_OK(r.out.result)) {
5877 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5878 return false;
5881 if (!torture_setting_bool(tctx, "samba3", false)) {
5882 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5883 ret = false;
5887 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
5888 ret = false;
5891 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
5892 ret = false;
5895 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
5896 ret = false;
5899 return ret;
5902 static bool check_mask(struct dcerpc_binding_handle *b,
5903 struct torture_context *tctx,
5904 struct policy_handle *handle, uint32_t rid,
5905 uint32_t acct_flag_mask)
5907 struct samr_OpenUser r;
5908 struct samr_QueryUserInfo q;
5909 union samr_UserInfo *info;
5910 struct policy_handle user_handle;
5911 bool ret = true;
5913 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5915 r.in.domain_handle = handle;
5916 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5917 r.in.rid = rid;
5918 r.out.user_handle = &user_handle;
5920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5921 "OpenUser failed");
5922 if (!NT_STATUS_IS_OK(r.out.result)) {
5923 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5924 return false;
5927 q.in.user_handle = &user_handle;
5928 q.in.level = 16;
5929 q.out.info = &info;
5931 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5932 "QueryUserInfo failed");
5933 if (!NT_STATUS_IS_OK(q.out.result)) {
5934 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5935 nt_errstr(q.out.result));
5936 ret = false;
5937 } else {
5938 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5939 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5940 acct_flag_mask, info->info16.acct_flags, rid);
5941 ret = false;
5945 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5946 ret = false;
5949 return ret;
5952 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
5953 struct torture_context *tctx,
5954 struct policy_handle *handle)
5956 struct samr_EnumDomainUsers r;
5957 uint32_t mask, resume_handle=0;
5958 int i, mask_idx;
5959 bool ret = true;
5960 struct samr_LookupNames n;
5961 struct samr_LookupRids lr ;
5962 struct lsa_Strings names;
5963 struct samr_Ids rids, types;
5964 struct samr_SamArray *sam = NULL;
5965 uint32_t num_entries = 0;
5967 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5968 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5969 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5970 ACB_PWNOEXP, 0};
5972 torture_comment(tctx, "Testing EnumDomainUsers\n");
5974 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5975 r.in.domain_handle = handle;
5976 r.in.resume_handle = &resume_handle;
5977 r.in.acct_flags = mask = masks[mask_idx];
5978 r.in.max_size = (uint32_t)-1;
5979 r.out.resume_handle = &resume_handle;
5980 r.out.num_entries = &num_entries;
5981 r.out.sam = &sam;
5983 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
5984 "EnumDomainUsers failed");
5985 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
5986 !NT_STATUS_IS_OK(r.out.result)) {
5987 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
5988 return false;
5991 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5993 if (sam->count == 0) {
5994 continue;
5997 for (i=0;i<sam->count;i++) {
5998 if (mask) {
5999 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6000 ret = false;
6002 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6003 ret = false;
6008 torture_comment(tctx, "Testing LookupNames\n");
6009 n.in.domain_handle = handle;
6010 n.in.num_names = sam->count;
6011 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6012 n.out.rids = &rids;
6013 n.out.types = &types;
6014 for (i=0;i<sam->count;i++) {
6015 n.in.names[i].string = sam->entries[i].name.string;
6017 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6018 "LookupNames failed");
6019 if (!NT_STATUS_IS_OK(n.out.result)) {
6020 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6021 ret = false;
6025 torture_comment(tctx, "Testing LookupRids\n");
6026 lr.in.domain_handle = handle;
6027 lr.in.num_rids = sam->count;
6028 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6029 lr.out.names = &names;
6030 lr.out.types = &types;
6031 for (i=0;i<sam->count;i++) {
6032 lr.in.rids[i] = sam->entries[i].idx;
6034 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6035 "LookupRids failed");
6036 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6038 return ret;
6042 try blasting the server with a bunch of sync requests
6044 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6045 struct policy_handle *handle)
6047 struct samr_EnumDomainUsers r;
6048 uint32_t resume_handle=0;
6049 int i;
6050 #define ASYNC_COUNT 100
6051 struct tevent_req *req[ASYNC_COUNT];
6053 if (!torture_setting_bool(tctx, "dangerous", false)) {
6054 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6057 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6059 r.in.domain_handle = handle;
6060 r.in.resume_handle = &resume_handle;
6061 r.in.acct_flags = 0;
6062 r.in.max_size = (uint32_t)-1;
6063 r.out.resume_handle = &resume_handle;
6065 for (i=0;i<ASYNC_COUNT;i++) {
6066 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6069 for (i=0;i<ASYNC_COUNT;i++) {
6070 tevent_req_poll(req[i], tctx->ev);
6071 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6072 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6073 i, nt_errstr(r.out.result)));
6076 torture_comment(tctx, "%d async requests OK\n", i);
6078 return true;
6081 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6082 struct torture_context *tctx,
6083 struct policy_handle *handle)
6085 struct samr_EnumDomainGroups r;
6086 uint32_t resume_handle=0;
6087 struct samr_SamArray *sam = NULL;
6088 uint32_t num_entries = 0;
6089 int i;
6090 bool ret = true;
6091 bool universal_group_found = false;
6093 torture_comment(tctx, "Testing EnumDomainGroups\n");
6095 r.in.domain_handle = handle;
6096 r.in.resume_handle = &resume_handle;
6097 r.in.max_size = (uint32_t)-1;
6098 r.out.resume_handle = &resume_handle;
6099 r.out.num_entries = &num_entries;
6100 r.out.sam = &sam;
6102 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6103 "EnumDomainGroups failed");
6104 if (!NT_STATUS_IS_OK(r.out.result)) {
6105 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6106 return false;
6109 if (!sam) {
6110 return false;
6113 for (i=0;i<sam->count;i++) {
6114 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6115 ret = false;
6117 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6118 "Enterprise Admins") == 0)) {
6119 universal_group_found = true;
6123 /* when we are running this on s4 we should get back at least the
6124 * "Enterprise Admins" universal group. If we don't get a group entry
6125 * at all we probably are performing the test on the builtin domain.
6126 * So ignore this case. */
6127 if (torture_setting_bool(tctx, "samba4", false)) {
6128 if ((sam->count > 0) && (!universal_group_found)) {
6129 ret = false;
6133 return ret;
6136 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6137 struct torture_context *tctx,
6138 struct policy_handle *handle)
6140 struct samr_EnumDomainAliases r;
6141 uint32_t resume_handle=0;
6142 struct samr_SamArray *sam = NULL;
6143 uint32_t num_entries = 0;
6144 int i;
6145 bool ret = true;
6147 torture_comment(tctx, "Testing EnumDomainAliases\n");
6149 r.in.domain_handle = handle;
6150 r.in.resume_handle = &resume_handle;
6151 r.in.max_size = (uint32_t)-1;
6152 r.out.sam = &sam;
6153 r.out.num_entries = &num_entries;
6154 r.out.resume_handle = &resume_handle;
6156 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6157 "EnumDomainAliases failed");
6158 if (!NT_STATUS_IS_OK(r.out.result)) {
6159 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6160 return false;
6163 if (!sam) {
6164 return false;
6167 for (i=0;i<sam->count;i++) {
6168 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6169 ret = false;
6173 return ret;
6176 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6177 struct torture_context *tctx,
6178 struct policy_handle *handle)
6180 struct samr_GetDisplayEnumerationIndex r;
6181 bool ret = true;
6182 uint16_t levels[] = {1, 2, 3, 4, 5};
6183 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6184 struct lsa_String name;
6185 uint32_t idx = 0;
6186 int i;
6188 for (i=0;i<ARRAY_SIZE(levels);i++) {
6189 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6191 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6193 r.in.domain_handle = handle;
6194 r.in.level = levels[i];
6195 r.in.name = &name;
6196 r.out.idx = &idx;
6198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6199 "GetDisplayEnumerationIndex failed");
6201 if (ok_lvl[i] &&
6202 !NT_STATUS_IS_OK(r.out.result) &&
6203 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6204 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6205 levels[i], nt_errstr(r.out.result));
6206 ret = false;
6209 init_lsa_String(&name, "zzzzzzzz");
6211 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6212 "GetDisplayEnumerationIndex failed");
6214 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6215 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6216 levels[i], nt_errstr(r.out.result));
6217 ret = false;
6221 return ret;
6224 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6225 struct torture_context *tctx,
6226 struct policy_handle *handle)
6228 struct samr_GetDisplayEnumerationIndex2 r;
6229 bool ret = true;
6230 uint16_t levels[] = {1, 2, 3, 4, 5};
6231 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6232 struct lsa_String name;
6233 uint32_t idx = 0;
6234 int i;
6236 for (i=0;i<ARRAY_SIZE(levels);i++) {
6237 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6239 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6241 r.in.domain_handle = handle;
6242 r.in.level = levels[i];
6243 r.in.name = &name;
6244 r.out.idx = &idx;
6246 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6247 "GetDisplayEnumerationIndex2 failed");
6248 if (ok_lvl[i] &&
6249 !NT_STATUS_IS_OK(r.out.result) &&
6250 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6251 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6252 levels[i], nt_errstr(r.out.result));
6253 ret = false;
6256 init_lsa_String(&name, "zzzzzzzz");
6258 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6259 "GetDisplayEnumerationIndex2 failed");
6260 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6261 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6262 levels[i], nt_errstr(r.out.result));
6263 ret = false;
6267 return ret;
6270 #define STRING_EQUAL_QUERY(s1, s2, user) \
6271 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6272 /* odd, but valid */ \
6273 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6274 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6275 #s1, user.string, s1.string, s2.string, __location__); \
6276 ret = false; \
6278 #define INT_EQUAL_QUERY(s1, s2, user) \
6279 if (s1 != s2) { \
6280 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6281 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6282 ret = false; \
6285 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6286 struct torture_context *tctx,
6287 struct samr_QueryDisplayInfo *querydisplayinfo,
6288 bool *seen_testuser)
6290 struct samr_OpenUser r;
6291 struct samr_QueryUserInfo q;
6292 union samr_UserInfo *info;
6293 struct policy_handle user_handle;
6294 int i, ret = true;
6295 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6296 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6297 for (i = 0; ; i++) {
6298 switch (querydisplayinfo->in.level) {
6299 case 1:
6300 if (i >= querydisplayinfo->out.info->info1.count) {
6301 return ret;
6303 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6304 break;
6305 case 2:
6306 if (i >= querydisplayinfo->out.info->info2.count) {
6307 return ret;
6309 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6310 break;
6311 case 3:
6312 /* Groups */
6313 case 4:
6314 case 5:
6315 /* Not interested in validating just the account name */
6316 return true;
6319 r.out.user_handle = &user_handle;
6321 switch (querydisplayinfo->in.level) {
6322 case 1:
6323 case 2:
6324 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6325 "OpenUser failed");
6326 if (!NT_STATUS_IS_OK(r.out.result)) {
6327 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6328 return false;
6332 q.in.user_handle = &user_handle;
6333 q.in.level = 21;
6334 q.out.info = &info;
6335 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6336 "QueryUserInfo failed");
6337 if (!NT_STATUS_IS_OK(r.out.result)) {
6338 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6339 return false;
6342 switch (querydisplayinfo->in.level) {
6343 case 1:
6344 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6345 *seen_testuser = true;
6347 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6348 info->info21.full_name, info->info21.account_name);
6349 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6350 info->info21.account_name, info->info21.account_name);
6351 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6352 info->info21.description, info->info21.account_name);
6353 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6354 info->info21.rid, info->info21.account_name);
6355 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6356 info->info21.acct_flags, info->info21.account_name);
6358 break;
6359 case 2:
6360 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6361 info->info21.account_name, info->info21.account_name);
6362 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6363 info->info21.description, info->info21.account_name);
6364 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6365 info->info21.rid, info->info21.account_name);
6366 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6367 info->info21.acct_flags, info->info21.account_name);
6369 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6370 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6371 info->info21.account_name.string);
6374 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6375 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6376 info->info21.account_name.string,
6377 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6378 info->info21.acct_flags);
6379 return false;
6382 break;
6385 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6386 return false;
6389 return ret;
6392 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6393 struct torture_context *tctx,
6394 struct policy_handle *handle)
6396 struct samr_QueryDisplayInfo r;
6397 struct samr_QueryDomainInfo dom_info;
6398 union samr_DomainInfo *info = NULL;
6399 bool ret = true;
6400 uint16_t levels[] = {1, 2, 3, 4, 5};
6401 int i;
6402 bool seen_testuser = false;
6403 uint32_t total_size;
6404 uint32_t returned_size;
6405 union samr_DispInfo disp_info;
6408 for (i=0;i<ARRAY_SIZE(levels);i++) {
6409 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6411 r.in.start_idx = 0;
6412 r.out.result = STATUS_MORE_ENTRIES;
6413 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6414 r.in.domain_handle = handle;
6415 r.in.level = levels[i];
6416 r.in.max_entries = 2;
6417 r.in.buf_size = (uint32_t)-1;
6418 r.out.total_size = &total_size;
6419 r.out.returned_size = &returned_size;
6420 r.out.info = &disp_info;
6422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6423 "QueryDisplayInfo failed");
6424 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6425 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6426 levels[i], nt_errstr(r.out.result));
6427 ret = false;
6429 switch (r.in.level) {
6430 case 1:
6431 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6432 ret = false;
6434 r.in.start_idx += r.out.info->info1.count;
6435 break;
6436 case 2:
6437 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6438 ret = false;
6440 r.in.start_idx += r.out.info->info2.count;
6441 break;
6442 case 3:
6443 r.in.start_idx += r.out.info->info3.count;
6444 break;
6445 case 4:
6446 r.in.start_idx += r.out.info->info4.count;
6447 break;
6448 case 5:
6449 r.in.start_idx += r.out.info->info5.count;
6450 break;
6453 dom_info.in.domain_handle = handle;
6454 dom_info.in.level = 2;
6455 dom_info.out.info = &info;
6457 /* Check number of users returned is correct */
6458 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6459 "QueryDomainInfo failed");
6460 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6461 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6462 r.in.level, nt_errstr(dom_info.out.result));
6463 ret = false;
6464 break;
6466 switch (r.in.level) {
6467 case 1:
6468 case 4:
6469 if (info->general.num_users < r.in.start_idx) {
6470 /* On AD deployments this numbers don't match
6471 * since QueryDisplayInfo returns universal and
6472 * global groups, QueryDomainInfo only global
6473 * ones. */
6474 if (torture_setting_bool(tctx, "samba3", false)) {
6475 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6476 r.in.start_idx, info->general.num_groups,
6477 info->general.domain_name.string);
6478 ret = false;
6481 if (!seen_testuser) {
6482 struct policy_handle user_handle;
6483 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6484 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6485 info->general.domain_name.string);
6486 ret = false;
6487 test_samr_handle_Close(b, tctx, &user_handle);
6490 break;
6491 case 3:
6492 case 5:
6493 if (info->general.num_groups != r.in.start_idx) {
6494 /* On AD deployments this numbers don't match
6495 * since QueryDisplayInfo returns universal and
6496 * global groups, QueryDomainInfo only global
6497 * ones. */
6498 if (torture_setting_bool(tctx, "samba3", false)) {
6499 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6500 r.in.start_idx, info->general.num_groups,
6501 info->general.domain_name.string);
6502 ret = false;
6506 break;
6511 return ret;
6514 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6515 struct torture_context *tctx,
6516 struct policy_handle *handle)
6518 struct samr_QueryDisplayInfo2 r;
6519 bool ret = true;
6520 uint16_t levels[] = {1, 2, 3, 4, 5};
6521 int i;
6522 uint32_t total_size;
6523 uint32_t returned_size;
6524 union samr_DispInfo info;
6526 for (i=0;i<ARRAY_SIZE(levels);i++) {
6527 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6529 r.in.domain_handle = handle;
6530 r.in.level = levels[i];
6531 r.in.start_idx = 0;
6532 r.in.max_entries = 1000;
6533 r.in.buf_size = (uint32_t)-1;
6534 r.out.total_size = &total_size;
6535 r.out.returned_size = &returned_size;
6536 r.out.info = &info;
6538 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6539 "QueryDisplayInfo2 failed");
6540 if (!NT_STATUS_IS_OK(r.out.result)) {
6541 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6542 levels[i], nt_errstr(r.out.result));
6543 ret = false;
6547 return ret;
6550 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6551 struct torture_context *tctx,
6552 struct policy_handle *handle)
6554 struct samr_QueryDisplayInfo3 r;
6555 bool ret = true;
6556 uint16_t levels[] = {1, 2, 3, 4, 5};
6557 int i;
6558 uint32_t total_size;
6559 uint32_t returned_size;
6560 union samr_DispInfo info;
6562 for (i=0;i<ARRAY_SIZE(levels);i++) {
6563 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6565 r.in.domain_handle = handle;
6566 r.in.level = levels[i];
6567 r.in.start_idx = 0;
6568 r.in.max_entries = 1000;
6569 r.in.buf_size = (uint32_t)-1;
6570 r.out.total_size = &total_size;
6571 r.out.returned_size = &returned_size;
6572 r.out.info = &info;
6574 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6575 "QueryDisplayInfo3 failed");
6576 if (!NT_STATUS_IS_OK(r.out.result)) {
6577 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6578 levels[i], nt_errstr(r.out.result));
6579 ret = false;
6583 return ret;
6587 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6588 struct torture_context *tctx,
6589 struct policy_handle *handle)
6591 struct samr_QueryDisplayInfo r;
6592 bool ret = true;
6593 uint32_t total_size;
6594 uint32_t returned_size;
6595 union samr_DispInfo info;
6597 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6599 r.in.domain_handle = handle;
6600 r.in.level = 1;
6601 r.in.start_idx = 0;
6602 r.in.max_entries = 1;
6603 r.in.buf_size = (uint32_t)-1;
6604 r.out.total_size = &total_size;
6605 r.out.returned_size = &returned_size;
6606 r.out.info = &info;
6608 do {
6609 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6610 "QueryDisplayInfo failed");
6611 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6612 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6613 torture_warning(tctx, "expected idx %d but got %d\n",
6614 r.in.start_idx + 1,
6615 r.out.info->info1.entries[0].idx);
6616 break;
6619 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6620 !NT_STATUS_IS_OK(r.out.result)) {
6621 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6622 r.in.level, nt_errstr(r.out.result));
6623 ret = false;
6624 break;
6626 r.in.start_idx++;
6627 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6628 NT_STATUS_IS_OK(r.out.result)) &&
6629 *r.out.returned_size != 0);
6631 return ret;
6634 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6635 struct torture_context *tctx,
6636 struct policy_handle *handle)
6638 struct samr_QueryDomainInfo r;
6639 union samr_DomainInfo *info = NULL;
6640 struct samr_SetDomainInfo s;
6641 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6642 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6643 int i;
6644 bool ret = true;
6645 struct dcerpc_binding_handle *b = p->binding_handle;
6646 const char *domain_comment = talloc_asprintf(tctx,
6647 "Tortured by Samba4 RPC-SAMR: %s",
6648 timestring(tctx, time(NULL)));
6650 s.in.domain_handle = handle;
6651 s.in.level = 4;
6652 s.in.info = talloc(tctx, union samr_DomainInfo);
6654 s.in.info->oem.oem_information.string = domain_comment;
6655 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6656 "SetDomainInfo failed");
6657 if (!NT_STATUS_IS_OK(s.out.result)) {
6658 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6659 s.in.level, nt_errstr(s.out.result));
6660 return false;
6663 for (i=0;i<ARRAY_SIZE(levels);i++) {
6664 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6666 r.in.domain_handle = handle;
6667 r.in.level = levels[i];
6668 r.out.info = &info;
6670 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6671 "QueryDomainInfo failed");
6672 if (!NT_STATUS_IS_OK(r.out.result)) {
6673 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6674 r.in.level, nt_errstr(r.out.result));
6675 ret = false;
6676 continue;
6679 switch (levels[i]) {
6680 case 2:
6681 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6682 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6683 levels[i], info->general.oem_information.string, domain_comment);
6684 if (!torture_setting_bool(tctx, "samba3", false)) {
6685 ret = false;
6688 if (!info->general.primary.string) {
6689 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6690 levels[i]);
6691 ret = false;
6692 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6693 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6694 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6695 levels[i], info->general.primary.string, dcerpc_server_name(p));
6698 break;
6699 case 4:
6700 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6701 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6702 levels[i], info->oem.oem_information.string, domain_comment);
6703 if (!torture_setting_bool(tctx, "samba3", false)) {
6704 ret = false;
6707 break;
6708 case 6:
6709 if (!info->info6.primary.string) {
6710 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6711 levels[i]);
6712 ret = false;
6714 break;
6715 case 11:
6716 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6717 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6718 levels[i], info->general2.general.oem_information.string, domain_comment);
6719 if (!torture_setting_bool(tctx, "samba3", false)) {
6720 ret = false;
6723 break;
6726 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6728 s.in.domain_handle = handle;
6729 s.in.level = levels[i];
6730 s.in.info = info;
6732 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6733 "SetDomainInfo failed");
6734 if (set_ok[i]) {
6735 if (!NT_STATUS_IS_OK(s.out.result)) {
6736 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6737 r.in.level, nt_errstr(s.out.result));
6738 ret = false;
6739 continue;
6741 } else {
6742 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6743 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6744 r.in.level, nt_errstr(s.out.result));
6745 ret = false;
6746 continue;
6750 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6751 "QueryDomainInfo failed");
6752 if (!NT_STATUS_IS_OK(r.out.result)) {
6753 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6754 r.in.level, nt_errstr(r.out.result));
6755 ret = false;
6756 continue;
6760 return ret;
6764 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6765 struct torture_context *tctx,
6766 struct policy_handle *handle)
6768 struct samr_QueryDomainInfo2 r;
6769 union samr_DomainInfo *info = NULL;
6770 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6771 int i;
6772 bool ret = true;
6774 for (i=0;i<ARRAY_SIZE(levels);i++) {
6775 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6777 r.in.domain_handle = handle;
6778 r.in.level = levels[i];
6779 r.out.info = &info;
6781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6782 "QueryDomainInfo2 failed");
6783 if (!NT_STATUS_IS_OK(r.out.result)) {
6784 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6785 r.in.level, nt_errstr(r.out.result));
6786 ret = false;
6787 continue;
6791 return true;
6794 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6795 set of group names. */
6796 static bool test_GroupList(struct dcerpc_binding_handle *b,
6797 struct torture_context *tctx,
6798 struct policy_handle *handle)
6800 struct samr_EnumDomainGroups q1;
6801 struct samr_QueryDisplayInfo q2;
6802 NTSTATUS status;
6803 uint32_t resume_handle=0;
6804 struct samr_SamArray *sam = NULL;
6805 uint32_t num_entries = 0;
6806 int i;
6807 bool ret = true;
6808 uint32_t total_size;
6809 uint32_t returned_size;
6810 union samr_DispInfo info;
6812 int num_names = 0;
6813 const char **names = NULL;
6815 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6817 q1.in.domain_handle = handle;
6818 q1.in.resume_handle = &resume_handle;
6819 q1.in.max_size = 5;
6820 q1.out.resume_handle = &resume_handle;
6821 q1.out.num_entries = &num_entries;
6822 q1.out.sam = &sam;
6824 status = STATUS_MORE_ENTRIES;
6825 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6826 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6827 "EnumDomainGroups failed");
6828 status = q1.out.result;
6830 if (!NT_STATUS_IS_OK(status) &&
6831 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6832 break;
6834 for (i=0; i<*q1.out.num_entries; i++) {
6835 add_string_to_array(tctx,
6836 sam->entries[i].name.string,
6837 &names, &num_names);
6841 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6843 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6845 q2.in.domain_handle = handle;
6846 q2.in.level = 5;
6847 q2.in.start_idx = 0;
6848 q2.in.max_entries = 5;
6849 q2.in.buf_size = (uint32_t)-1;
6850 q2.out.total_size = &total_size;
6851 q2.out.returned_size = &returned_size;
6852 q2.out.info = &info;
6854 status = STATUS_MORE_ENTRIES;
6855 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6856 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6857 "QueryDisplayInfo failed");
6858 status = q2.out.result;
6859 if (!NT_STATUS_IS_OK(status) &&
6860 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6861 break;
6863 for (i=0; i<q2.out.info->info5.count; i++) {
6864 int j;
6865 const char *name = q2.out.info->info5.entries[i].account_name.string;
6866 bool found = false;
6867 for (j=0; j<num_names; j++) {
6868 if (names[j] == NULL)
6869 continue;
6870 if (strequal(names[j], name)) {
6871 names[j] = NULL;
6872 found = true;
6873 break;
6877 if (!found) {
6878 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6879 name);
6880 ret = false;
6883 q2.in.start_idx += q2.out.info->info5.count;
6886 if (!NT_STATUS_IS_OK(status)) {
6887 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6888 nt_errstr(status));
6889 ret = false;
6892 for (i=0; i<num_names; i++) {
6893 if (names[i] != NULL) {
6894 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6895 names[i]);
6896 ret = false;
6900 return ret;
6903 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
6904 struct torture_context *tctx,
6905 struct policy_handle *group_handle)
6907 struct samr_DeleteDomainGroup d;
6909 torture_comment(tctx, "Testing DeleteDomainGroup\n");
6911 d.in.group_handle = group_handle;
6912 d.out.group_handle = group_handle;
6914 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
6915 "DeleteDomainGroup failed");
6916 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
6918 return true;
6921 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
6922 struct torture_context *tctx,
6923 struct policy_handle *domain_handle)
6925 struct samr_TestPrivateFunctionsDomain r;
6926 bool ret = true;
6928 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6930 r.in.domain_handle = domain_handle;
6932 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
6933 "TestPrivateFunctionsDomain failed");
6934 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6936 return ret;
6939 static bool test_RidToSid(struct dcerpc_binding_handle *b,
6940 struct torture_context *tctx,
6941 struct dom_sid *domain_sid,
6942 struct policy_handle *domain_handle)
6944 struct samr_RidToSid r;
6945 bool ret = true;
6946 struct dom_sid *calc_sid, *out_sid;
6947 int rids[] = { 0, 42, 512, 10200 };
6948 int i;
6950 for (i=0;i<ARRAY_SIZE(rids);i++) {
6951 torture_comment(tctx, "Testing RidToSid\n");
6953 calc_sid = dom_sid_dup(tctx, domain_sid);
6954 r.in.domain_handle = domain_handle;
6955 r.in.rid = rids[i];
6956 r.out.sid = &out_sid;
6958 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
6959 "RidToSid failed");
6960 if (!NT_STATUS_IS_OK(r.out.result)) {
6961 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
6962 ret = false;
6963 } else {
6964 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6966 if (!dom_sid_equal(calc_sid, out_sid)) {
6967 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6968 dom_sid_string(tctx, out_sid),
6969 dom_sid_string(tctx, calc_sid));
6970 ret = false;
6975 return ret;
6978 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
6979 struct torture_context *tctx,
6980 struct policy_handle *domain_handle)
6982 struct samr_GetBootKeyInformation r;
6983 bool ret = true;
6984 uint32_t unknown = 0;
6985 NTSTATUS status;
6987 torture_comment(tctx, "Testing GetBootKeyInformation\n");
6989 r.in.domain_handle = domain_handle;
6990 r.out.unknown = &unknown;
6992 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
6993 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
6994 status = r.out.result;
6996 if (!NT_STATUS_IS_OK(status)) {
6997 /* w2k3 seems to fail this sometimes and pass it sometimes */
6998 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7001 return ret;
7004 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7005 struct torture_context *tctx,
7006 struct policy_handle *domain_handle,
7007 struct policy_handle *group_handle)
7009 NTSTATUS status;
7010 struct samr_AddGroupMember r;
7011 struct samr_DeleteGroupMember d;
7012 struct samr_QueryGroupMember q;
7013 struct samr_RidTypeArray *rids = NULL;
7014 struct samr_SetMemberAttributesOfGroup s;
7015 uint32_t rid;
7016 bool found_member = false;
7017 int i;
7019 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7020 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7022 r.in.group_handle = group_handle;
7023 r.in.rid = rid;
7024 r.in.flags = 0; /* ??? */
7026 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7028 d.in.group_handle = group_handle;
7029 d.in.rid = rid;
7031 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7032 "DeleteGroupMember failed");
7033 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7035 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7036 "AddGroupMember failed");
7037 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7039 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7040 "AddGroupMember failed");
7041 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7043 if (torture_setting_bool(tctx, "samba4", false) ||
7044 torture_setting_bool(tctx, "samba3", false)) {
7045 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7046 } else {
7047 /* this one is quite strange. I am using random inputs in the
7048 hope of triggering an error that might give us a clue */
7050 s.in.group_handle = group_handle;
7051 s.in.unknown1 = random();
7052 s.in.unknown2 = random();
7054 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7055 "SetMemberAttributesOfGroup failed");
7056 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7059 q.in.group_handle = group_handle;
7060 q.out.rids = &rids;
7062 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7063 "QueryGroupMember failed");
7064 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7065 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7067 for (i=0; i < rids->count; i++) {
7068 if (rids->rids[i] == rid) {
7069 found_member = true;
7073 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7075 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7076 "DeleteGroupMember failed");
7077 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7079 rids = NULL;
7080 found_member = false;
7082 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7083 "QueryGroupMember failed");
7084 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7085 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7087 for (i=0; i < rids->count; i++) {
7088 if (rids->rids[i] == rid) {
7089 found_member = true;
7093 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7095 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7096 "AddGroupMember failed");
7097 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7099 return true;
7103 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7104 struct torture_context *tctx,
7105 struct policy_handle *domain_handle,
7106 const char *group_name,
7107 struct policy_handle *group_handle,
7108 struct dom_sid *domain_sid,
7109 bool test_group)
7111 struct samr_CreateDomainGroup r;
7112 uint32_t rid;
7113 struct lsa_String name;
7114 bool ret = true;
7116 init_lsa_String(&name, group_name);
7118 r.in.domain_handle = domain_handle;
7119 r.in.name = &name;
7120 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7121 r.out.group_handle = group_handle;
7122 r.out.rid = &rid;
7124 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7126 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7127 "CreateDomainGroup failed");
7129 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7130 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7131 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7132 return true;
7133 } else {
7134 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7135 nt_errstr(r.out.result));
7136 return false;
7140 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7141 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7142 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7143 nt_errstr(r.out.result));
7144 return false;
7146 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7147 "CreateDomainGroup failed");
7149 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7150 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7152 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7153 nt_errstr(r.out.result));
7154 return false;
7156 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7157 "CreateDomainGroup failed");
7159 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7161 if (!test_group) {
7162 return ret;
7165 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7166 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7167 ret = false;
7170 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7171 ret = false;
7174 return ret;
7179 its not totally clear what this does. It seems to accept any sid you like.
7181 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7182 struct torture_context *tctx,
7183 struct policy_handle *domain_handle)
7185 struct samr_RemoveMemberFromForeignDomain r;
7187 r.in.domain_handle = domain_handle;
7188 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7190 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7191 "RemoveMemberFromForeignDomain failed");
7192 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7194 return true;
7197 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7198 struct torture_context *tctx,
7199 struct policy_handle *domain_handle,
7200 uint32_t *total_num_entries_p)
7202 NTSTATUS status;
7203 struct samr_EnumDomainUsers r;
7204 uint32_t resume_handle = 0;
7205 uint32_t num_entries = 0;
7206 uint32_t total_num_entries = 0;
7207 struct samr_SamArray *sam;
7209 r.in.domain_handle = domain_handle;
7210 r.in.acct_flags = 0;
7211 r.in.max_size = (uint32_t)-1;
7212 r.in.resume_handle = &resume_handle;
7214 r.out.sam = &sam;
7215 r.out.num_entries = &num_entries;
7216 r.out.resume_handle = &resume_handle;
7218 torture_comment(tctx, "Testing EnumDomainUsers\n");
7220 do {
7221 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7222 "EnumDomainUsers failed");
7223 if (NT_STATUS_IS_ERR(r.out.result)) {
7224 torture_assert_ntstatus_ok(tctx, r.out.result,
7225 "failed to enumerate users");
7228 total_num_entries += num_entries;
7229 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7231 if (total_num_entries_p) {
7232 *total_num_entries_p = total_num_entries;
7235 return true;
7238 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7239 struct torture_context *tctx,
7240 struct policy_handle *domain_handle,
7241 uint32_t *total_num_entries_p)
7243 NTSTATUS status;
7244 struct samr_EnumDomainGroups r;
7245 uint32_t resume_handle = 0;
7246 uint32_t num_entries = 0;
7247 uint32_t total_num_entries = 0;
7248 struct samr_SamArray *sam;
7250 r.in.domain_handle = domain_handle;
7251 r.in.max_size = (uint32_t)-1;
7252 r.in.resume_handle = &resume_handle;
7254 r.out.sam = &sam;
7255 r.out.num_entries = &num_entries;
7256 r.out.resume_handle = &resume_handle;
7258 torture_comment(tctx, "Testing EnumDomainGroups\n");
7260 do {
7261 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7262 "EnumDomainGroups failed");
7263 if (NT_STATUS_IS_ERR(r.out.result)) {
7264 torture_assert_ntstatus_ok(tctx, r.out.result,
7265 "failed to enumerate groups");
7268 total_num_entries += num_entries;
7269 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7271 if (total_num_entries_p) {
7272 *total_num_entries_p = total_num_entries;
7275 return true;
7278 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7279 struct torture_context *tctx,
7280 struct policy_handle *domain_handle,
7281 uint32_t *total_num_entries_p)
7283 NTSTATUS status;
7284 struct samr_EnumDomainAliases r;
7285 uint32_t resume_handle = 0;
7286 uint32_t num_entries = 0;
7287 uint32_t total_num_entries = 0;
7288 struct samr_SamArray *sam;
7290 r.in.domain_handle = domain_handle;
7291 r.in.max_size = (uint32_t)-1;
7292 r.in.resume_handle = &resume_handle;
7294 r.out.sam = &sam;
7295 r.out.num_entries = &num_entries;
7296 r.out.resume_handle = &resume_handle;
7298 torture_comment(tctx, "Testing EnumDomainAliases\n");
7300 do {
7301 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7302 "EnumDomainAliases failed");
7303 if (NT_STATUS_IS_ERR(r.out.result)) {
7304 torture_assert_ntstatus_ok(tctx, r.out.result,
7305 "failed to enumerate aliases");
7308 total_num_entries += num_entries;
7309 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7311 if (total_num_entries_p) {
7312 *total_num_entries_p = total_num_entries;
7315 return true;
7318 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7319 struct torture_context *tctx,
7320 struct policy_handle *handle,
7321 uint16_t level,
7322 uint32_t *total_num_entries_p)
7324 NTSTATUS status;
7325 struct samr_QueryDisplayInfo r;
7326 uint32_t total_num_entries = 0;
7328 r.in.domain_handle = handle;
7329 r.in.level = level;
7330 r.in.start_idx = 0;
7331 r.in.max_entries = (uint32_t)-1;
7332 r.in.buf_size = (uint32_t)-1;
7334 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7336 do {
7337 uint32_t total_size;
7338 uint32_t returned_size;
7339 union samr_DispInfo info;
7341 r.out.total_size = &total_size;
7342 r.out.returned_size = &returned_size;
7343 r.out.info = &info;
7345 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7346 "failed to query displayinfo");
7347 if (NT_STATUS_IS_ERR(r.out.result)) {
7348 torture_assert_ntstatus_ok(tctx, r.out.result,
7349 "failed to query displayinfo");
7352 if (*r.out.returned_size == 0) {
7353 break;
7356 switch (r.in.level) {
7357 case 1:
7358 total_num_entries += info.info1.count;
7359 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7360 break;
7361 case 2:
7362 total_num_entries += info.info2.count;
7363 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7364 break;
7365 case 3:
7366 total_num_entries += info.info3.count;
7367 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7368 break;
7369 case 4:
7370 total_num_entries += info.info4.count;
7371 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7372 break;
7373 case 5:
7374 total_num_entries += info.info5.count;
7375 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7376 break;
7377 default:
7378 return false;
7381 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7383 if (total_num_entries_p) {
7384 *total_num_entries_p = total_num_entries;
7387 return true;
7390 static bool test_ManyObjects(struct dcerpc_pipe *p,
7391 struct torture_context *tctx,
7392 struct policy_handle *domain_handle,
7393 struct dom_sid *domain_sid,
7394 struct torture_samr_context *ctx)
7396 uint32_t num_total = ctx->num_objects_large_dc;
7397 uint32_t num_enum = 0;
7398 uint32_t num_disp = 0;
7399 uint32_t num_created = 0;
7400 uint32_t num_anounced = 0;
7401 bool ret = true;
7402 uint32_t i;
7403 struct dcerpc_binding_handle *b = p->binding_handle;
7405 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7407 /* query */
7410 struct samr_QueryDomainInfo2 r;
7411 union samr_DomainInfo *info;
7412 r.in.domain_handle = domain_handle;
7413 r.in.level = 2;
7414 r.out.info = &info;
7416 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7417 "QueryDomainInfo2 failed");
7418 torture_assert_ntstatus_ok(tctx, r.out.result,
7419 "failed to query domain info");
7421 switch (ctx->choice) {
7422 case TORTURE_SAMR_MANY_ACCOUNTS:
7423 num_anounced = info->general.num_users;
7424 break;
7425 case TORTURE_SAMR_MANY_GROUPS:
7426 num_anounced = info->general.num_groups;
7427 break;
7428 case TORTURE_SAMR_MANY_ALIASES:
7429 num_anounced = info->general.num_aliases;
7430 break;
7431 default:
7432 return false;
7436 /* create */
7438 for (i=0; i < num_total; i++) {
7440 const char *name = NULL;
7442 switch (ctx->choice) {
7443 case TORTURE_SAMR_MANY_ACCOUNTS:
7444 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7445 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7446 break;
7447 case TORTURE_SAMR_MANY_GROUPS:
7448 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7449 ret &= test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7450 break;
7451 case TORTURE_SAMR_MANY_ALIASES:
7452 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7453 ret &= test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7454 break;
7455 default:
7456 return false;
7458 if (!policy_handle_empty(&handles[i])) {
7459 num_created++;
7463 /* enum */
7465 switch (ctx->choice) {
7466 case TORTURE_SAMR_MANY_ACCOUNTS:
7467 ret &= test_EnumDomainUsers(b, tctx, domain_handle, &num_enum);
7468 break;
7469 case TORTURE_SAMR_MANY_GROUPS:
7470 ret &= test_EnumDomainGroups(b, tctx, domain_handle, &num_enum);
7471 break;
7472 case TORTURE_SAMR_MANY_ALIASES:
7473 ret &= test_EnumDomainAliases(b, tctx, domain_handle, &num_enum);
7474 break;
7475 default:
7476 return false;
7479 /* dispinfo */
7481 switch (ctx->choice) {
7482 case TORTURE_SAMR_MANY_ACCOUNTS:
7483 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp);
7484 break;
7485 case TORTURE_SAMR_MANY_GROUPS:
7486 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp);
7487 break;
7488 case TORTURE_SAMR_MANY_ALIASES:
7489 /* no aliases in dispinfo */
7490 break;
7491 default:
7492 return false;
7495 /* close or delete */
7497 for (i=0; i < num_total; i++) {
7499 if (policy_handle_empty(&handles[i])) {
7500 continue;
7503 if (torture_setting_bool(tctx, "samba3", false)) {
7504 ret &= test_samr_handle_Close(b, tctx, &handles[i]);
7505 } else {
7506 switch (ctx->choice) {
7507 case TORTURE_SAMR_MANY_ACCOUNTS:
7508 ret &= test_DeleteUser(b, tctx, &handles[i]);
7509 break;
7510 case TORTURE_SAMR_MANY_GROUPS:
7511 ret &= test_DeleteDomainGroup(b, tctx, &handles[i]);
7512 break;
7513 case TORTURE_SAMR_MANY_ALIASES:
7514 ret &= test_DeleteAlias(b, tctx, &handles[i]);
7515 break;
7516 default:
7517 return false;
7522 talloc_free(handles);
7524 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7525 torture_comment(tctx,
7526 "unexpected number of results (%u) returned in enum call, expected %u\n",
7527 num_enum, num_anounced + num_created);
7529 torture_comment(tctx,
7530 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7531 num_disp, num_anounced + num_created);
7533 return ret;
7536 static bool test_Connect(struct dcerpc_binding_handle *b,
7537 struct torture_context *tctx,
7538 struct policy_handle *handle);
7540 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7541 struct torture_samr_context *ctx, struct dom_sid *sid)
7543 struct samr_OpenDomain r;
7544 struct policy_handle domain_handle;
7545 struct policy_handle alias_handle;
7546 struct policy_handle user_handle;
7547 struct policy_handle group_handle;
7548 bool ret = true;
7549 struct dcerpc_binding_handle *b = p->binding_handle;
7551 ZERO_STRUCT(alias_handle);
7552 ZERO_STRUCT(user_handle);
7553 ZERO_STRUCT(group_handle);
7554 ZERO_STRUCT(domain_handle);
7556 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7558 r.in.connect_handle = &ctx->handle;
7559 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7560 r.in.sid = sid;
7561 r.out.domain_handle = &domain_handle;
7563 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7564 "OpenDomain failed");
7565 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7567 /* run the domain tests with the main handle closed - this tests
7568 the servers reference counting */
7569 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7571 switch (ctx->choice) {
7572 case TORTURE_SAMR_PASSWORDS:
7573 case TORTURE_SAMR_USER_PRIVILEGES:
7574 if (!torture_setting_bool(tctx, "samba3", false)) {
7575 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7577 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7578 if (!ret) {
7579 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7581 break;
7582 case TORTURE_SAMR_USER_ATTRIBUTES:
7583 if (!torture_setting_bool(tctx, "samba3", false)) {
7584 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7586 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7587 /* This test needs 'complex' users to validate */
7588 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7589 if (!ret) {
7590 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7592 break;
7593 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7594 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7595 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7596 if (!torture_setting_bool(tctx, "samba3", false)) {
7597 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7599 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7600 if (!ret) {
7601 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7603 break;
7604 case TORTURE_SAMR_MANY_ACCOUNTS:
7605 case TORTURE_SAMR_MANY_GROUPS:
7606 case TORTURE_SAMR_MANY_ALIASES:
7607 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7608 if (!ret) {
7609 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7611 break;
7612 case TORTURE_SAMR_OTHER:
7613 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7614 if (!ret) {
7615 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7617 if (!torture_setting_bool(tctx, "samba3", false)) {
7618 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7620 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7621 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7622 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7623 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7624 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7625 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7626 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7627 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7628 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7629 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7630 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7631 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7632 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7634 if (torture_setting_bool(tctx, "samba4", false)) {
7635 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7636 } else {
7637 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7638 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7640 ret &= test_GroupList(b, tctx, &domain_handle);
7641 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7642 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7643 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7644 if (!ret) {
7645 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7647 break;
7650 if (!policy_handle_empty(&user_handle) &&
7651 !test_DeleteUser(b, tctx, &user_handle)) {
7652 ret = false;
7655 if (!policy_handle_empty(&alias_handle) &&
7656 !test_DeleteAlias(b, tctx, &alias_handle)) {
7657 ret = false;
7660 if (!policy_handle_empty(&group_handle) &&
7661 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7662 ret = false;
7665 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7667 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7668 /* reconnect the main handle */
7670 if (!ret) {
7671 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7674 return ret;
7677 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7678 struct torture_samr_context *ctx, const char *domain)
7680 struct samr_LookupDomain r;
7681 struct dom_sid2 *sid = NULL;
7682 struct lsa_String n1;
7683 struct lsa_String n2;
7684 bool ret = true;
7685 struct dcerpc_binding_handle *b = p->binding_handle;
7687 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7689 /* check for correct error codes */
7690 r.in.connect_handle = &ctx->handle;
7691 r.in.domain_name = &n2;
7692 r.out.sid = &sid;
7693 n2.string = NULL;
7695 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7696 "LookupDomain failed");
7697 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7699 init_lsa_String(&n2, "xxNODOMAINxx");
7701 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7702 "LookupDomain failed");
7703 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7705 r.in.connect_handle = &ctx->handle;
7707 init_lsa_String(&n1, domain);
7708 r.in.domain_name = &n1;
7710 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7711 "LookupDomain failed");
7712 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7714 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7715 ret = false;
7718 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7719 ret = false;
7722 return ret;
7726 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7727 struct torture_samr_context *ctx)
7729 struct samr_EnumDomains r;
7730 uint32_t resume_handle = 0;
7731 uint32_t num_entries = 0;
7732 struct samr_SamArray *sam = NULL;
7733 int i;
7734 bool ret = true;
7735 struct dcerpc_binding_handle *b = p->binding_handle;
7737 r.in.connect_handle = &ctx->handle;
7738 r.in.resume_handle = &resume_handle;
7739 r.in.buf_size = (uint32_t)-1;
7740 r.out.resume_handle = &resume_handle;
7741 r.out.num_entries = &num_entries;
7742 r.out.sam = &sam;
7744 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7745 "EnumDomains failed");
7746 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7748 if (!*r.out.sam) {
7749 return false;
7752 for (i=0;i<sam->count;i++) {
7753 if (!test_LookupDomain(p, tctx, ctx,
7754 sam->entries[i].name.string)) {
7755 ret = false;
7759 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7760 "EnumDomains failed");
7761 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7763 return ret;
7767 static bool test_Connect(struct dcerpc_binding_handle *b,
7768 struct torture_context *tctx,
7769 struct policy_handle *handle)
7771 struct samr_Connect r;
7772 struct samr_Connect2 r2;
7773 struct samr_Connect3 r3;
7774 struct samr_Connect4 r4;
7775 struct samr_Connect5 r5;
7776 union samr_ConnectInfo info;
7777 struct policy_handle h;
7778 uint32_t level_out = 0;
7779 bool ret = true, got_handle = false;
7781 torture_comment(tctx, "Testing samr_Connect\n");
7783 r.in.system_name = 0;
7784 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7785 r.out.connect_handle = &h;
7787 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7788 "Connect failed");
7789 if (!NT_STATUS_IS_OK(r.out.result)) {
7790 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7791 ret = false;
7792 } else {
7793 got_handle = true;
7794 *handle = h;
7797 torture_comment(tctx, "Testing samr_Connect2\n");
7799 r2.in.system_name = NULL;
7800 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7801 r2.out.connect_handle = &h;
7803 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7804 "Connect2 failed");
7805 if (!NT_STATUS_IS_OK(r2.out.result)) {
7806 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7807 ret = false;
7808 } else {
7809 if (got_handle) {
7810 test_samr_handle_Close(b, tctx, handle);
7812 got_handle = true;
7813 *handle = h;
7816 torture_comment(tctx, "Testing samr_Connect3\n");
7818 r3.in.system_name = NULL;
7819 r3.in.unknown = 0;
7820 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7821 r3.out.connect_handle = &h;
7823 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7824 "Connect3 failed");
7825 if (!NT_STATUS_IS_OK(r3.out.result)) {
7826 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7827 ret = false;
7828 } else {
7829 if (got_handle) {
7830 test_samr_handle_Close(b, tctx, handle);
7832 got_handle = true;
7833 *handle = h;
7836 torture_comment(tctx, "Testing samr_Connect4\n");
7838 r4.in.system_name = "";
7839 r4.in.client_version = 0;
7840 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7841 r4.out.connect_handle = &h;
7843 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
7844 "Connect4 failed");
7845 if (!NT_STATUS_IS_OK(r4.out.result)) {
7846 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
7847 ret = false;
7848 } else {
7849 if (got_handle) {
7850 test_samr_handle_Close(b, tctx, handle);
7852 got_handle = true;
7853 *handle = h;
7856 torture_comment(tctx, "Testing samr_Connect5\n");
7858 info.info1.client_version = 0;
7859 info.info1.unknown2 = 0;
7861 r5.in.system_name = "";
7862 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7863 r5.in.level_in = 1;
7864 r5.out.level_out = &level_out;
7865 r5.in.info_in = &info;
7866 r5.out.info_out = &info;
7867 r5.out.connect_handle = &h;
7869 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
7870 "Connect5 failed");
7871 if (!NT_STATUS_IS_OK(r5.out.result)) {
7872 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
7873 ret = false;
7874 } else {
7875 if (got_handle) {
7876 test_samr_handle_Close(b, tctx, handle);
7878 got_handle = true;
7879 *handle = h;
7882 return ret;
7886 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
7887 struct torture_context *tctx)
7889 struct samr_ValidatePassword r;
7890 union samr_ValidatePasswordReq req;
7891 union samr_ValidatePasswordRep *repp = NULL;
7892 NTSTATUS status;
7893 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7894 int i;
7895 struct dcerpc_binding_handle *b = p->binding_handle;
7897 torture_comment(tctx, "Testing samr_ValidatePassword\n");
7899 ZERO_STRUCT(r);
7900 r.in.level = NetValidatePasswordReset;
7901 r.in.req = &req;
7902 r.out.rep = &repp;
7904 ZERO_STRUCT(req);
7905 req.req3.account.string = "non-existant-account-aklsdji";
7907 for (i=0; passwords[i]; i++) {
7908 req.req3.password.string = passwords[i];
7910 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
7911 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
7912 torture_skip(tctx, "ValidatePassword not supported by server\n");
7914 torture_assert_ntstatus_ok(tctx, status,
7915 "samr_ValidatePassword failed");
7916 torture_assert_ntstatus_ok(tctx, r.out.result,
7917 "samr_ValidatePassword failed");
7918 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7919 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7920 req.req3.password.string, repp->ctr3.status);
7923 return true;
7926 bool torture_rpc_samr(struct torture_context *torture)
7928 NTSTATUS status;
7929 struct dcerpc_pipe *p;
7930 bool ret = true;
7931 struct torture_samr_context *ctx;
7932 struct dcerpc_binding_handle *b;
7934 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7935 if (!NT_STATUS_IS_OK(status)) {
7936 return false;
7938 b = p->binding_handle;
7940 ctx = talloc_zero(torture, struct torture_samr_context);
7942 ctx->choice = TORTURE_SAMR_OTHER;
7944 ret &= test_Connect(b, torture, &ctx->handle);
7946 if (!torture_setting_bool(torture, "samba3", false)) {
7947 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7950 ret &= test_EnumDomains(p, torture, ctx);
7952 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7954 ret &= test_Shutdown(b, torture, &ctx->handle);
7956 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7958 return ret;
7962 bool torture_rpc_samr_users(struct torture_context *torture)
7964 NTSTATUS status;
7965 struct dcerpc_pipe *p;
7966 bool ret = true;
7967 struct torture_samr_context *ctx;
7968 struct dcerpc_binding_handle *b;
7970 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7971 if (!NT_STATUS_IS_OK(status)) {
7972 return false;
7974 b = p->binding_handle;
7976 ctx = talloc_zero(torture, struct torture_samr_context);
7978 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7980 ret &= test_Connect(b, torture, &ctx->handle);
7982 if (!torture_setting_bool(torture, "samba3", false)) {
7983 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7986 ret &= test_EnumDomains(p, torture, ctx);
7988 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7990 ret &= test_Shutdown(b, torture, &ctx->handle);
7992 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7994 return ret;
7998 bool torture_rpc_samr_passwords(struct torture_context *torture)
8000 NTSTATUS status;
8001 struct dcerpc_pipe *p;
8002 bool ret = true;
8003 struct torture_samr_context *ctx;
8004 struct dcerpc_binding_handle *b;
8006 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8007 if (!NT_STATUS_IS_OK(status)) {
8008 return false;
8010 b = p->binding_handle;
8012 ctx = talloc_zero(torture, struct torture_samr_context);
8014 ctx->choice = TORTURE_SAMR_PASSWORDS;
8016 ret &= test_Connect(b, torture, &ctx->handle);
8018 ret &= test_EnumDomains(p, torture, ctx);
8020 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8022 ret &= test_samr_ValidatePassword(p, torture);
8024 return ret;
8027 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8028 struct dcerpc_pipe *p2,
8029 struct cli_credentials *machine_credentials)
8031 NTSTATUS status;
8032 struct dcerpc_pipe *p;
8033 bool ret = true;
8034 struct torture_samr_context *ctx;
8035 struct dcerpc_binding_handle *b;
8037 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8038 if (!NT_STATUS_IS_OK(status)) {
8039 return false;
8041 b = p->binding_handle;
8043 ctx = talloc_zero(torture, struct torture_samr_context);
8045 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8046 ctx->machine_credentials = machine_credentials;
8048 ret &= test_Connect(b, torture, &ctx->handle);
8050 ret &= test_EnumDomains(p, torture, ctx);
8052 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8054 return ret;
8057 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8059 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
8060 struct torture_rpc_tcase *tcase;
8062 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8063 &ndr_table_samr,
8064 TEST_ACCOUNT_NAME_PWD);
8066 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8067 torture_rpc_samr_pwdlastset);
8069 return suite;
8072 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8073 struct dcerpc_pipe *p2,
8074 struct cli_credentials *machine_credentials)
8076 NTSTATUS status;
8077 struct dcerpc_pipe *p;
8078 bool ret = true;
8079 struct torture_samr_context *ctx;
8080 struct dcerpc_binding_handle *b;
8082 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8083 if (!NT_STATUS_IS_OK(status)) {
8084 return false;
8086 b = p->binding_handle;
8088 ctx = talloc_zero(torture, struct torture_samr_context);
8090 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8091 ctx->machine_credentials = machine_credentials;
8093 ret &= test_Connect(b, torture, &ctx->handle);
8095 ret &= test_EnumDomains(p, torture, ctx);
8097 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8099 return ret;
8102 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8104 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
8105 struct torture_rpc_tcase *tcase;
8107 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8108 &ndr_table_samr,
8109 TEST_ACCOUNT_NAME_PWD);
8111 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8112 torture_rpc_samr_users_privileges_delete_user);
8114 return suite;
8117 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8118 struct dcerpc_pipe *p2,
8119 void *data)
8121 NTSTATUS status;
8122 struct dcerpc_pipe *p;
8123 bool ret = true;
8124 struct torture_samr_context *ctx =
8125 talloc_get_type_abort(data, struct torture_samr_context);
8126 struct dcerpc_binding_handle *b;
8128 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8129 if (!NT_STATUS_IS_OK(status)) {
8130 return false;
8132 b = p->binding_handle;
8134 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8135 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8136 ctx->num_objects_large_dc);
8138 ret &= test_Connect(b, torture, &ctx->handle);
8140 ret &= test_EnumDomains(p, torture, ctx);
8142 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8144 return ret;
8147 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8148 struct dcerpc_pipe *p2,
8149 void *data)
8151 NTSTATUS status;
8152 struct dcerpc_pipe *p;
8153 bool ret = true;
8154 struct torture_samr_context *ctx =
8155 talloc_get_type_abort(data, struct torture_samr_context);
8156 struct dcerpc_binding_handle *b;
8158 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8159 if (!NT_STATUS_IS_OK(status)) {
8160 return false;
8162 b = p->binding_handle;
8164 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8165 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8166 ctx->num_objects_large_dc);
8168 ret &= test_Connect(b, torture, &ctx->handle);
8170 ret &= test_EnumDomains(p, torture, ctx);
8172 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8174 return ret;
8177 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8178 struct dcerpc_pipe *p2,
8179 void *data)
8181 NTSTATUS status;
8182 struct dcerpc_pipe *p;
8183 bool ret = true;
8184 struct torture_samr_context *ctx =
8185 talloc_get_type_abort(data, struct torture_samr_context);
8186 struct dcerpc_binding_handle *b;
8188 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8189 if (!NT_STATUS_IS_OK(status)) {
8190 return false;
8192 b = p->binding_handle;
8194 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8195 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8196 ctx->num_objects_large_dc);
8198 ret &= test_Connect(b, torture, &ctx->handle);
8200 ret &= test_EnumDomains(p, torture, ctx);
8202 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8204 return ret;
8207 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8209 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
8210 struct torture_rpc_tcase *tcase;
8211 struct torture_samr_context *ctx;
8213 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8215 ctx = talloc_zero(suite, struct torture_samr_context);
8216 ctx->num_objects_large_dc = 150;
8218 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8219 torture_rpc_samr_many_aliases, ctx);
8220 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8221 torture_rpc_samr_many_groups, ctx);
8222 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8223 torture_rpc_samr_many_accounts, ctx);
8225 return suite;
8228 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8229 struct dcerpc_pipe *p2,
8230 struct cli_credentials *machine_credentials)
8232 NTSTATUS status;
8233 struct dcerpc_pipe *p;
8234 bool ret = true;
8235 struct torture_samr_context *ctx;
8236 struct dcerpc_binding_handle *b;
8238 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8239 if (!NT_STATUS_IS_OK(status)) {
8240 return false;
8242 b = p->binding_handle;
8244 ctx = talloc_zero(torture, struct torture_samr_context);
8246 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8247 ctx->machine_credentials = machine_credentials;
8249 ret &= test_Connect(b, torture, &ctx->handle);
8251 ret &= test_EnumDomains(p, torture, ctx);
8253 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8255 return ret;
8258 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8260 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
8261 struct torture_rpc_tcase *tcase;
8263 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8264 &ndr_table_samr,
8265 TEST_ACCOUNT_NAME_PWD);
8267 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8268 torture_rpc_samr_badpwdcount);
8270 return suite;
8273 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8274 struct dcerpc_pipe *p2,
8275 struct cli_credentials *machine_credentials)
8277 NTSTATUS status;
8278 struct dcerpc_pipe *p;
8279 bool ret = true;
8280 struct torture_samr_context *ctx;
8281 struct dcerpc_binding_handle *b;
8283 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8284 if (!NT_STATUS_IS_OK(status)) {
8285 return false;
8287 b = p->binding_handle;
8289 ctx = talloc_zero(torture, struct torture_samr_context);
8291 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8292 ctx->machine_credentials = machine_credentials;
8294 ret &= test_Connect(b, torture, &ctx->handle);
8296 ret &= test_EnumDomains(p, torture, ctx);
8298 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8300 return ret;
8303 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8305 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8306 struct torture_rpc_tcase *tcase;
8308 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8309 &ndr_table_samr,
8310 TEST_ACCOUNT_NAME_PWD);
8312 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8313 torture_rpc_samr_lockout);
8315 return suite;